@@ -33,12 +33,30 @@ std.assertEqual(std.makeArray(10, function(i) i + 1), [1, 2, 3, 4, 5, 6, 7, 8, 9
3333std.assertEqual (std.makeArray (0 , function (i) null ), []) &&
3434
3535local assertClose(a, b) =
36+ // Using 1e-12 as tolerance. Jsonnet uses double-precision floats with machine epsilon of 2**-53 ≈ 1.11e-16.
37+ // This tolerance is ~9000x the machine epsilon, which is quite lenient and should work across
38+ // different platforms and math libraries.
39+ //
40+ // We use a combination of absolute and relative error to handle both small and large values:
41+ // - For values near zero, we use absolute error to avoid division issues
42+ // - For larger values, we use relative error to maintain precision
43+ //
44+ // This correctly handles cases like:
45+ // assertClose(1e-15, 0) - should pass (both are essentially zero)
46+ // assertClose(-100, 0) - should fail (significant difference)
47+ // assertClose(std.sin(std.pi), 0) - should pass (tiny floating point error)
48+ local abs_a = std.abs (a);
49+ local abs_b = std.abs (b);
50+ local diff = std.abs (a - b);
51+ local max_abs = std.max (abs_a, abs_b);
3652 local err =
37- if b == 0 then
38- a - b
53+ if abs_a == 0 && abs_b == 0 then
54+ 0 // Both are exactly zero, so no error
55+ else if max_abs < 1e-12 then
56+ diff // For very small values, use absolute error
3957 else
40- if a / b - 1 > 0 then a / b - 1 else 1 - a / b;
41- if err > 0.000005 then
58+ diff / max_abs; // For larger values, use relative error
59+ if err > 1e-12 then
4260 error 'Assertion failed (error ' + err + '). ' + a + ' !~ ' + b
4361 else
4462 true ;
0 commit comments