diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 42fcfff..42090c2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,7 +2,7 @@ name: CI on: [push] jobs: build: - name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }} + name: Build and test on Node ${{ matrix.node }} and ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: @@ -22,9 +22,6 @@ jobs: - name: Install deps and build (with cache) uses: bahmutov/npm-install@v1 - - name: Lint - run: yarn lint - - name: Test run: yarn test --ci --coverage --maxWorkers=2 diff --git a/README.md b/README.md index 148aba6..4277faf 100644 --- a/README.md +++ b/README.md @@ -6,19 +6,19 @@ This NPM package is intended to ease the flow of developing FE applications for ```typescript // @da manipulation -function parseDa(da: string): BigInteger; -function formatDa(da: BigInteger): string; +function parseDa(da: string): bigint; +function formatDa(da: bigint): string; // Given a bigint representing an urbit date, returns a unix timestamp. -function daToUnix(da: BigInteger): number; +function daToUnix(da: bigint): number; // Given a unix timestamp, returns a bigint representing an urbit date -function unixToDa(unix: number): BigInteger; +function unixToDa(unix: number): bigint; // @p manipulation // Convert a number to a @p-encoded string. -function patp(arg: string | number | BigInteger): string; +function patp(arg: string | number | bigint): string; function hex2patp(hex: string): string; function patp2hex(name: string): string; -function patp2bn(name: string): BigInteger; +function patp2bn(name: string): bigint; function patp2dec(name: string): string; // Determine the ship class of a @p value. function clan(who: string): string; @@ -35,10 +35,10 @@ function cite(ship: string): string | null; // @q manipulation // Convert a number to a @q-encoded string. -function patq(arg: string | number | BigInteger): string; +function patq(arg: string | number | bigint): string; function hex2patq(arg: string): string; function patq2hex(name: string): string; -function patq2bn(name: string): BigInteger; +function patq2bn(name: string): bigint; function patq2dec(name: string): string; // Validate a @q string. function isValidPatq(str: string): boolean; @@ -46,16 +46,16 @@ function isValidPatq(str: string): boolean; function eqPatq(p: string, q: string): boolean; // @ud manipulation -function parseUd(ud: string): BigInteger; -function formatUd(ud: BigInteger): string; +function parseUd(ud: string): bigint; +function formatUd(ud: bigint): string; // @uv manipulation -function parseUv(x: string): BigInteger; -function formatUv(x: BigInteger | string): string; +function parseUv(x: string): bigint; +function formatUv(x: bigint | string): string; // @uw manipulation -function parseUw(x: string): BigInteger; -function formatUw(x: BigInteger | string): string; +function parseUw(x: string): bigint; +function formatUw(x: bigint | string): string; // @ux manipulation function parseUx(ux: string): string; diff --git a/package-lock.json b/package-lock.json index 668d10e..b800e41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,6 @@ "engines": { "node": ">=16", "npm": ">=8" - }, - "peerDependencies": { - "big-integer": "^1.6.51" } }, "node_modules/@ampproject/remapping": { @@ -3996,15 +3993,6 @@ } ] }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "peer": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -13665,12 +13653,6 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "peer": true - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", diff --git a/package.json b/package.json index df67423..ec86eb9 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { - "version": "1.0.0", + "version": "2.0.0", "license": "MIT", "name": "@urbit/aura", - "author": "Liam Fitzgerald", "module": "dist/aura.esm.js", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -21,14 +20,10 @@ "start": "dts watch", "build": "dts build", "test": "dts test", - "lint": "dts lint", "prepare": "dts build", "size": "size-limit", "analyze": "size-limit --why" }, - "peerDependencies": { - "big-integer": "^1.6.51" - }, "devDependencies": { "@size-limit/preset-small-lib": "^8.2.4", "@tsconfig/recommended": "^1.0.2", @@ -46,13 +41,6 @@ "pre-commit": "dts lint" } }, - "prettier": { - "printWidth": 80, - "semi": true, - "singleQuote": true, - "trailingComma": "es5", - "endOfLine": "auto" - }, "size-limit": [ { "path": "dist/aura.cjs.production.min.js", diff --git a/src/da.ts b/src/da.ts index d48b32d..c337aa8 100644 --- a/src/da.ts +++ b/src/da.ts @@ -1,132 +1,132 @@ -import bigInt, { BigInteger } from 'big-integer'; interface Dat { pos: boolean; - year: BigInteger; - month: BigInteger; + year: bigint; + month: bigint; time: Tarp; } interface Tarp { - day: BigInteger; - hour: BigInteger; - minute: BigInteger; - second: BigInteger; - ms: BigInteger[]; + day: bigint; + hour: bigint; + minute: bigint; + second: bigint; + ms: bigint[]; } -const DA_UNIX_EPOCH = bigInt('170141184475152167957503069145530368000'); // `@ud` ~1970.1.1 +const DA_UNIX_EPOCH = BigInt('170141184475152167957503069145530368000'); // `@ud` ~1970.1.1 -const DA_SECOND = bigInt('18446744073709551616'); // `@ud` ~s1 +const DA_SECOND = BigInt('18446744073709551616'); // `@ud` ~s1 -const EPOCH = bigInt('292277024400'); -const zero = bigInt.zero; +const EPOCH = BigInt('292277024400'); -function isLeapYear(year: BigInteger) { - return year.mod(4).eq(zero) && (year.mod(100).neq(0) || year.mod(400).eq(0)); +function isLeapYear(year: bigint) { + return (year % 4n) === 0n + && (year % 100n) !== 0n + || (year % 400n) === 0n; } const MOH_YO = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const MOY_YO = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; -const DAY_YO = bigInt(86400); -const HOR_YO = bigInt(3600); -const MIT_YO = bigInt(60); -const ERA_YO = bigInt(146097); -const CET_YO = bigInt(36524); +const DAY_YO = 86400n; +const HOR_YO = 3600n; +const MIT_YO = 60n; +const ERA_YO = 146097n; +const CET_YO = 36524n; export function year(det: Dat) { const yer = det.pos - ? EPOCH.add(bigInt(det.year)) - : EPOCH.subtract(bigInt(det.year).prev()); + ? EPOCH + (BigInt(det.year)) + : EPOCH - (BigInt(det.year) - 1n); const day = (() => { let cah = isLeapYear(yer) ? MOY_YO : MOH_YO; - let d = det.time.day.prev(); - let m = det.month.prev(); - while (m.neq(0)) { + let d = det.time.day - 1n; + let m = det.month - 1n; + while (m !== 0n) { const [first, ...rest] = cah; - d = d.add(bigInt(first)); - m = m.prev(); + d = d + BigInt(first); + m = m - 1n; cah = rest; } let loop: boolean = true; let y = yer; while (loop == true) { - if (y.mod(4).neq(zero)) { - y = y.minus(1); - d = d.add(isLeapYear(y) ? 366 : 365); - } else if (y.mod(100).neq(zero)) { - y = y.minus(bigInt(4)); - d = d.add(isLeapYear(y) ? 1461 : 1460); - } else if (y.mod(400).neq(zero)) { - y = y.minus(bigInt(100)); - d = d.add(isLeapYear(y) ? 36525 : 36524); + if ((y % 4n) !== 0n) { + y = y - 1n; + d = d + (isLeapYear(y) ? 366n : 365n); + } else if ((y % 100n) !== 0n) { + y = y - 4n; + d = d + (isLeapYear(y) ? 1461n : 1460n); + } else if ((y % 400n) !== 0n) { + y = y - 100n; + d = d + (isLeapYear(y) ? 36525n : 36524n); } else { - let eras = y.divide(bigInt(400)); - d = d.add(eras.multiply(bigInt(4).multiply(bigInt(36524)).next())); + let eras = y / 400n; + d = d + (eras * (4n * 36524n + 1n)); loop = false; } } return d; })(); - let sec = bigInt(det.time.second) - .add(DAY_YO.multiply(day)) - .add(HOR_YO.multiply(bigInt(det.time.hour))) - .add(MIT_YO.multiply(bigInt(det.time.minute))); + let sec = BigInt(det.time.second) + + (DAY_YO * day) + + (HOR_YO * BigInt(det.time.hour)) + + (MIT_YO * BigInt(det.time.minute)); let ms = det.time.ms; - let fac = bigInt.zero; + let fac = 0n; let muc = 3; while (ms.length !== 0) { const [first, ...rest] = ms; - fac = fac.add(first.shiftLeft(bigInt(16 * muc))); + fac = fac + (first << BigInt(16 * muc)); ms = rest; muc -= 1; } - return fac.or(sec.shiftLeft(64)); + return fac | (sec << 64n); } /** * Given a string formatted as a @da, returns a bigint representing the urbit date. * * @return {string} x The formatted @da - * @return {BigInteger} x The urbit date as bigint + * @return {bigint} x The urbit date as bigint */ -export function parseDa(x: string): BigInteger { +export function parseDa(x: string): bigint { const [date, time, ms] = x.split('..'); const [yer, month, day] = date.slice(1).split('.'); const [hour, minute, sec] = time.split('.'); - const millis = ms.split('.').map((m) => bigInt(m, 16)); + const millis = ms.split('.').map((m) => BigInt('0x'+m)); return year({ pos: true, - year: bigInt(yer, 10), - month: bigInt(month, 10), + year: BigInt(yer), + month: BigInt(month), time: { - day: bigInt(day, 10), - hour: bigInt(hour, 10), - minute: bigInt(minute, 10), - second: bigInt(sec, 10), + day: BigInt(day), + hour: BigInt(hour), + minute: BigInt(minute), + second: BigInt(sec), ms: millis, }, }); } -function yell(x: BigInteger): Tarp { - let sec = x.shiftRight(64); - const milliMask = bigInt('ffffffffffffffff', 16); - const millis = milliMask.and(x); +function yell(x: bigint): Tarp { + let sec = x >> 64n; + const milliMask = BigInt('0xffffffffffffffff'); + const millis = milliMask & x; const ms = millis .toString(16) .match(/.{1,4}/g)! .filter((x) => x !== '0000') - .map((x) => bigInt(x, 16)); - let day = sec.divide(DAY_YO); - sec = sec.mod(DAY_YO); - let hor = sec.divide(HOR_YO); - sec = sec.mod(HOR_YO); - let mit = sec.divide(MIT_YO); - sec = sec.mod(MIT_YO); + .map((x) => BigInt('0x'+x)); + let day = sec / DAY_YO; + sec = sec % DAY_YO; + let hor = sec / HOR_YO; + sec = sec % HOR_YO; + let mit = sec / MIT_YO; + sec = sec % MIT_YO; return { ms, @@ -137,53 +137,53 @@ function yell(x: BigInteger): Tarp { }; } -function yall(day: BigInteger): [BigInteger, BigInteger, BigInteger] { - let era = zero; - let cet = zero; +function yall(day: bigint): [bigint, bigint, bigint] { + let era = 0n; + let cet = 0n; let lep = false; - era = day.divide(ERA_YO); - day = day.mod(ERA_YO); - if (day.lt(CET_YO.next())) { + era = day / ERA_YO; + day = day % ERA_YO; + if (day < (CET_YO + 1n)) { lep = true; } else { lep = false; - cet = bigInt(1); - day = day.minus(CET_YO.next()); - cet = cet.add(day.divide(CET_YO)); - day = day.mod(CET_YO); + cet = 1n; + day = day - (CET_YO + 1n); + cet = cet + (day / CET_YO); + day = day % CET_YO; } - let yer = era.multiply(400).add(cet.multiply(100)); + let yer = (era * 400n) + (cet * 100n); let loop = true; while (loop == true) { - let dis = lep ? 366 : 365; - if (!day.lt(dis)) { - yer = yer.next(); - day = day.minus(dis); - lep = yer.mod(4).eq(0); + let dis = lep ? 366n : 365n; + if (!(day < dis)) { + yer = yer + 1n; + day = day - dis; + lep = (yer % 4n) === 0n; } else { loop = false; let inner = true; - let mot = zero; + let mot = 0n; while (inner) { let cah = lep ? MOY_YO : MOH_YO; - let zis = cah[mot.toJSNumber()]; - if (day.lt(zis)) { - return [yer, mot.next(), day.next()]; + let zis = BigInt(cah[Number(mot)]); + if (day < zis) { + return [yer, mot + 1n, day + 1n]; } - mot = mot.next(); - day = day.minus(zis); + mot = mot + 1n; + day = day - zis; } } } - return [zero, zero, zero]; + return [0n, 0n, 0n]; } -function yore(x: BigInteger): Dat { +function yore(x: bigint): Dat { const time = yell(x); const [y, month, d] = yall(time.day); time.day = d; - const pos = y.gt(EPOCH); - const year = pos ? y.minus(EPOCH) : EPOCH.minus(y).next(); + const pos = y > EPOCH; + const year = pos ? y - EPOCH : EPOCH + 1n - y; return { pos, @@ -196,12 +196,12 @@ function yore(x: BigInteger): Dat { /** * Given a bigint representing an urbit date, returns a string formatted as a proper @da. * - * @param {BigInteger} x The urbit date as bigint + * @param {bigint} x The urbit date as bigint * @return {string} The formatted @da */ -export function formatDa(x: BigInteger | string) { +export function formatDa(x: bigint | string) { if (typeof x === 'string') { - x = bigInt(x); + x = BigInt(x); } const { year, month, time } = yore(x); @@ -213,16 +213,16 @@ export function formatDa(x: BigInteger | string) { /** * Given a bigint representing an urbit date, returns a unix timestamp. * - * @param {BigInteger} da The urbit date + * @param {bigint} da The urbit date * @return {number} The unix timestamp */ -export function daToUnix(da: BigInteger): number { +export function daToUnix(da: bigint): number { // ported from +time:enjs:format in hoon.hoon - const offset = DA_SECOND.divide(bigInt(2000)); - const epochAdjusted = offset.add(da.subtract(DA_UNIX_EPOCH)); + const offset = DA_SECOND / 2000n; + const epochAdjusted = offset + (da - DA_UNIX_EPOCH); return Math.round( - epochAdjusted.multiply(bigInt(1000)).divide(DA_SECOND).toJSNumber() + Number(epochAdjusted * 1000n / DA_SECOND) ); } @@ -230,9 +230,9 @@ export function daToUnix(da: BigInteger): number { * Given a unix timestamp, returns a bigint representing an urbit date * * @param {number} unix The unix timestamp - * @return {BigInteger} The urbit date + * @return {bigint} The urbit date */ -export function unixToDa(unix: number): BigInteger { - const timeSinceEpoch = bigInt(unix).multiply(DA_SECOND).divide(bigInt(1000)); - return DA_UNIX_EPOCH.add(timeSinceEpoch); +export function unixToDa(unix: number): bigint { + const timeSinceEpoch = BigInt(unix) * DA_SECOND / 1000n; + return DA_UNIX_EPOCH + timeSinceEpoch; } diff --git a/src/hoon/index.ts b/src/hoon/index.ts index b265726..2bb0359 100644 --- a/src/hoon/index.ts +++ b/src/hoon/index.ts @@ -1,8 +1,3 @@ -import bigInt, { BigInteger } from 'big-integer'; - -const zero = bigInt(0); -const one = bigInt(1); -const two = bigInt(2); export const pre = ` dozmarbinwansamlitsighidfidlissogdirwacsabwissib\ @@ -45,16 +40,16 @@ lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\ export const prefixes = pre.match(/.{1,3}/g) as RegExpMatchArray; export const suffixes = suf.match(/.{1,3}/g) as RegExpMatchArray; -export const bex = (n: BigInteger) => two.pow(n); +export const bex = (n: bigint) => 2n ** n; -export const rsh = (a: BigInteger, b: BigInteger, c: BigInteger) => - c.divide(bex(bex(a).multiply(b))); +export const rsh = (a: bigint, b: bigint, c: bigint) => + c / bex(bex(a) * b); -export const met = (a: BigInteger, b: BigInteger, c = zero): BigInteger => - b.eq(zero) ? c : met(a, rsh(a, one, b), c.add(one)); +export const met = (a: bigint, b: bigint, c = 0n): bigint => + (b === 0n) ? c : met(a, rsh(a, 1n, b), c + 1n); -export const end = (a: BigInteger, b: BigInteger, c: BigInteger) => - c.mod(bex(bex(a).multiply(b))); +export const end = (a: bigint, b: bigint, c: bigint) => + c % bex(bex(a) * b); export const patp2syls = (name: string): string[] => name.replace(/[\^~-]/g, '').match(/.{1,3}/g) || []; diff --git a/src/hoon/muk.ts b/src/hoon/muk.ts index 5fe5024..04a830f 100644 --- a/src/hoon/muk.ts +++ b/src/hoon/muk.ts @@ -1,25 +1,20 @@ -import bigInt, { BigInteger } from 'big-integer'; // ++ muk // // See arvo/sys/hoon.hoon. -const ux_FF = bigInt(0xff); -const ux_FF00 = bigInt(0xff00); -const u_256 = bigInt(256); - /** * Standard murmur3. * * @param {Number} syd * @param {Number} len - * @param {BigInteger} key - * @return {BigInteger} + * @param {bigint} key + * @return {bigint} */ -export const muk = (syd: number, key: BigInteger) => { - const lo = key.and(ux_FF).toJSNumber(); - const hi = key.and(ux_FF00).divide(u_256).toJSNumber(); +export const muk = (syd: number, key: bigint): bigint => { + const lo = Number(key & 0xffn); + const hi = Number((key & 0xff00n) / 256n); const kee = String.fromCharCode(lo) + String.fromCharCode(hi); - return bigInt(murmurhash3_32_gc(kee, syd)); + return BigInt(murmurhash3_32_gc(kee, syd)); }; // see: https://github.com/garycourt/murmurhash-js diff --git a/src/hoon/ob.ts b/src/hoon/ob.ts index ad6c097..4b43809 100644 --- a/src/hoon/ob.ts +++ b/src/hoon/ob.ts @@ -1,21 +1,11 @@ -import bigInt, { BigInteger } from 'big-integer'; import { muk } from './muk'; // ++ ob // // See arvo/sys/hoon.hoon. -const ux_1_0000 = bigInt('10000', 16); -const ux_ffff_ffff = bigInt('ffffffff', 16); -const ux_1_0000_0000 = bigInt('100000000', 16); -const ux_ffff_ffff_ffff_ffff = bigInt('ffffffffffffffff', 16); -const ux_ffff_ffff_0000_0000 = bigInt('ffffffff00000000', 16); - -const u_65535 = bigInt('65535'); -const u_65536 = bigInt('65536'); - // a PRF for j in { 0, .., 3 } -const F = (j: number, arg: BigInteger) => { +const F = (j: number, arg: bigint): bigint => { const raku = [0xb76d5eed, 0xee281300, 0x85bcae01, 0x4b387af7]; return muk(raku[j], arg); @@ -24,43 +14,43 @@ const F = (j: number, arg: BigInteger) => { /** * Conceal structure v3. * - * @param {String, Number, BigInteger} pyn - * @return {BigInteger} + * @param {String, Number, bigint} pyn + * @return {bigint} */ -const fein = (arg: any): BigInteger => { - const loop = (pyn: BigInteger): BigInteger => { - const lo = pyn.and(ux_ffff_ffff); - const hi = pyn.and(ux_ffff_ffff_0000_0000); - - return pyn.geq(ux_1_0000) && pyn.leq(ux_ffff_ffff) - ? ux_1_0000.add(feis(pyn.subtract(ux_1_0000))) - : pyn.geq(ux_1_0000_0000) && pyn.leq(ux_ffff_ffff_ffff_ffff) - ? hi.or(loop(lo)) +const fein = (arg: bigint): bigint => { + const loop = (pyn: bigint): bigint => { + const lo = pyn & 0xffffffffn; + const hi = pyn & 0xffffffff00000000n; + + return (pyn >= 0x10000n) && (pyn <= 0xffffffffn) + ? (0x10000n + feis(pyn - 0x10000n)) + : (pyn >= 0x100000000n) && (pyn <= 0xffffffffffffffffn) + ? (hi | loop(lo)) : pyn; }; - return loop(bigInt(arg)); + return loop(arg); }; /** * Restore structure v3. * - * @param {String, Number, BigInteger} cry - * @return {BN} + * @param {String, Number, bigint} cry + * @return {bigint} */ -const fynd = (arg: any) => { - const loop = (cry: BigInteger): BigInteger => { - const lo = cry.and(ux_ffff_ffff); - const hi = cry.and(ux_ffff_ffff_0000_0000); - - return cry.geq(ux_1_0000) && cry.leq(ux_ffff_ffff) - ? ux_1_0000.add(tail(cry.subtract(ux_1_0000))) - : cry.geq(ux_1_0000_0000) && cry.leq(ux_ffff_ffff_ffff_ffff) - ? hi.or(loop(lo)) +const fynd = (arg: bigint): bigint => { + const loop = (cry: bigint): bigint => { + const lo = cry & 0xffffffffn; + const hi = cry & 0xffffffff00000000n; + + return (cry >= 0x10000n) && (cry <= 0xffffffffn) + ? (0x10000n + tail(cry - 0x10000n)) + : (cry >= 0x100000000n) && (cry <= 0xffffffffffffffffn) + ? (hi | loop(lo)) : cry; }; - return loop(bigInt(arg)); + return loop(BigInt(arg)); }; /** @@ -71,49 +61,49 @@ const fynd = (arg: any) => { * Note that this has been adjusted from the reference paper in order to * support some legacy behaviour. * - * @param {String, Number, BigInteger} + * @param {String, Number, bigint} * @return {BN} */ -const feis = (arg: any) => - Fe(4, u_65535, u_65536, ux_ffff_ffff, F, bigInt(arg)); +const feis = (arg: bigint) => + Fe(4, 65535n, 65536n, 0xffffffffn, F, arg); const Fe = ( r: number, - a: BigInteger, - b: BigInteger, - k: BigInteger, + a: bigint, + b: bigint, + k: bigint, f: typeof F, - m: BigInteger + m: bigint ) => { const c = fe(r, a, b, f, m); - return c.lt(k) ? c : fe(r, a, b, f, c); + return (c < k) ? c : fe(r, a, b, f, c); }; const fe = ( r: number, - a: BigInteger, - b: BigInteger, + a: bigint, + b: bigint, f: typeof F, - m: BigInteger + m: bigint ) => { - const loop = (j: number, ell: BigInteger, arr: BigInteger): BigInteger => { + const loop = (j: number, ell: bigint, arr: bigint): bigint => { if (j > r) { return r % 2 !== 0 - ? a.multiply(arr).add(ell) - : arr.eq(a) - ? a.multiply(arr).add(ell) - : a.multiply(ell).add(arr); + ? (a * arr) + ell + : arr === a + ? (a * arr) + ell + : (a * ell) + arr; } else { - const eff = f(j - 1, arr); + const eff = BigInt(f(j - 1, arr).toString()); - const tmp = j % 2 !== 0 ? ell.add(eff).mod(a) : ell.add(eff).mod(b); + const tmp = j % 2 !== 0 ? ((ell + eff) % a) : ((ell + eff) % b); return loop(j + 1, arr, tmp); } }; - const L = m.mod(a); - const R = m.divide(a); + const L = m % a; + const R = m / a; return loop(1, L, R); }; @@ -126,21 +116,21 @@ const fe = ( * Note that this has been adjusted from the reference paper in order to * support some legacy behaviour. * - * @param {Number, String, BN} arg - * @return {BN} + * @param {bigint} arg + * @return {bigint} */ -const tail = (arg: any) => - Fen(4, u_65535, u_65536, ux_ffff_ffff, F, bigInt(arg)); +const tail = (arg: bigint) => + Fen(4, 65535n, 65536n, 0xffffffffn, F, arg); const Fen: typeof Fe = (r, a, b, k, f, m) => { const c = fen(r, a, b, f, m); - return c.lt(k) ? c : fen(r, a, b, f, c); + return (c < k) ? c : fen(r, a, b, f, c); }; const fen: typeof fe = (r, a, b, f, m) => { - const loop = (j: number, ell: BigInteger, arr: BigInteger): BigInteger => { + const loop = (j: number, ell: bigint, arr: bigint): bigint => { if (j < 1) { - return a.multiply(arr).add(ell); + return (a * arr) + ell; } else { const eff = f(j - 1, ell); @@ -152,20 +142,20 @@ const fen: typeof fe = (r, a, b, f, m) => { // const tmp = j % 2 !== 0 - ? arr.add(a).subtract(eff.mod(a)).mod(a) - : arr.add(b).subtract(eff.mod(b)).mod(b); + ? ((arr + a) - (eff % a)) % a + : ((arr + b) - (eff % b)) % b; return loop(j - 1, tmp, ell); } }; - const ahh = r % 2 !== 0 ? m.divide(a) : m.mod(a); + const ahh = r % 2 !== 0 ? (m / a) : (m % a); - const ale = r % 2 !== 0 ? m.mod(a) : m.divide(a); + const ale = r % 2 !== 0 ? (m % a) : (m / a); - const L = ale.eq(a) ? ahh : ale; + const L = ale === a ? ahh : ale; - const R = ale.eq(a) ? ale : ahh; + const R = ale === a ? ale : ahh; return loop(r, L, R); }; diff --git a/src/p.ts b/src/p.ts index ce05868..93934cb 100644 --- a/src/p.ts +++ b/src/p.ts @@ -1,4 +1,3 @@ -import bigInt, { BigInteger } from 'big-integer'; import { isValidPat, patp2syls, @@ -10,13 +9,6 @@ import { } from './hoon'; import ob from './hoon/ob'; -const zero = bigInt(0); -const one = bigInt(1); -const two = bigInt(2); -const three = bigInt(3); -const four = bigInt(4); -const five = bigInt(5); - /** * Convert a hex-encoded string to a @p-encoded string. * @@ -27,7 +19,7 @@ export function hex2patp(hex: string): string { if (hex === null) { throw new Error('hex2patp: null input'); } - return patp(bigInt(hex, 16)); + return patp(BigInt('0x'+hex)); } /** @@ -52,7 +44,7 @@ export function patp2hex(name: string): string { '' ); - const bn = bigInt(addr, 2); + const bn = BigInt('0b'+addr); const hex = ob.fynd(bn).toString(16); return hex.length % 2 !== 0 ? hex.padStart(hex.length + 1, '0') : hex; } @@ -61,10 +53,10 @@ export function patp2hex(name: string): string { * Convert a @p-encoded string to a bignum. * * @param {String} name @p - * @return {BigInteger} + * @return {bigint} */ -export function patp2bn(name: string): BigInteger { - return bigInt(patp2hex(name), 16); +export function patp2bn(name: string): bigint { + return BigInt('0x'+patp2hex(name)); } /** @@ -74,7 +66,7 @@ export function patp2bn(name: string): BigInteger { * @return {String} */ export function patp2dec(name: string): string { - let bn: BigInteger; + let bn: bigint; try { bn = patp2bn(name); } catch (_) { @@ -90,21 +82,21 @@ export function patp2dec(name: string): string { * @return {String} */ export function clan(who: string): string { - let name: BigInteger; + let name: bigint; try { name = patp2bn(who); } catch (_) { throw new Error('clan: not a valid @p'); } - const wid = met(three, name); - return wid.leq(one) + const wid = met(3n, name); + return wid <= 1n ? 'galaxy' - : wid.eq(two) + : wid === 2n ? 'star' - : wid.leq(four) + : wid <= 4n ? 'planet' - : wid.leq(bigInt(8)) + : wid <= 8n ? 'moon' : 'comet'; } @@ -116,7 +108,7 @@ export function clan(who: string): string { * @return {String} */ export function sein(name: string): string { - let who: BigInteger; + let who: bigint; try { who = patp2bn(name); } catch (_) { @@ -134,12 +126,12 @@ export function sein(name: string): string { mir === 'galaxy' ? who : mir === 'star' - ? end(three, one, who) + ? end(3n, 1n, who) : mir === 'planet' - ? end(four, one, who) + ? end(4n, 1n, who) : mir === 'moon' - ? end(five, one, who) - : zero; + ? end(5n, 1n, who) + : 0n; return patp(res); } @@ -156,33 +148,33 @@ export function isValidPatp(str: string): boolean { /** * Convert a number to a @p-encoded string. * - * @param {String, Number, BN} arg + * @param {String, Number, bigint} arg * @return {String} */ -export function patp(arg: string | number | BigInteger) { +export function patp(arg: string | number | bigint) { if (arg === null) { throw new Error('patp: null input'); } - const n = bigInt(arg as any); + const n = BigInt(arg); const sxz = ob.fein(n); - const dyy = met(four, sxz); + const dyy = met(4n, sxz); - function loop(tsxz: BigInteger, timp: BigInteger, trep: string): string { - const log = end(four, one, tsxz); - const pre = prefixes[rsh(three, one, log).toJSNumber()]; - const suf = suffixes[end(three, one, log).toJSNumber()]; - const etc = timp.mod(four).eq(zero) ? (timp.eq(zero) ? '' : '--') : '-'; + function loop(tsxz: bigint, timp: bigint, trep: string): string { + const log = end(4n, 1n, tsxz); + const pre = prefixes[Number(rsh(3n, 1n, log))]; + const suf = suffixes[Number(end(3n, 1n, log))]; + const etc = (timp % 4n) === 0n ? ((timp === 0n) ? '' : '--') : '-'; const res = pre + suf + etc + trep; - return timp.eq(dyy) ? trep : loop(rsh(four, one, tsxz), timp.add(one), res); + return timp === dyy ? trep : loop(BigInt(rsh(4n, 1n, tsxz).toString()), timp + 1n, res); } - const dyx = met(three, sxz); + const dyx = BigInt(met(3n, sxz).toString()); return ( - '~' + (dyx.leq(one) ? suffixes[sxz.toJSNumber()] : loop(sxz, zero, '')) + '~' + (dyx <= 1n ? suffixes[Number(sxz)] : loop(BigInt(sxz.toString()), 0n, '')) ); } diff --git a/src/q.ts b/src/q.ts index f91a3c1..53d2d0c 100644 --- a/src/q.ts +++ b/src/q.ts @@ -1,16 +1,21 @@ -import bigInt, { BigInteger } from 'big-integer'; import { isValidPat, prefixes, suffixes } from './hoon'; import { chunk, splitAt } from './utils'; +//TODO investigate whether native UintArrays are more portable +// than node Buffers + /** * Convert a number to a @q-encoded string. * - * @param {String, Number, BN} arg + * @param {String, Number, bigint} arg * @return {String} */ -export function patq(arg: string | number | BigInteger) { - const bn = bigInt(arg as any); - const buf = Buffer.from(bn.toArray(256).value); +export function patq(arg: string | number | bigint) { + const bn = BigInt(arg); + //NOTE stupid hack to work around bad node Buffer spec + const hex = bn.toString(16); + const lex = hex.length; + const buf = Buffer.from(hex.padStart(lex+lex%2, '0'), 'hex'); return buf2patq(buf); } @@ -89,9 +94,9 @@ export function patq2hex(name: string): string { * Convert a @q-encoded string to a bignum. * * @param {String} name @q - * @return {BigInteger} + * @return {bigint} */ -export const patq2bn = (name: string): BigInteger => bigInt(patq2hex(name), 16); +export const patq2bn = (name: string): bigint => BigInt('0x'+patq2hex(name)); /** * Convert a @q-encoded string to a decimal-encoded string. @@ -100,7 +105,7 @@ export const patq2bn = (name: string): BigInteger => bigInt(patq2hex(name), 16); * @return {String} */ export function patq2dec(name: string): string { - let bn: BigInteger; + let bn: bigint; try { bn = patq2bn(name); } catch (_) { diff --git a/src/ud.ts b/src/ud.ts index facbacd..6d06166 100644 --- a/src/ud.ts +++ b/src/ud.ts @@ -1,23 +1,22 @@ -import bigInt, { BigInteger } from 'big-integer'; import { chunk } from './utils'; /** * Given a string representing a @ud, returns a bigint * * @param {string} ud the number as @ud - * @return {BigInteger} the number as bigint + * @return {bigint} the number as bigint */ -export function parseUd(ud: string): BigInteger { - return bigInt(ud.replace(/\./g, '')); +export function parseUd(ud: string): bigint { + return BigInt(ud.replace(/\./g, '')); } /** * Given a bigint representing a @ud, returns a proper @ud as string * - * @param {BigInteger} ud the number as bigint + * @param {bigint} ud the number as bigint * @return {string} the number as @ud */ -export function formatUd(ud: BigInteger): string { +export function formatUd(ud: bigint): string { const transform = chunk(ud.toString().split('').reverse(), 3) .map((group) => group.reverse().join('')) .reverse() diff --git a/src/uv.ts b/src/uv.ts index 8e306bc..c0d38db 100644 --- a/src/uv.ts +++ b/src/uv.ts @@ -1,30 +1,28 @@ -import bigInt, { BigInteger } from 'big-integer'; import { chunkFromRight } from './utils'; -const uvMask = bigInt(31); const uvAlphabet = '0123456789abcdefghijklmnopqrstuv'; export function parseUv(x: string) { - let res = bigInt(0); + let res = 0n; x = x.slice(2); while (x !== '') { if (x[0] !== '.') { - res = res.shiftLeft(5).add(uvAlphabet.indexOf(x[0])); + res = (res << 5n) + BigInt(uvAlphabet.indexOf(x[0])); } x = x.slice(1); } return res; } -export function formatUv(x: BigInteger | string) { +export function formatUv(x: bigint | string) { if (typeof x === 'string') { - x = bigInt(x); + x = BigInt(x); } let res = ''; - while (x.neq(bigInt.zero)) { - let nextSix = x.and(uvMask).toJSNumber(); - res = uvAlphabet[nextSix] + res; - x = x.shiftRight(5); + while (x !== 0n) { + let nextFive = Number(BigInt.asUintN(5, x)); + res = uvAlphabet[nextFive] + res; + x = x >> 5n; } return `0v${chunkFromRight(res, 5).join('.')}`; } diff --git a/src/uw.ts b/src/uw.ts index 81a7e14..6a5017a 100644 --- a/src/uw.ts +++ b/src/uw.ts @@ -1,31 +1,29 @@ -import bigInt, { BigInteger } from 'big-integer'; import { chunkFromRight } from './utils'; -const uwMask = bigInt(63); const uwAlphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-~'; export function parseUw(x: string) { - let res = bigInt(0); + let res = 0n; x = x.slice(2); while (x !== '') { if (x[0] !== '.') { - res = res.shiftLeft(6).add(uwAlphabet.indexOf(x[0])); + res = (res << 6n) + BigInt(uwAlphabet.indexOf(x[0])); } x = x.slice(1); } return res; } -export function formatUw(x: BigInteger | string) { +export function formatUw(x: bigint | string) { if (typeof x === 'string') { - x = bigInt(x); + x = BigInt(x); } let res = ''; - while (x.neq(bigInt.zero)) { - let nextSix = x.and(uwMask).toJSNumber(); + while (x !== 0n) { + let nextSix = Number(BigInt.asUintN(6, x)); res = uwAlphabet[nextSix] + res; - x = x.shiftRight(6); + x = x >> 6n; } return `0w${chunkFromRight(res, 5).join('.')}`; } diff --git a/test/aura.test.ts b/test/aura.test.ts index f4179ff..4d976d7 100644 --- a/test/aura.test.ts +++ b/test/aura.test.ts @@ -10,16 +10,15 @@ import { parseUx, formatUx, } from '../src'; -import bigInt, { BigInteger } from 'big-integer'; -const DA_PAIRS: [string, BigInteger][] = [ +const DA_PAIRS: [string, bigint][] = [ [ '~2022.5.2..15.50.20..b4cb', - bigInt('170141184505617087925707667943685357568'), + BigInt('170141184505617087925707667943685357568'), ], [ '~2022.5.2..18.52.34..8166.240c.0635.b423', - bigInt('170141184505617289618704043249403016227'), + BigInt('170141184505617289618704043249403016227'), ], ]; describe('@da', () => { @@ -27,8 +26,8 @@ describe('@da', () => { describe(`case ${idx}`, () => { it('parses', () => { const res = parseDa(da); - const diff = integer.minus(res); - expect(diff.eq(bigInt.zero)).toBe(true); + const diff = integer - res; + expect(diff == 0n).toBe(true); }); it('formats', () => { const res = formatDa(integer); @@ -38,12 +37,12 @@ describe('@da', () => { }); }); -const UD_PAIRS: [string, BigInteger][] = [ - ['123', bigInt(123)], - ['7.827.527.286', bigInt(7827527286)], +const UD_PAIRS: [string, bigint][] = [ + ['123', 123n], + ['7.827.527.286', 7827527286n], [ '927.570.172.527.456.683.282.759.587.841.913.712.910.138.850.310.449.267.827.527.286', - bigInt('927570172527456683282759587841913712910138850310449267827527286'), + BigInt('927570172527456683282759587841913712910138850310449267827527286'), ], ]; @@ -52,8 +51,8 @@ describe('@ud', () => { describe(`case ${idx}`, () => { it('parses', () => { const res = parseUd(ud); - const diff = integer.minus(res); - expect(diff.eq(bigInt.zero)).toBe(true); + const diff = integer - res; + expect(diff === 0n).toBe(true); }); it('formats', () => { const res = formatUd(integer); @@ -63,17 +62,17 @@ describe('@ud', () => { }); }); -const UW_PAIRS: [string, BigInteger][] = [ - ['0wji', bigInt(1234)], +const UW_PAIRS: [string, bigint][] = [ + ['0wji', 1234n], [ '0w2.VNFPq.zLWXr.mHG98.cOSaU.jD-HK.WOAEW.icKX-.-UOti.RrLxM.BEdKI.U8j~T.rgqLe.HuVVm.m5aDi.FcUj0.z-9H9.PWYVS', - bigInt( + BigInt( '9729869760580312915057700420931106632029212932045019789366559593013069886734510969807231346927570172527456683282759587841913712910138850310449267827527286' ), ], [ '0w8.~wwXK.5Jbvq.EPFfs.mWqAa.G6VLL.Hp5RZ.1ztU0.OdjK6.rwC4f.IUflm.bew2G.q2V58.Yvb-y.8D7JP.mAX5-.tTUnZ.4PIzy.fU8eX.xriTS.GcWjT.5KCF2.GxKrX.WShtv.goTu0.czkXx.CU9x3.Xe3Rl.yPE0G.CwKhi.f7O~E.y9NXs.RFeNv.Dt-5~.hcX8U.z-23K.UmQJZ.GzeAZ.NrFGg.GErC-.-JAnn.Q6dTw.38ReU.pK2og.-PwZl.oIW0a.FEbAk.zNYLW.8ysuT.dqjIn.VTvxv.QjeOe', - bigInt( + BigInt( '338660688809191135992117047766620650717811482934943979674885003948246397791915632356127816874957444994283298782534439422236465196123969501940528462017413072176474702992911473379692926314882846435461316330442229390384286920909868601208813714735355172837223931275587957994082972971545840145432819726749971121524031459169847685770572005049993814978529576884322644499161452167351136603982630270130940863597682766057587354154988711969349941809951888309135835193470094' ), ], @@ -83,8 +82,8 @@ describe('@uw', () => { describe(`case ${idx}`, () => { it('parses', () => { const res = parseUw(uw); - const diff = integer.minus(res); - expect(diff.eq(bigInt.zero)).toBe(true); + const diff = integer - res; + expect(diff === 0n).toBe(true); }); it('formats', () => { const res = formatUw(integer); @@ -94,17 +93,17 @@ describe('@uw', () => { }); }); -const UV_PAIRS: [string, BigInteger][] = [ - ['0v16i', bigInt(1234)], +const UV_PAIRS: [string, bigint][] = [ + ['0v16i', 1234n], [ '0v1d0.l2h7n.mo1ro.s3r8e.4f6gd.dfsp1.hc5en.a0k8j.1v7vk.16jqd.oog39.5ool7.mrkdp.vvofi.gd2d6.vnmi9.a1dlt.7lbbm.iq76k.u5ivc.pp8qa', - bigInt( + BigInt( '4715838753694475992579249794985609354876653107513376869107585916141874120351297535898666953377988719385257642282348313095587079274499396365843215360500554' ), ], [ '0v1q7.2j1o2.gsrac.v0lr2.4qq3l.dl4dl.geimi.ti4kn.nerpk.io8e9.fb6u8.qdo3a.f6jnl.4t0ro.mnphj.45eu3.aasog.tgnop.mgknj.vrf7c.qh8uk.uhoko.e0k76.qj7o5.eoh6m.gtbd9.3dc3k.lknch.55trm.ud4m2.3ibqp.ni6je.0qjpk.tt978.6u5lu.ccp1b.ngqin.647c5.u6dk5.5svur.pr6ka.7l7ke.563g5.1pmkp.u1bm4.9lk7a.ra8rb.0t5d5.r499f.etnj9.5ggsi.umdsh.krg6k.ud7fa.9q1nh.dfj36.8ats6.klph1.r1fhj.d19f7.vmuep.l2ht9', - bigInt( + BigInt( '2192679466494434890472543084060582766548642415978526232232529756549132081077716901494847003622252677433111645469887112954835308752404322485369993198040597565692723588585723772692969275396046341198068016409658069930178326315327541379152850899800598824712189194725563892210423915200062671509436137248472305920263160462934628062386175666117414052493363024883656571948762124184585291750029792031534226654202512820124560651712985859227347538529179923696933418921183145' ), ], @@ -114,8 +113,8 @@ describe('@uv', () => { describe(`case ${idx}`, () => { it('parses', () => { const res = parseUv(uv); - const diff = integer.minus(res); - expect(diff.eq(bigInt.zero)).toBe(true); + const diff = integer - res; + expect(diff === 0n).toBe(true); }); it('formats', () => { const res = formatUv(integer); diff --git a/tsconfig.json b/tsconfig.json index cb030df..0b99bf5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "include": ["src", "types"], "compilerOptions": { "module": "esnext", - "moduleResolution": "nodenext" + "moduleResolution": "nodenext", + "target": "es2020" } }