jsadvent/lib/BNMath.js

127 lines
2.1 KiB
JavaScript

const toIntLookup = new Map(
Object.entries({
'0': 0n,
'1': 1n,
'2': 2n,
'3': 3n,
'4': 4n,
'5': 5n,
'6': 6n,
'7': 7n,
'8': 8n,
'9': 9n,
a: 10n,
A: 10n,
b: 11n,
B: 11n,
c: 12n,
C: 12n,
d: 13n,
D: 13n,
e: 14n,
E: 14n,
f: 15n,
F: 15n,
g: 16n,
G: 16n,
h: 17n,
H: 17n,
i: 18n,
I: 18n,
j: 19n,
J: 19n,
k: 20n,
K: 20n,
l: 21n,
L: 21n,
m: 22n,
M: 22n,
n: 23n,
N: 23n,
o: 24n,
O: 24n,
p: 25n,
P: 25n,
q: 26n,
Q: 26n,
r: 27n,
R: 27n,
s: 28n,
S: 28n,
t: 29n,
T: 29n,
u: 30n,
U: 30n,
v: 31n,
V: 31n,
w: 32n,
W: 32n,
x: 33n,
X: 33n,
y: 34n,
Y: 34n,
z: 35n,
Z: 35n,
}),
);
const BNMath = (module.exports = {
min(...nums) {
if (nums.length === 0) {
throw new Error('invalid arguments');
}
return nums.reduce((a, b) => (a < b ? a : b));
},
max(...nums) {
if (nums.length === 0) {
throw new Error('invalid arguments');
}
return nums.reduce((a, b) => (a > b ? a : b));
},
abs(num) {
if (num < 0n) {
return num * -1n;
}
return num;
},
sqrt(num) {
if (num < 0n) {
throw new Error('no sqrt of negative');
}
if (num <= 1n) {
return num;
}
let x0 = num >> 1n;
let x1 = (x0 + num / x0) >> 1n;
while (x1 < x0) {
x0 = x1;
x1 = (x0 + num / x0) >> 1n;
}
return x0;
},
// todo: implement longer string parsing, should be simple-ish to do with
// some looping and multiplication
parseInt(string, radix) {
if (string.length <= 10) {
return BigInt(parseInt(string, radix));
}
radix = BigInt(radix);
let result = 0n;
for (let i = 0; i < string.length; i++) {
const char = string[string.length - i - 1];
const num = toIntLookup.get(char);
if (num >= radix) {
console.log(char);
throw new Error('invalid');
}
result += num * radix ** i.n;
}
return result;
},
});