/*
 * Java
 *
 * Copyright 2023 MicroEJ Corp. This file has been modified and/or created by MicroEJ Corp.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.time;

/**
 * Provides missing methods in java.lang.Integer.
 */
class IntegerHelper {

	/**
	 * Returns the number of zero bits preceding the highest-order ("leftmost") one-bit in the two's complement binary
	 * representation of the specified {@code int} value. Returns 32 if the specified value has no one-bits in its two's
	 * complement representation, in other words if it is equal to zero.
	 *
	 * <p>
	 * Note that this method is closely related to the logarithm base 2. For all positive {@code int} values x:
	 * <ul>
	 * <li>floor(log<sub>2</sub>(x)) = {@code 31 - numberOfLeadingZeros(x)}
	 * <li>ceil(log<sub>2</sub>(x)) = {@code 32 - numberOfLeadingZeros(x - 1)}
	 * </ul>
	 *
	 * @param i
	 *            the value whose number of leading zeros is to be computed
	 * @return the number of zero bits preceding the highest-order ("leftmost") one-bit in the two's complement binary
	 *         representation of the specified {@code int} value, or 32 if the value is equal to zero.
	 * @since 1.5
	 */
	static int numberOfLeadingZeros(int i) {
		// HD, Figure 5-6
		if (i == 0) {
			return 32;
		}
		int n = 1;
		if (i >>> 16 == 0) {
			n += 16;
			i <<= 16;
		}
		if (i >>> 24 == 0) {
			n += 8;
			i <<= 8;
		}
		if (i >>> 28 == 0) {
			n += 4;
			i <<= 4;
		}
		if (i >>> 30 == 0) {
			n += 2;
			i <<= 2;
		}
		n -= i >>> 31;
		return n;
	}

	/**
	 * Returns the number of zero bits following the lowest-order ("rightmost") one-bit in the two's complement binary
	 * representation of the specified {@code int} value. Returns 32 if the specified value has no one-bits in its two's
	 * complement representation, in other words if it is equal to zero.
	 *
	 * @param i
	 *            the value whose number of trailing zeros is to be computed
	 * @return the number of zero bits following the lowest-order ("rightmost") one-bit in the two's complement binary
	 *         representation of the specified {@code int} value, or 32 if the value is equal to zero.
	 * @since 1.5
	 */
	static int numberOfTrailingZeros(int i) {
		// HD, Figure 5-14
		int y;
		if (i == 0) {
			return 32;
		}
		int n = 31;
		y = i << 16;
		if (y != 0) {
			n = n - 16;
			i = y;
		}
		y = i << 8;
		if (y != 0) {
			n = n - 8;
			i = y;
		}
		y = i << 4;
		if (y != 0) {
			n = n - 4;
			i = y;
		}
		y = i << 2;
		if (y != 0) {
			n = n - 2;
			i = y;
		}
		return n - ((i << 1) >>> 31);
	}

	/**
	 * Returns the number of one-bits in the two's complement binary representation of the specified {@code int} value.
	 * This function is sometimes referred to as the <i>population count</i>.
	 *
	 * @param i
	 *            the value whose bits are to be counted
	 * @return the number of one-bits in the two's complement binary representation of the specified {@code int} value.
	 * @since 1.5
	 */
	static int bitCount(int i) {
		// HD, Figure 5-2
		i = i - ((i >>> 1) & 0x55555555);
		i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
		i = (i + (i >>> 4)) & 0x0f0f0f0f;
		i = i + (i >>> 8);
		i = i + (i >>> 16);
		return i & 0x3f;
	}
}
