From 5e89c567d2aa0194408a438366e0af2b29268c36 Mon Sep 17 00:00:00 2001 From: fang Date: Tue, 26 Mar 2024 17:21:09 +0100 Subject: [PATCH 1/4] bigint: use native bigint instead of big-integer To make it easier for our libraries to be used together, we are doing a pass over them, standardizing on using native bigint for big numbers. Nock-js already uses these. This library should follow. This commit updates all aura-js library code to use native bigints, and removed the big-integer dependency altogether. --- README.md | 28 +++---- package-lock.json | 18 ---- package.json | 3 - src/da.ts | 204 +++++++++++++++++++++++----------------------- src/hoon/index.ts | 19 ++--- src/hoon/muk.ts | 17 ++-- src/hoon/ob.ts | 126 +++++++++++++--------------- src/p.ts | 66 +++++++-------- src/q.ts | 21 +++-- src/ud.ts | 11 ++- src/uv.ts | 18 ++-- src/uw.ts | 16 ++-- test/aura.test.ts | 47 ++++++----- tsconfig.json | 3 +- 14 files changed, 274 insertions(+), 323 deletions(-) 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..05610d5 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,6 @@ "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", 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..c655527 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; //TODO 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..5db0e15 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], //TODO 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" } } From 5ce2eedd4503e651a73f504d9910a419d5d8abfc Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 27 Mar 2024 19:21:26 +0100 Subject: [PATCH 2/4] lint: remove A fair chunk of the stuff it's throwing errors on right now is made worse by its suggestions. We could tweak it until it's good, but, not very many people working on this repo right now, and we can always police egregious style mishaps in PR review. --- .github/workflows/main.yml | 5 +---- package.json | 8 -------- 2 files changed, 1 insertion(+), 12 deletions(-) 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/package.json b/package.json index 05610d5..7951094 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "start": "dts watch", "build": "dts build", "test": "dts test", - "lint": "dts lint", "prepare": "dts build", "size": "size-limit", "analyze": "size-limit --why" @@ -43,13 +42,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", From 73d4415126cddfd600bc0649bc07199bcf83117f Mon Sep 17 00:00:00 2001 From: fang Date: Tue, 16 Apr 2024 18:03:21 +0200 Subject: [PATCH 3/4] remove stale todo's --- src/uv.ts | 2 +- test/aura.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uv.ts b/src/uv.ts index c655527..c0d38db 100644 --- a/src/uv.ts +++ b/src/uv.ts @@ -3,7 +3,7 @@ import { chunkFromRight } from './utils'; const uvAlphabet = '0123456789abcdefghijklmnopqrstuv'; export function parseUv(x: string) { - let res = 0n; //TODO 0n + let res = 0n; x = x.slice(2); while (x !== '') { if (x[0] !== '.') { diff --git a/test/aura.test.ts b/test/aura.test.ts index 5db0e15..4d976d7 100644 --- a/test/aura.test.ts +++ b/test/aura.test.ts @@ -94,7 +94,7 @@ describe('@uw', () => { }); const UV_PAIRS: [string, bigint][] = [ - ['0v16i', 1234n], //TODO 1234n + ['0v16i', 1234n], [ '0v1d0.l2h7n.mo1ro.s3r8e.4f6gd.dfsp1.hc5en.a0k8j.1v7vk.16jqd.oog39.5ool7.mrkdp.vvofi.gd2d6.vnmi9.a1dlt.7lbbm.iq76k.u5ivc.pp8qa', BigInt( From 38d44551aa431b4ac2dcc6bd4387c3ae305afd36 Mon Sep 17 00:00:00 2001 From: fang Date: Tue, 16 Apr 2024 18:03:29 +0200 Subject: [PATCH 4/4] package: v2.0.0 --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 7951094..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",