Visitar URL original
Fix sign() returning 1 for NaN by MaxFreedomPollard · Pull Request #215 · ekzhang/jax-js · GitHub
Skip to content

Fix sign() returning 1 for NaN - #215

Merged
ekzhang merged 1 commit into
ekzhang:mainfrom
MaxFreedomPollard:fix-sign-nan
Sep 10, 2026
Merged

ekzhang merged 1 commit into
ekzhang:mainfrom
MaxFreedomPollard:fix-sign-nan

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown
Contributor

np.sign(np.array([-Infinity, -2.5, -0, 0, 2.5, Infinity, NaN])) returns [-1, -1, 0, 0, 1, 1, 1]. NumPy returns [-1, -1, 0, 0, 1, 1, nan], and the numpy.sign docs are explicit: "The sign function returns -1 if x < 0, 0 if x==0, 1 if x > 0. nan is returned for nan inputs." jax.numpy.sign is the same function, so a NaN that goes into a pipeline through sign() currently comes back out as a real number.

The cause is at src/library/numpy.ts:2637, where(notEqual(x.ref, 0), where(less(x, 0), -1, 1), 0). Every comparison against NaN is false, so notEqual(x, 0) is true and less(x, 0) is false, and NaN falls through to the positive branch. test/numpy.test.ts has carried a test.fails for this since #127 with a TODO: Fix sign(NaN) returning 1 instead of NaN comment.

The fix keeps the existing sign tests and selects NaN explicitly with the isnan() helper that already sits in this file. isnan() returns an all-false mask for integer and boolean dtypes, so those inputs and the float32 output dtype that sign() has always produced are untouched, and only the NaN values change. The test.fails becomes a normal test that also pins the two infinities and both signed zeros, guarded by hasStrictNumerics() since webgl does not have dependable NaN semantics.

Verified on node 22 with pnpm test run test/numpy.test.ts -t "sign" --no-browser, covering the cpu and wasm devices: the new assertions fail on unmodified main with expected 1 to be NaN on both devices and pass with the change, the full --no-browser suite has an identical failure set before and after (all of it Float16Array is not defined on this node version, which CI does not hit on node 26), and pnpm check, pnpm lint --max-warnings 0 and pnpm format:check are clean.

NaN compares false against zero in both directions, so it reached the
positive branch of the sign tests. Select NaN explicitly instead, and
turn the existing test.fails case into a real test.

@ekzhang ekzhang left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for resolving the TODO!

@ekzhang
ekzhang merged commit ef32174 into ekzhang:main Sep 10, 2026
5 checks passed

This branch was successfully deployed

1 active deployment
Preview — 8c6a2793 Deployed Sep 10, 2026 by vercel[bot]
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.

2 participants