//examples of hash functions: map state coordinates onto a hash value //#define GETHASHBIN(X, Y) (Y*WIDTH_Y+X) //here we have state coord: <X1, X2, X3, X4> unsigned int EnvironmentROBARM::GETHASHBIN(short unsigned int* coord, int numofcoord) { int val = 0; for(int i = 0; i < numofcoord; i++) { val += inthash(coord[i]) << i; } return inthash(val) & (EnvROBARM.HashTableSize-1); }
static uintptr_t jl_object_id_(jl_value_t *tv, jl_value_t *v) { if (tv == (jl_value_t*)jl_sym_type) return ((jl_sym_t*)v)->hash; if (tv == (jl_value_t*)jl_simplevector_type) return hash_svec((jl_svec_t*)v); jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; // `name->wrapper` is cacheable even though it contains TypeVars // that don't have stable IDs. //if (jl_egal(dtv->name->wrapper, v)) // return bitmix(~dtv->name->hash, 0xaa5566aa); return bitmix(~dtv->name->hash, hash_svec(dtv->parameters)); } if (dt == jl_typename_type) return ((jl_typename_t*)v)->hash; #ifdef _P64 if (v == jl_ANY_flag) return 0x31c472f68ee30bddULL; #else if (v == jl_ANY_flag) return 0x8ee30bdd; #endif if (dt == jl_string_type) { #ifdef _P64 return memhash_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #else return memhash32_seed(jl_string_data(v), jl_string_len(v), 0xedc3b677); #endif } if (dt->mutabl) return inthash((uintptr_t)v); size_t sz = jl_datatype_size(tv); uintptr_t h = jl_object_id(tv); if (sz == 0) return ~h; size_t nf = jl_datatype_nfields(dt); if (nf == 0) { return bits_hash(jl_data_ptr(v), sz) ^ h; } for (size_t f=0; f < nf; f++) { size_t offs = jl_field_offset(dt, f); char *vo = (char*)jl_data_ptr(v) + offs; uintptr_t u; if (jl_field_isptr(dt, f)) { jl_value_t *f = *(jl_value_t**)vo; u = f==NULL ? 0 : jl_object_id(f); } else { jl_datatype_t *fieldtype = (jl_datatype_t*)jl_field_type(dt, f); assert(jl_is_datatype(fieldtype) && !fieldtype->abstract && !fieldtype->mutabl); if (fieldtype->layout->haspadding) u = jl_object_id_((jl_value_t*)fieldtype, (jl_value_t*)vo); else u = bits_hash(vo, jl_field_size(dt, f)); } h = bitmix(h, u); } return h; }
DLLEXPORT uptrint_t jl_object_id(jl_value_t *v) { if (jl_is_symbol(v)) return ((jl_sym_t*)v)->hash; jl_value_t *tv = (jl_value_t*)jl_typeof(v); if (tv == (jl_value_t*)jl_tuple_type) { uptrint_t h = 0; size_t l = jl_tuple_len(v); for(size_t i = 0; i < l; i++) { uptrint_t u = jl_object_id(jl_tupleref(v,i)); h = bitmix(h, u); } return h; } jl_datatype_t *dt = (jl_datatype_t*)tv; if (dt == jl_datatype_type) { jl_datatype_t *dtv = (jl_datatype_t*)v; uptrint_t h = inthash((uptrint_t)tv); return bitmix(bitmix(h, jl_object_id((jl_value_t*)dtv->name)), jl_object_id((jl_value_t*)dtv->parameters)); } if (dt->mutabl) return inthash((uptrint_t)v); size_t sz = jl_datatype_size(tv); uptrint_t h = inthash((uptrint_t)tv); if (sz == 0) return ~h; size_t nf = jl_tuple_len(dt->names); if (nf == 0) { return bits_hash(jl_data_ptr(v), sz) ^ h; } for (size_t f=0; f < nf; f++) { size_t offs = dt->fields[f].offset; char *vo = (char*)jl_data_ptr(v) + offs; uptrint_t u; if (dt->fields[f].isptr) { jl_value_t *f = *(jl_value_t**)vo; u = f==NULL ? 0 : jl_object_id(f); } else { u = bits_hash(vo, dt->fields[f].size); } h = bitmix(h, u); } return h; }
DLLEXPORT uptrint_t jl_object_id(jl_value_t *v) { if (jl_is_symbol(v)) return ((jl_sym_t*)v)->hash; jl_value_t *tv = (jl_value_t*)jl_typeof(v); if (jl_is_bits_type(tv)) { size_t nb = jl_bitstype_nbits(tv)/8; uptrint_t h = inthash((uptrint_t)tv); switch (nb) { case 1: return int32hash(*(int8_t*)jl_bits_data(v) ^ h); case 2: return int32hash(*(int16_t*)jl_bits_data(v) ^ h); case 4: return int32hash(*(int32_t*)jl_bits_data(v) ^ h); case 8: return hash64(*(int64_t*)jl_bits_data(v) ^ h); default: #ifdef __LP64__ return h ^ memhash((char*)jl_bits_data(v), nb); #else return h ^ memhash32((char*)jl_bits_data(v), nb); #endif } } if (tv == (jl_value_t*)jl_union_kind) { #ifdef __LP64__ return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5A5A5A5A5L; #else return jl_object_id(jl_fieldref(v,0))^0xA5A5A5A5; #endif } if (jl_is_struct_type(tv)) return inthash((uptrint_t)v); assert(jl_is_tuple(v)); uptrint_t h = 0; size_t l = jl_tuple_len(v); for(size_t i = 0; i < l; i++) { uptrint_t u = jl_object_id(jl_tupleref(v,i)); h = bitmix(h, u); } return h; }
int main() { int i = -42; bool b = true; std::string str = "erich"; std::hash<std::string> strhash; std::hash<bool> boolhash; std::hash<int> inthash; std::cout << (size_t)i << ":" << inthash(i)<<std::endl; std::cout << str << ":" << strhash(str)<<std::endl; std::cout << b << ":" << boolhash(b)<<std::endl; }
/* The firehose hash uses open addressing as a collision resolution scheme, * since space occupied by each entry must be minimized. */ static void * fh_hash_find(fh_hash_t *hash, fh_int_t key) { void *val; fh_int_t keyhash = inthash(key) & hash->fh_mask; val = hash->fh_table[keyhash]; while (val != NULL && key != ((fh_dummy_entry_t *) val)->hash_key) { val = ((fh_dummy_entry_t *) val)->hash_next; } return val; }
/* Given a (non-NULL) entry, by address not by key, replace * it with another entry, or delete if replacement is NULL */ static void fh_hash_replace(fh_hash_t *hash, void *val, void *newval) { fh_int_t keyhash; fh_dummy_entry_t *cur; keyhash = inthash(((fh_dummy_entry_t *)val)->hash_key) & hash->fh_mask; cur = (fh_dummy_entry_t *)(hash->fh_table[keyhash]); /* Handle head of list case first */ if (cur == ((fh_dummy_entry_t *) val)) { if (newval == NULL) { /* Delete */ hash->fh_table[keyhash] = cur->hash_next; } else { /* Replace */ ((fh_dummy_entry_t *) newval)->hash_next = cur->hash_next; hash->fh_table[keyhash] = newval; } return; } /* Now handle non-head case */ while (cur != NULL) { fh_dummy_entry_t *next = cur->hash_next; if (next == ((fh_dummy_entry_t *) val)) { if (newval == NULL) { /* Delete */ cur->hash_next = next->hash_next; } else { /* Replace */ cur->hash_next = newval; ((fh_dummy_entry_t *) newval)->hash_next = next->hash_next; } return; } cur = next; } }
static uintptr_t type_object_id_(jl_value_t *v, jl_varidx_t *env) { if (v == NULL) return 0; jl_datatype_t *tv = (jl_datatype_t*)jl_typeof(v); if (tv == jl_tvar_type) { jl_varidx_t *pe = env; int i = 0; while (pe != NULL) { if (pe->var == (jl_tvar_t*)v) return (i<<8) + 42; i++; pe = pe->prev; } return inthash((uintptr_t)v); } if (tv == jl_uniontype_type) { return bitmix(bitmix(jl_object_id((jl_value_t*)tv), type_object_id_(((jl_uniontype_t*)v)->a, env)), type_object_id_(((jl_uniontype_t*)v)->b, env)); } if (tv == jl_unionall_type) { jl_unionall_t *u = (jl_unionall_t*)v; uintptr_t h = u->var->name->hash; h = bitmix(h, type_object_id_(u->var->lb, env)); h = bitmix(h, type_object_id_(u->var->ub, env)); jl_varidx_t e = { u->var, env }; return bitmix(h, type_object_id_(u->body, &e)); } if (tv == jl_datatype_type) { uintptr_t h = ~((jl_datatype_t*)v)->name->hash; size_t i, l = jl_nparams(v); for (i = 0; i < l; i++) { h = bitmix(h, type_object_id_(jl_tparam(v, i), env)); } return h; } return jl_object_id_((jl_value_t*)tv, v); }
/* * fh_hash_insert(hash, key, val) * If val==NULL, the key is removed from the table */ static void * fh_hash_insert(fh_hash_t *hash, fh_int_t key, void *newval) { fh_int_t keyhash; void *val; keyhash = inthash(key) & hash->fh_mask; val = hash->fh_table[keyhash]; #ifdef FH_HASH_STATS hash->fh_col_table[keyhash]++; #endif /* May be a deletion request */ if (newval == NULL) { fh_dummy_entry_t *prev = NULL; fh_dummy_entry_t *cur = (fh_dummy_entry_t *) val; while (cur != NULL) { /* * If the key matches, adjust list and return the entry. * */ if (cur->hash_key == key) { if (prev == NULL) hash->fh_table[keyhash] = cur->hash_next; else prev->hash_next = cur->hash_next; return cur; } prev = cur; cur = cur->hash_next; } /* * No keys found matching deletion request * */ return NULL; } /* Add the key mapping */ else { _fh_entries_add(hash); /* bucket unused, simply copy the new data */ if (val == NULL) { hash->fh_table[keyhash] = newval; ((fh_dummy_entry_t *) newval)->hash_next = NULL; } else { _fh_collision(hash); ((fh_dummy_entry_t *) newval)->hash_next = hash->fh_table[keyhash]; hash->fh_table[keyhash] = newval; } return newval; } }
// *oob: output argument, means we hit the limit specified by 'bound' static uptrint_t bounded_hash(value_t a, int bound, int *oob) { *oob = 0; union { double d; int64_t i64; } u; numerictype_t nt; size_t i, len; cvalue_t *cv; cprim_t *cp; void *data; uptrint_t h = 0; int oob2, tg = tag(a); switch(tg) { case TAG_NUM : case TAG_NUM1: u.d = (double)numval(a); return doublehash(u.i64); case TAG_FUNCTION: if (uintval(a) > N_BUILTINS) return bounded_hash(((function_t*)ptr(a))->bcode, bound, oob); return inthash(a); case TAG_SYM: return ((symbol_t*)ptr(a))->hash; case TAG_CPRIM: cp = (cprim_t*)ptr(a); data = cp_data(cp); if (cp_class(cp) == wchartype) return inthash(*(int32_t*)data); nt = cp_numtype(cp); u.d = conv_to_double(data, nt); return doublehash(u.i64); case TAG_CVALUE: cv = (cvalue_t*)ptr(a); data = cv_data(cv); return memhash(data, cv_len(cv)); case TAG_VECTOR: if (bound <= 0) { *oob = 1; return 1; } len = vector_size(a); for(i=0; i < len; i++) { h = MIX(h, bounded_hash(vector_elt(a,i), bound/2, &oob2)^1); if (oob2) bound/=2; *oob = *oob || oob2; } return h; case TAG_CONS: do { if (bound <= 0) { *oob = 1; return h; } h = MIX(h, bounded_hash(car_(a), bound/2, &oob2)); // bounds balancing: try to share the bounds efficiently // so we can hash better when a list is cdr-deep (a common case) if (oob2) bound/=2; else bound--; // recursive OOB propagation. otherwise this case is slow: // (hash '#2=((#0=(#1=(#1#) . #0#)) . #2#)) *oob = *oob || oob2; a = cdr_(a); } while (iscons(a)); h = MIX(h, bounded_hash(a, bound-1, &oob2)^2); *oob = *oob || oob2; return h; } return 0; }
ulong ptrhash(void *key) { return inthash((uintptr_t)key); }
std::size_t operator()(const ns::my_int& m) const { return inthash(m.d); }