Skip to content

fix: reject NaN results from arithmetic operations#914

Closed
He-Pin wants to merge 2 commits into
databricks:masterfrom
He-Pin:fix/nan-handling
Closed

fix: reject NaN results from arithmetic operations#914
He-Pin wants to merge 2 commits into
databricks:masterfrom
He-Pin:fix/nan-handling

Conversation

@He-Pin

@He-Pin He-Pin commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix NaN handling in arithmetic operations to match go-jsonnet behavior.

Problem

sjsonnet was inconsistent with go-jsonnet for NaN-producing operations:

Operation go-jsonnet sjsonnet (before) sjsonnet (after)
0.0 / 0.0 "Not a number" NaN ❌ "division by zero" ✅
0.0 % 0.0 "Division by zero." NaN ❌ "not a number" ✅
1.0 % 0.0 "Division by zero." Infinity ❌ "not a number" ✅

Changes

Evaluator.scala

  1. Division (/): Added NaN check after division

    if (result.isNaN) Error.fail("Not a number", pos)
  2. Modulo (%): Added zero check and NaN check

    if (rd == 0) Error.fail("Division by zero.", pos)
    val result = ld % rd
    if (result.isNaN) Error.fail("Not a number", pos)
  3. Inline arithmetic fast path: Added NaN checks to tryInlineArith

References

  • go-jsonnet builtins.go:1108: makeDoubleCheck function checks both NaN and Infinity
  • go-jsonnet builtins.go:117-120: Division checks y.value == 0 before computing
  • go-jsonnet builtins.go:132-135: Modulo checks y.value == 0 before computing

Test

All existing tests pass. The fix ensures sjsonnet behaves identically to go-jsonnet for arithmetic edge cases.

He-Pin added 2 commits June 10, 2026 14:59
Motivation:
std.primitiveEquals(-0.0, 0.0) was returning false instead of true.
This is incorrect because IEEE 754 defines -0.0 == 0.0 as true.

Modification:
Changed TypeModule.scala to use rawDouble == rawDouble for number
comparison instead of ev.compare(x, y) == 0 which uses
java.lang.Double.compare that treats -0.0 and 0.0 as different.

Result:
std.primitiveEquals(-0.0, 0.0) now returns true, matching go-jsonnet
and C++ jsonnet behavior.

References:
- go-jsonnet builtins.go:264 uses left.value == right.value
- C++ Jsonnet vm.cpp:1436 uses args[0].v.d == args[1].v.d
- Add NaN check to division and modulo operations
- Match go-jsonnet behavior: 'Not a number' error for NaN results
- Match go-jsonnet behavior: 'Division by zero.' error for modulo by zero
- Fixes inconsistency with go-jsonnet where 0.0/0.0 returned NaN instead of erroring
@He-Pin He-Pin closed this Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant