export function hashCodeNumberUpdate ( hash , v ) { hash += v ; hash += hash << 10 ; hash += hash >>> 6 ; return hash >>> 0 ; } export function hashCodeNumberFinish ( hash ) { hash += hash << 3 ; hash ^= hash >>> 11 ; hash += hash << 15 ; return hash >>> 0 ; } export function nullHashFunc < T > ( k ) { return 0 ; } export type EqualFunc < K > = ( a : K , b : K ) => boolean ; export type HashFunc < K > = ( a : K ) => number ; class HashBucket < K , V > { public keys : K [ ] = [ ] ; public values : V [ ] = [ ] ; } export class HashMap < K , V > { public buckets = new Map < number , HashBucket < K , V > > ( ) ; constructor ( private keyEqualFunc , private keyHashFunc ) { } private findBucketIndex ( bucket , k ) { for ( let i = 0 ; i < bucket . keys . length ; i ++ ) if ( this . keyEqualFunc ( k , bucket . keys [ i ] ) ) return i ; return - 1 ; } private findBucket ( k ) { const bw = this . keyHashFunc ( k ) ; return this . buckets . get ( bw ) ; } public get ( k ) { const bucket = this . findBucket ( k ) ; if ( bucket === undefined ) return null ; const bi = this . findBucketIndex ( bucket , k ) ; if ( bi < 0 ) return null ; return bucket . values [ bi ] ; } public add ( k , v ) { const bw = this . keyHashFunc ( k ) ; if ( this . buckets . get ( bw ) === undefined ) this . buckets . set ( bw , new HashBucket < K , V > ( ) ) ; const bucket = this . buckets . get ( bw ) ! ; bucket . keys . push ( k ) ; bucket . values . push ( v ) ; } public delete ( k ) { const bucket = this . findBucket ( k ) ; if ( bucket === undefined ) return ; const bi = this . findBucketIndex ( bucket , k ) ; if ( bi === - 1 ) return ; bucket . keys . splice ( bi , 1 ) ; bucket . values . splice ( bi , 1 ) ; } public clear ( ) { this . buckets . clear ( ) ; } public size ( ) { let acc = 0 ; for ( const bucket of this . buckets . values ( ) ) acc += bucket . values . length ; return acc ; } public * values ( ) { for ( const bucket of this . buckets . values ( ) ) for ( let j = bucket . values . length - 1 ; j >= 0 ; j -- ) yield bucket . values [ j ] ; } }