UNPKG

xen-dev-utils

Version:

Utility functions used by the Scale Workshop ecosystem

201 lines 6.18 kB
"use strict"; // 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