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

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-js.git


The following commit(s) were added to refs/heads/main by this push:
     new af1efd9  fix: Fix precision loss in IntervalMonthDayNano nanosecond 
(#321)
af1efd9 is described below

commit af1efd9255b6e1d909954f965abe6412b01681a9
Author: George <[email protected]>
AuthorDate: Mon Nov 3 19:45:53 2025 -0500

    fix: Fix precision loss in IntervalMonthDayNano nanosecond (#321)
    
    ## Rationale for this change
    
    Integration tests were failing when JavaScript produced
    IntervalMonthDayNano data that was consumed by C++, Rust, or nanoarrow
    implementations. The nanosecond values differed by small amounts (e.g.,
    216 nanoseconds) due to precision loss during BigInt to Number
    conversion.
    
    **Example failure:**
    - Expected: `6684525287992311000ns`
    - JS Output: `6684525287992310784ns`
    - Difference: 216ns
    
    ## What changes are included in this PR?
    
    Fixed the `toIntervalMonthDayNanoInt32Array` function in
    `src/util/interval.ts` to properly handle unsigned 32-bit integer
    conversion without precision loss. The issue was that `Number(BigInt)`
    conversion for large values (>2^53-1) loses precision. Applied unsigned
    right shift (`>>> 0`) to ensure correct unsigned 32-bit representation.
    
    **Changed:**
    ```typescript
    // Before (loses precision):
    data[ai++] = Number(BigInt(nanoseconds) & BigInt(0xFFFFFFFF));
    data[ai++] = Number(BigInt(nanoseconds) >> BigInt(32));
    
    // After (preserves precision):
    const ns = BigInt(nanoseconds);
    data[ai++] = Number(ns & BigInt(0xFFFFFFFF)) >>> 0;
    data[ai++] = Number(ns >> BigInt(32)) >>> 0;
    ```
    
    Fixes apache/arrow#46203
    
    Closes #15.
---
 src/util/interval.ts | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/util/interval.ts b/src/util/interval.ts
index a601807..597ccf9 100644
--- a/src/util/interval.ts
+++ b/src/util/interval.ts
@@ -46,8 +46,10 @@ export function toIntervalMonthDayNanoInt32Array(objects: 
Partial<IntervalMonthD
         data[ai++] = interval['days'] ?? 0;
         const nanoseconds = interval['nanoseconds'];
         if (nanoseconds) {
-            data[ai++] = Number(BigInt(nanoseconds) & BigInt(0xFFFFFFFF));
-            data[ai++] = Number(BigInt(nanoseconds) >> BigInt(32));
+            const ns = BigInt(nanoseconds);
+            // Convert to unsigned 32-bit integers to avoid precision loss
+            data[ai++] = Number(ns & BigInt(0xFFFFFFFF)) >>> 0;
+            data[ai++] = Number(ns >> BigInt(32)) >>> 0;
         } else {
             ai += 2;
         }

Reply via email to