Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/ops/arith.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,25 @@ ray_t* ray_idiv_fn(ray_t* a, ray_t* b) {
ray_type_name(a->type), ray_type_name(b->type));
if (RAY_ATOM_IS_NULL(a) || RAY_ATOM_IS_NULL(b))
return ray_typed_null(-RAY_I64);
double bv = as_f64(b);
if (bv == 0.0)
return ray_typed_null(-RAY_I64);
double q = floor(as_f64(a) / bv);
if (q < (double)INT64_MIN || q > (double)INT64_MAX)
if (is_float_op(a, b)) {
double bv = as_f64(b);
if (bv == 0.0)
return ray_typed_null(-RAY_I64);
double q = floor(as_f64(a) / bv);
if (q >= 9223372036854775808.0 || q < (double)INT64_MIN)
return ray_typed_null(-RAY_I64);
return make_i64((int64_t)q);
}
/* Integer div: stay in int64 space. The double round-trip above silently
* loses precision for magnitudes > 2^53 and is UB for q == 2^63. */
int64_t bv = as_i64(b);
if (bv == 0)
return ray_typed_null(-RAY_I64);
return make_i64((int64_t)q);
int64_t la = as_i64(a);
int64_t q = la / bv;
if (la % bv != 0 && ((la < 0) != (bv < 0)))
q--; /* floor toward -inf */
return make_i64(q);
}

ray_t* ray_mod_fn(ray_t* a, ray_t* b) {
Expand Down
27 changes: 27 additions & 0 deletions test/rfl/integration/math.rfl
Original file line number Diff line number Diff line change
Expand Up @@ -2478,3 +2478,30 @@
;; Test division with type conversion
(/ [100 200 300] 3.0) -- [33.33 66.67 100.0]
(% [100 200 300] 3.0) -- [1.0 2.0 0.0]

;; ========== I64 FLOOR DIV EXACTNESS / UB REGRESSIONS ==========
;; Integer div must stay in int64 space: the old double round-trip lost
;; precision above 2^53 and hit UB at q == 2^63 (div -9223372036854775807 -1).
(div 9007199254740993 1) -- 9007199254740993
(div 9007199254740993 3) -- 3002399751580331
(div 18014398509481985 1) -- 18014398509481985
(div 123456789012345678 1) -- 123456789012345678
(div 9223372036854775807 1) -- 9223372036854775807
(div 9223372036854775807 -1) -- -9223372036854775807
(div -9223372036854775807 -1) -- 9223372036854775807
(div -9223372036854775807 2) -- -4611686018427387904
(div -9223372036854775807 -2) -- 4611686018427387903
(div 9223372036854775807 2) -- 4611686018427387903
;; vectors (1-element vectors route through the scalar path)
(div [9007199254740993 9007199254740993] 3) -- [3002399751580331 3002399751580331]
(div [123456789012345678 9007199254740993] 1) -- [123456789012345678 9007199254740993]
(div [9223372036854775807] -1) -- [-9223372036854775807]
(div [-9223372036854775807] -1) -- [9223372036854775807]
;; out-of-int64-range (float input) still clamps to null
(div 1e308 1) -- 0Nl
(div -1e308 1) -- 0Nl
(div [1e308 9.3e18] 1) -- [0Nl 0Nl]
(div 9223372036854775808.0 1) -- 0Nl
;; floor semantics preserved for int operands
(div [-7 7 -7] [2 -2 -2]) -- [-4 -4 3]
(div [7 8 9] 2) -- [3 4 4]
Loading