/*
 * HPPC
 *
 * Copyright (C) 2010-2024 Carrot Search s.c. and contributors
 * All rights reserved.
 *
 * Refer to the full license file "LICENSE.txt":
 * https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
 */
package com.carrotsearch.hppc;

/** A variety of high efficiency bit twiddling routines. */
final class BitUtil {
	/**
	 * returns the next highest power of two, or the current value if it's already a
	 * power of two or zero
	 */
	public static int nextHighestPowerOfTwo(int v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v++;
		return v;
	}

	// The pop methods used to rely on bit-manipulation tricks for speed but it
	// turns out that it is faster to use the Long.bitCount method (which is an
	// intrinsic since Java 6u18) in a naive loop, see LUCENE-2221

	/**
	 * returns the next highest power of two, or the current value if it's already a
	 * power of two or zero
	 */
	public static long nextHighestPowerOfTwo(long v) {
		v--;
		v |= v >> 1;
		v |= v >> 2;
		v |= v >> 4;
		v |= v >> 8;
		v |= v >> 16;
		v |= v >> 32;
		v++;
		return v;
	}

	/**
	 * Returns the popcount or cardinality of A &amp; ~B. Neither array is modified.
	 */
	public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) {
		long popCount = 0;
		for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
			popCount += Long.bitCount(arr1[i] & ~arr2[i]);
		}
		return popCount;
	}

	/** Returns the number of set bits in an array of longs. */
	public static long pop_array(long[] arr, int wordOffset, int numWords) {
		long popCount = 0;
		for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
			popCount += Long.bitCount(arr[i]);
		}
		return popCount;
	}

	/**
	 * Returns the popcount or cardinality of the two sets after an intersection.
	 * Neither array is modified.
	 */
	public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) {
		long popCount = 0;
		for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
			popCount += Long.bitCount(arr1[i] & arr2[i]);
		}
		return popCount;
	}

	/**
	 * Returns the popcount or cardinality of the union of two sets. Neither array
	 * is modified.
	 */
	public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) {
		long popCount = 0;
		for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
			popCount += Long.bitCount(arr1[i] | arr2[i]);
		}
		return popCount;
	}

	/** Returns the popcount or cardinality of A ^ B Neither array is modified. */
	public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) {
		long popCount = 0;
		for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
			popCount += Long.bitCount(arr1[i] ^ arr2[i]);
		}
		return popCount;
	}

	private BitUtil() {
	} // no instance
}
