All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.druid.extendedset.utilities.BitCount Maven / Gradle / Ivy

/* 
 * (c) 2010 Alessandro Colantonio
 * 
 * 
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.druid.extendedset.utilities;

import java.util.Random;

/**
 * Population count (a.k.a. Hamming distance) of a bitmap represented by an
 * array of int.
 * 

* Derived from http * ://dalkescientific.com/writings/diary/popcnt.c * * @author Alessandro Colantonio * @version $Id: BitCount.java 157 2011-11-14 14:25:15Z cocciasik $ */ public class BitCount { /** * Population count * * @param buffer array of int * * @return population count */ public static int count(int[] buffer) { return count(buffer, buffer.length); } /** * Population count *

* It counts 24 words at a time, then 3 at a time, then 1 at a time * * @param buffer array of int * @param n number of elements of buffer to count * * @return population count */ public static int count(int[] buffer, int n) { final int n1 = n - n % 24; final int n2 = n - n % 3; int cnt = 0; int i; for (i = 0; i < n1; i += 24) { cnt += merging3(buffer, i); } for (; i < n2; i += 3) { cnt += merging2(buffer, i); } cnt += popcount_fbsd2(buffer, i, n); return cnt; } // used by count() private static int merging3(int[] buffer, int x) { int cnt1; int cnt2; int cnt = 0; for (int i = x; i < x + 24; i += 3) { cnt1 = buffer[i]; cnt2 = buffer[i + 1]; final int w = buffer[i + 2]; cnt1 = cnt1 - ((cnt1 >>> 1) & 0x55555555) + (w & 0x55555555); cnt2 = cnt2 - ((cnt2 >>> 1) & 0x55555555) + ((w >>> 1) & 0x55555555); cnt1 = (cnt1 & 0x33333333) + ((cnt1 >>> 2) & 0x33333333); cnt1 += (cnt2 & 0x33333333) + ((cnt2 >>> 2) & 0x33333333); cnt += (cnt1 & 0x0F0F0F0F) + ((cnt1 >>> 4) & 0x0F0F0F0F); } cnt = (cnt & 0x00FF00FF) + ((cnt >>> 8) & 0x00FF00FF); cnt += cnt >>> 16; return cnt & 0x00000FFFF; } // used by count() private static int merging2(int[] buffer, int x) { int cnt1 = buffer[x]; int cnt2 = buffer[x + 1]; final int w = buffer[x + 2]; cnt1 = cnt1 - ((cnt1 >>> 1) & 0x55555555) + (w & 0x55555555); cnt2 = cnt2 - ((cnt2 >>> 1) & 0x55555555) + ((w >>> 1) & 0x55555555); cnt1 = (cnt1 & 0x33333333) + ((cnt1 >>> 2) & 0x33333333); cnt2 = (cnt2 & 0x33333333) + ((cnt2 >>> 2) & 0x33333333); cnt1 += cnt2; cnt1 = (cnt1 & 0x0F0F0F0F) + ((cnt1 >>> 4) & 0x0F0F0F0F); cnt1 += cnt1 >>> 8; cnt1 += cnt1 >>> 16; return cnt1 & 0x000000FF; } // used by count() private static int popcount_fbsd2(int[] data, int x, int n) { int cnt = 0; for (; x < n; x++) { cnt += Integer.bitCount(data[x]); } return cnt; } /** * Population count, skipping words at even positions * * @param buffer array of int * * @return population count */ public static int count_2(int[] buffer) { return count_2(buffer, buffer.length); } /** * Population count, skipping words at even positions *

* It counts 24 words at a time, then 3 at a time, then 1 at a time * * @param buffer array of int * @param n number of elements of buffer to count * * @return population count */ public static int count_2(int[] buffer, int n) { final int n1 = n - n % 48; final int n2 = n - n % 6; int cnt = 0; int i; for (i = 0; i < n1; i += 48) { cnt += merging3_2(buffer, i); } for (; i < n2; i += 6) { cnt += merging2_2(buffer, i); } cnt += popcount_fbsd2_2(buffer, i, n); return cnt; } // used by count_2() private static int merging3_2(int[] buffer, int x) { int cnt1; int cnt2; int cnt = 0; for (int i = x; i < x + 48; i += 6) { cnt1 = buffer[i + 1]; cnt2 = buffer[i + 3]; final int w = buffer[i + 5]; cnt1 = cnt1 - ((cnt1 >>> 1) & 0x55555555) + (w & 0x55555555); cnt2 = cnt2 - ((cnt2 >>> 1) & 0x55555555) + ((w >>> 1) & 0x55555555); cnt1 = (cnt1 & 0x33333333) + ((cnt1 >>> 2) & 0x33333333); cnt1 += (cnt2 & 0x33333333) + ((cnt2 >>> 2) & 0x33333333); cnt += (cnt1 & 0x0F0F0F0F) + ((cnt1 >>> 4) & 0x0F0F0F0F); } cnt = (cnt & 0x00FF00FF) + ((cnt >>> 8) & 0x00FF00FF); cnt += cnt >>> 16; return cnt & 0x00000FFFF; } // used by count_2() private static int merging2_2(int[] buffer, int x) { int cnt1 = buffer[x + 1]; int cnt2 = buffer[x + 3]; final int w = buffer[x + 5]; cnt1 = cnt1 - ((cnt1 >>> 1) & 0x55555555) + (w & 0x55555555); cnt2 = cnt2 - ((cnt2 >>> 1) & 0x55555555) + ((w >>> 1) & 0x55555555); cnt1 = (cnt1 & 0x33333333) + ((cnt1 >>> 2) & 0x33333333); cnt2 = (cnt2 & 0x33333333) + ((cnt2 >>> 2) & 0x33333333); cnt1 += cnt2; cnt1 = (cnt1 & 0x0F0F0F0F) + ((cnt1 >>> 4) & 0x0F0F0F0F); cnt1 += cnt1 >>> 8; cnt1 += cnt1 >>> 16; return cnt1 & 0x000000FF; } // used by count_2() private static int popcount_fbsd2_2(int[] data, int x, int n) { int cnt = 0; for (x++; x < n; x += 2) { cnt += Integer.bitCount(data[x]); } return cnt; } /** * Test * * @param args */ public static void main(String[] args) { final int trials = 10000; final int maxLength = 10000; Random rnd = new Random(); final int seed = rnd.nextInt(); System.out.print("Test correctness... "); rnd = new Random(seed); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength)]; for (int j = 0; j < x.length; j++) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } int size1 = 0; for (int j = 0; j < x.length; j++) { size1 += Integer.bitCount(x[j]); } int size2 = count(x); if (size1 != size2) { System.out.println("i = " + i); System.out.println("ERRORE!"); System.out.println(size1 + ", " + size2); for (int j = 0; j < x.length; j++) { System.out.format("x[%d] = %d --> %d\n", j, x[j], Integer.bitCount(x[j])); } return; } } System.out.println("done!"); System.out.print("Test correctness II... "); rnd = new Random(seed); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength << 1)]; for (int j = 1; j < x.length; j += 2) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } int size1 = 0; for (int j = 1; j < x.length; j += 2) { size1 += Integer.bitCount(x[j]); } int size2 = count_2(x); if (size1 != size2) { System.out.println("i = " + i); System.out.println("ERRORE!"); System.out.println(size1 + ", " + size2); for (int j = 1; j < x.length; j += 2) { System.out.format("x[%d] = %d --> %d\n", j, x[j], Integer.bitCount(x[j])); } return; } } System.out.println("done!"); System.out.print("Test time count(): "); rnd = new Random(seed); long t = System.currentTimeMillis(); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength)]; for (int j = 0; j < x.length; j++) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } @SuppressWarnings("unused") int size = 0; for (int j = 0; j < x.length; j++) { size += Integer.bitCount(x[j]); } } System.out.println(System.currentTimeMillis() - t); System.out.print("Test time BitCount.count(): "); rnd = new Random(seed); t = System.currentTimeMillis(); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength)]; for (int j = 0; j < x.length; j++) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } count(x); } System.out.println(System.currentTimeMillis() - t); System.out.print("Test II time count(): "); rnd = new Random(seed); t = System.currentTimeMillis(); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength << 1)]; for (int j = 1; j < x.length; j += 2) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } @SuppressWarnings("unused") int size = 0; for (int j = 1; j < x.length; j += 2) { size += Integer.bitCount(x[j]); } } System.out.println(System.currentTimeMillis() - t); System.out.print("Test II time BitCount.count(): "); rnd = new Random(seed); t = System.currentTimeMillis(); for (int i = 0; i < trials; i++) { int[] x = new int[rnd.nextInt(maxLength << 1)]; for (int j = 1; j < x.length; j += 2) { x[j] = rnd.nextInt(Integer.MAX_VALUE); } count_2(x); } System.out.println(System.currentTimeMillis() - t); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy