This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 05c691440 fix(javascript): underflow tiny float16 magnitudes to signed 
zero (#4004)
05c691440 is described below

commit 05c691440f02b8b4e5d1a2579f6b681bd580bf2c
Author: Ayush Kumar <[email protected]>
AuthorDate: Mon Aug 31 08:10:42 2026 +0530

    fix(javascript): underflow tiny float16 magnitudes to signed zero (#4004)
    
    ## Why?
    toFloat16Bits shifted the significand by (-1 - exponent) for subnormals;
    for magnitudes below 2^-32 the shift count reaches 32 and JS masks it
    with & 31, leaving garbage bits (1e-10 encoded as -15352, 1e-11 as NaN).
    Underflow values below the smallest float16 subnormal to signed zero.
    
    ## What does this PR do?
    
    
    
    ## Related issues
    
    
    
    ## AI Contribution Checklist
    
    
    
    - [ ] Substantial AI assistance was used in this PR: `yes` / `no`
    - [ ] If `yes`, I included a completed [AI Contribution
    
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
    in this PR description and the required `AI Usage Disclosure`.
    - [ ] If `yes`, my PR description includes the required `ai_review`
    summary and screenshot evidence or equivalent persisted links of the
    final clean AI review results from both fresh reviewers described in
    `AI_POLICY.md`, the Fory-guided reviewer and the independent general
    reviewer, on the current PR diff or current HEAD after the latest code
    changes.
    
    
    
    ## Does this PR introduce any user-facing change?
    
    
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
---
 javascript/packages/core/lib/types/float16.ts |  7 +++++++
 javascript/test/number.test.ts                | 14 ++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/javascript/packages/core/lib/types/float16.ts 
b/javascript/packages/core/lib/types/float16.ts
index de2fc9100..20ffcd332 100644
--- a/javascript/packages/core/lib/types/float16.ts
+++ b/javascript/packages/core/lib/types/float16.ts
@@ -35,6 +35,13 @@ export function toFloat16Bits(value: number) {
     return sign | 0x7c00;
   }
 
+  if (exponent < -24) {
+    // Too small for a float16 subnormal. Larger shifts below would wrap
+    // (JS masks shift counts with & 31) and leave garbage bits, so
+    // underflow to signed zero.
+    return sign;
+  }
+
   if (exponent < -14) {
     return sign | ((significand | 0x800000) >> (13 - 14 - exponent));
   }
diff --git a/javascript/test/number.test.ts b/javascript/test/number.test.ts
index c1e84754f..7da913422 100644
--- a/javascript/test/number.test.ts
+++ b/javascript/test/number.test.ts
@@ -154,6 +154,20 @@ describe("number", () => {
     expect(result.a).toBe(NaN);
   });
 
+  test("should float16 underflow tiny magnitudes to signed zero", () => {
+    // Magnitudes below the smallest float16 subnormal must encode as zero;
+    // shift counts of 32 or more wrapped (JS masks them with & 31) and left
+    // garbage bits in the half.
+    const fory = new Fory({ compatible: false, ref: true });
+    const { serialize, deserialize } = fory.register(
+      Type.struct({ typeName: "example.f16zero" }, { a: Type.float16() }),
+    );
+    expect(deserialize(serialize({ a: 1e-10 })).a).toBe(0);
+    expect(deserialize(serialize({ a: 1e-11 })).a).toBe(0);
+    expect(deserialize(serialize({ a: 1e-40 })).a).toBe(0);
+    expect(deserialize(serialize({ a: -1e-10 })).a).toBe(-0);
+  });
+
   test("should float16 Infinity work", () => {
     const fory = new Fory({ compatible: false, ref: true });
     const serializer = fory.register(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to