-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A POC that replaces all BigInt to JSBI.BigInt (#101)
- Loading branch information
Showing
11 changed files
with
161 additions
and
114 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,9 @@ | |
], | ||
"author": "Jesse Alama <[email protected]>", | ||
"license": "ISC", | ||
"dependencies": { | ||
"jsbi": "^4.3.0" | ||
}, | ||
"devDependencies": { | ||
"@rollup/plugin-typescript": "^12.1.1", | ||
"@types/jest": "^29.5.1", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
* @author Jesse Alama <[email protected]> | ||
*/ | ||
|
||
import JSBI from "jsbi"; | ||
|
||
import { | ||
RoundingMode, | ||
ROUNDING_MODES, | ||
|
@@ -28,7 +30,7 @@ const EXPONENT_MAX = 6111; | |
const NORMAL_EXPONENT_MAX = 6144; | ||
const MAX_SIGNIFICANT_DIGITS = 34; | ||
|
||
const bigTen = BigInt(10); | ||
const bigTen = JSBI.BigInt(10); | ||
|
||
type NaNValue = "NaN"; | ||
type InfiniteValue = "Infinity" | "-Infinity"; | ||
|
@@ -39,7 +41,7 @@ type Decimal128Value = NaNValue | InfiniteValue | FiniteValue; | |
const NAN = "NaN"; | ||
const POSITIVE_INFINITY = "Infinity"; | ||
const NEGATIVE_INFINITY = "-Infinity"; | ||
const TEN_MAX_EXPONENT = bigTen ** BigInt(MAX_SIGNIFICANT_DIGITS); | ||
const TEN_MAX_EXPONENT = JSBI.exponentiate(bigTen, JSBI.BigInt(MAX_SIGNIFICANT_DIGITS)); | ||
|
||
function pickQuantum( | ||
d: "0" | "-0" | Rational, | ||
|
@@ -80,7 +82,7 @@ function adjustDecimal128(d: Decimal): Decimal128Value { | |
|
||
let coef = d.coefficient(); | ||
|
||
if (coef <= TEN_MAX_EXPONENT && EXPONENT_MIN <= q && q <= EXPONENT_MAX) { | ||
if (JSBI.LE(coef, TEN_MAX_EXPONENT) && JSBI.LE(EXPONENT_MIN, q) && JSBI.LE(q, EXPONENT_MAX)) { | ||
return d; | ||
} | ||
|
||
|
@@ -166,10 +168,18 @@ export class Decimal128 { | |
private readonly _isFinite: boolean = true; | ||
private readonly _isNegative: boolean = false; | ||
|
||
constructor(n: string | number | bigint | Decimal) { | ||
constructor(n: string | number | bigint | JSBI | Decimal) { | ||
let data; | ||
if ("object" === typeof n) { | ||
data = n; | ||
if (n instanceof JSBI) { | ||
// Note: when using babel-plugin-transform-jsbi-to-bigint, | ||
// the condition above may get transpiled into "typeof n === 'bigint'", | ||
// causing the condition above to always be false. | ||
// This is fine as we will be hanlding bigint below. | ||
data = handleDecimalNotation(n.toString()) | ||
} else { | ||
data = n; | ||
} | ||
} else { | ||
let s: string; | ||
|
||
|
@@ -262,7 +272,7 @@ export class Decimal128 { | |
let decimalOne = new Decimal128("1"); | ||
let decimalTen = new Decimal128("10"); | ||
|
||
while (0 <= x.cmp(decimalTen)) { | ||
while (JSBI.LE(0, x.cmp(decimalTen))) { | ||
x = x.scale10(-1); | ||
} | ||
|
||
|
@@ -303,7 +313,7 @@ export class Decimal128 { | |
); | ||
} | ||
|
||
private coefficient(): bigint { | ||
private coefficient(): JSBI { | ||
let d = this.d as Decimal; | ||
return d.coefficient(); | ||
} | ||
|
@@ -463,7 +473,7 @@ export class Decimal128 { | |
|
||
let n = opts.digits; | ||
|
||
if (n <= 0) { | ||
if (JSBI.LE(n, 0)) { | ||
throw new RangeError("Argument must be positive"); | ||
} | ||
|
||
|
@@ -484,15 +494,15 @@ export class Decimal128 { | |
let [lhs, rhs] = s.split(/[.]/); | ||
let p = this.isNegative() ? "-" : ""; | ||
|
||
if (n <= lhs.length) { | ||
if (JSBI.LE(n, lhs.length)) { | ||
if (lhs.length === n) { | ||
return p + lhs; | ||
} | ||
|
||
return p + s.substring(0, n) + "e+" + `${lhs.length - n + 1}`; | ||
} | ||
|
||
if (n <= lhs.length + rhs.length) { | ||
if (JSBI.LE(n, lhs.length + rhs.length)) { | ||
let rounded = this.round(n - lhs.length); | ||
return rounded.emitDecimal(); | ||
} | ||
|
@@ -523,7 +533,7 @@ export class Decimal128 { | |
|
||
let n = opts.digits; | ||
|
||
if (n <= 0) { | ||
if (JSBI.LE(n, 0)) { | ||
throw new RangeError("Argument must be positive"); | ||
} | ||
|
||
|
@@ -539,7 +549,7 @@ export class Decimal128 { | |
|
||
let p = this.isNegative() ? "-" : ""; | ||
|
||
if (rhs.length <= n) { | ||
if (JSBI.LE(rhs.length, n)) { | ||
return p + lhs + "." + rhs + "0".repeat(n - rhs.length) + "e" + exp; | ||
} | ||
|
||
|
@@ -558,7 +568,7 @@ export class Decimal128 { | |
return !!rhs.match(/^0+$/); | ||
} | ||
|
||
toBigInt(): bigint { | ||
toBigInt(): JSBI { | ||
if (this.isNaN()) { | ||
throw new RangeError("NaN cannot be converted to a BigInt"); | ||
} | ||
|
@@ -573,7 +583,7 @@ export class Decimal128 { | |
); | ||
} | ||
|
||
return BigInt(this.toString()); | ||
return JSBI.BigInt(this.toString()); | ||
} | ||
|
||
toNumber(): number { | ||
|
@@ -931,34 +941,34 @@ export class Decimal128 { | |
let dividendCoefficient = this.coefficient(); | ||
let divisorCoefficient = x.coefficient(); | ||
|
||
if (dividendCoefficient !== 0n) { | ||
while (dividendCoefficient < divisorCoefficient) { | ||
dividendCoefficient = dividendCoefficient * 10n; | ||
if (JSBI.notEqual(dividendCoefficient, JSBI.BigInt(0))) { | ||
while (JSBI.LT(dividendCoefficient, divisorCoefficient)) { | ||
dividendCoefficient = JSBI.multiply(dividendCoefficient, JSBI.BigInt(10)); | ||
adjust++; | ||
} | ||
} | ||
|
||
while (dividendCoefficient > divisorCoefficient * 10n) { | ||
divisorCoefficient = divisorCoefficient * 10n; | ||
while (JSBI.GT(dividendCoefficient, JSBI.multiply(divisorCoefficient, JSBI.BigInt(10)))) { | ||
divisorCoefficient = JSBI.multiply(divisorCoefficient, JSBI.BigInt(10)); | ||
adjust--; | ||
} | ||
|
||
let resultCoefficient = 0n; | ||
let resultCoefficient = JSBI.BigInt(0); | ||
let done = false; | ||
|
||
while (!done) { | ||
while (divisorCoefficient <= dividendCoefficient) { | ||
dividendCoefficient = dividendCoefficient - divisorCoefficient; | ||
resultCoefficient++; | ||
while (JSBI.LE(divisorCoefficient, dividendCoefficient)) { | ||
dividendCoefficient = JSBI.subtract(dividendCoefficient, divisorCoefficient); | ||
resultCoefficient = JSBI.add(resultCoefficient, JSBI.BigInt(1)); | ||
} | ||
if ( | ||
(dividendCoefficient === 0n && adjust >= 0) || | ||
(JSBI.equal(dividendCoefficient, JSBI.BigInt(0)) && adjust >= 0) || | ||
resultCoefficient.toString().length > MAX_SIGNIFICANT_DIGITS | ||
) { | ||
done = true; | ||
} else { | ||
resultCoefficient = resultCoefficient * 10n; | ||
dividendCoefficient = dividendCoefficient * 10n; | ||
resultCoefficient = JSBI.multiply(resultCoefficient, JSBI.BigInt(10)); | ||
dividendCoefficient = JSBI.multiply(dividendCoefficient, JSBI.BigInt(10)); | ||
adjust++; | ||
} | ||
} | ||
|
@@ -1123,7 +1133,7 @@ export class Decimal128 { | |
return this.exponent(); | ||
} | ||
|
||
scaledSignificand(): bigint { | ||
scaledSignificand(): JSBI { | ||
if (this.isNaN()) { | ||
throw new RangeError("NaN does not have a scaled significand"); | ||
} | ||
|
@@ -1133,7 +1143,7 @@ export class Decimal128 { | |
} | ||
|
||
if (this.isZero()) { | ||
return 0n; | ||
return JSBI.BigInt(0); | ||
} | ||
|
||
let v = this.cohort() as Rational; | ||
|
Oops, something went wrong.