Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit fc0e300

Browse files
authored
A POC that replaces all BigInt to JSBI.BigInt (#101)
1 parent 094a0f7 commit fc0e300

11 files changed

+161
-114
lines changed

package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
],
4646
"author": "Jesse Alama <[email protected]>",
4747
"license": "ISC",
48+
"dependencies": {
49+
"jsbi": "^4.3.0"
50+
},
4851
"devDependencies": {
4952
"@rollup/plugin-typescript": "^12.1.1",
5053
"@types/jest": "^29.5.1",

src/Decimal.mts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import JSBI from "jsbi";
12
import { Rational } from "./Rational.mjs";
23

34
function _cohort(s: string): "0" | "-0" | Rational {
@@ -88,7 +89,7 @@ export class Decimal {
8889
});
8990
}
9091

91-
public coefficient(): bigint {
92+
public coefficient(): JSBI {
9293
let v = this.cohort as Rational;
9394
let q = this.quantum;
9495
let c = v.scale10(0 - q);

src/Decimal128.mts

+38-28
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* @author Jesse Alama <[email protected]>
1414
*/
1515

16+
import JSBI from "jsbi";
17+
1618
import {
1719
RoundingMode,
1820
ROUNDING_MODES,
@@ -28,7 +30,7 @@ const EXPONENT_MAX = 6111;
2830
const NORMAL_EXPONENT_MAX = 6144;
2931
const MAX_SIGNIFICANT_DIGITS = 34;
3032

31-
const bigTen = BigInt(10);
33+
const bigTen = JSBI.BigInt(10);
3234

3335
type NaNValue = "NaN";
3436
type InfiniteValue = "Infinity" | "-Infinity";
@@ -39,7 +41,7 @@ type Decimal128Value = NaNValue | InfiniteValue | FiniteValue;
3941
const NAN = "NaN";
4042
const POSITIVE_INFINITY = "Infinity";
4143
const NEGATIVE_INFINITY = "-Infinity";
42-
const TEN_MAX_EXPONENT = bigTen ** BigInt(MAX_SIGNIFICANT_DIGITS);
44+
const TEN_MAX_EXPONENT = JSBI.exponentiate(bigTen, JSBI.BigInt(MAX_SIGNIFICANT_DIGITS));
4345

4446
function pickQuantum(
4547
d: "0" | "-0" | Rational,
@@ -80,7 +82,7 @@ function adjustDecimal128(d: Decimal): Decimal128Value {
8082

8183
let coef = d.coefficient();
8284

83-
if (coef <= TEN_MAX_EXPONENT && EXPONENT_MIN <= q && q <= EXPONENT_MAX) {
85+
if (JSBI.LE(coef, TEN_MAX_EXPONENT) && JSBI.LE(EXPONENT_MIN, q) && JSBI.LE(q, EXPONENT_MAX)) {
8486
return d;
8587
}
8688

@@ -166,10 +168,18 @@ export class Decimal128 {
166168
private readonly _isFinite: boolean = true;
167169
private readonly _isNegative: boolean = false;
168170

169-
constructor(n: string | number | bigint | Decimal) {
171+
constructor(n: string | number | bigint | JSBI | Decimal) {
170172
let data;
171173
if ("object" === typeof n) {
172-
data = n;
174+
if (n instanceof JSBI) {
175+
// Note: when using babel-plugin-transform-jsbi-to-bigint,
176+
// the condition above may get transpiled into "typeof n === 'bigint'",
177+
// causing the condition above to always be false.
178+
// This is fine as we will be hanlding bigint below.
179+
data = handleDecimalNotation(n.toString())
180+
} else {
181+
data = n;
182+
}
173183
} else {
174184
let s: string;
175185

@@ -262,7 +272,7 @@ export class Decimal128 {
262272
let decimalOne = new Decimal128("1");
263273
let decimalTen = new Decimal128("10");
264274

265-
while (0 <= x.cmp(decimalTen)) {
275+
while (JSBI.LE(0, x.cmp(decimalTen))) {
266276
x = x.scale10(-1);
267277
}
268278

@@ -303,7 +313,7 @@ export class Decimal128 {
303313
);
304314
}
305315

306-
private coefficient(): bigint {
316+
private coefficient(): JSBI {
307317
let d = this.d as Decimal;
308318
return d.coefficient();
309319
}
@@ -463,7 +473,7 @@ export class Decimal128 {
463473

464474
let n = opts.digits;
465475

466-
if (n <= 0) {
476+
if (JSBI.LE(n, 0)) {
467477
throw new RangeError("Argument must be positive");
468478
}
469479

@@ -484,15 +494,15 @@ export class Decimal128 {
484494
let [lhs, rhs] = s.split(/[.]/);
485495
let p = this.isNegative() ? "-" : "";
486496

487-
if (n <= lhs.length) {
497+
if (JSBI.LE(n, lhs.length)) {
488498
if (lhs.length === n) {
489499
return p + lhs;
490500
}
491501

492502
return p + s.substring(0, n) + "e+" + `${lhs.length - n + 1}`;
493503
}
494504

495-
if (n <= lhs.length + rhs.length) {
505+
if (JSBI.LE(n, lhs.length + rhs.length)) {
496506
let rounded = this.round(n - lhs.length);
497507
return rounded.emitDecimal();
498508
}
@@ -523,7 +533,7 @@ export class Decimal128 {
523533

524534
let n = opts.digits;
525535

526-
if (n <= 0) {
536+
if (JSBI.LE(n, 0)) {
527537
throw new RangeError("Argument must be positive");
528538
}
529539

@@ -539,7 +549,7 @@ export class Decimal128 {
539549

540550
let p = this.isNegative() ? "-" : "";
541551

542-
if (rhs.length <= n) {
552+
if (JSBI.LE(rhs.length, n)) {
543553
return p + lhs + "." + rhs + "0".repeat(n - rhs.length) + "e" + exp;
544554
}
545555

@@ -558,7 +568,7 @@ export class Decimal128 {
558568
return !!rhs.match(/^0+$/);
559569
}
560570

561-
toBigInt(): bigint {
571+
toBigInt(): JSBI {
562572
if (this.isNaN()) {
563573
throw new RangeError("NaN cannot be converted to a BigInt");
564574
}
@@ -573,7 +583,7 @@ export class Decimal128 {
573583
);
574584
}
575585

576-
return BigInt(this.toString());
586+
return JSBI.BigInt(this.toString());
577587
}
578588

579589
toNumber(): number {
@@ -931,34 +941,34 @@ export class Decimal128 {
931941
let dividendCoefficient = this.coefficient();
932942
let divisorCoefficient = x.coefficient();
933943

934-
if (dividendCoefficient !== 0n) {
935-
while (dividendCoefficient < divisorCoefficient) {
936-
dividendCoefficient = dividendCoefficient * 10n;
944+
if (JSBI.notEqual(dividendCoefficient, JSBI.BigInt(0))) {
945+
while (JSBI.LT(dividendCoefficient, divisorCoefficient)) {
946+
dividendCoefficient = JSBI.multiply(dividendCoefficient, JSBI.BigInt(10));
937947
adjust++;
938948
}
939949
}
940950

941-
while (dividendCoefficient > divisorCoefficient * 10n) {
942-
divisorCoefficient = divisorCoefficient * 10n;
951+
while (JSBI.GT(dividendCoefficient, JSBI.multiply(divisorCoefficient, JSBI.BigInt(10)))) {
952+
divisorCoefficient = JSBI.multiply(divisorCoefficient, JSBI.BigInt(10));
943953
adjust--;
944954
}
945955

946-
let resultCoefficient = 0n;
956+
let resultCoefficient = JSBI.BigInt(0);
947957
let done = false;
948958

949959
while (!done) {
950-
while (divisorCoefficient <= dividendCoefficient) {
951-
dividendCoefficient = dividendCoefficient - divisorCoefficient;
952-
resultCoefficient++;
960+
while (JSBI.LE(divisorCoefficient, dividendCoefficient)) {
961+
dividendCoefficient = JSBI.subtract(dividendCoefficient, divisorCoefficient);
962+
resultCoefficient = JSBI.add(resultCoefficient, JSBI.BigInt(1));
953963
}
954964
if (
955-
(dividendCoefficient === 0n && adjust >= 0) ||
965+
(JSBI.equal(dividendCoefficient, JSBI.BigInt(0)) && adjust >= 0) ||
956966
resultCoefficient.toString().length > MAX_SIGNIFICANT_DIGITS
957967
) {
958968
done = true;
959969
} else {
960-
resultCoefficient = resultCoefficient * 10n;
961-
dividendCoefficient = dividendCoefficient * 10n;
970+
resultCoefficient = JSBI.multiply(resultCoefficient, JSBI.BigInt(10));
971+
dividendCoefficient = JSBI.multiply(dividendCoefficient, JSBI.BigInt(10));
962972
adjust++;
963973
}
964974
}
@@ -1123,7 +1133,7 @@ export class Decimal128 {
11231133
return this.exponent();
11241134
}
11251135

1126-
scaledSignificand(): bigint {
1136+
scaledSignificand(): JSBI {
11271137
if (this.isNaN()) {
11281138
throw new RangeError("NaN does not have a scaled significand");
11291139
}
@@ -1133,7 +1143,7 @@ export class Decimal128 {
11331143
}
11341144

11351145
if (this.isZero()) {
1136-
return 0n;
1146+
return JSBI.BigInt(0);
11371147
}
11381148

11391149
let v = this.cohort() as Rational;

0 commit comments

Comments
 (0)