xen-dev-utils
Version:
Utility functions used by the Scale Workshop ecosystem
201 lines • 6.18 kB
JavaScript
;
// Legacy implementations that need to be tsc compiled for fair benchmark comparison.
Object.defineProperty(exports, "__esModule", { value: true });
exports.toMonzoLegacy = toMonzoLegacy;
exports.primeLimitLegacy = primeLimitLegacy;
exports.toMonzoAndResidualLegacy = toMonzoAndResidualLegacy;
const fraction_1 = require("./fraction");
const monzo_1 = require("./monzo");
const primes_1 = require("./primes");
// Old implementation to test how the compiled package performs
function toMonzoLegacy(n) {
if (typeof n === 'bigint') {
return bigIntToMonzo(n);
}
if (typeof n !== 'number') {
n = new fraction_1.Fraction(n);
return (0, monzo_1.sub)(toMonzoLegacy(n.n), toMonzoLegacy(n.d));
}
if (n < 1 || Math.round(n) !== n) {
throw new Error(`Cannot convert number ${n} to monzo`);
}
if (n === 1) {
return [];
}
const result = [];
for (const prime of primes_1.PRIMES) {
let component = 0;
while (n % prime === 0) {
n /= prime;
component++;
}
result.push(component);
if (n === 1) {
break;
}
}
if (n !== 1) {
throw new Error('Out of primes');
}
return result;
}
function primeLimitLegacy(n, asOrdinal = false, maxLimit = 7919) {
if (typeof n === 'bigint') {
return bigIntPrimeLimit(n, asOrdinal, maxLimit);
}
if (typeof n !== 'number') {
n = new fraction_1.Fraction(n);
return Math.max(primeLimitLegacy(n.n, asOrdinal, maxLimit), primeLimitLegacy(n.d, asOrdinal, maxLimit));
}
if (n < 1 || Math.round(n) !== n) {
return NaN;
}
if (n === 1) {
return 1;
}
// Accumulate increasingly complex factors into the probe
// until it reaches the input value.
let probe = 1;
let limitIndex = 0;
if (n < 0x100000000) {
// Bit-magic for small 2-limit
while (!(n & 1)) {
n >>= 1;
}
if (n === 1) {
return 2;
}
limitIndex = 1;
}
while (true) {
const lastProbe = probe;
probe *= primes_1.PRIMES[limitIndex];
if (n % probe) {
probe = lastProbe;
limitIndex++;
if (limitIndex >= primes_1.PRIMES.length || primes_1.PRIMES[limitIndex] > maxLimit) {
return Infinity;
}
}
else if (n === probe) {
return primes_1.PRIMES[limitIndex];
}
}
}
// This was the current implementation at the time of writing. Re-printed here because we don't want to export it.
function bigIntToMonzo(n) {
if (n < 1n) {
throw new Error('Cannot convert non-positive big integer to monzo');
}
if (n === 1n) {
return [];
}
const result = [0];
// Accumulate increasingly complex factors into the probe
// until it reaches the input value.
let probe = 1n;
let limitIndex = 0;
while (true) {
const lastProbe = probe;
probe *= primes_1.BIG_INT_PRIMES[limitIndex];
if (n % probe) {
probe = lastProbe;
result.push(0);
limitIndex++;
if (limitIndex >= primes_1.BIG_INT_PRIMES.length) {
throw new Error('Out of primes');
}
}
else if (n === probe) {
result[limitIndex]++;
return result;
}
else {
result[limitIndex]++;
}
}
}
function bigIntPrimeLimit(n, asOrdinal, maxLimit) {
if (n < 1n) {
return NaN;
}
if (n === 1n) {
return asOrdinal ? 0 : 1;
}
// Accumulate increasingly complex factors into the probe
// until it reaches the input value.
// Bit-magic for 2-limit
let probe = (n ^ (n - 1n)) & n;
if (n === probe) {
return asOrdinal ? 1 : 2;
}
let limitIndex = 1;
while (true) {
const lastProbe = probe;
probe *= primes_1.BIG_INT_PRIMES[limitIndex];
if (n % probe) {
probe = lastProbe;
limitIndex++;
// Using non-big primes here is intentional, the arrays have the same length.
if (limitIndex >= primes_1.PRIMES.length || primes_1.PRIMES[limitIndex] > maxLimit) {
return Infinity;
}
}
else if (n === probe) {
return asOrdinal ? limitIndex + 1 : primes_1.PRIMES[limitIndex];
}
}
}
function toMonzoAndResidualLegacy(n, numberOfComponents) {
if (typeof n === 'bigint') {
return bigIntToMonzoAndResidualLegacy(n, numberOfComponents);
}
n = new fraction_1.Fraction(n);
const numerator = n.n;
const denominator = n.d;
if (!n.n) {
return [Array(numberOfComponents).fill(0), new fraction_1.Fraction(0)];
}
let nProbe = 1;
let dProbe = 1;
const result = Array(numberOfComponents).fill(-1);
for (let i = 0; i < numberOfComponents; ++i) {
let lastProbe;
do {
lastProbe = nProbe;
nProbe *= primes_1.PRIMES[i];
result[i]++;
} while (numerator % nProbe === 0);
nProbe = lastProbe;
// The fraction is in lowest terms so we know that positive components exclude negative components.
if (result[i]) {
continue;
}
result[i] = 1;
do {
lastProbe = dProbe;
dProbe *= primes_1.PRIMES[i];
result[i]--;
} while (denominator % dProbe === 0);
dProbe = lastProbe;
}
return [result, n.div(new fraction_1.Fraction(nProbe, dProbe))];
}
function bigIntToMonzoAndResidualLegacy(n, numberOfComponents) {
if (!n) {
return [Array(numberOfComponents).fill(0), 0n];
}
let probe = 1n;
const result = Array(numberOfComponents).fill(-1);
for (let i = 0; i < numberOfComponents; ++i) {
let lastProbe;
do {
lastProbe = probe;
probe *= primes_1.BIG_INT_PRIMES[i];
result[i]++;
} while (n % probe === 0n);
probe = lastProbe;
}
return [result, n / probe];
}
//# sourceMappingURL=legacy.js.map