static intnat hash_nat(value v) { bngsize len, i; uint32 h; len = bng_num_digits(&Digit_val(v,0), Wosize_val(v) - 1); h = 0; for (i = 0; i < len; i++) { bngdigit d = Digit_val(v, i); #ifdef ARCH_SIXTYFOUR /* Mix the two 32-bit halves as if we were on a 32-bit platform, namely low 32 bits first, then high 32 bits. Also, ignore final 32 bits if they are zero. */ h = caml_hash_mix_uint32(h, (uint32) d); d = d >> 32; if (d == 0 && i + 1 == len) break; h = caml_hash_mix_uint32(h, (uint32) d); #else h = caml_hash_mix_uint32(h, d); #endif } return h; }
static intnat caml_ba_hash(value v) { struct caml_ba_array * b = Caml_ba_array_val(v); intnat num_elts, n; uint32 h, w; int i; num_elts = 1; for (i = 0; i < b->num_dims; i++) num_elts = num_elts * b->dim[i]; h = 0; switch (b->flags & CAML_BA_KIND_MASK) { case CAML_BA_SINT8: case CAML_BA_UINT8: { uint8 * p = b->data; if (num_elts > 256) num_elts = 256; for (n = 0; n + 4 <= num_elts; n += 4, p += 4) { w = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); h = caml_hash_mix_uint32(h, w); } w = 0; switch (num_elts & 3) { case 3: w = p[2] << 16; /* fallthrough */ case 2: w |= p[1] << 8; /* fallthrough */ case 1: w |= p[0]; h = caml_hash_mix_uint32(h, w); } break; } case CAML_BA_SINT16: case CAML_BA_UINT16: { uint16 * p = b->data; if (num_elts > 128) num_elts = 128; for (n = 0; n + 2 <= num_elts; n += 2, p += 2) { w = p[0] | (p[1] << 16); h = caml_hash_mix_uint32(h, w); } if ((num_elts & 1) != 0) h = caml_hash_mix_uint32(h, p[0]); break; } case CAML_BA_INT32: { uint32 * p = b->data; if (num_elts > 64) num_elts = 64; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p); break; } case CAML_BA_CAML_INT: case CAML_BA_NATIVE_INT: { intnat * p = b->data; if (num_elts > 64) num_elts = 64; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_intnat(h, *p); break; } case CAML_BA_INT64: { int64 * p = b->data; if (num_elts > 32) num_elts = 32; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p); break; } case CAML_BA_COMPLEX32: num_elts *= 2; /* fallthrough */ case CAML_BA_FLOAT32: { float * p = b->data; if (num_elts > 64) num_elts = 64; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_float(h, *p); break; } case CAML_BA_COMPLEX64: num_elts *= 2; /* fallthrough */ case CAML_BA_FLOAT64: { double * p = b->data; if (num_elts > 32) num_elts = 32; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_double(h, *p); break; } } return h; }