MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / bigint

Function bigint

src/compute-engine/numerics/bigint.ts:3–69  ·  view source on GitHub ↗
(
  a: BigDecimal | number | bigint | string
)

Source from the content-addressed store, hash-verified

1import { BigDecimal } from '../../big-decimal/index.js';
2
3export function bigint(
4 a: BigDecimal | number | bigint | string
5): bigint | null {
6 if (typeof a === 'bigint') return a;
7
8 if (typeof a === 'number') {
9 if (!Number.isInteger(a)) return null;
10 // `BigInt(a)` is exact for any integer-valued double, including those
11 // beyond MAX_SAFE_INTEGER (it returns the exact integer the double stores).
12 // The previous guard `a >= MAX && a <= MAX` was only true at exactly MAX,
13 // so every other integer fell through to `bigint(a.toString())` — which
14 // fails for large values, since `(2.46e100).toString()` is `"2.46e+100"`
15 // (a decimal mantissa the string parser rejects) → `null`.
16 return BigInt(a);
17 }
18
19 // Recognize a BigDecimal — including one constructed in a *different* bundle,
20 // whose class object differs from ours so `instanceof` returns false. The
21 // opt-in `integration-rules` plugin re-bundles `big-decimal`, so a BigDecimal
22 // carried by a host-engine expression is a genuine BigDecimal that would fail
23 // the `instanceof` check and then crash on `.toLowerCase` below. Duck-type it.
24 if (
25 a instanceof BigDecimal ||
26 (typeof a === 'object' &&
27 a !== null &&
28 typeof (a as any).isInteger === 'function' &&
29 typeof (a as any).toFixed === 'function')
30 ) {
31 const bd = a as BigDecimal;
32 if (!bd.isInteger()) return null;
33 // Use toFixed(0) to get the full integer representation without
34 // scientific notation (which would have a decimal point like "3.14e+10")
35 return BigInt(bd.toFixed(0));
36 }
37
38 // Anything that is not a string here (e.g. a foreign object we don't
39 // recognize) has no exact-integer reading — don't crash on `.toLowerCase`.
40 if (typeof a !== 'string') return null;
41
42 let s = a.toLowerCase();
43
44 // BigInt constructor does not deal well with e.g. `1e30`
45 // Only convert to bigint if there's NO decimal point - a decimal point
46 // indicates an approximate value, not an exact integer
47 const m = s.match(/^([+-]?[0-9]+)e([+-]?[0-9]+)$/);
48 if (m) {
49 // Group 1 is the integer part (no decimal point)
50 // Group 2 is the exponent
51 const exp = parseInt(m[2]);
52 if (exp < 0) return null;
53 // Materializing the integer appends `exp` zero digits. Guard against
54 // exponents so large the digit string cannot be allocated (`'0'.repeat`
55 // throws `RangeError: Invalid string length`). A 1M-digit integer still
56 // works today and stays supported; anything larger has no exact reading
57 // here, so bail like the `exp < 0` case (the caller falls back to a float).
58 if (exp > 1_000_000) return null;
59 s = m[1] + '0'.repeat(exp);
60 }

Callers 15

_numericValueMethod · 0.90
isSameMethod · 0.90
canonicalNumberStringFunction · 0.90
canonicalDivideFunction · 0.90
asRationalFunction · 0.90
asBigintFunction · 0.90
toBigintFunction · 0.90
bigPrimeFactorsFunction · 0.90
bigintValueFunction · 0.90
canonicalIntegerFunction · 0.90
asExactMethod · 0.90

Calls 4

toFixedMethod · 0.80
matchMethod · 0.65
errorMethod · 0.65
isIntegerMethod · 0.45

Tested by

no test coverage detected