lucene org.apache.lucene.util.BitVector.java


1 org.apache.lucene.义齿apache.lucene.util; Optimized implementation of a vector of bits.  This is more-or-less like java.util.BitSet, but also includes the following: a count() method, which efficiently computes the number of one bits; optimized read from and write to disk; inlinable get() method; store and load, as bit set or d-gaps, depending on sparseness; /*最適化はビットベクトルを実現した.Javaにほぼ似ている.util.BitSetですが、bit 1の個数を効率的に計算するcount()メソッドと、bit 1の個数を効率的に計算するcount()メソッドと、ディスクの読み取りと書き込みを最適化します.  get() method;(inlinable?) 疎度に応じて、ビット変数を格納およびロードするか、d-gapsを使用するかを決定します.*/
public final int count() {
    // if the vector has been modified
    if (count == -1) {
      int c = 0;
      int end = bits.length;
      for (int i = 0; i < end; i++)
        c += BYTE_COUNTS[bits[i] & 0xFF];	  // sum bits per byte
      count = c;
    }
    return count;
  }

count()法は,このbitベクトルの1の個数を統計するために用いられる.bitは実はbyte配列の形で格納されているため、1つのbyteには8つのbitがあります.従来の方法では、byte毎に変位またはビット和で各判定が1であるか否かを求め、総数を求めることができる.ここでの方法は次のとおりです.
これは実は1つのルックアップテーブルで、8ビットのbyteに対して、1ビットごとに1あるいは0の2種類の可能性があるので、全部で2^8=256種類の可能な値があって、1値ごとに1の個数に対応するのは固定です.もし私たちがこの256種類の可能な値を配列に保存しておけば、その時になると一度に値を取ればいいです.テーブルの検索は、関数の引数の範囲が小さい場合に適用される空間的に時間を変える方法です.それは著しく速度を高めることができます(すべて直接値を取りました...).
http://michaelo-o.spaces.live.com/Blog/cns!2E4590EFB3E88D3A!364.entry
まずbits to intの変換で得られたint値はBYTE_COUNTS[int]でbit 1の個数を取得します.
テストコードは次のとおりです.
public class Test {
	private static final byte[] BYTE_COUNTS = {	  // table of bits/byte
	    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
	    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
	    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
	    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
	    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
	    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
	    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
	    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
	  };
	
    public static void main(String[] args){
    	byte b = (byte)-1;
    	char[] c = getraw(b);
    	
    	System.out.println("int fomate(between -128~127):"+(int)b);
    	int i=8;
    	System.out.print("raw fomate:");
    	while(i--!=0){
    		System.out.print(c[i]);
    	}
    	System.out.println();
    	System.out.println("bit 1 counts:"+count(b));
    }
    
    public static  int count(byte bits) {
    	int c = BYTE_COUNTS[bits & 0xFF];
    	return c;
      }
    
    
    public static char[] getraw(byte bits){
    	int i=0;
    	char[] c = new char[8];
    	c[i] = (bits&1)==0?'0':'1';i++;
    	while((bits>>=1)!=0&&i<8){
    		c[i] = (bits&1)==0?'0':'1';i++;
    	}
    	while(i<8){
    		c[i]='0';i++;
    	}
    	return c;
    }
    
}

プログラム結果:
int fomate(between -128~127):-1 raw fomate:11111111 bit 1 counts:8