package org.streaminer.util.hash.function; import org.streaminer.util.math.Prime; import java.io.Serializable; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; /** * <p> * Computes a two universal hash function lik it was described in the paper * 'Universal classes of hash functions' written by 'Carter, J. L. and Wegman, M. N. (1977)'. * </p> * * @author Marcin Skirzynski * * @param <T> */ public class TwoUniversalHashFunction<T> implements HashFunction<T>, Serializable { private static final long serialVersionUID = -5451250100120165585L; private final long coDomain; private final long prime; private final long a; private final long b; private transient final Map<T, Long> indices = new ConcurrentHashMap<T, Long>(); private long lastIndex = 0; public TwoUniversalHashFunction( int domain, int coDomain ) { this.coDomain = coDomain; this.prime = Prime.getRandom(domain, 2*(long)domain); Random rnd = new Random(); long aTemp = 0; while (aTemp == 0) { aTemp = rnd.nextLong(); } this.a = aTemp; this.b = -this.prime + (int)(Math.random() * ((this.prime + this.prime) + 1)); } @Override public long hash(T x) { if( !this.indices.containsKey(x) ) { this.indices.put(x, ++this.lastIndex); } long xi = this.indices.get(x); return Math.abs(((this.a*xi + this.b) % this.prime)%this.coDomain); } }