functionalscript 0.4.2 → 0.4.3
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/crypto/hmac/module.f.d.ts +28 -0
- package/crypto/hmac/module.f.js +60 -0
- package/crypto/hmac/test.f.d.ts +6 -0
- package/crypto/hmac/test.f.js +24 -0
- package/crypto/sha2/module.f.d.ts +10 -0
- package/crypto/sha2/module.f.js +11 -2
- package/crypto/sha2/test.f.js +28 -21
- package/package.json +1 -1
- package/types/bigint/module.f.d.ts +83 -2
- package/types/bigint/module.f.js +98 -2
- package/types/bigint/test.f.d.ts +4 -0
- package/types/bigint/test.f.js +66 -6
- package/types/bit_vec/module.f.d.ts +1 -1
- package/types/number/module.f.d.ts +4 -0
- package/types/number/module.f.js +16 -0
- package/types/number/test.f.d.ts +1 -0
- package/types/number/test.f.js +19 -3
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
|
+
*
|
|
4
|
+
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { vec } from '../../types/bit_vec/module.f.ts'
|
|
12
|
+
* import { msbUtf8 } from '../../text/module.f.ts'
|
|
13
|
+
* import { sha256 } from '../sha2/module.f.ts'
|
|
14
|
+
*
|
|
15
|
+
* const r = hmac(sha256)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'))
|
|
16
|
+
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { type Vec } from '../../types/bit_vec/module.f.ts';
|
|
20
|
+
import { type Sha2 } from '../sha2/module.f.ts';
|
|
21
|
+
/**
|
|
22
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified SHA-2 hash function.
|
|
23
|
+
*
|
|
24
|
+
* @param sha2 - The SHA-2 hash function implementation to use.
|
|
25
|
+
* @returns - A function that takes a key and returns another function
|
|
26
|
+
* that takes a message and computes the HMAC.
|
|
27
|
+
*/
|
|
28
|
+
export declare const hmac: (sha2: Sha2) => (k: Vec) => (m: Vec) => Vec;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides an implementation of HMAC (Hash-based Message Authentication Code).
|
|
3
|
+
*
|
|
4
|
+
* https://en.wikipedia.org/wiki/HMAC
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { vec } from '../../types/bit_vec/module.f.ts'
|
|
12
|
+
* import { msbUtf8 } from '../../text/module.f.ts'
|
|
13
|
+
* import { sha256 } from '../sha2/module.f.ts'
|
|
14
|
+
*
|
|
15
|
+
* const r = hmac(sha256)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'))
|
|
16
|
+
* if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) { throw r }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
import { length } from "../../types/bit_vec/module.f.js";
|
|
20
|
+
import { empty, msb, vec, vec8 } from "../../types/bit_vec/module.f.js";
|
|
21
|
+
import { flip } from "../../types/function/module.f.js";
|
|
22
|
+
import { repeat } from "../../types/monoid/module.f.js";
|
|
23
|
+
import { computeSync } from "../sha2/module.f.js";
|
|
24
|
+
const { concat } = msb;
|
|
25
|
+
/**
|
|
26
|
+
* Outer padding.
|
|
27
|
+
*/
|
|
28
|
+
const oPad = vec8(0x5cn);
|
|
29
|
+
/**
|
|
30
|
+
* Inner padding.
|
|
31
|
+
*/
|
|
32
|
+
const iPad = vec8(0x36n);
|
|
33
|
+
/**
|
|
34
|
+
* Repeats a vector to create a padded block of the desired length.
|
|
35
|
+
*/
|
|
36
|
+
const padRepeat = repeat({ identity: empty, operation: concat });
|
|
37
|
+
/**
|
|
38
|
+
* Generates an HMAC (Hash-based Message Authentication Code) using the specified SHA-2 hash function.
|
|
39
|
+
*
|
|
40
|
+
* @param sha2 - The SHA-2 hash function implementation to use.
|
|
41
|
+
* @returns - A function that takes a key and returns another function
|
|
42
|
+
* that takes a message and computes the HMAC.
|
|
43
|
+
*/
|
|
44
|
+
export const hmac = (sha2) => {
|
|
45
|
+
const { blockLength } = sha2;
|
|
46
|
+
const p = flip(padRepeat)(blockLength >> 3n);
|
|
47
|
+
const ip = p(iPad);
|
|
48
|
+
const op = p(oPad);
|
|
49
|
+
const c = computeSync(sha2);
|
|
50
|
+
const vbl = vec(blockLength);
|
|
51
|
+
const xor = (a) => (b) => vbl(a ^ b);
|
|
52
|
+
return k => m => {
|
|
53
|
+
const k1 = length(k) > blockLength ? c([k]) : k;
|
|
54
|
+
const k2 = concat(k1)(vec(blockLength - length(k1))(0n));
|
|
55
|
+
const xk2 = xor(k2);
|
|
56
|
+
const f = (p, msg) => c([xk2(p), msg]);
|
|
57
|
+
const m1 = f(ip, m);
|
|
58
|
+
return f(op, m1);
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { msbUtf8 } from "../../text/module.f.js";
|
|
2
|
+
import { vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { sha256, sha512 } from "../sha2/module.f.js";
|
|
4
|
+
import { hmac } from "./module.f.js";
|
|
5
|
+
export default {
|
|
6
|
+
example: () => {
|
|
7
|
+
const r = hmac(sha256)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
|
|
8
|
+
if (r !== vec(256n)(0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n)) {
|
|
9
|
+
throw r;
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
sha256: () => {
|
|
13
|
+
const r = hmac(sha256)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
|
|
14
|
+
if (r !== 0x1f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8n) {
|
|
15
|
+
throw r;
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
sha512: () => {
|
|
19
|
+
const r = hmac(sha512)(msbUtf8('key'))(msbUtf8('The quick brown fox jumps over the lazy dog'));
|
|
20
|
+
if (r !== 0x1b42af09057bac1e2d41708e48a902e09b5ff7f12ab428a4fe86653c73dd248fb82f948a549f7b791a5b41915ee4d1ec3935357e4e2317250d0372afa2ebeeb3an) {
|
|
21
|
+
throw r;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Array16, Array8 } from '../../types/array/module.f.ts';
|
|
2
2
|
import { type Vec } from '../../types/bit_vec/module.f.ts';
|
|
3
|
+
import { type List } from '../../types/list/module.f.ts';
|
|
3
4
|
export type V8 = Array8<bigint>;
|
|
4
5
|
export type V16 = Array16<bigint>;
|
|
5
6
|
/**
|
|
@@ -40,6 +41,14 @@ export type Base = {
|
|
|
40
41
|
* ```
|
|
41
42
|
*/
|
|
42
43
|
export type Sha2 = {
|
|
44
|
+
/**
|
|
45
|
+
* A hash length.
|
|
46
|
+
*/
|
|
47
|
+
readonly hashLength: bigint;
|
|
48
|
+
/**
|
|
49
|
+
* An internal block length.
|
|
50
|
+
*/
|
|
51
|
+
readonly blockLength: bigint;
|
|
43
52
|
/**
|
|
44
53
|
* Initial state of the SHA-2 algorithm.
|
|
45
54
|
*/
|
|
@@ -60,6 +69,7 @@ export type Sha2 = {
|
|
|
60
69
|
*/
|
|
61
70
|
readonly end: (state: State) => bigint;
|
|
62
71
|
};
|
|
72
|
+
export declare const computeSync: ({ append, init, end }: Sha2) => (list: List<Vec>) => Vec;
|
|
63
73
|
export declare const base32: Base;
|
|
64
74
|
export declare const base64: Base;
|
|
65
75
|
/** SHA-256 */
|
package/crypto/sha2/module.f.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { mask } from "../../types/bigint/module.f.js";
|
|
2
2
|
import { vec, length, empty, msb } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { flip } from "../../types/function/module.f.js";
|
|
4
|
+
import { fold } from "../../types/list/module.f.js";
|
|
3
5
|
const { concat, popFront, front } = msb;
|
|
4
6
|
const lastOne = vec(1n)(1n);
|
|
5
7
|
const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
@@ -138,6 +140,7 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
138
140
|
},
|
|
139
141
|
end: (hashLength) => {
|
|
140
142
|
const offset = (bitLength << 3n) - hashLength;
|
|
143
|
+
const result = vec(hashLength);
|
|
141
144
|
return (state) => {
|
|
142
145
|
const { len, remainder } = state;
|
|
143
146
|
let { hash } = state;
|
|
@@ -148,12 +151,14 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
148
151
|
hash = compress(hash)(u);
|
|
149
152
|
u = 0n;
|
|
150
153
|
}
|
|
151
|
-
return fromV8(compress(hash)(u | (len + rLen))) >> offset;
|
|
154
|
+
return result(fromV8(compress(hash)(u | (len + rLen))) >> offset);
|
|
152
155
|
};
|
|
153
156
|
}
|
|
154
157
|
};
|
|
155
158
|
};
|
|
156
|
-
const sha2 = ({ append, end }, hash, hashLength) => ({
|
|
159
|
+
const sha2 = ({ append, end, chunkLength }, hash, hashLength) => ({
|
|
160
|
+
hashLength,
|
|
161
|
+
blockLength: chunkLength,
|
|
157
162
|
init: {
|
|
158
163
|
hash,
|
|
159
164
|
len: 0n,
|
|
@@ -162,6 +167,10 @@ const sha2 = ({ append, end }, hash, hashLength) => ({
|
|
|
162
167
|
append,
|
|
163
168
|
end: end(hashLength),
|
|
164
169
|
});
|
|
170
|
+
export const computeSync = ({ append, init, end }) => {
|
|
171
|
+
const f = fold(flip(append))(init);
|
|
172
|
+
return (list) => end(f(list));
|
|
173
|
+
};
|
|
165
174
|
export const base32 = base({
|
|
166
175
|
logBitLen: 5n,
|
|
167
176
|
k: [
|
package/crypto/sha2/test.f.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { msbUtf8 } from "../../text/module.f.js";
|
|
2
2
|
import { empty, msb, vec } from "../../types/bit_vec/module.f.js";
|
|
3
|
+
import { map } from "../../types/list/module.f.js";
|
|
3
4
|
import { repeat } from "../../types/monoid/module.f.js";
|
|
4
|
-
import { base32, base64, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js";
|
|
5
|
+
import { base32, base64, computeSync, sha224, sha256, sha384, sha512, sha512x224, sha512x256, } from "./module.f.js";
|
|
5
6
|
const { concat: beConcat } = msb;
|
|
6
7
|
const checkEmpty = ({ init, end }) => (x) => {
|
|
7
8
|
const result = end(init);
|
|
@@ -22,7 +23,7 @@ export default {
|
|
|
22
23
|
const result = fromV8(compress(sha256.init.hash)(e));
|
|
23
24
|
const x = 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n;
|
|
24
25
|
if (result !== x) {
|
|
25
|
-
throw [result, x];
|
|
26
|
+
throw [result.toString(16), x.toString(16)];
|
|
26
27
|
}
|
|
27
28
|
},
|
|
28
29
|
s224: () => {
|
|
@@ -70,29 +71,35 @@ export default {
|
|
|
70
71
|
}
|
|
71
72
|
},
|
|
72
73
|
sha2: {
|
|
73
|
-
sha256: () => checkEmpty(sha256)(
|
|
74
|
-
sha224: () => checkEmpty(sha224)(
|
|
75
|
-
sha512: () => checkEmpty(sha512)(
|
|
76
|
-
sha384: () => checkEmpty(sha384)(
|
|
77
|
-
sha512x256: () => checkEmpty(sha512x256)(
|
|
78
|
-
sha512x224: () => checkEmpty(sha512x224)(
|
|
74
|
+
sha256: () => checkEmpty(sha256)(0x1e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855n),
|
|
75
|
+
sha224: () => checkEmpty(sha224)(0x1d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42fn),
|
|
76
|
+
sha512: () => checkEmpty(sha512)(0x1cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3en),
|
|
77
|
+
sha384: () => checkEmpty(sha384)(0x138b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95bn),
|
|
78
|
+
sha512x256: () => checkEmpty(sha512x256)(0x1c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967an),
|
|
79
|
+
sha512x224: () => checkEmpty(sha512x224)(0x16ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4n),
|
|
79
80
|
},
|
|
80
81
|
utf8: [
|
|
81
82
|
() => {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
const e = 0x1730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525n;
|
|
84
|
+
{
|
|
85
|
+
const s = msbUtf8("The quick brown fox jumps over the lazy dog");
|
|
86
|
+
const h = computeSync(sha224)([s]);
|
|
87
|
+
if (h !== e) {
|
|
88
|
+
throw h;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
{
|
|
92
|
+
const s = ['The', ' quick', ' brown', ' fox', ' jumps', ' over', ' the', ' lazy', ' dog'];
|
|
93
|
+
const h = computeSync(sha224)(map(msbUtf8)(s));
|
|
94
|
+
if (h !== e) {
|
|
95
|
+
throw h;
|
|
96
|
+
}
|
|
88
97
|
}
|
|
89
98
|
},
|
|
90
99
|
() => {
|
|
91
100
|
const s = msbUtf8("The quick brown fox jumps over the lazy dog.");
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const h = sha224.end(state);
|
|
95
|
-
if (h !== 0x619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
|
|
101
|
+
const h = computeSync(sha224)([s]);
|
|
102
|
+
if (h !== 0x1619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4cn) {
|
|
96
103
|
throw h;
|
|
97
104
|
}
|
|
98
105
|
},
|
|
@@ -104,7 +111,7 @@ export default {
|
|
|
104
111
|
let state = sha256.init;
|
|
105
112
|
state = sha256.append(state)(s);
|
|
106
113
|
const h = sha256.end(state);
|
|
107
|
-
if (h !==
|
|
114
|
+
if (h !== 0x1b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9n) {
|
|
108
115
|
throw h;
|
|
109
116
|
}
|
|
110
117
|
}
|
|
@@ -117,7 +124,7 @@ export default {
|
|
|
117
124
|
let state = sha256.init;
|
|
118
125
|
state = sha256.append(state)(r);
|
|
119
126
|
const h = sha256.end(state);
|
|
120
|
-
if (h >> 224n !==
|
|
127
|
+
if (h >> 224n !== 0x18a83665fn) {
|
|
121
128
|
throw h;
|
|
122
129
|
}
|
|
123
130
|
},
|
|
@@ -126,7 +133,7 @@ export default {
|
|
|
126
133
|
let state = sha256.init;
|
|
127
134
|
state = sha256.append(state)(r);
|
|
128
135
|
const h = sha256.end(state);
|
|
129
|
-
if (h !==
|
|
136
|
+
if (h !== 0x13138bb9bc78df27c473ecfd1410f7bd45ebac1f59cf3ff9cfe4db77aab7aedd3n) {
|
|
130
137
|
throw h;
|
|
131
138
|
}
|
|
132
139
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Utility functions for working with `bigint` values.
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*
|
|
@@ -14,17 +14,67 @@
|
|
|
14
14
|
* const bitCount = bitLength(255n) // 8n
|
|
15
15
|
* const bitmask = mask(5n) // 31n
|
|
16
16
|
* const m = min(3n)(13n) // 3n
|
|
17
|
+
* const c = combination([3n, 2n, 1n]) // 60n
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
20
|
import { type Sign } from '../function/compare/module.f.ts';
|
|
20
21
|
import type * as Operator from '../function/operator/module.f.ts';
|
|
21
22
|
import { type List } from '../list/module.f.ts';
|
|
23
|
+
/**
|
|
24
|
+
* Type representing a unary operation on `bigint`.
|
|
25
|
+
*/
|
|
22
26
|
export type Unary = Operator.Unary<bigint, bigint>;
|
|
27
|
+
/**
|
|
28
|
+
* Type representing a reduction operation on `bigint` values.
|
|
29
|
+
*/
|
|
23
30
|
export type Reduce = Operator.Reduce<bigint>;
|
|
31
|
+
/**
|
|
32
|
+
* Adds two `bigint` values.
|
|
33
|
+
*
|
|
34
|
+
* @param a - The first bigint value.
|
|
35
|
+
* @returns A function that takes the second bigint value and returns the sum.
|
|
36
|
+
*/
|
|
24
37
|
export declare const addition: Reduce;
|
|
38
|
+
/**
|
|
39
|
+
* Calculates the sum of a list of `bigint` values.
|
|
40
|
+
*
|
|
41
|
+
* @param input - A list of bigint values.
|
|
42
|
+
* @returns The sum of all values in the list.
|
|
43
|
+
*/
|
|
25
44
|
export declare const sum: (input: List<bigint>) => bigint;
|
|
45
|
+
/**
|
|
46
|
+
* Multiplies two `bigint` values.
|
|
47
|
+
*
|
|
48
|
+
* @param a - The first bigint value.
|
|
49
|
+
* @returns A function that takes the second bigint value and returns the product.
|
|
50
|
+
*/
|
|
51
|
+
export declare const multiple: Reduce;
|
|
52
|
+
/**
|
|
53
|
+
* Calculates the product of a list of `bigint` values.
|
|
54
|
+
*
|
|
55
|
+
* @param input - A list of bigint values.
|
|
56
|
+
* @returns The product of all values in the list.
|
|
57
|
+
*/
|
|
58
|
+
export declare const product: (input: List<bigint>) => bigint;
|
|
59
|
+
/**
|
|
60
|
+
* Calculates the absolute value of a `bigint`.
|
|
61
|
+
*
|
|
62
|
+
* @param a - The bigint value.
|
|
63
|
+
* @returns The absolute value of the input bigint.
|
|
64
|
+
*/
|
|
26
65
|
export declare const abs: Unary;
|
|
66
|
+
/**
|
|
67
|
+
* Determines the sign of a `bigint`.
|
|
68
|
+
* @param a - The bigint value.
|
|
69
|
+
* @returns `1` if positive, `-1` if negative, and `0` if zero.
|
|
70
|
+
*/
|
|
27
71
|
export declare const sign: (a: bigint) => Sign;
|
|
72
|
+
/**
|
|
73
|
+
* Serializes a `bigint` to a string representation.
|
|
74
|
+
*
|
|
75
|
+
* @param a - The bigint value.
|
|
76
|
+
* @returns A string representation of the bigint (e.g., '123n').
|
|
77
|
+
*/
|
|
28
78
|
export declare const serialize: (a: bigint) => string;
|
|
29
79
|
/**
|
|
30
80
|
* Calculates the base-2 logarithm (floor).
|
|
@@ -81,6 +131,37 @@ export declare const bitLength: (v: bigint) => bigint;
|
|
|
81
131
|
*/
|
|
82
132
|
export declare const mask: (len: bigint) => bigint;
|
|
83
133
|
/**
|
|
84
|
-
*
|
|
134
|
+
* Returns the smaller of two `bigint` values.
|
|
135
|
+
*
|
|
136
|
+
* @param a - The first bigint.
|
|
137
|
+
* @returns A function that takes the second bigint and returns the smaller value.
|
|
85
138
|
*/
|
|
86
139
|
export declare const min: (a: bigint) => (b: bigint) => bigint;
|
|
140
|
+
/**
|
|
141
|
+
* Returns the larger of two `bigint` values.
|
|
142
|
+
*
|
|
143
|
+
* @param a - The first bigint.
|
|
144
|
+
* @returns A function that takes the second bigint and returns the larger value.
|
|
145
|
+
*/
|
|
146
|
+
export declare const max: (a: bigint) => (b: bigint) => bigint;
|
|
147
|
+
/**
|
|
148
|
+
* Calculates the partial factorial `b!/a!`.
|
|
149
|
+
*
|
|
150
|
+
* @param a - The starting bigint value.
|
|
151
|
+
* @returns A function that takes `b` and computes `b!/a!`.
|
|
152
|
+
*/
|
|
153
|
+
export declare const partialFactorial: (a: bigint) => (b: bigint) => bigint;
|
|
154
|
+
/**
|
|
155
|
+
* Calculates the factorial of a `bigint`.
|
|
156
|
+
*
|
|
157
|
+
* @param b - The bigint value.
|
|
158
|
+
* @returns The factorial of the input.
|
|
159
|
+
*/
|
|
160
|
+
export declare const factorial: (b: bigint) => bigint;
|
|
161
|
+
/**
|
|
162
|
+
* Calculates the number of combinations for a list of `bigint` values.
|
|
163
|
+
*
|
|
164
|
+
* @param k - A list of bigint values.
|
|
165
|
+
* @returns The number of combinations.
|
|
166
|
+
*/
|
|
167
|
+
export declare const combination: (...k: readonly bigint[]) => bigint;
|
package/types/bigint/module.f.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Utility functions for working with `bigint` values.
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*
|
|
@@ -14,14 +14,58 @@
|
|
|
14
14
|
* const bitCount = bitLength(255n) // 8n
|
|
15
15
|
* const bitmask = mask(5n) // 31n
|
|
16
16
|
* const m = min(3n)(13n) // 3n
|
|
17
|
+
* const c = combination([3n, 2n, 1n]) // 60n
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
20
|
import { unsafeCmp } from "../function/compare/module.f.js";
|
|
20
21
|
import { reduce } from "../list/module.f.js";
|
|
22
|
+
/**
|
|
23
|
+
* Adds two `bigint` values.
|
|
24
|
+
*
|
|
25
|
+
* @param a - The first bigint value.
|
|
26
|
+
* @returns A function that takes the second bigint value and returns the sum.
|
|
27
|
+
*/
|
|
21
28
|
export const addition = a => b => a + b;
|
|
29
|
+
/**
|
|
30
|
+
* Calculates the sum of a list of `bigint` values.
|
|
31
|
+
*
|
|
32
|
+
* @param input - A list of bigint values.
|
|
33
|
+
* @returns The sum of all values in the list.
|
|
34
|
+
*/
|
|
22
35
|
export const sum = reduce(addition)(0n);
|
|
36
|
+
/**
|
|
37
|
+
* Multiplies two `bigint` values.
|
|
38
|
+
*
|
|
39
|
+
* @param a - The first bigint value.
|
|
40
|
+
* @returns A function that takes the second bigint value and returns the product.
|
|
41
|
+
*/
|
|
42
|
+
export const multiple = a => b => a * b;
|
|
43
|
+
/**
|
|
44
|
+
* Calculates the product of a list of `bigint` values.
|
|
45
|
+
*
|
|
46
|
+
* @param input - A list of bigint values.
|
|
47
|
+
* @returns The product of all values in the list.
|
|
48
|
+
*/
|
|
49
|
+
export const product = reduce(multiple)(1n);
|
|
50
|
+
/**
|
|
51
|
+
* Calculates the absolute value of a `bigint`.
|
|
52
|
+
*
|
|
53
|
+
* @param a - The bigint value.
|
|
54
|
+
* @returns The absolute value of the input bigint.
|
|
55
|
+
*/
|
|
23
56
|
export const abs = a => a >= 0 ? a : -a;
|
|
57
|
+
/**
|
|
58
|
+
* Determines the sign of a `bigint`.
|
|
59
|
+
* @param a - The bigint value.
|
|
60
|
+
* @returns `1` if positive, `-1` if negative, and `0` if zero.
|
|
61
|
+
*/
|
|
24
62
|
export const sign = (a) => unsafeCmp(a)(0n);
|
|
63
|
+
/**
|
|
64
|
+
* Serializes a `bigint` to a string representation.
|
|
65
|
+
*
|
|
66
|
+
* @param a - The bigint value.
|
|
67
|
+
* @returns A string representation of the bigint (e.g., '123n').
|
|
68
|
+
*/
|
|
25
69
|
export const serialize = (a) => `${a}n`;
|
|
26
70
|
const { isFinite } = Number;
|
|
27
71
|
const { log2: mathLog2 } = Math;
|
|
@@ -139,6 +183,58 @@ export const bitLength = (v) => {
|
|
|
139
183
|
*/
|
|
140
184
|
export const mask = (len) => (1n << len) - 1n;
|
|
141
185
|
/**
|
|
142
|
-
*
|
|
186
|
+
* Returns the smaller of two `bigint` values.
|
|
187
|
+
*
|
|
188
|
+
* @param a - The first bigint.
|
|
189
|
+
* @returns A function that takes the second bigint and returns the smaller value.
|
|
143
190
|
*/
|
|
144
191
|
export const min = (a) => (b) => a < b ? a : b;
|
|
192
|
+
/**
|
|
193
|
+
* Returns the larger of two `bigint` values.
|
|
194
|
+
*
|
|
195
|
+
* @param a - The first bigint.
|
|
196
|
+
* @returns A function that takes the second bigint and returns the larger value.
|
|
197
|
+
*/
|
|
198
|
+
export const max = (a) => (b) => a < b ? b : a;
|
|
199
|
+
/**
|
|
200
|
+
* Calculates the partial factorial `b!/a!`.
|
|
201
|
+
*
|
|
202
|
+
* @param a - The starting bigint value.
|
|
203
|
+
* @returns A function that takes `b` and computes `b!/a!`.
|
|
204
|
+
*/
|
|
205
|
+
export const partialFactorial = (a) => (b) => {
|
|
206
|
+
let result = b;
|
|
207
|
+
while (true) {
|
|
208
|
+
--b;
|
|
209
|
+
if (b <= a) {
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
result *= b;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Calculates the factorial of a `bigint`.
|
|
217
|
+
*
|
|
218
|
+
* @param b - The bigint value.
|
|
219
|
+
* @returns The factorial of the input.
|
|
220
|
+
*/
|
|
221
|
+
export const factorial = partialFactorial(1n);
|
|
222
|
+
/**
|
|
223
|
+
* Calculates the number of combinations for a list of `bigint` values.
|
|
224
|
+
*
|
|
225
|
+
* @param k - A list of bigint values.
|
|
226
|
+
* @returns The number of combinations.
|
|
227
|
+
*/
|
|
228
|
+
export const combination = (...k) => {
|
|
229
|
+
let s = 0n;
|
|
230
|
+
let m = 1n;
|
|
231
|
+
let p = 1n;
|
|
232
|
+
for (let i of k) {
|
|
233
|
+
s += i;
|
|
234
|
+
if (i >= m) {
|
|
235
|
+
[i, m] = [m, i];
|
|
236
|
+
}
|
|
237
|
+
p *= factorial(i);
|
|
238
|
+
}
|
|
239
|
+
return partialFactorial(m)(s) / p;
|
|
240
|
+
};
|
package/types/bigint/test.f.d.ts
CHANGED
package/types/bigint/test.f.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sum, abs, serialize, log2, bitLength, mask, min } from "./module.f.js";
|
|
1
|
+
import { sum, abs, serialize, log2, bitLength, mask, min, combination, factorial } from "./module.f.js";
|
|
2
2
|
const oldLog2 = (v) => {
|
|
3
3
|
if (v <= 0n) {
|
|
4
4
|
return -1n;
|
|
@@ -174,15 +174,19 @@ export default {
|
|
|
174
174
|
if (m !== 3n) {
|
|
175
175
|
throw m;
|
|
176
176
|
}
|
|
177
|
+
const c = combination(3n, 2n, 1n); // 60n
|
|
178
|
+
if (c !== 60n) {
|
|
179
|
+
throw c;
|
|
180
|
+
}
|
|
177
181
|
},
|
|
178
182
|
benchmark: () => {
|
|
179
183
|
const list = {
|
|
180
|
-
strBinLog2,
|
|
181
|
-
strHexLog2,
|
|
184
|
+
// strBinLog2,
|
|
185
|
+
// strHexLog2,
|
|
182
186
|
str32Log2,
|
|
183
|
-
oldLog2,
|
|
184
|
-
clz32Log2,
|
|
185
|
-
m1023log2,
|
|
187
|
+
// oldLog2,
|
|
188
|
+
// clz32Log2,
|
|
189
|
+
// m1023log2,
|
|
186
190
|
log2,
|
|
187
191
|
};
|
|
188
192
|
const transform = (b) => Object.fromEntries(Object.entries(list).map(([k, f]) => [k, b(f)]));
|
|
@@ -391,5 +395,61 @@ export default {
|
|
|
391
395
|
}
|
|
392
396
|
},
|
|
393
397
|
]
|
|
398
|
+
},
|
|
399
|
+
factorial: () => {
|
|
400
|
+
{
|
|
401
|
+
const r = factorial(3n);
|
|
402
|
+
if (r !== 6n) {
|
|
403
|
+
throw r;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
{
|
|
407
|
+
const r = factorial(5n);
|
|
408
|
+
if (r !== 120n) {
|
|
409
|
+
throw r;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
combination: () => {
|
|
414
|
+
const r = combination(2n, 3n);
|
|
415
|
+
if (r != 120n / (2n * 6n)) {
|
|
416
|
+
throw r;
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
combination50x50: () => {
|
|
420
|
+
{
|
|
421
|
+
const r = combination(1n, 1n);
|
|
422
|
+
if (r !== 2n) {
|
|
423
|
+
throw r;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
{
|
|
427
|
+
const r = combination(2n, 2n);
|
|
428
|
+
if (r !== 6n) {
|
|
429
|
+
throw r;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
{
|
|
433
|
+
const r = combination(3n, 3n);
|
|
434
|
+
if (r !== 20n) {
|
|
435
|
+
throw r;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
{
|
|
439
|
+
const r = combination(4n, 4n);
|
|
440
|
+
if (r !== 70n) {
|
|
441
|
+
throw r;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
combination3: () => {
|
|
446
|
+
const r = combination(2n, 3n, 4n, 2n);
|
|
447
|
+
// 2! * 3! * 4! * 2! : 2! * 2! * 3!
|
|
448
|
+
// 2+3+4+2 = 5*6*7*8*9*10*11
|
|
449
|
+
// e = 5 * 6 * 7 * 8 * 9 * 10 * 11 / (2n * 2n * 6n) =
|
|
450
|
+
// e = 5 * 7 * 2 * 9 * 10 * 11 = 69300
|
|
451
|
+
if (r !== 69300n) {
|
|
452
|
+
throw r;
|
|
453
|
+
}
|
|
394
454
|
}
|
|
395
455
|
};
|
|
@@ -4,3 +4,7 @@ export declare const sum: (input: List<number>) => number;
|
|
|
4
4
|
export declare const min: (input: List<number>) => number | null;
|
|
5
5
|
export declare const max: (input: List<number>) => number | null;
|
|
6
6
|
export declare const cmp: (a: number) => (b: number) => Sign;
|
|
7
|
+
/**
|
|
8
|
+
* Count a number of ones in 32 bit number
|
|
9
|
+
*/
|
|
10
|
+
export declare const countOnes: (n: number) => number;
|
package/types/number/module.f.js
CHANGED
|
@@ -5,3 +5,19 @@ export const sum = reduce(addition)(0);
|
|
|
5
5
|
export const min = reduce(minOp)(null);
|
|
6
6
|
export const max = reduce(maxOp)(null);
|
|
7
7
|
export const cmp = unsafeCmp;
|
|
8
|
+
const mo = [
|
|
9
|
+
[0x5555_5555, 1],
|
|
10
|
+
[0x3333_3333, 2],
|
|
11
|
+
[0x0F0F_0F0F, 4],
|
|
12
|
+
[0x00FF_00FF, 8],
|
|
13
|
+
[0x0000_FFFF, 16],
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Count a number of ones in 32 bit number
|
|
17
|
+
*/
|
|
18
|
+
export const countOnes = (n) => {
|
|
19
|
+
for (const [mask, offset] of mo) {
|
|
20
|
+
n = (n & mask) + ((n >> offset) & mask);
|
|
21
|
+
}
|
|
22
|
+
return n;
|
|
23
|
+
};
|
package/types/number/test.f.d.ts
CHANGED
package/types/number/test.f.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sum, min, max, cmp } from "./module.f.js";
|
|
1
|
+
import { sum, min, max, cmp, countOnes } from "./module.f.js";
|
|
2
2
|
export default {
|
|
3
3
|
sum: () => {
|
|
4
4
|
const result = sum([2, 3, 4, 5]);
|
|
@@ -34,7 +34,7 @@ export default {
|
|
|
34
34
|
},
|
|
35
35
|
standard: () => {
|
|
36
36
|
const check = a => b => {
|
|
37
|
-
if (BigInt(Number(a))
|
|
37
|
+
if (BigInt(Number(a)) !== b) {
|
|
38
38
|
throw [a, b];
|
|
39
39
|
}
|
|
40
40
|
};
|
|
@@ -119,5 +119,21 @@ export default {
|
|
|
119
119
|
// 4_3210_FEDC_BA98_7654_3210_FEDC_BA98_7654_3210_FEDC_BA98_7654_3210_1234
|
|
120
120
|
check(104002482718319358n)(104002482718319360n);
|
|
121
121
|
check(142693895881191444n)(142693895881191440n);
|
|
122
|
-
}
|
|
122
|
+
},
|
|
123
|
+
countOnes: [
|
|
124
|
+
() => {
|
|
125
|
+
// 1121 2231 = 5 + 8 = 13
|
|
126
|
+
const r = countOnes(0x1234_5678);
|
|
127
|
+
if (r !== 13) {
|
|
128
|
+
throw r;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
() => {
|
|
132
|
+
// 2232 3340 = 9 + 10 = 19
|
|
133
|
+
const r = countOnes(0x9ABC_DEF0);
|
|
134
|
+
if (r !== 19) {
|
|
135
|
+
throw r;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]
|
|
123
139
|
};
|