/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.bitmap;
import java.util.Random;
import org.h2.bitmap.BitSet;
import org.h2.bitmap.OpenBitSet;
import org.h2.test.TestBase;
/**
* @author Min Zhou (coderplay@gmail.com)
*/
public class TestOpenBitSet extends TestBase {
private int nums = 1024 * 1024;
private BitSet bitset;
private BitSet[] bitmap;
private int[] values;
/**
* Run just this test.
*
* @param a
* ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
prepareBitmap();
testAnd();
testOr();
testXor();
testAndNot();
testSum();
testRange();
}
private void prepareBitmap() {
Random rand = new Random(System.nanoTime());
bitset = new OpenBitSet(nums);
for (int i = 0; i < (nums / 2); i++) {
bitset.set(rand.nextInt(nums));
}
bitmap = new OpenBitSet[Integer.SIZE];
for (int i = 0; i < bitmap.length; i++) {
bitmap[i] = new OpenBitSet(nums);
}
values = new int[nums];
for (int i = 0; i < nums; i++) {
values[i] = rand.nextInt(0x7fffffff);
for (int j = 0; j < bitmap.length; j++) {
int v = (values[i] >> j) & 0x01;
if (v == 0x01) {
bitmap[j].set(i);
}
}
}
}
private void testAnd() {
int originCard = bitset.cardinality();
bitset.and(bitset);
int afterCard = bitset.cardinality();
assertEquals(originCard, afterCard);
int card1 = bitset.andCardinality(bitmap[0]);
bitset.and(bitmap[0]);
int card2 = bitset.cardinality();
assertEquals(card1, card2);
}
private void testOr() {
int originCard = bitset.cardinality();
bitset.or(bitset);
int afterCard = bitset.cardinality();
assertEquals(originCard, afterCard);
int card1 = bitset.orCardinality(bitmap[1]);
bitset.or(bitmap[1]);
int card2 = bitset.cardinality();
assertEquals(card1, card2);
}
private void testXor() {
int card1 = bitset.xorCardinality(bitmap[2]);
bitset.xor(bitmap[2]);
int card2 = bitset.cardinality();
assertEquals(card1, card2);
}
private void testAndNot() {
int card1 = bitset.andNotCardinality(bitmap[3]);
bitset.andNot(bitmap[3]);
int card2 = bitset.cardinality();
assertEquals(card1, card2);
}
/**
* select sum(column)
*/
private void testSum() {
long start = System.nanoTime();
long sumArray = 0L;
for (int i = 0; i < nums; i++) {
sumArray += values[i];
}
System.out.println("sum by array cost time: "
+ (System.nanoTime() - start));
// The cardinality of a bitmap is always cached
// so this aggregation should be super fast, O(1) time
// however in this case, we assume that wasn't cached
start = System.nanoTime();
long sumBitmap = 0L;
for (int j = 0; j < bitmap.length; j++) {
sumBitmap += ((long) bitmap[j].cardinality()) << j;
}
System.out.println("sum by bitmap cost time: "
+ (System.nanoTime() - start));
assertEquals(sumArray, sumBitmap);
}
/**
* select count(1) from table where column >= lower and column <= upper
*/
private void testRange() {
int lower = 0x17777777;
int upper = 0x5ddddddd;
long start = System.nanoTime();
int countArray = 0;
for (int i = 0; i < nums; i++) {
if ((values[i] >= lower) && (values[i] <= upper))
countArray++;
}
System.out.println("range count by array cost time: "
+ (System.nanoTime() - start));
start = System.nanoTime();
BitSet greaterThanLower = new OpenBitSet(nums);
BitSet equalsToLower = new OpenBitSet(nums);
equalsToLower.set(0, nums);
BitSet lessThanUpper = new OpenBitSet(nums);
BitSet equalsToUpper = new OpenBitSet(nums);
equalsToUpper.set(0, nums);
for(int i = 0; i < Integer.SIZE; i++) {
// >= lower
if( ((lower << i) & 0x80000000) == 0x80000000) {
equalsToLower.and(bitmap[Integer.SIZE - 1 - i]);
} else {
BitSet tmp = equalsToLower.clone();
tmp.and(bitmap[Integer.SIZE - 1 - i]);
greaterThanLower.or(tmp);
equalsToLower.andNot(bitmap[Integer.SIZE - 1 - i]);
}
// <= upper
if( ((upper << i) & 0x80000000) == 0x80000000) {
BitSet tmp = equalsToUpper.clone();
tmp.andNot(bitmap[Integer.SIZE - 1 - i]);
lessThanUpper.or(tmp);
equalsToUpper.and(bitmap[Integer.SIZE - 1 - i]);
} else {
equalsToUpper.andNot(bitmap[Integer.SIZE - 1 - i]);
}
}
BitSet result = greaterThanLower.clone();
result.and(lessThanUpper);
result.or(equalsToLower);
result.or(equalsToUpper);
int intBitmtap = result.cardinality();
System.out.println("range count by bitmap cost time: "
+ (System.nanoTime() - start));
assertEquals(countArray, intBitmtap);
}
}