Skip to content

Commit afcc155

Browse files
vouillonhhugo
authored andcommitted
Fix bigarray hashing
1 parent 51bf9cc commit afcc155

File tree

4 files changed

+100
-19
lines changed

4 files changed

+100
-19
lines changed

compiler/tests-jsoo/dune

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
test_io
4646
test_floats
4747
test_float16
48+
test_bigarray
4849
test_marshal_compressed
4950
test_parsing
5051
calc_parser
@@ -62,7 +63,7 @@
6263
(name test_float16)
6364
(build_if
6465
(>= %{ocaml_version} 5.2))
65-
(modules test_float16)
66+
(modules test_float16 test_bigarray)
6667
(modes js wasm native))
6768

6869
(ocamlyacc calc_parser)

compiler/tests-jsoo/test_bigarray.ml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,57 @@ let%expect_test "blit bytes-ba" =
265265
{|
266266
\000\001\002\003\004\005\006\007\008\009
267267
\255\255\255\255\255\255\003\004\005\255 |}]
268+
269+
let%expect_test "hash" =
270+
let test_hash nm kind conv sz =
271+
let a = Array1.create kind c_layout sz in
272+
for i = 0 to sz - 1 do
273+
a.{i} <- conv (i - 10)
274+
done;
275+
Printf.printf "%08x %s %d\n" (Hashtbl.hash a) nm sz
276+
in
277+
let test nm kind conv =
278+
test_hash nm kind conv 20;
279+
test_hash nm kind conv 300
280+
in
281+
test "float16" float16 float;
282+
test "float32" float32 float;
283+
test "float64" float64 float;
284+
test "complex32" complex32 (fun i -> { Complex.re = float i; im = float i +. 0.5 });
285+
test "complex64" complex64 (fun i -> { Complex.re = float i; im = float i +. 0.5 });
286+
test "int8_signed" int8_signed Fun.id;
287+
test "int8_unsigned" int8_unsigned Fun.id;
288+
test "int16_signed" int16_signed Fun.id;
289+
test "int16_unsigned" int16_unsigned Fun.id;
290+
test "int" int Fun.id;
291+
test "int32" int32 Int32.of_int;
292+
test "int64" int64 Int64.of_int;
293+
test "nativeint" nativeint Nativeint.of_int;
294+
[%expect
295+
{|
296+
25078b88 float16 20
297+
2343870b float16 300
298+
302739c9 float32 20
299+
11498d5d float32 300
300+
15f7508d float64 20
301+
09855d61 float64 300
302+
20854307 complex32 20
303+
283a36fa complex32 300
304+
26f9c576 complex64 20
305+
26f9c576 complex64 300
306+
31a28c90 int8_signed 20
307+
350c179a int8_signed 300
308+
31a28c90 int8_unsigned 20
309+
350c179a int8_unsigned 300
310+
16a15c12 int16_signed 20
311+
31ebf1b2 int16_signed 300
312+
16a15c12 int16_unsigned 20
313+
31ebf1b2 int16_unsigned 300
314+
1e14ef2b int 20
315+
314148ee int 300
316+
1e14ef2b int32 20
317+
314148ee int32 300
318+
00b18db2 int64 20
319+
1c259f64 int64 300
320+
1e14ef2b nativeint 20
321+
314148ee nativeint 300 |}]

runtime/js/bigarray.js

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ function caml_ba_create_from(data1, data2, jstyp, kind, layout, dims) {
979979

980980
//Provides: caml_ba_hash const
981981
//Requires: caml_ba_get_size, caml_hash_mix_int, caml_hash_mix_float
982-
//Requires: caml_unpackFloat16, caml_hash_mix_float16
982+
//Requires: caml_unpackFloat16, caml_hash_mix_float16, caml_hash_mix_float32
983983
function caml_ba_hash(ba) {
984984
var num_elts = caml_ba_get_size(ba.dims);
985985
var h = 0;
@@ -990,11 +990,11 @@ function caml_ba_hash(ba) {
990990
if (num_elts > 256) num_elts = 256;
991991
var w = 0,
992992
i = 0;
993-
for (i = 0; i + 4 <= ba.data.length; i += 4) {
993+
for (i = 0; i + 4 <= num_elts; i += 4) {
994994
w =
995-
ba.data[i + 0] |
996-
(ba.data[i + 1] << 8) |
997-
(ba.data[i + 2] << 16) |
995+
(ba.data[i + 0] & 0xff) |
996+
((ba.data[i + 1] & 0xff) << 8) |
997+
((ba.data[i + 2] & 0xff) << 16) |
998998
(ba.data[i + 3] << 24);
999999
h = caml_hash_mix_int(h, w);
10001000
}
@@ -1018,8 +1018,8 @@ function caml_ba_hash(ba) {
10181018
if (num_elts > 128) num_elts = 128;
10191019
var w = 0,
10201020
i = 0;
1021-
for (i = 0; i + 2 <= ba.data.length; i += 2) {
1022-
w = ba.data[i + 0] | (ba.data[i + 1] << 16);
1021+
for (i = 0; i + 2 <= num_elts; i += 2) {
1022+
w = (ba.data[i + 0] & 0xffff) | (ba.data[i + 1] << 16);
10231023
h = caml_hash_mix_int(h, w);
10241024
}
10251025
if ((num_elts & 1) !== 0) h = caml_hash_mix_int(h, ba.data[i]);
@@ -1046,7 +1046,8 @@ function caml_ba_hash(ba) {
10461046
// fallthrough
10471047
case 0: // Float32Array
10481048
if (num_elts > 64) num_elts = 64;
1049-
for (var i = 0; i < num_elts; i++) h = caml_hash_mix_float(h, ba.data[i]);
1049+
for (var i = 0; i < num_elts; i++)
1050+
h = caml_hash_mix_float32(h, ba.data[i]);
10501051
break;
10511052
case 11: // Float64Array (complex64)
10521053
// biome-ignore lint/suspicious/noFallthroughSwitchClause:
@@ -1079,6 +1080,24 @@ function caml_hash_mix_float16(hash, d) {
10791080
return caml_hash_mix_int(hash, d);
10801081
}
10811082

1083+
//Provides: caml_hash_mix_float32
1084+
//Requires: caml_int32_bits_of_float
1085+
//Requires: caml_hash_mix_int
1086+
function caml_hash_mix_float32(hash, v) {
1087+
var i = caml_int32_bits_of_float(v);
1088+
/* Normalize NaNs */
1089+
if ((i & 0x7f800000) === 0x7f800000 && (i & 0x7fffff) !== 0) {
1090+
i = 0x7f800001;
1091+
} else if (i === (0x80000000 | 0)) {
1092+
/* Normalize -0 into +0 */
1093+
// This code path is not used by caml_hash because 0 and -0 look
1094+
// like integers
1095+
i = 0;
1096+
}
1097+
hash = caml_hash_mix_int(hash, i);
1098+
return hash;
1099+
}
1100+
10821101
//Provides: caml_ba_to_typed_array mutable
10831102
function caml_ba_to_typed_array(ba) {
10841103
return ba.data;

runtime/wasm/bigarray.wat

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@
263263
(br $loop))))
264264
(return (local.get $h)))
265265
;; int64
266-
(if (i32.gt_u (local.get $len) (i32.const 32))
267-
(then (local.set $len (i32.const 32))))
266+
(if (i32.gt_u (local.get $len) (i32.const 64))
267+
(then (local.set $len (i32.const 64))))
268268
(loop $loop
269269
(if (i32.lt_u (local.get $i) (local.get $len))
270270
(then
@@ -328,7 +328,9 @@
328328
(call $caml_hash_mix_int
329329
(local.get $h)
330330
(i32.or
331-
(call $ta_get_i16 (local.get $data) (local.get $i))
331+
(i32.and (i32.const 0xFFFF)
332+
(call $ta_get_i16 (local.get $data)
333+
(local.get $i)))
332334
(i32.shl (call $ta_get_i16 (local.get $data)
333335
(i32.add (local.get $i) (i32.const 1)))
334336
(i32.const 16)))))
@@ -386,14 +388,19 @@
386388
(local.get $h)
387389
(i32.or
388390
(i32.or
389-
(call $ta_get_i8 (local.get $data) (local.get $i))
390-
(i32.shl (call $ta_get_i8 (local.get $data)
391-
(i32.add (local.get $i) (i32.const 1)))
392-
(i32.const 8)))
391+
(i32.and (i32.const 0xFF)
392+
(call $ta_get_i8 (local.get $data) (local.get $i)))
393+
(i32.shl
394+
(i32.and (i32.const 0xFF)
395+
(call $ta_get_i8 (local.get $data)
396+
(i32.add (local.get $i) (i32.const 1))))
397+
(i32.const 8)))
393398
(i32.or
394-
(i32.shl (call $ta_get_i8 (local.get $data)
395-
(i32.add (local.get $i) (i32.const 2)))
396-
(i32.const 16))
399+
(i32.shl
400+
(i32.and (i32.const 0xFF)
401+
(call $ta_get_i8 (local.get $data)
402+
(i32.add (local.get $i) (i32.const 2))))
403+
(i32.const 16))
397404
(i32.shl (call $ta_get_i8 (local.get $data)
398405
(i32.add (local.get $i) (i32.const 3)))
399406
(i32.const 24))))))

0 commit comments

Comments
 (0)