From c19b4a340655d0c0b0142e970c2bed48edf2b638 Mon Sep 17 00:00:00 2001 From: Abdul Kaium Date: Thu, 24 Sep 2026 03:10:36 +0600 Subject: [PATCH 1/6] fix: support full 64-bit integer range for number inputs in Int64 constructor --- .../@stdlib/number/int64/ctor/README.md | 2 ++ .../@stdlib/number/int64/ctor/lib/main.js | 29 ++++++----------- .../@stdlib/number/int64/ctor/test/test.js | 31 +++++++++++++++++-- .../number/int64/ctor/test/test.to_string.js | 22 ++++++++++--- 4 files changed, 59 insertions(+), 25 deletions(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/README.md b/lib/node_modules/@stdlib/number/int64/ctor/README.md index c4e931bd71b1..3ba8f26b3197 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/README.md +++ b/lib/node_modules/@stdlib/number/int64/ctor/README.md @@ -190,6 +190,8 @@ var v = x.valueOf(); ## Notes - A 64-bit signed integer has a range of \[`-(2^63)`, `2^63-1`]. +- The constructor accepts either a `number` or a `bigint` on the interval \[`-(2^63)`, `2^63-1`]. +- Passing a `number` argument is safe and exact for integers within \[`-2^53`, `2^53`]. For values exceeding `2^53` in magnitude, JavaScript numbers incur precision loss; provide a `bigint` argument or construct from words using [`Int64.of()`](#int64of-high-low-) or [`Int64.from()`](#int64from-array-). diff --git a/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js b/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js index 65b9c865b7a3..23152c3c5bd9 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js @@ -32,14 +32,13 @@ var isBetween = require( '@stdlib/assert/is-between' ); var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); var BigInt = require( '@stdlib/bigint/ctor' ); -var Number = require( '@stdlib/number/ctor' ); var Uint32Array = require( '@stdlib/array/uint32' ); var join = require( '@stdlib/array/base/join' ); var UINT32_MAX = require( '@stdlib/constants/uint32/max' ); -var MAX_SAFE_INTEGER = require( '@stdlib/constants/float64/max-safe-integer' ); -var MIN_SAFE_INTEGER = require( '@stdlib/constants/float64/min-safe-integer' ); var format = require( '@stdlib/string/format' ); var ToPrimitiveSymbol = require( '@stdlib/symbol/to-primitive' ); +var bigint2words = require( '@stdlib/number/uint64/base/bigint2words' ).assign; +var number2words = require( '@stdlib/number/int64/base/number2words' ).assign; var indices = require( './indices.js' ); var int2str = require( './to_string.js' ); @@ -48,6 +47,9 @@ var int2str = require( './to_string.js' ); var HAS_BIGINT = hasBigIntSupport(); var TWO_32 = 0x100000000; // 2^32 +var TWO_63 = 0x8000000000000000; // 2^63 +var STRIDE = indices.LOW - indices.HIGH; +var OFFSET = indices.HIGH; // MAIN // @@ -67,27 +69,16 @@ var TWO_32 = 0x100000000; // 2^32 */ function Int64( value ) { var buffer; - var v; if ( !( this instanceof Int64 ) ) { throw new TypeError( 'invalid invocation. Constructor must be called with the `new` keyword.' ); } buffer = new Uint32Array( 2 ); - if ( isBigInt( value ) ) { - if ( BigInt.asIntN( 64, value ) !== value ) { - throw new TypeError( format( 'invalid argument. Must provide an integer on the interval [-(2^63), 2^63-1]. Value: `%s`.', value ) ); - } - v = BigInt.asUintN( 64, value ); // Convert to unsigned to make it fixed-width - buffer[ indices.HIGH ] = Number( v >> BigInt( 32 ) ); - buffer[ indices.LOW ] = Number( v & BigInt( UINT32_MAX ) ); - } else if ( isInteger( value ) && isBetween( value, MIN_SAFE_INTEGER, MAX_SAFE_INTEGER ) ) { - buffer[ indices.LOW ] = value >>> 0; // Truncate to 32-bit unsigned integer - if ( value >= 0 ) { - buffer[ indices.HIGH ] = ( value / TWO_32 ) >>> 0; - } else { - buffer[ indices.HIGH ] = ( ~( ( -value ) / TWO_32 ) + !buffer[ indices.LOW ] ) >>> 0; // 2's complement with carry from low word - } + if ( isBigInt( value ) && BigInt.asIntN( 64, value ) === value ) { + bigint2words( value, buffer, STRIDE, OFFSET ); + } else if ( isInteger( value ) && isBetween( value, -TWO_63, TWO_63, 'closed', 'open' ) ) { + number2words( value, buffer, STRIDE, OFFSET ); } else { - throw new TypeError( format( 'invalid argument. Must provide an integer on the interval [-(2^53-1), 2^53-1]. Value: `%s`.', value ) ); + throw new TypeError( format( 'invalid argument. Must provide an integer on the interval [-(2^63), 2^63-1]. Value: `%s`.', value ) ); } setReadOnly( this, '_buffer', buffer ); return this; diff --git a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js index d0ee4217954f..a2fa79473e3d 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js @@ -36,6 +36,7 @@ var Int64 = require( './../lib' ); // VARIABLES // var HAS_BIGINT = hasBigIntSupport(); +var TWO_63 = 0x8000000000000000; // 2^63 // TESTS // @@ -94,8 +95,9 @@ tape( 'the constructor throws an error if provided an invalid/unsupported number values = [ 0.5, -0.5, - MAX_SAFE_INTEGER + 1, - MIN_SAFE_INTEGER - 1 + TWO_63, + TWO_63 + 2048, + -TWO_63 - 2048 ]; for ( i = 0; i < values.length; i++ ) { t.throws( badValue( values[i] ), TypeError, format( 'throws an error when provided %s', values[i] ) ); @@ -164,6 +166,31 @@ tape( 'the constructor returns a 64-bit signed integer', function test( t ) { t.strictEqual( x.hi, 4292870144, 'returns expected value' ); t.strictEqual( x.lo, 1, 'returns expected value' ); + x = new Int64( MAX_SAFE_INTEGER + 1 ); + t.ok( x instanceof Int64, 'returns expected value' ); + t.strictEqual( x.hi, 2097152, 'returns expected value' ); + t.strictEqual( x.lo, 0, 'returns expected value' ); + + x = new Int64( MIN_SAFE_INTEGER - 1 ); + t.ok( x instanceof Int64, 'returns expected value' ); + t.strictEqual( x.hi, 4292870144, 'returns expected value' ); + t.strictEqual( x.lo, 0, 'returns expected value' ); + + x = new Int64( TWO_63 - 1024 ); // Maximum integer value less than 2^63 that can be stored in a 64-bit float + t.ok( x instanceof Int64, 'returns expected value' ); + t.strictEqual( x.hi, 2147483647, 'returns expected value' ); + t.strictEqual( x.lo, 4294966272, 'returns expected value' ); + + x = new Int64( -TWO_63 ); // Minimum integer value on the interval [-(2^63), 2^63-1] + t.ok( x instanceof Int64, 'returns expected value' ); + t.strictEqual( x.hi, 2147483648, 'returns expected value' ); + t.strictEqual( x.lo, 0, 'returns expected value' ); + + x = new Int64( -TWO_63 + 1024 ); + t.ok( x instanceof Int64, 'returns expected value' ); + t.strictEqual( x.hi, 2147483648, 'returns expected value' ); + t.strictEqual( x.lo, 1024, 'returns expected value' ); + if ( HAS_BIGINT ) { x = new Int64( BigInt( 0 ) ); t.ok( x instanceof Int64, 'returns expected value' ); diff --git a/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js b/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js index e3a7d2f5fa62..099836c93c66 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js @@ -21,11 +21,21 @@ // MODULES // var tape = require( 'tape' ); +var hasBigIntSupport = require( '@stdlib/assert/has-bigint-support' ); +var BigInt = require( '@stdlib/bigint/ctor' ); var MAX_SAFE_INTEGER = require( '@stdlib/constants/float64/max-safe-integer' ); var UINT32_MAX = require( '@stdlib/constants/uint32/max' ); var Int64 = require( './../lib' ); +// VARIABLES // + +var TWO_63 = 0x8000000000000000; // 2^63 +var opts = { + 'skip': !hasBigIntSupport() +}; + + // TESTS // tape( 'main export is a function', function test( t ) { @@ -49,7 +59,7 @@ tape( 'the constructor returns an instance having a `toString` method for serial t.end(); }); -tape( 'the method accepts a radix parameter for serializing an instance as a string in bases 2 through 36', function test( t ) { +tape( 'the method accepts a radix parameter for serializing an instance as a string in bases 2 through 36', opts, function test( t ) { var values; var radix; var i; @@ -71,11 +81,13 @@ tape( 'the method accepts a radix parameter for serializing an instance as a str UINT32_MAX, UINT32_MAX + 1, MAX_SAFE_INTEGER - 1, - MAX_SAFE_INTEGER + MAX_SAFE_INTEGER, + MAX_SAFE_INTEGER + 1, + TWO_63 - 1024 // Maximum integer value less than 2^63 that can be stored in a 64-bit float ]; for ( i = 0; i < values.length; i++ ) { - z = values[i]; + z = BigInt( values[i] ); x = new Int64( z ); for ( radix = 2; radix <= 36; radix++ ) { @@ -83,9 +95,11 @@ tape( 'the method accepts a radix parameter for serializing an instance as a str } } + values.push( TWO_63 ); // when negated, corresponds to -(2^63) + // Negative values: for ( i = 0; i < values.length; i++ ) { - z = -values[i]; + z = -BigInt( values[i] ); x = new Int64( z ); for ( radix = 2; radix <= 36; radix++ ) { From a953f5c32c5b78dcf72ba23b27e1af5cc18e32a3 Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 24 Sep 2026 01:40:26 -0700 Subject: [PATCH 2/6] fix: remove parentheses Signed-off-by: Athan --- lib/node_modules/@stdlib/number/int64/ctor/lib/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js b/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js index 23152c3c5bd9..fe6f2fcf0cb5 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/lib/main.js @@ -78,7 +78,7 @@ function Int64( value ) { } else if ( isInteger( value ) && isBetween( value, -TWO_63, TWO_63, 'closed', 'open' ) ) { number2words( value, buffer, STRIDE, OFFSET ); } else { - throw new TypeError( format( 'invalid argument. Must provide an integer on the interval [-(2^63), 2^63-1]. Value: `%s`.', value ) ); + throw new TypeError( format( 'invalid argument. Must provide an integer on the interval [-2^63, 2^63-1]. Value: `%s`.', value ) ); } setReadOnly( this, '_buffer', buffer ); return this; From 6a485c37e54f4adbf640e7f31de32038ac51247b Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 24 Sep 2026 01:42:47 -0700 Subject: [PATCH 3/6] test: skip test if env lacks BigInt support Signed-off-by: Athan --- .../@stdlib/number/int64/ctor/test/test.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js index a2fa79473e3d..d940871ca6fa 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js @@ -38,6 +38,10 @@ var Int64 = require( './../lib' ); var HAS_BIGINT = hasBigIntSupport(); var TWO_63 = 0x8000000000000000; // 2^63 +var opts = { + 'skip': !HAS_BIGINT +}; + // TESTS // @@ -112,15 +116,10 @@ tape( 'the constructor throws an error if provided an invalid/unsupported number } }); -tape( 'the constructor throws an error if provided an invalid/unsupported BigInt', function test( t ) { +tape( 'the constructor throws an error if provided an invalid/unsupported BigInt', opts, function test( t ) { var values; var i; - if ( !HAS_BIGINT ) { - t.end(); - return; - } - values = [ BigInt( '0x8000000000000000' ), // 2^63 -BigInt( '0x80000000000000001' ) // -(2^63) - 1 From a1eb80295e31d2cf6eca733e26af95100794cf23 Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 24 Sep 2026 01:44:02 -0700 Subject: [PATCH 4/6] docs: update comments Signed-off-by: Athan --- lib/node_modules/@stdlib/number/int64/ctor/test/test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js index d940871ca6fa..6acd9fe9af23 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/test/test.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/test/test.js @@ -175,12 +175,12 @@ tape( 'the constructor returns a 64-bit signed integer', function test( t ) { t.strictEqual( x.hi, 4292870144, 'returns expected value' ); t.strictEqual( x.lo, 0, 'returns expected value' ); - x = new Int64( TWO_63 - 1024 ); // Maximum integer value less than 2^63 that can be stored in a 64-bit float + x = new Int64( TWO_63 - 1024 ); // Largest integer value less than 2^63 exactly representable as a double t.ok( x instanceof Int64, 'returns expected value' ); t.strictEqual( x.hi, 2147483647, 'returns expected value' ); t.strictEqual( x.lo, 4294966272, 'returns expected value' ); - x = new Int64( -TWO_63 ); // Minimum integer value on the interval [-(2^63), 2^63-1] + x = new Int64( -TWO_63 ); // Smallest integer value on the interval [-(2^63), 2^63-1] t.ok( x instanceof Int64, 'returns expected value' ); t.strictEqual( x.hi, 2147483648, 'returns expected value' ); t.strictEqual( x.lo, 0, 'returns expected value' ); From d242f2a00f33cb5d982ec468fdfa7b6e752cd5ed Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 24 Sep 2026 01:45:13 -0700 Subject: [PATCH 5/6] docs: update comment Signed-off-by: Athan --- .../@stdlib/number/int64/ctor/test/test.to_string.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js b/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js index 099836c93c66..98854628d786 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js +++ b/lib/node_modules/@stdlib/number/int64/ctor/test/test.to_string.js @@ -83,7 +83,7 @@ tape( 'the method accepts a radix parameter for serializing an instance as a str MAX_SAFE_INTEGER - 1, MAX_SAFE_INTEGER, MAX_SAFE_INTEGER + 1, - TWO_63 - 1024 // Maximum integer value less than 2^63 that can be stored in a 64-bit float + TWO_63 - 1024 // Largest integer value less than 2^63 exactly representable as a double ]; for ( i = 0; i < values.length; i++ ) { From 849465611cbaa6ced0cf1f09f99e6bb00936fead Mon Sep 17 00:00:00 2001 From: Athan Date: Thu, 24 Sep 2026 01:47:37 -0700 Subject: [PATCH 6/6] docs: add anchor links Signed-off-by: Athan --- lib/node_modules/@stdlib/number/int64/ctor/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/node_modules/@stdlib/number/int64/ctor/README.md b/lib/node_modules/@stdlib/number/int64/ctor/README.md index 3ba8f26b3197..d44e6c5364d8 100644 --- a/lib/node_modules/@stdlib/number/int64/ctor/README.md +++ b/lib/node_modules/@stdlib/number/int64/ctor/README.md @@ -121,6 +121,8 @@ var w = x.lo; ### Static Methods + + #### Int64.from( array ) Creates a new 64-bit signed integer from an array-like object containing a high and low word. @@ -132,6 +134,8 @@ var x = Int64.from( [ 1234, 5678 ] ); #### Int64.of( high, low ) + + Creates a new 64-bit signed integer from a high and low word. ```javascript @@ -189,9 +193,9 @@ var v = x.valueOf(); ## Notes -- A 64-bit signed integer has a range of \[`-(2^63)`, `2^63-1`]. -- The constructor accepts either a `number` or a `bigint` on the interval \[`-(2^63)`, `2^63-1`]. -- Passing a `number` argument is safe and exact for integers within \[`-2^53`, `2^53`]. For values exceeding `2^53` in magnitude, JavaScript numbers incur precision loss; provide a `bigint` argument or construct from words using [`Int64.of()`](#int64of-high-low-) or [`Int64.from()`](#int64from-array-). +- A 64-bit signed integer has a range of `[-2^63, 2^63-1]`. +- The constructor accepts either a `number` or a `bigint` on the interval `[-2^63, 2^63-1]`. +- Passing a number argument is safe and exact for integers within `[-2^53, 2^53]`. For values exceeding `2^53` in magnitude, JavaScript numbers incur precision loss; provide a `bigint` argument or construct from words using [`Int64.of()`](#static-method-of) or [`Int64.from()`](#static-method-from).