functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
66 lines (65 loc) • 1.78 kB
JavaScript
import { abs, sign } from "../bigint/module.f.js";
const twoPow53 = 9007199254740992n;
const twoPow54 = 18014398509481984n;
const increaseMantissa = ([m, e]) => (min) => {
if (m === 0n) {
return [m, e];
}
const s = sign(m);
m = abs(m);
while (true) {
if (m >= min) {
return [BigInt(s) * m, e];
}
m = m << 1n;
e--;
}
};
const decreaseMantissa = ([m, e]) => (max) => {
if (m === 0n) {
return [m, e];
}
const s = sign(m);
m = abs(m);
while (true) {
if (m < max) {
return [BigInt(s) * m, e];
}
m = m >> 1n;
e++;
}
};
const pow = (base) => (exp) => base ** BigInt(exp);
const pow5 = pow(5n);
export const multiply = ([m, e]) => (mul) => [m * mul, e];
const divide = ([m, e]) => (div) => [[m / div, e], m % div];
const round53 = ([[m, e], r]) => {
const mabs = abs(m);
const s = BigInt(sign(m));
const [m54, e54] = decreaseMantissa([mabs, e])(twoPow54);
const o54 = m54 & 1n;
const m53 = m54 >> 1n;
const e53 = e54 + 1;
if (o54 === 1n && r === 0n && mabs === m54 >> BigInt(e - e54)) {
const odd = m53 & 1n;
return multiply([m53 + odd, e53])(s);
}
return multiply([m53 + o54, e53])(s);
};
export const decToBin = (dec) => {
if (dec[0] === 0n) {
return [0n, 0];
}
if (dec[1] >= 0) {
const bin = [dec[0] * pow5(dec[1]), dec[1]];
const inc = increaseMantissa(bin)(twoPow53);
return round53([inc, 0n]);
}
const p = pow5(-dec[1]);
const [m, e] = increaseMantissa(dec)(p * twoPow53);
const mAbs = abs(m);
const s = BigInt(sign(m));
const qr = divide([mAbs, e])(p);
const r53 = round53(qr);
return multiply(r53)(s);
};