/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program 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 Lesser General Public License
* for more details.
*
* Last commit: $Rev: 1182 $ by $Author: glycoslave $ on $Date:: 2009-06-10 #$
*/
package test.eurocarbdb.util;
import java.util.Set;
import java.util.HashSet;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import org.testng.annotations.*;
import org.eurocarbdb.util.BitSet;
import static java.lang.System.out;
import static org.eurocarbdb.util.StringUtils.join;
/**
*<p>
* Tests basic {@link BitSet} operations; test group is 'util.bitset'.
*</p>
*
*<h2>Performance</h2>
*<p>
* The benchmarking method, {@link #bitsetBenchmark}, which compares
* performance of this class versus {@link java.util.BitSet}
* and a {@link HashSet} of Integersis disabled by default,
* and needs to be manually enabled in the source to be run.
*</p>
*<p>
* However, these are the typcial results for my machine (2.5GHz core duo macbook pro):
*<pre>
* iterations = 100000, size = 16
* add to bitset: 53 msec
* add to hashset: 82 msec
* add to java bitset: 16 msec
* bitset: 70 msec
* hashset: 282 msec
* javabitset: 57 msec
*
* iterations = 1000000, size = 16
* add to bitset: 105 msec
* add to hashset: 804 msec
* add to java bitset: 130 msec
* bitset: 667 msec
* hashset: 2677 msec
* javabitset: 420 msec
*
* iterations = 100000, size = 32
* add to bitset: 33 msec
* add to hashset: 159 msec
* add to java bitset: 24 msec
* bitset: 132 msec
* hashset: 520 msec
* javabitset: 83 msec
*
* iterations = 100000, size = 64
* add to bitset: 66 msec
* add to hashset: 330 msec
* add to java bitset: 52 msec
* bitset: 269 msec
* hashset: 1024 msec
* javabitset: 170 msec
*
* iterations = 100000, size = 128
* add to bitset: 248 msec
* add to hashset: 813 msec
* add to java bitset: 152 msec
* bitset: 800 msec
* hashset: 2549 msec
* javabitset: 550 msec
*</pre>
* The first 3 results of each test are for add operations only, the
* second set of 3 results are for an add, contains and delete operation.
*</p>
*<p>
* It should be noted that this BitSet class uses a fraction of the memory
* of a HashSet and is also always smaller than a java.util.BitSet
* for all values.
*</p>
*
* @author mjh
*/
@Test( groups="util.bitset", sequential=true, timeOut=2000 )
public class BitSetTest
{
@Test
public void bitsetCreate()
{
BitSet b = new BitSet( 4 );
System.out.println("empty set:");
assert b.size() == 0;
print( b );
System.out.println("add 2");
b.add( 2 );
print( b );
assert b.size() == 1;
System.out.println("add 7");
b.add( 7 );
print( b );
assert b.size() == 2;
System.out.println("add 5");
b.add( 5 );
print( b );
assert b.size() == 3;
System.out.println("add 5 again");
b.add( 5 );
print( b );
assert b.size() == 3;
System.out.println("add 25");
b.add( 25 );
print( b );
assert b.size() == 4;
System.out.println("add a set:");
BitSet a = new BitSet( 3 );
a.addAll( 1, 2, 3 );
System.out.print("set to add = ");
print( a );
assert a.size() == 3;
b.addAll( a );
System.out.print("resulting set = ");
print( b );
assert b.size() == 6;
}
@Test
public void bitsetContains()
{
BitSet a = BitSet.of( 1, 3, 5, 7 );
print( a );
boolean b;
b = a.contains( 1 );
System.out.println("contains 1: " + b );
assert b;
b = a.contains( 3 );
System.out.println("contains 3: " + b );
assert b;
b = a.contains( 5 );
System.out.println("contains 5: " + b );
assert b;
b = a.contains( 2 );
System.out.println("contains 2: " + b );
assert ! b;
b = a.contains( 8 );
System.out.println("contains 8: " + b );
assert ! b;
b = a.contains( 0 );
System.out.println("contains 0: " + b );
assert ! b;
}
@Test
public void bitsetAnd()
{
BitSet a = BitSet.of( 1, 3, 5, 7 );
BitSet b = BitSet.of( 0, 2, 4, 6, 8 );
BitSet c = BitSet.of( 1, 2, 3, 4, 5, 6, 7, 8 );
System.out.print("a = ");
print( a );
System.out.print("b = ");
print( b );
System.out.print("c = ");
print( c );
assert a.equals( a );
assert b.equals( b );
assert c.equals( c );
System.out.print("a intersect a: ");
BitSet d = a.bitwiseAndEquals( a );
print( d );
assert d.equals( a );
System.out.print("a intersect b (should be empty set): ");
BitSet e = a.bitwiseAndEquals( b );
print( e );
assert e.size() == 0;
assert e.isEmpty();
System.out.print("a intersect c: ");
BitSet f = a.bitwiseAndEquals( c );
print( f );
assert f.size() == 4;
assert f.equals( a );
System.out.print("b intersect c: ");
BitSet g = b.bitwiseAndEquals( c );
print( g );
assert b.size() == 5;
assert g.size() == 4; // : "b == " + b + "; c == " + c + "; g == " + g;
assert ! g.equals( b );// : "b == " + b + "; c == " + c + "; intersect == " + g;
System.out.print("(a union b) intersect c: ");
BitSet h = new BitSet( a.size() + b.size() );
h.addAll( a );
h.addAll( b );
h.retainAll( c );
print( h );
assert h.equals( c );
}
@Test
public void bitsetOr()
{
BitSet a = BitSet.of( 1, 3, 5, 7 );
BitSet b = BitSet.of( 0, 2, 4, 6, 8 );
BitSet c = BitSet.of( 1, 2, 3, 4, 5, 6, 7, 8 );
System.out.print("a = ");
print( a );
System.out.print("b = ");
print( b );
System.out.print("c = ");
print( c );
assert a.equals( a );
assert b.equals( b );
assert c.equals( c );
System.out.print("a union a: ");
BitSet d = a.bitwiseOrEquals( a );
print( d );
assert a.equals( d );
System.out.print("a union b: ");
BitSet e = a.bitwiseOrEquals( b );
print( e );
assert ! e.equals( a );
assert ! e.equals( b );
assert e.size() == 9;
System.out.print("a union c: ");
BitSet f = a.bitwiseOrEquals( c );
print( f );
assert f.equals( c );
assert f.size() == 8;
System.out.print("b union c: ");
BitSet g = b.bitwiseOrEquals( c );
print( g );
assert ! g.equals( c );
assert g.size() == 9;
}
@Test
public void bitsetXor()
{
BitSet a = BitSet.of( 1, 3, 5, 7 );
BitSet b = BitSet.of( 0, 2, 4, 6, 8 );
BitSet c = BitSet.of( 1, 2, 3, 4, 5, 6, 7, 8 );
System.out.print("a = ");
print( a );
System.out.print("a ^ a = ");
BitSet a_xor = a.bitwiseXorEquals( a );
print( a_xor );
System.out.print("a ^ a ^ a = ");
BitSet a_xor_xor = a_xor.bitwiseXorEquals( a );
print( a_xor_xor );
assert a.equals( a_xor_xor );
// System.out.print("b = ");
// print( b );
// System.out.print("c = ");
// print( c );
}
@Test( dependsOnMethods={"bitsetString"} )
public void bitsetShift()
{
// left shift
String bitstring1 = "110011";
BitSet a = BitSet.forString( bitstring1 );
System.out.println( "test bitstring : " + a.toBitString() );
assert a.toBitString().equals( bitstring1 );
a.bitShift( -2 );
System.out.println( "left shift << 2 : " + a.toBitString() );
assert a.toBitString().equals( bitstring1 + "00" );
System.out.println();
// right shift
String bitstring2 = "110011";
BitSet b = BitSet.forString( bitstring2 );
System.out.println( "test bitstring : " + b.toBitString() );
assert b.toBitString().equals( bitstring2 );
b.bitShift( 2 );
System.out.println( "right shift >> 2: " + b.toBitString() );
assert b.toBitString().equals( "1100" );
System.out.println();
// shift + insert
BitSet c = new BitSet( 5 );
c.bitComplement();
System.out.println( "before insert : " + c.toBitString() );
assert c.toBitString().equals( "11111" );
c.bitShiftInsert( 2, new BitSet( 2 ) );
System.out.println( "after insert : " + c.toBitString() );
assert c.toBitString().equals( "1110011" );
}
@Test
public void bitsetString()
{
String bitstring1 = "1001101001110111";
System.out.println( "test bitstring: " + bitstring1 );
BitSet a = BitSet.forString( bitstring1 );
System.out.println( a );
System.out.println( a.toBitString() );
assert a.size() == 10;
assert a.length() == 16;
assert a.toBitString().equals( bitstring1 );
System.out.println();
String bitstring2 = "0000";
System.out.println( "test bitstring: " + bitstring2 );
BitSet b = BitSet.forString( bitstring2 );
System.out.println( b );
System.out.println( b.toBitString() );
assert b.size() == 0;
assert b.length() == 4;
assert b.toBitString().equals( bitstring2 );
}
/**
* Compares performance of this class versus {@link java.util.BitSet}
* and a {@link HashSet} of Integers; test is disabled by default.
*/
@Test( enabled=false )
public void bitsetBenchmark()
{
runBenchmark( 100000, 16 );
runBenchmark( 1000000, 16 );
runBenchmark( 100000, 32 );
runBenchmark( 100000, 64 );
runBenchmark( 100000, 128 );
runBenchmark( 100000, 512 );
}
private void runBenchmark( int iterations, int size )
{
System.out.println();
System.out.println("iterations = " + iterations + ", size = " + size );
BitSet bitset = new BitSet( size * 2 );
Set<Integer> hashset = new HashSet<Integer>( size * 2 );
java.util.BitSet javabitset = new java.util.BitSet( size * 2 );
int[] odds = new int[size], evens = new int[size];
for ( int i = 0, j = 0; i < size; i++ )
{
odds[j] = i * 2 + 1;
evens[j] = i * 2;
j++;
}
long start;
// add
start = now();
for ( int j = 0; j < iterations; j++ )
for ( int i : odds )
bitset.add( i );
System.out.println("add to bitset: " + (now() - start) + " msec");
// add
start = now();
for ( int j = 0; j < iterations; j++ )
for ( int i : odds )
hashset.add( i );
System.out.println("add to hashset: " + (now() - start) + " msec");
start = now();
for ( int j = 0; j < iterations; j++ )
for ( int i : odds )
javabitset.set( i );
System.out.println("add to java bitset: " + (now() - start) + " msec");
// add/contains/remove
boolean pointless;
start = now();
for ( int j = 0; j < iterations; j++ )
{
for ( int i : odds )
bitset.add( i );
// bitset.set( i );
for ( int i : odds )
pointless = bitset.contains( i );
for ( int i : odds )
bitset.remove( i );
// bitset.clear( i );
}
System.out.println("bitset: " + (now() - start) + " msec");
start = now();
for ( int j = 0; j < iterations; j++ )
{
for ( int i : odds )
hashset.add( i );
for ( int i : odds )
pointless = hashset.contains( i );
for ( int i : odds )
hashset.remove( i );
}
System.out.println("hashset: " + (now() - start) + " msec");
start = now();
for ( int j = 0; j < iterations; j++ )
{
for ( int i : odds )
javabitset.set( i );
for ( int i : odds )
pointless = javabitset.get( i );
for ( int i : odds )
javabitset.clear( i );
}
System.out.println("javabitset: " + (now() - start) + " msec");
}
private static final long now()
{
return System.currentTimeMillis();
}
private void print( BitSet b )
{
System.out.println();
System.out.print("set: ");
System.out.println( b );
System.out.print("bitstring: ");
System.out.println( b.toBitString() );
System.out.println();
}
} // end class