/** * */ package is2.data; import is2.util.DB; /** * @author Dr. Bernd Bohnet, 20.05.2011 * * */ public class RandomIndex implements Long2IntInterface { final int[] prims = {52349171, 199951347, 89990, 5001, 32891, 17, 19, 23, 29, 31, 37, 47, 53, 59, 61, 67, 71}; // final int[] prims = {1,3,5,7,11,17,19,23,29,31,37,47,53,59,61,67,71}; final long hashFunctionModifiers[]; final int kbit, lbit; final int hsize; // maximal size of hash final int bits; // available bits final int moves; // needed moves to put a number into /** * Creates the random functions. * * @param kbit The bits to be mapped * @param lbit The left shift of the bits * @param hsize The size of the featurs space (not included in the original * algorithm) * @param numberFunctions The number of the hash functions */ public RandomIndex(int kbit, int lbit, int hsize, int numberFunctions) { this.kbit = kbit; this.lbit = lbit; if (hsize <= 0) { this.hsize = 67000001; // default value } else { this.hsize = hsize; } bits = (int) Math.ceil(Math.log(this.hsize) / Math.log(2)); moves = (int) Math.ceil(64f / (float) bits); DB.println("moves " + moves + " bits " + bits + " hsize " + hsize); hashFunctionModifiers = new long[numberFunctions]; for (int f = 0; f < numberFunctions; f++) { hashFunctionModifiers[f] = prims[f]; } } public int[] hash(long x) { int[] hvals = new int[hashFunctionModifiers.length]; for (int k = 0; k < hashFunctionModifiers.length; k++) { // the original function: value = ((x+1) * hashFunctionModifiers[k] & m ) >> n; // the first part of the original function long value = (x + 1) * hashFunctionModifiers[k]; // do the above >> n with a maximal size of the available hash values // Shift all bits until they have been each xor-ed (^) in the range of the hash // in order the have all information potentially represented there. for (int j = 1; j <= moves; j++) { value = value ^ (value >> (bits * j)); } // Map the value to the range of the available space should be the same as (value & m) . hvals[k] = Math.abs((int) value % hsize); } return hvals; } public int[] hashU(long x) { int[] hvals = new int[hashFunctionModifiers.length]; long y = Long.reverse(x); for (int k = 0; k < hashFunctionModifiers.length; k++) { // the original function: value = ((x+1) * hashFunctionModifiers[k] & m ) >> n; // the first part of the original function long value1 = (((y + 1) * hashFunctionModifiers[k]) /* * % 2 pow 64 */) >> (kbit - lbit); // I get probably only the first part lets get the second part too // long value2 = (((y+1>>20) * hashFunctionModifiers[k]) /* % 2 pow 64 */ ) >> (kbit-lbit); // the modulo (%) 2 pow 64 is done since the long number can not be larger than 2 pow 64. // System.out.println("value "+value+" shift "+(lbit-kbit)); hvals[k] = Math.abs((int) value1); } return hvals; } /* * (defun generate-hash-fn (&key (k-bit 32) (l-bit 8) verbosep constants * (count 4)) * * (labels ((random-constant () (let ((a (+ (random (- (expt 2 k-bit) 1)) * 1))) (logior a 1)))) ;; inclusive OR ensures odd number. (let ((pdiff (- * (- k-bit l-bit)));; neg. sign to do a rightshift, see ash() (sub1 (- * (expt 2 k-bit) 1)) (constants (copy-list constants))) (unless constants * (loop ;; a = odd number a where 0 < a < u. until (= count (length * constants)) do (pushnew (random-constant) constants))) (when verbosep * (format t "~&generate-hash-fn(): using random constants: ~a~%" * constants)) (values #'(lambda (x) (loop for a in constants ;;; always add * 1 to x to avoid f(0)=0. collect (ash (logand (* (+ 1 x) a) sub1) pdiff))) * constants)))) * */ /* * (non-Javadoc) @see is2.data.Long2IntInterface#l2i(long) */ @Override public int l2i(long l) { // TODO Auto-generated method stub return 0; } /* * (non-Javadoc) @see is2.data.Long2IntInterface#size() */ @Override public int size() { return hsize; } }