package net.varkhan.base.containers.set;
import net.varkhan.base.containers.Hashes;
import net.varkhan.base.containers.HashingStrategy;
import net.varkhan.base.containers.Iterator;
import net.varkhan.base.containers.array.BitArrays;
import java.io.Serializable;
/**
* <b></b>.
* <p/>
*
* @author varkhan
* @date 2/11/12
* @time 4:13 PM
*/
public class BloomSet<Key> implements Set<Key>, Serializable, Cloneable {
protected final HashingStrategy<Key> hash;
protected int size = 0;
protected final int num;
protected final int len;
protected final long msk;
protected /*final*/ byte[] filter;
public BloomSet() {
this(10,7);
}
@SuppressWarnings("unchecked")
public BloomSet(int num, int deg) {
this((HashingStrategy<Key>) Hashes.DefaultHashingStrategy,num,deg);
}
public BloomSet(HashingStrategy<Key> hash, int num, int len) {
this.hash=hash;
this.num = num>512?512:num;
this.len = (1<<(BitArrays.lsb(len)-3));
this.msk = (1<<BitArrays.lsb(len))-1;
this.filter = new byte[this.len];
}
protected long hash(long h, int i) {
return Hashes.mix(h+i) & msk;
}
public long size() {
return size;
}
public boolean isEmpty() {
return size==0;
}
public void clear() {
size = 0;
for(int i=0; i<filter.length; i++) filter[i] = 0;
}
public boolean add(Key key) {
long h = hash.hash(key);
boolean a = false;
for(int i=0; i<num; i++) {
long p = hash(h, i);
int o = (int) (p >>> 3);
int m = 1 << (p & 7);
// If bit is not set, mark as add
if( ( filter[o] & m ) == 0 ) a = true;
filter[o] |= m;
}
if(a) size++;
return a;
}
public boolean has(Key key) {
long h = hash.hash(key);
for(int i=0; i<num; i++) {
long p = hash(h, i);
int o = (int) (p >>> 3);
int m = 1 << (p & 7);
if( ( filter[o] & m) == 0 ) return false;
}
return true;
}
public boolean del(Key key) {
return false;
}
@SuppressWarnings({ "unchecked" })
public Iterator<? extends Key> iterator() {
return Iterator.EMPTY;
}
public <Par> long visit(Visitor<Key,Par> vis, Par par) {
return 0;
}
@SuppressWarnings("unchecked")
public BloomSet<Key> clone() {
BloomSet<Key> c;
try {
c = (BloomSet<Key>) super.clone();
}
catch(CloneNotSupportedException cantHappen) {
throw new InternalError();
}
c.filter = this.filter.clone();
return c;
}
}