Mercurial > repos > rliterman > csp2
diff CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/bbmap-39.01-1/current/bbmin/LongHashSet.java @ 68:5028fdace37b
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 16:23:26 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/bbmap-39.01-1/current/bbmin/LongHashSet.java Tue Mar 18 16:23:26 2025 -0400 @@ -0,0 +1,301 @@ +package bbmin; + +import java.util.Arrays; +import java.util.Random; + +/** + * @author Brian Bushnell + * @date July 6, 2016 + * + */ +public final class LongHashSet{ + + /*--------------------------------------------------------------*/ + /*---------------- Initialization ----------------*/ + /*--------------------------------------------------------------*/ + + public LongHashSet(){ + this(256); + } + + public LongHashSet(int initialSize){ + this(initialSize, 0.7f); + } + + public LongHashSet(int initialSize, float loadFactor_){ + invalid=randy.nextLong()|MINMASK; + assert(invalid<0); + assert(initialSize>0) : "Attempting to initialize a "+getClass().getSimpleName()+" of size<1."; + assert(loadFactor_>0 && loadFactor_<1) : "Attempting to initialize a "+getClass().getSimpleName()+" with invalid load factor: "+loadFactor_; + loadFactor=mid(0.25f, loadFactor_, 0.90f); + resize(initialSize); + } + + /*--------------------------------------------------------------*/ + /*---------------- Public Methods ----------------*/ + /*--------------------------------------------------------------*/ + + public void clear(){ + if(size<1){return;} + Arrays.fill(array, invalid); + size=0; + } + + public boolean contains(long value){ + return value==invalid ? false : findCell(value)>=0; + } + + /** + * Add this value to the set. + * @param value + * @return true if the value was added, false if it was already contained. + */ + public boolean add(long value){ + if(value==invalid){resetInvalid();} + int cell=findCellOrEmpty(value); + if(array[cell]==invalid){ + array[cell]=value; + size++; + if(size>sizeLimit){resize();} + return true; + } + assert(array[cell]==value); + return false; + } + + /** + * Remove this value from the set. + * @param value + * @return true if the value was removed, false if it was not present. + */ + public boolean remove(long value){ + if(value==invalid){return false;} + final int cell=findCell(value); + if(cell<0){return false;} + assert(array[cell]==value); + array[cell]=invalid; + size--; + + rehashFrom(cell); + return true; + } + + public int size(){return size;} + + public boolean isEmpty(){return size==0;} + + /*--------------------------------------------------------------*/ + /*---------------- String Methods ----------------*/ + /*--------------------------------------------------------------*/ + + @Override + public String toString(){ + return toStringListView(); + } + + public String toStringSetView(){ + StringBuilder sb=new StringBuilder(); + sb.append('['); + String comma=""; + for(int i=0; i<array.length; i++){ + if(array[i]!=invalid){ + sb.append(comma+"("+i+", "+array[i]+")"); + comma=", "; + } + } + sb.append(']'); + return sb.toString(); + } + + public String toStringListView(){ + StringBuilder sb=new StringBuilder(); + sb.append('['); + String comma=""; + for(int i=0; i<array.length; i++){ + if(array[i]!=invalid){ + sb.append(comma+array[i]); + comma=", "; + } + } + sb.append(']'); + return sb.toString(); + } + + public long[] toArray(){ + long[] x=new long[array.length]; + int i=0; + for(long v : array){ + x[i]=v; + i++; + } + return x; + } + + /*--------------------------------------------------------------*/ + /*---------------- Private Methods ----------------*/ + /*--------------------------------------------------------------*/ + + public boolean verify(){ + int numValues=0; + int numFound=0; + for(int i=0; i<array.length; i++){ + final long value=array[i]; + if(value!=invalid){ + numValues++; + final int cell=findCell(value); + if(i==cell){ + numFound++; + }else{ + return false; + } + } + } + return numValues==numFound && numValues==size; + } + + private void rehashFrom(int initial){ + if(size<1){return;} + final int limit=array.length; + for(int cell=initial+1; cell<limit; cell++){ + final long x=array[cell]; + if(x==invalid){return;} + rehashCell(cell); + } + for(int cell=0; cell<initial; cell++){ + final long x=array[cell]; + if(x==invalid){return;} + rehashCell(cell); + } + } + + private boolean rehashCell(final int cell){ + final long value=array[cell]; + assert(value!=invalid); + if(value==invalid){resetInvalid();} + final int dest=findCellOrEmpty(value); + if(cell==dest){return false;} + assert(array[dest]==invalid); + array[cell]=invalid; + array[dest]=value; + return true; + } + + private void resetInvalid(){ + final long old=invalid; + long x=invalid; + while(x==old || contains(x)){x=randy.nextLong()|MINMASK;} + assert(x<0); + invalid=x; + for(int i=0; i<array.length; i++){ + if(array[i]==old){array[i]=invalid;} + } + } + + private int findCell(final long value){ + if(value==invalid){return -1;} + + final int limit=array.length, initial=(int)((value&MASK)%modulus); + for(int cell=initial; cell<limit; cell++){ + final long x=array[cell]; + if(x==value){return cell;} + if(x==invalid){return -1;} + } + for(int cell=0; cell<initial; cell++){ + final long x=array[cell]; + if(x==value){return cell;} + if(x==invalid){return -1;} + } + return -1; + } + + private int findCellOrEmpty(final long value){ + assert(value!=invalid) : "Collision - this should have been intercepted."; + + final int limit=array.length, initial=(int)((value&MASK)%modulus); + for(int cell=initial; cell<limit; cell++){ + final long x=array[cell]; + if(x==value || x==invalid){return cell;} + } + for(int cell=0; cell<initial; cell++){ + final long x=array[cell]; + if(x==value || x==invalid){return cell;} + } + throw new RuntimeException("No empty cells - size="+size+", limit="+limit); + } + + public final void resizeDestructive(int newSize){ + size=0; + sizeLimit=0; + array=null; + resize(newSize); + } + + private final void resize(){ + assert(size>=sizeLimit); + resize(array.length*2L+1); + } + + private final void resize(final long size2){ + assert(size2>size) : size+", "+size2; + + //This is supposed to be a prime but the primes code is ripped out in this version. + //Any odd number is fine in most cases. + long newPrime=size2|1; + if(newPrime+extra>Integer.MAX_VALUE){ + newPrime=(Integer.MAX_VALUE-extra-2)|1; + } + assert(newPrime>modulus) : "Overflow: "+size+", "+size2+", "+modulus+", "+newPrime; + modulus=(int)newPrime; + + final int size3=(int)(newPrime+extra); + sizeLimit=(int)(modulus*loadFactor); + final long[] old=array; + array=new long[size3]; + Arrays.fill(array, invalid); + +// System.err.println("Resizing "+(old==null ? "null" : ""+old.length)+" to "+size3); + + if(size<1){return;} + + size=0; + for(long value : old){ + if(value!=invalid){ + add(value); + } + } + } + + /*--------------------------------------------------------------*/ + /*---------------- Stuff From BBTools ----------------*/ + /*--------------------------------------------------------------*/ + + public static final float mid(float x, float y, float z){ + return x<y ? (x<z ? min(y, z) : x) : (y<z ? min(x, z) : y); + } + public static final float min(float x, float y){return x<y ? x : y;} + public static final float max(float x, float y){return x>y ? x : y;} + + /** Number of values that can be held without resizing */ + public int capacity(){ + return sizeLimit; + } + + /*--------------------------------------------------------------*/ + /*---------------- Fields ----------------*/ + /*--------------------------------------------------------------*/ + + private long[] array; + private int size=0; + /** Value for empty cells */ + private long invalid; + private int modulus; + private int sizeLimit; + private final float loadFactor; + + private static final Random randy=new Random(1); + private static final long MASK=Long.MAX_VALUE; + private static final long MINMASK=Long.MIN_VALUE; + + private static final int extra=10; + +}