@tktb-tess/util-fns 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # tess-math-fns
2
+
3
+ 個人的に使う用の便利関数ライブラリ
package/dist/bundle.js ADDED
@@ -0,0 +1,2 @@
1
+ const n=(n,t)=>{if(n.length!==t.length)return!1;for(let r=0;r<n.length;r++)if(n[r]!==t[r])return!1;return!0},t=n=>new Promise(t=>{setTimeout(()=>{t()},n)}),r=n=>(...t)=>()=>n(...t),e=n=>{const t=[];let r=[],e="",o=!1;for(let i=0;i<n.length;i++){const s=n[i];'"'!==s||0!==i&&"\\"===n[i-1]?","!==s||o?"\n"!==s||o?e+=s:(r.push(e.trim()),t.push(r),r=[],e=""):(r.push(e.trim()),e=""):o=!o}return r.push(e.trim()),t.push(r),t},o=async(n,t)=>{const r=Buffer.from(n,"utf8");return crypto.subtle.digest(t,r).then(n=>Buffer.from(n))},i=n=>{let t=n.toString(16);return 1&t.length&&(t="0"+t),Buffer.from(t,"hex")},s=n=>{const t=n.toString("hex")||"00";return BigInt("0x"+t)},u=(n,t)=>Math.floor(Math.random()*(t-n)+n),f=(n,t)=>{const r=n%t;return r<0n?r+t:r},a=(...n)=>n.map(n=>BigInt(n)),g=(n,t=!1)=>{if(!Number.isFinite(n))throw Error("`length` is not a valid number");if(n<=0)throw Error("`length` must be positive");const r=Math.ceil(n/32),e=crypto.getRandomValues(new Uint32Array(r));let o=Array.from(e,n=>n.toString(2).padStart(32,"0")).join("");return o=o.slice(0,n),t&&(o=o.replace(/^./,"1")),BigInt("0b"+o)},h=(n,t)=>{if(n>=t)throw Error("RangeError");const r=t-n,e=r.toString(2).length;return n+(()=>{for(let n=0;n<1e5;n++){const n=g(e);if(n>=c(2n,BigInt(e),r))return n%r}throw Error("Failed to generate a random bigint")})()},c=(n,t,r)=>{if(r<1n)throw Error("`mod` must be positive");if(t<0n)throw Error("`power` must not be negative");for(;n<0n;)n+=r;if(1n===r)return 0n;if(n%r===1n||n%r===0n)return n;if(n===r-1n)return 1n&t?r-1n:1n;let e=1n;for(;t>0n;)1n&t&&(e=e*n%r),n=n*n%r,t>>=1n;return e},l=(n,t)=>{if(0n===n&&0n===t)return{x:0n,y:0n,gcd:0n};if(0n===n)return t>0n?{x:0n,y:-1n,gcd:t}:{x:0n,y:1n,gcd:-t};if(0n===t)return n>0n?{x:1n,y:0n,gcd:n}:{x:-1n,y:0n,gcd:-n};let[r,e,o]=[1n,0n,n],[i,s,u]=[0n,-1n,t];for(;;){const n=o/u,t=o-n*u;if(0n===t)break;[r,i]=[i,r-n*i],[e,s]=[s,e-n*s],[o,u]=[u,t]}return u<0n&&(i*=-1n,s*=-1n,u*=-1n),{x:i,y:s,gcd:u}},d=n=>{if(n<0n)throw Error("'n_' must be non-negative");if(0n===n)return 1n;const t=(n,r)=>{if(n>=r)return 1n;const e=(r-n)/2n;if(BigInt((r-2n).toString(2).length)*e<63n){let t=n;for(let e=n+2n;e<r;e+=2n)t*=e;return t}const o=n+e|1n;return t(n,o)*t(o,r)},r=n-BigInt(n.toString(2).match(/1/g)?.length??0),e=(n=>{let r=3n,e=1n,o=1n;for(let i=BigInt(n.toString(2).length)-1n-1n;i>-1n;--i){const s=1n+(n>>i)|1n;o*=t(r,s),r=s,e*=o}return e})(n);return e<<r},m=(n,t)=>BigInt.asUintN(32,n>>(31n&t)|n<<(31n&-t)),b=(n,t)=>n>>>(31&t)|n<<(31&-t),p=(n,t)=>{if(t<1n||t%2n==0n)throw Error("`n` is invalid");for(;n<0n;)n+=t;n%=t;let r=1n;for(;0n!==n;){for(;n%2n==0n;){n/=2n;const e=t%8n;3n!==e&&5n!==e||(r*=-1n)}[n,t]=[t,n],n%4n==3n&&t%4n==3n&&(r*=-1n),n%=t}return 1n===t?r:0n},w=n=>{if(n<0n)return!1;if(0n===n)return!0;let t=1n,r=n;for(;t+1n<r;){const e=(t+r)/2n;e**2n<n?t=e:r=e}return n===t**2n||n===(t+1n)**2n},y=[0x853c49e6748fea9bn,0xda3e39cb94b95bdbn];class B{#n=new BigUint64Array(2);get[Symbol.toStringTag](){return B.name}static getSeed(){return crypto.getRandomValues(new BigUint64Array(2))}constructor(n){n&&n[0]&&n[1]?(this.#n[1]=n[1]<<1n|1n,this.step(),this.#n[0]=n[0],this.step()):(this.#n[0]=y[0],this.#n[1]=y[1])}step(){this.#n[0]&&this.#n[1]&&(this.#n[0]=6364136223846793005n*this.#n[0]+this.#n[1])}get value(){const n=this.#n[0];if(!n)throw Error("empty state");const t=n>>59n,r=BigInt.asUintN(32,(n^n>>18n)>>27n);return b(Number(r),Number(t))}getRand(){return this.step(),this.value}getBoundedRand(n){const t=4294967296;if(n>t)throw Error("bound exceeded limit (2^32)");const r=t%n;for(;;){const t=this.getRand();if(t>=r)return t%n}}async*genRands(n,t){for(let r=0;r<n;r++)yield t?this.getBoundedRand(t):this.getRand()}}const E=(n,t)=>f(1n==(1n&n)?n+t>>1n:n>>1n,t),x=(n,t,r,e)=>{if(n%2n!=1n)throw Error("`n` must be odd");let o=n+1n,i=0n;for(;o%2n==0n;)o>>=1n,i+=1n;const[s,u]=((n,t,r,e)=>{let o=1n,i=r;const s=n.toString(2).slice(1);for(const n of s)[o,i]=[f(o*i,t),E(i*i+e*o*o,t)],"1"===n&&([o,i]=[E(r*o+i,t),E(e*o+r*i,t)]);return[o,i]})(o,n,r,t);let a=u;if(0n===s)return!0;e=c(e,o,n);for(let t=0n;t<i;t++){if(0n===a)return!0;a=f(a*a-2n*e,n),e=c(e,2n,n)}return!1},S=n=>{if(n<=1n)return!1;if(n%2n==0n)return 2n===n;const t=[2n,3n,5n,7n,11n,13n,17n,19n,23n,29n,31n,37n,41n,43n,47n,53n,59n,61n,67n,71n,73n,79n,83n,89n,97n,101n];for(const r of t)if(n%r===0n)return n===r;if(!(n=>{if(n<=1n)return!1;if(n%2n==0n)return 2n===n;let t=n-1n,r=0n;for(;t%2n==0n;)t>>=1n,r+=1n;const[e,o]=[t,r];let i=c(2n,e,n);if(1n===i)return!0;for(let t=0n;t<o;t++){if(i===n-1n)return!0;i=i*i%n}return!1})(n))return!1;const[r,e]=(n=>{let t=5n,r=p(t,n);for(;r>0n;){if(t=t>0n?t+2n:t-2n,t*=-1n,-15n===t&&w(n))return[0n,0n];r=p(t,n)}return[t,r]})(n);if(0n===e)return!1;return x(n,r,1n,(1n-r)/4n)},I=(n,t)=>{if(t<2n)throw Error("noPrimesFound");for(let r=0;r<1e5;r++){const r=h(n,t);if(S(r))return r}throw Error("noPrimesFound")},R=(n,t=!1)=>{if(n<2)throw Error("noPrimesFound");for(let r=0;r<1e5;r++){const r=g(n,t);if(S(r))return r}throw Error("noPrimesFound")};export{i as BItoBuffer,B as PCGMinimal,S as bailliePSW,s as bufferToBI,l as exEuclidean,d as factorial,o as getHash,g as getRandBIByBitLength,h as getRandBIByRange,R as getRandPrimeByBitLength,I as getRandPrimeByRange,u as getRndInt,n as isEqArray,w as isSquare,p as jacobiSymbol,r as lazify,c as modPow,e as parseCSV,f as residue,b as rot32,m as rot32BI,t as sleep,a as toBigInt};
2
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sources":["../src/util.ts","../src/math.ts","../src/pcg-minimal.ts","../src/baillie-psw.ts"],"sourcesContent":[null,null,null,null],"names":["isEqArray","arr1","arr2","length","i","sleep","delay","Promise","resolve","setTimeout","lazify","func","args","parseCSV","csv","rows","row","currentField","isInsideOfQuote","char","push","trim","getHash","async","str","algorithm","utf8","Buffer","from","crypto","subtle","digest","then","hash","BItoBuffer","n","toString","bufferToBI","buf","BigInt","getRndInt","min","max","Math","floor","random","residue","mod","ans","toBigInt","nums","map","getRandBIByBitLength","fixed","Number","isFinite","Error","div","ceil","u32Arr","getRandomValues","Uint32Array","result","Array","padStart","join","slice","replace","getRandBIByRange","diff","bitLength","res","modPow","base","power","exEuclidean","a","b","x","y","gcd","x_1","y_1","c_1","x_2","y_2","c_2","q","c_nxt","factorial","oddProd","num_odds","mid","two_exp","match","odd_part","L_i","tmp","U_i","oddPart","rot32BI","value","rot","asUintN","rot32","jacobiSymbol","nMod8","isSquare","initialState","PCGMinimal","state","BigUint64Array","Symbol","toStringTag","name","getSeed","constructor","seeds","this","step","prev","shifted","getRand","getBoundedRand","bound","limit","threshold","r","genRands","div2Mod","lucasSPP","D","P","Q","d","s","U","V_","k","V","digits","digit","UVSubscript","bailliePSW","smallPrimes","p","d_","s_","millerRabinAtBase2","j","DChooser","getRandPrimeByRange","count","getRandPrimeByBitLength"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Baillie-PSW素数判定法
3
+ * @param n 判定したい整数
4
+ * @returns
5
+ */
6
+ export declare const bailliePSW: (n: bigint) => boolean;
7
+ /**
8
+ * 指定範囲内の確率的素数を返す
9
+ * @param min 下限
10
+ * @param max 上限
11
+ * @returns
12
+ */
13
+ export declare const getRandPrimeByRange: (min: bigint, max: bigint) => bigint;
14
+ /**
15
+ * 指定ビットの確率的素数を返す
16
+ * @param bitLength ビット長
17
+ * @param fixed true: 固定長, false (デフォルト値): `length` ビット以下の可変ビット長
18
+ * @returns
19
+ */
20
+ export declare const getRandPrimeByBitLength: (bitLength: number, fixed?: boolean) => bigint;
21
+ //# sourceMappingURL=baillie-psw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baillie-psw.d.ts","sourceRoot":"","sources":["../../src/baillie-psw.ts"],"names":[],"mappings":"AAuIA;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,YAoDnC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAW3D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,WAAW,MAAM,EAAE,eAAa,WAWvE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { isEqArray, sleep, lazify, parseCSV, getHash, BItoBuffer, bufferToBI } from './util';
2
+ import { getRndInt, residue, toBigInt, getRandBIByBitLength, getRandBIByRange, modPow, exEuclidean, factorial, rot32, rot32BI, jacobiSymbol, isSquare } from './math';
3
+ import PCGMinimal from './pcg-minimal';
4
+ import { bailliePSW, getRandPrimeByBitLength, getRandPrimeByRange } from './baillie-psw';
5
+ export { isEqArray, sleep, lazify, parseCSV, getHash, BItoBuffer, bufferToBI, getRndInt, residue, toBigInt, getRandBIByBitLength, getRandBIByRange, modPow, exEuclidean, factorial, rot32, rot32BI, jacobiSymbol, isSquare, bailliePSW, getRandPrimeByBitLength, getRandPrimeByRange, PCGMinimal, };
6
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,UAAU,EACX,MAAM,QAAQ,CAAC;AAChB,OAAO,EACL,SAAS,EACT,OAAO,EACP,QAAQ,EACR,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,WAAW,EACX,SAAS,EACT,KAAK,EACL,OAAO,EACP,YAAY,EACZ,QAAQ,EACT,MAAM,QAAQ,CAAC;AAEhB,OAAO,UAAU,MAAM,eAAe,CAAC;AACvC,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAO,EACP,UAAU,EACV,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,WAAW,EACX,SAAS,EACT,KAAK,EACL,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,uBAAuB,EACvB,mBAAmB,EACnB,UAAU,GACX,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * min以上, max未満の整数を返す
3
+ * @param min
4
+ * @param max
5
+ * @returns 範囲内の整数乱数
6
+ */
7
+ export declare const getRndInt: (min: number, max: number) => number;
8
+ /**
9
+ * 剰余、ただし正の範囲の値を返す
10
+ * @param n
11
+ * @param mod
12
+ * @returns
13
+ */
14
+ export declare const residue: (n: bigint, mod: bigint) => bigint;
15
+ /**
16
+ * number を bigint に変換
17
+ * @param nums
18
+ * @returns
19
+ */
20
+ export declare const toBigInt: (...nums: number[]) => bigint[];
21
+ /**
22
+ * `length` ビットの乱数 or `length` ビット以下の乱数を出力する
23
+ * @param length ビット長
24
+ * @param fixed true: 固定長, false (デフォルト値): `length` ビット以下の可変ビット長
25
+ *
26
+ */
27
+ export declare const getRandBIByBitLength: (length: number, fixed?: boolean) => bigint;
28
+ /**
29
+ * `min` 以上 `max` 未満の乱数を返す
30
+ * @param min 下限
31
+ * @param max 上限
32
+ * @returns `min` 以上 `max` 未満の乱数
33
+ */
34
+ export declare const getRandBIByRange: (min: bigint, max: bigint) => bigint;
35
+ /**
36
+ * 冪剰余を計算する
37
+ * @param base 底
38
+ * @param power 指数
39
+ * @param mod 法
40
+ * @returns 冪剰余
41
+ */
42
+ export declare const modPow: (base: bigint, power: bigint, mod: bigint) => bigint;
43
+ /**
44
+ * 拡張ユークリッドの互除法 \
45
+ * 参考: https://qiita.com/angel_p_57/items/56a902cbd1fe519747bd
46
+ *
47
+ * @description `ax - by = gcd(a, b)`
48
+ * @param a
49
+ * @param b
50
+ * @returns `{x, y, gcd(a, b)}`
51
+ */
52
+ export declare const exEuclidean: (a: bigint, b: bigint) => {
53
+ x: bigint;
54
+ y: bigint;
55
+ gcd: bigint;
56
+ };
57
+ /**
58
+ * 階乗を計算する \
59
+ * 参考: https://qiita.com/AkariLuminous/items/1b2e964ebabde9419224
60
+ * @param n_ 整数
61
+ * @returns 引数の階乗
62
+ */
63
+ export declare const factorial: (n: bigint) => bigint;
64
+ /**
65
+ * 32ビット回転 (bigint)
66
+ * @param value 値
67
+ * @param rot 回転数
68
+ * @returns
69
+ */
70
+ export declare const rot32BI: (value: bigint, rot: bigint) => bigint;
71
+ /**
72
+ * 32ビット回転
73
+ * @param value 値
74
+ * @param rot 回転数
75
+ * @returns
76
+ */
77
+ export declare const rot32: (value: number, rot: number) => number;
78
+ /**
79
+ * ヤコビ記号
80
+ * @param a 正の整数
81
+ * @param n 正の奇数
82
+ */
83
+ export declare const jacobiSymbol: (a: bigint, n: bigint) => bigint;
84
+ /**
85
+ * 平方数かの判定
86
+ * @param n
87
+ * @returns
88
+ */
89
+ export declare const isSquare: (n: bigint) => boolean;
90
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/math.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAEjD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,WAG7C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,MAAM,EAAE,aAEzC,CAAC;AAGF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,EAAE,eAAa,WAajE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,WAiBxD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,GAAI,MAAM,MAAM,EAAE,OAAO,MAAM,EAAE,KAAK,MAAM,WAiB9D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM;;;;CA8B/C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,WAwDlC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,WAEjD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,WAE/C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WA2BhD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,YAejC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * PCG-XSH-RR (Permuted congruential generator) 乱数のクラス
3
+ */
4
+ export default class PCGMinimal {
5
+ #private;
6
+ get [Symbol.toStringTag](): string;
7
+ /** シード値の配列を返す */
8
+ static getSeed(): BigUint64Array<ArrayBuffer>;
9
+ /**
10
+ * @param seeds 64bit整数の配列 (長さ2以上), 省略した場合, 常に同じ値によって初期化される
11
+ */
12
+ constructor(seeds?: BigUint64Array<ArrayBuffer>);
13
+ /** 内部状態を1サイクル進める */
14
+ step(): void;
15
+ /** 32bit 乱数を返す (内部状態は変わらない) */
16
+ get value(): number;
17
+ /** 内部状態を1進め、乱数を返す \
18
+ * 普通はこれを使う
19
+ */
20
+ getRand(): number;
21
+ /** `bound` 以下の乱数を返す */
22
+ getBoundedRand(bound: number): number;
23
+ /**
24
+ * step の値だけ乱数を生成するジェネレーター関数
25
+ * @param step
26
+ * @param bound
27
+ */
28
+ genRands(step: number, bound?: number): AsyncGenerator<number, void, unknown>;
29
+ }
30
+ //# sourceMappingURL=pcg-minimal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pcg-minimal.d.ts","sourceRoot":"","sources":["../../src/pcg-minimal.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;;IAG7B,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,WAEvB;IAED,iBAAiB;IACjB,MAAM,CAAC,OAAO;IAId;;OAEG;gBACS,KAAK,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC;IAa/C,oBAAoB;IACpB,IAAI;IAMJ,+BAA+B;IAC/B,IAAI,KAAK,WAMR;IAED;;OAEG;IACH,OAAO;IAKP,uBAAuB;IACvB,cAAc,CAAC,KAAK,EAAE,MAAM;IAc5B;;;;OAIG;IACI,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAK7C"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 配列が等しいかどうかの真偽値を返す
3
+ * @returns
4
+ */
5
+ export declare const isEqArray: <T>(arr1: T[], arr2: T[]) => boolean;
6
+ /**
7
+ * スリープ
8
+ * @param delay スリープ時間 (ms)
9
+ * @returns
10
+ */
11
+ export declare const sleep: (delay: number) => Promise<void>;
12
+ /** 遅延評価関数化する */
13
+ export declare const lazify: <ArgT extends unknown[], RetT>(func: (...args: ArgT) => RetT) => (...args: ArgT) => () => RetT;
14
+ /**
15
+ * CSVをパースする \
16
+ * クォート対応
17
+ * @param csv CSV
18
+ * @returns 2次元配列
19
+ */
20
+ export declare const parseCSV: (csv: string) => string[][];
21
+ /**
22
+ * 文字列のハッシュ値を返す
23
+ * @param str 文字列
24
+ * @param algorithm アルゴリズム
25
+ * @returns ハッシュ値
26
+ */
27
+ export declare const getHash: (str: string, algorithm: AlgorithmIdentifier) => Promise<Buffer<ArrayBuffer>>;
28
+ export declare const BItoBuffer: (n: bigint) => Buffer<ArrayBuffer>;
29
+ export declare const bufferToBI: (buf: Buffer) => bigint;
30
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/util.ts"],"names":[],"mappings":"AACA;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,YAShD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,kBAMlC,CAAC;AAEF,gBAAgB;AAChB,eAAO,MAAM,MAAM,GAChB,IAAI,SAAS,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,IAAI,MAC3D,GAAG,MAAM,IAAI,eAEC,CAAC;AAElB;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,eAiCnC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAAU,KAAK,MAAM,EAAE,WAAW,mBAAmB,iCAKxE,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,wBAInC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,WAGrC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@tktb-tess/util-fns",
3
+ "version": "0.1.0",
4
+ "main": "dist/bundle.js",
5
+ "type": "module",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "scripts": {
10
+ "build": "rollup -c"
11
+ },
12
+ "author": "Tessyrrhaqt",
13
+ "license": "MIT",
14
+ "description": "個人的に使う用の便利関数ライブラリ",
15
+ "devDependencies": {
16
+ "@rollup/plugin-commonjs": "^28.0.6",
17
+ "@rollup/plugin-node-resolve": "^16.0.1",
18
+ "@rollup/plugin-terser": "^0.4.4",
19
+ "@rollup/plugin-typescript": "^12.1.4",
20
+ "@types/node": "^24.3.0",
21
+ "npm-check-updates": "^18.0.2",
22
+ "rollup": "^4.47.1",
23
+ "tslib": "^2.8.1",
24
+ "tsx": "^4.20.4",
25
+ "typescript": "^5.9.2"
26
+ }
27
+ }
@@ -0,0 +1,14 @@
1
+ import typescript from '@rollup/plugin-typescript';
2
+ import terser from '@rollup/plugin-terser';
3
+ import commonjs from '@rollup/plugin-commonjs';
4
+ import nodeResolve from '@rollup/plugin-node-resolve';
5
+
6
+ export default {
7
+ input: 'src/main.ts',
8
+ output: {
9
+ file: 'dist/bundle.js',
10
+ format: 'es',
11
+ sourcemap: true,
12
+ },
13
+ plugins: [typescript(), terser(), commonjs(), nodeResolve()],
14
+ };
@@ -0,0 +1,231 @@
1
+ import {
2
+ modPow,
3
+ jacobiSymbol,
4
+ isSquare,
5
+ residue,
6
+ getRandBIByBitLength,
7
+ getRandBIByRange
8
+ } from './math';
9
+
10
+ /**
11
+ * translated from python codes in
12
+ * https://github.com/armchaircaver/Baillie-PSW/blob/623b2541b8c659dcb4312a3ddc6c00802e34f1a1/baillie_psw.py
13
+ *
14
+ */
15
+
16
+ /**
17
+ * Miller-Rabin テスト (底2)
18
+ * @param n 判定する整数
19
+ *
20
+ * @returns
21
+ */
22
+ const millerRabinAtBase2 = (n: bigint) => {
23
+ if (n <= 1n) return false;
24
+ if (n % 2n === 0n) return n === 2n;
25
+ let d_ = n - 1n;
26
+ let s_ = 0n;
27
+
28
+ while (d_ % 2n === 0n) {
29
+ d_ >>= 1n;
30
+ s_ += 1n;
31
+ }
32
+ const [d, s] = [d_, s_];
33
+
34
+ const a = 2n;
35
+ let y = modPow(a, d, n);
36
+
37
+ if (y === 1n) return true;
38
+
39
+ for (let i = 0n; i < s; i++) {
40
+ if (y === n - 1n) return true;
41
+ y = (y * y) % n;
42
+ }
43
+ return false;
44
+ };
45
+
46
+ const DChooser = (n: bigint): [bigint, bigint] => {
47
+ let D = 5n;
48
+ let j = jacobiSymbol(D, n);
49
+
50
+ while (j > 0n) {
51
+ D = D > 0n ? D + 2n : D - 2n;
52
+ D *= -1n;
53
+
54
+ if (D === -15n && isSquare(n)) {
55
+ //The value of D isn't 0, but we are just communicating
56
+ // that we have found a square
57
+ return [0n, 0n];
58
+ }
59
+ j = jacobiSymbol(D, n);
60
+ }
61
+ return [D, j];
62
+ };
63
+
64
+ /**
65
+ * `n` を法として `x` を2で割った値 (`n` は奇数を想定)
66
+ * @param x
67
+ * @param n
68
+ * @returns
69
+ */
70
+ const div2Mod = (x: bigint, n: bigint) => {
71
+ return (x & 1n) === 1n ? residue((x + n) >> 1n, n) : residue(x >> 1n, n);
72
+ };
73
+
74
+ /**
75
+ * ここ何してるのかわからん
76
+ * @param k
77
+ * @param n
78
+ * @param P
79
+ * @param D
80
+ * @returns
81
+ */
82
+ const UVSubscript = (k: bigint, n: bigint, P: bigint, D: bigint): [bigint, bigint] => {
83
+ let U = 1n;
84
+ let V = P;
85
+ const digits = k.toString(2).slice(1);
86
+
87
+ for (const digit of digits) {
88
+ [U, V] = [residue(U * V, n), div2Mod(V * V + D * U * U, n)];
89
+
90
+ if (digit === '1') {
91
+ [U, V] = [div2Mod(P * U + V, n), div2Mod(D * U + P * V, n)];
92
+ }
93
+ }
94
+
95
+ return [U, V];
96
+ };
97
+
98
+ /**
99
+ * Lucasの強素数判定法
100
+ * @param n
101
+ * @param D
102
+ * @param P
103
+ * @param Q
104
+ * @returns
105
+ */
106
+ const lucasSPP = (n: bigint, D: bigint, P: bigint, Q: bigint) => {
107
+ if (n % 2n !== 1n) throw Error('`n` must be odd');
108
+ let d = n + 1n;
109
+ let s = 0n;
110
+
111
+ while (d % 2n === 0n) {
112
+ d >>= 1n;
113
+ s += 1n;
114
+ }
115
+ //console.log('d:', d, 's:', s);
116
+
117
+ const [U, V_] = UVSubscript(d, n, P, D);
118
+ let V = V_;
119
+
120
+ //console.log('U:', U, 'V:', V);
121
+
122
+ if (U === 0n) return true;
123
+
124
+ Q = modPow(Q, d, n);
125
+
126
+ for (let i = 0n; i < s; i++) {
127
+ //console.log(i, V, Q);
128
+ if (V === 0n) return true;
129
+
130
+ V = residue(V * V - 2n * Q, n);
131
+ Q = modPow(Q, 2n, n);
132
+ }
133
+ return false;
134
+ };
135
+
136
+ /**
137
+ * Baillie-PSW素数判定法
138
+ * @param n 判定したい整数
139
+ * @returns
140
+ */
141
+ export const bailliePSW = (n: bigint) => {
142
+ if (n <= 1n) return false;
143
+ if (n % 2n === 0n) return n === 2n;
144
+
145
+ // 小さな素数で試し割り
146
+ const smallPrimes: readonly bigint[] = [
147
+ 2n,
148
+ 3n,
149
+ 5n,
150
+ 7n,
151
+ 11n,
152
+ 13n,
153
+ 17n,
154
+ 19n,
155
+ 23n,
156
+ 29n,
157
+ 31n,
158
+ 37n,
159
+ 41n,
160
+ 43n,
161
+ 47n,
162
+ 53n,
163
+ 59n,
164
+ 61n,
165
+ 67n,
166
+ 71n,
167
+ 73n,
168
+ 79n,
169
+ 83n,
170
+ 89n,
171
+ 97n,
172
+ 101n
173
+ ];
174
+
175
+ for (const p of smallPrimes) {
176
+ if (n % p === 0n) {
177
+ return n === p;
178
+ }
179
+ }
180
+
181
+ if (!millerRabinAtBase2(n)) {
182
+ // console.log(n, 'Miller-Rabin', false);
183
+ return false;
184
+ }
185
+
186
+ const [D, j] = DChooser(n);
187
+ if (j === 0n) return false;
188
+
189
+ const Q = (1n - D) / 4n;
190
+ //console.log('n:', n, 'D:', D, 'P:', 1n, 'Q:', Q);
191
+ return lucasSPP(n, D, 1n, Q);
192
+ // console.log(n, 'Lucas-Strong', res);
193
+ };
194
+
195
+ /**
196
+ * 指定範囲内の確率的素数を返す
197
+ * @param min 下限
198
+ * @param max 上限
199
+ * @returns
200
+ */
201
+ export const getRandPrimeByRange = (min: bigint, max: bigint) => {
202
+ const LIMIT = 100000;
203
+ if (max < 2n) {
204
+ throw Error('noPrimesFound');
205
+ }
206
+ for (let count = 0; count < LIMIT; count++) {
207
+ const p = getRandBIByRange(min, max);
208
+ if (bailliePSW(p)) return p;
209
+ }
210
+
211
+ throw Error('noPrimesFound');
212
+ };
213
+
214
+ /**
215
+ * 指定ビットの確率的素数を返す
216
+ * @param bitLength ビット長
217
+ * @param fixed true: 固定長, false (デフォルト値): `length` ビット以下の可変ビット長
218
+ * @returns
219
+ */
220
+ export const getRandPrimeByBitLength = (bitLength: number, fixed = false) => {
221
+ const LIMIT = 100000;
222
+ if (bitLength < 2) {
223
+ throw Error('noPrimesFound');
224
+ }
225
+ for (let count = 0; count < LIMIT; count++) {
226
+ const p = getRandBIByBitLength(bitLength, fixed);
227
+ if (bailliePSW(p)) return p;
228
+ }
229
+
230
+ throw Error('noPrimesFound');
231
+ };
package/src/main.ts ADDED
@@ -0,0 +1,56 @@
1
+ import {
2
+ isEqArray,
3
+ sleep,
4
+ lazify,
5
+ parseCSV,
6
+ getHash,
7
+ BItoBuffer,
8
+ bufferToBI,
9
+ } from './util';
10
+ import {
11
+ getRndInt,
12
+ residue,
13
+ toBigInt,
14
+ getRandBIByBitLength,
15
+ getRandBIByRange,
16
+ modPow,
17
+ exEuclidean,
18
+ factorial,
19
+ rot32,
20
+ rot32BI,
21
+ jacobiSymbol,
22
+ isSquare,
23
+ } from './math';
24
+
25
+ import PCGMinimal from './pcg-minimal';
26
+ import {
27
+ bailliePSW,
28
+ getRandPrimeByBitLength,
29
+ getRandPrimeByRange,
30
+ } from './baillie-psw';
31
+
32
+ export {
33
+ isEqArray,
34
+ sleep,
35
+ lazify,
36
+ parseCSV,
37
+ getHash,
38
+ BItoBuffer,
39
+ bufferToBI,
40
+ getRndInt,
41
+ residue,
42
+ toBigInt,
43
+ getRandBIByBitLength,
44
+ getRandBIByRange,
45
+ modPow,
46
+ exEuclidean,
47
+ factorial,
48
+ rot32,
49
+ rot32BI,
50
+ jacobiSymbol,
51
+ isSquare,
52
+ bailliePSW,
53
+ getRandPrimeByBitLength,
54
+ getRandPrimeByRange,
55
+ PCGMinimal,
56
+ };
package/src/math.ts ADDED
@@ -0,0 +1,283 @@
1
+ /**
2
+ * min以上, max未満の整数を返す
3
+ * @param min
4
+ * @param max
5
+ * @returns 範囲内の整数乱数
6
+ */
7
+ export const getRndInt = (min: number, max: number) => {
8
+ return Math.floor(Math.random() * (max - min) + min);
9
+ };
10
+
11
+ /**
12
+ * 剰余、ただし正の範囲の値を返す
13
+ * @param n
14
+ * @param mod
15
+ * @returns
16
+ */
17
+ export const residue = (n: bigint, mod: bigint) => {
18
+ const ans = n % mod;
19
+ return ans < 0n ? ans + mod : ans;
20
+ };
21
+
22
+ /**
23
+ * number を bigint に変換
24
+ * @param nums
25
+ * @returns
26
+ */
27
+ export const toBigInt = (...nums: number[]) => {
28
+ return nums.map((n) => BigInt(n));
29
+ };
30
+
31
+
32
+ /**
33
+ * `length` ビットの乱数 or `length` ビット以下の乱数を出力する
34
+ * @param length ビット長
35
+ * @param fixed true: 固定長, false (デフォルト値): `length` ビット以下の可変ビット長
36
+ *
37
+ */
38
+ export const getRandBIByBitLength = (length: number, fixed = false) => {
39
+ if (!Number.isFinite(length)) throw Error('`length` is not a valid number');
40
+ if (length <= 0) throw Error('`length` must be positive');
41
+
42
+ const div = Math.ceil(length / 32);
43
+ const u32Arr = crypto.getRandomValues(new Uint32Array(div));
44
+ let result = Array.from(u32Arr, (n) => n.toString(2).padStart(32, '0')).join(
45
+ ''
46
+ );
47
+ result = result.slice(0, length);
48
+ if (fixed) result = result.replace(/^./, '1');
49
+ // console.log(result);
50
+ return BigInt('0b' + result);
51
+ };
52
+
53
+ /**
54
+ * `min` 以上 `max` 未満の乱数を返す
55
+ * @param min 下限
56
+ * @param max 上限
57
+ * @returns `min` 以上 `max` 未満の乱数
58
+ */
59
+ export const getRandBIByRange = (min: bigint, max: bigint) => {
60
+ if (min >= max) throw Error('RangeError');
61
+ const diff = max - min;
62
+ const bitLength = diff.toString(2).length;
63
+
64
+ const res = (() => {
65
+ const limit = 100000;
66
+ for (let i = 0; i < limit; i++) {
67
+ const res = getRandBIByBitLength(bitLength);
68
+ if (res >= modPow(2n, BigInt(bitLength), diff)) {
69
+ return res % diff;
70
+ }
71
+ }
72
+ throw Error('Failed to generate a random bigint');
73
+ })();
74
+
75
+ return min + res;
76
+ };
77
+
78
+ /**
79
+ * 冪剰余を計算する
80
+ * @param base 底
81
+ * @param power 指数
82
+ * @param mod 法
83
+ * @returns 冪剰余
84
+ */
85
+ export const modPow = (base: bigint, power: bigint, mod: bigint) => {
86
+ if (mod < 1n) throw Error('`mod` must be positive');
87
+ if (power < 0n) throw Error('`power` must not be negative');
88
+
89
+ while (base < 0n) base += mod;
90
+ if (mod === 1n) return 0n;
91
+ if (base % mod === 1n || base % mod === 0n) return base;
92
+ if (base === mod - 1n) return power & 1n ? mod - 1n : 1n;
93
+
94
+ let result = 1n;
95
+ while (power > 0n) {
96
+ if (power & 1n) result = (result * base) % mod;
97
+ base = (base * base) % mod;
98
+ power >>= 1n;
99
+ // console.log(base, power, mod);
100
+ }
101
+ return result;
102
+ };
103
+
104
+ /**
105
+ * 拡張ユークリッドの互除法 \
106
+ * 参考: https://qiita.com/angel_p_57/items/56a902cbd1fe519747bd
107
+ *
108
+ * @description `ax - by = gcd(a, b)`
109
+ * @param a
110
+ * @param b
111
+ * @returns `{x, y, gcd(a, b)}`
112
+ */
113
+ export const exEuclidean = (a: bigint, b: bigint) => {
114
+ // a, b に 0 がある場合の処理
115
+ if (a === 0n && b === 0n) return { x: 0n, y: 0n, gcd: 0n };
116
+ if (a === 0n)
117
+ return b > 0n ? { x: 0n, y: -1n, gcd: b } : { x: 0n, y: 1n, gcd: -b };
118
+ if (b === 0n)
119
+ return a > 0n ? { x: 1n, y: 0n, gcd: a } : { x: -1n, y: 0n, gcd: -a };
120
+
121
+ let [x_1, y_1, c_1] = [1n, 0n, a];
122
+ let [x_2, y_2, c_2] = [0n, -1n, b];
123
+
124
+ while (true) {
125
+ const q = c_1 / c_2;
126
+ const c_nxt = c_1 - q * c_2;
127
+
128
+ if (c_nxt === 0n) break;
129
+
130
+ [x_1, x_2] = [x_2, x_1 - q * x_2];
131
+ [y_1, y_2] = [y_2, y_1 - q * y_2];
132
+ [c_1, c_2] = [c_2, c_nxt];
133
+ }
134
+
135
+ // GCD が負の場合 -1 倍する
136
+ if (c_2 < 0n) {
137
+ x_2 *= -1n;
138
+ y_2 *= -1n;
139
+ c_2 *= -1n;
140
+ }
141
+
142
+ return { x: x_2, y: y_2, gcd: c_2 };
143
+ };
144
+
145
+ /**
146
+ * 階乗を計算する \
147
+ * 参考: https://qiita.com/AkariLuminous/items/1b2e964ebabde9419224
148
+ * @param n_ 整数
149
+ * @returns 引数の階乗
150
+ */
151
+ export const factorial = (n: bigint) => {
152
+ if (n < 0n) throw Error(`'n_' must be non-negative`);
153
+ if (n === 0n) return 1n;
154
+
155
+ /**
156
+ * min 以上 max 「未満」 の奇数の積を返す
157
+ * @param min 最小値
158
+ * @param max 最大値
159
+ * @returns min 以上 max 未満 の奇数の積
160
+ */
161
+ const oddProd = (min: bigint, max: bigint): bigint => {
162
+ if (min >= max) return 1n;
163
+
164
+ const max_bits = BigInt((max - 2n).toString(2).length);
165
+ const num_odds = (max - min) / 2n;
166
+
167
+ if (max_bits * num_odds < 63n) {
168
+ let result = min;
169
+ for (let i = min + 2n; i < max; i += 2n) {
170
+ result *= i;
171
+ }
172
+ return result;
173
+ }
174
+
175
+ const mid = (min + num_odds) | 1n;
176
+ const lower = oddProd(min, mid);
177
+ const higher = oddProd(mid, max);
178
+ return lower * higher;
179
+ };
180
+
181
+ /**
182
+ * 階乗の奇数部分を計算する
183
+ * @param n 整数
184
+ * @returns 奇数部の積
185
+ */
186
+ const oddPart = (n: bigint) => {
187
+ let L_i = 3n,
188
+ result = 1n,
189
+ tmp = 1n;
190
+ const m = BigInt(n.toString(2).length) - 1n;
191
+
192
+ for (let i = m - 1n; i > -1n; --i) {
193
+ const U_i = ((n >> i) + 1n) | 1n;
194
+
195
+ tmp *= oddProd(L_i, U_i);
196
+ L_i = U_i;
197
+ result *= tmp;
198
+ }
199
+
200
+ return result;
201
+ };
202
+
203
+ const two_exp = n - BigInt(n.toString(2).match(/1/g)?.length ?? 0);
204
+ const odd_part = oddPart(n);
205
+
206
+ return odd_part << two_exp;
207
+ };
208
+
209
+ /**
210
+ * 32ビット回転 (bigint)
211
+ * @param value 値
212
+ * @param rot 回転数
213
+ * @returns
214
+ */
215
+ export const rot32BI = (value: bigint, rot: bigint) => {
216
+ return BigInt.asUintN(32, (value >> (rot & 31n)) | (value << (-rot & 31n)));
217
+ };
218
+
219
+ /**
220
+ * 32ビット回転
221
+ * @param value 値
222
+ * @param rot 回転数
223
+ * @returns
224
+ */
225
+ export const rot32 = (value: number, rot: number) => {
226
+ return (value >>> (rot & 31)) | (value << (-rot & 31));
227
+ };
228
+
229
+ /**
230
+ * ヤコビ記号
231
+ * @param a 正の整数
232
+ * @param n 正の奇数
233
+ */
234
+ export const jacobiSymbol = (a: bigint, n: bigint) => {
235
+ if (n < 1n || n % 2n === 0n) {
236
+ throw Error('`n` is invalid');
237
+ }
238
+ while (a < 0n) {
239
+ a += n;
240
+ }
241
+ a %= n;
242
+
243
+ let result = 1n;
244
+ while (a !== 0n) {
245
+ while (a % 2n === 0n) {
246
+ a /= 2n;
247
+ const nMod8 = n % 8n;
248
+ if (nMod8 === 3n || nMod8 === 5n) {
249
+ result *= -1n;
250
+ }
251
+ }
252
+ [a, n] = [n, a];
253
+
254
+ if (a % 4n === 3n && n % 4n === 3n) {
255
+ result *= -1n;
256
+ }
257
+ a %= n;
258
+ }
259
+
260
+ return n === 1n ? result : 0n;
261
+ };
262
+
263
+ /**
264
+ * 平方数かの判定
265
+ * @param n
266
+ * @returns
267
+ */
268
+ export const isSquare = (n: bigint) => {
269
+ if (n < 0n) return false;
270
+ if (n === 0n) return true;
271
+ let x = 1n;
272
+ let y = n;
273
+ while (x + 1n < y) {
274
+ const mid = (x + y) / 2n;
275
+
276
+ if (mid ** 2n < n) {
277
+ x = mid;
278
+ } else {
279
+ y = mid;
280
+ }
281
+ }
282
+ return n === x ** 2n || n === (x + 1n) ** 2n;
283
+ };
@@ -0,0 +1,89 @@
1
+ import { rot32 } from './math';
2
+
3
+ /** シードなし時の静的初期化定数 */
4
+ const initialState = [0x853c49e6748fea9bn, 0xda3e39cb94b95bdbn] as const;
5
+
6
+ /** 乗数 */
7
+ const increment = 0x5851f42d4c957f2dn;
8
+
9
+ /**
10
+ * PCG-XSH-RR (Permuted congruential generator) 乱数のクラス
11
+ */
12
+ export default class PCGMinimal {
13
+ readonly #state = new BigUint64Array(2);
14
+
15
+ get [Symbol.toStringTag]() {
16
+ return PCGMinimal.name;
17
+ }
18
+
19
+ /** シード値の配列を返す */
20
+ static getSeed() {
21
+ return crypto.getRandomValues(new BigUint64Array(2));
22
+ }
23
+
24
+ /**
25
+ * @param seeds 64bit整数の配列 (長さ2以上), 省略した場合, 常に同じ値によって初期化される
26
+ */
27
+ constructor(seeds?: BigUint64Array<ArrayBuffer>) {
28
+
29
+ if (seeds && seeds[0] && seeds[1]) {
30
+ this.#state[1] = (seeds[1] << 1n) | 1n;
31
+ this.step();
32
+ this.#state[0] = seeds[0];
33
+ this.step();
34
+ } else {
35
+ this.#state[0] = initialState[0];
36
+ this.#state[1] = initialState[1];
37
+ }
38
+ }
39
+
40
+ /** 内部状態を1サイクル進める */
41
+ step() {
42
+ if (this.#state[0] && this.#state[1]) {
43
+ this.#state[0] = this.#state[0] * increment + this.#state[1];
44
+ }
45
+ }
46
+
47
+ /** 32bit 乱数を返す (内部状態は変わらない) */
48
+ get value() {
49
+ const prev = this.#state[0];
50
+ if (!prev) throw Error('empty state');
51
+ const rot = prev >> 59n;
52
+ const shifted = BigInt.asUintN(32, (prev ^ (prev >> 18n)) >> 27n);
53
+ return rot32(Number(shifted), Number(rot));
54
+ }
55
+
56
+ /** 内部状態を1進め、乱数を返す \
57
+ * 普通はこれを使う
58
+ */
59
+ getRand() {
60
+ this.step();
61
+ return this.value;
62
+ }
63
+
64
+ /** `bound` 以下の乱数を返す */
65
+ getBoundedRand(bound: number) {
66
+ /** 32bit 上限 */
67
+ const limit = 0x100000000;
68
+
69
+ if (bound > limit) throw Error('bound exceeded limit (2^32)');
70
+
71
+ const threshold = limit % bound;
72
+
73
+ while (true) {
74
+ const r = this.getRand();
75
+ if (r >= threshold) return r % bound;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * step の値だけ乱数を生成するジェネレーター関数
81
+ * @param step
82
+ * @param bound
83
+ */
84
+ async *genRands(step: number, bound?: number) {
85
+ for (let i = 0; i < step; i++) {
86
+ yield bound ? this.getBoundedRand(bound) : this.getRand();
87
+ }
88
+ }
89
+ }
package/src/util.ts ADDED
@@ -0,0 +1,100 @@
1
+
2
+ /**
3
+ * 配列が等しいかどうかの真偽値を返す
4
+ * @returns
5
+ */
6
+ export const isEqArray = <T>(arr1: T[], arr2: T[]) => {
7
+ if (arr1.length !== arr2.length) return false;
8
+ else {
9
+ for (let i = 0; i < arr1.length; i++) {
10
+ if (arr1[i] !== arr2[i]) return false;
11
+ }
12
+
13
+ return true;
14
+ }
15
+ };
16
+
17
+ /**
18
+ * スリープ
19
+ * @param delay スリープ時間 (ms)
20
+ * @returns
21
+ */
22
+ export const sleep = (delay: number) => {
23
+ return new Promise<void>((resolve) => {
24
+ setTimeout(() => {
25
+ resolve();
26
+ }, delay);
27
+ });
28
+ };
29
+
30
+ /** 遅延評価関数化する */
31
+ export const lazify =
32
+ <ArgT extends unknown[], RetT>(func: (...args: ArgT) => RetT) =>
33
+ (...args: ArgT) =>
34
+ () =>
35
+ func(...args);
36
+
37
+ /**
38
+ * CSVをパースする \
39
+ * クォート対応
40
+ * @param csv CSV
41
+ * @returns 2次元配列
42
+ */
43
+ export const parseCSV = (csv: string) => {
44
+ const rows: string[][] = [];
45
+ let row: string[] = [];
46
+ let currentField = '';
47
+ let isInsideOfQuote = false;
48
+
49
+ for (let i = 0; i < csv.length; i++) {
50
+ const char = csv[i];
51
+
52
+ if (char === '"' && (i === 0 || csv[i - 1] !== '\\')) {
53
+ // ダブルクォート(not エスケープ)に入った/出た時にトグル
54
+ isInsideOfQuote = !isInsideOfQuote;
55
+ } else if (char === ',' && !isInsideOfQuote) {
56
+ // クォート内でないコンマ
57
+ row.push(currentField.trim()); // フィールドを列配列に追加
58
+ currentField = ''; // クリア
59
+ } else if (char === '\n' && !isInsideOfQuote) {
60
+ // クォート内でない改行
61
+ row.push(currentField.trim()); // フィールドを列配列に追加
62
+ rows.push(row); // 列配列を2次元配列に追加
63
+ row = []; // 列配列, フィールドをクリア
64
+ currentField = '';
65
+ } else {
66
+ // フィールドに文字を追加
67
+ currentField += char;
68
+ }
69
+ }
70
+
71
+ // 最後のセルと行を追加
72
+ row.push(currentField.trim());
73
+ rows.push(row);
74
+
75
+ return rows;
76
+ };
77
+
78
+ /**
79
+ * 文字列のハッシュ値を返す
80
+ * @param str 文字列
81
+ * @param algorithm アルゴリズム
82
+ * @returns ハッシュ値
83
+ */
84
+ export const getHash = async (str: string, algorithm: AlgorithmIdentifier) => {
85
+ const utf8 = Buffer.from(str, 'utf8');
86
+ return crypto.subtle
87
+ .digest(algorithm, utf8)
88
+ .then((hash) => Buffer.from(hash));
89
+ };
90
+
91
+ export const BItoBuffer = (n: bigint) => {
92
+ let str = n.toString(16);
93
+ if (str.length & 1) str = '0' + str;
94
+ return Buffer.from(str, 'hex');
95
+ };
96
+
97
+ export const bufferToBI = (buf: Buffer) => {
98
+ const str = buf.toString('hex') || '00';
99
+ return BigInt('0x' + str);
100
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ "module": "esnext",
5
+ "target": "esnext",
6
+ "sourceMap": true,
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "declarationDir": "dist/types",
10
+ "noUncheckedIndexedAccess": true,
11
+ "exactOptionalPropertyTypes": true,
12
+ "emitDeclarationOnly": true,
13
+ "strict": true,
14
+ "verbatimModuleSyntax": true,
15
+ "isolatedModules": true,
16
+ "noUncheckedSideEffectImports": true,
17
+ "moduleDetection": "force",
18
+ "skipLibCheck": true,
19
+ "moduleResolution": "bundler"
20
+ },
21
+ "include": ["src/**/*.ts"]
22
+ }