functionalscript 0.0.547 → 0.0.549
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/.github/workflows/ci.yml +1 -1
- package/package.json +4 -4
- package/prime_field/module.f.cjs +94 -0
- package/prime_field/test.f.cjs +86 -0
package/.github/workflows/ci.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functionalscript",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.549",
|
|
4
4
|
"description": "FunctionalScript is a functional subset of JavaScript",
|
|
5
5
|
"main": "module.f.cjs",
|
|
6
6
|
"scripts": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git+https://github.com/functionalscript/functionalscript.git"
|
|
16
16
|
},
|
|
17
|
-
"author": "
|
|
17
|
+
"author": "Sergey Shandar",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"keywords": [
|
|
20
20
|
"lambda",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"homepage": "https://github.com/functionalscript/functionalscript#readme",
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"typescript": "^5.
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"typescript": "^5.5.4"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{
|
|
3
|
+
* readonly p: bigint
|
|
4
|
+
* readonly a: bigint
|
|
5
|
+
* readonly b: bigint
|
|
6
|
+
* readonly g: readonly[bigint, bigint]
|
|
7
|
+
* readonly n: bigint
|
|
8
|
+
* }} Curve
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{
|
|
13
|
+
* readonly middle: bigint
|
|
14
|
+
* readonly max: bigint
|
|
15
|
+
* readonly neg: (a: bigint) => bigint
|
|
16
|
+
* readonly sub: (a: bigint) => (b: bigint) => bigint
|
|
17
|
+
* readonly add: (a: bigint) => (b: bigint) => bigint
|
|
18
|
+
* readonly abs: (a: bigint) => bigint
|
|
19
|
+
* readonly mul: (a: bigint) => (b: bigint) => bigint
|
|
20
|
+
* readonly reciprocal: (a: bigint) => bigint
|
|
21
|
+
* readonly div: (a: bigint) => (b: bigint) => bigint
|
|
22
|
+
* readonly pow: (a: bigint) => (b: bigint) => bigint
|
|
23
|
+
* readonly sqrt: (a: bigint) => bigint|null
|
|
24
|
+
* }} PrimeField
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** @type {(p: bigint) => PrimeField} */
|
|
28
|
+
const prime_field = p => {
|
|
29
|
+
/** @type {(a: bigint) => (b: bigint) => bigint} */
|
|
30
|
+
const sub = a => b => {
|
|
31
|
+
const r = a - b
|
|
32
|
+
return r < 0 ? r + p : r
|
|
33
|
+
}
|
|
34
|
+
/** @type {(a: bigint) => (b: bigint) => bigint} */
|
|
35
|
+
const mul = a => b => a * b % p
|
|
36
|
+
/** @type {(a: bigint) => bigint} */
|
|
37
|
+
const reciprocal = a => {
|
|
38
|
+
if (a === 0n) { throw '1/0' }
|
|
39
|
+
let a1 = a
|
|
40
|
+
let a0 = p
|
|
41
|
+
let f0 = 0n
|
|
42
|
+
let f1 = 1n
|
|
43
|
+
while (a1 !== 1n) {
|
|
44
|
+
const q = a0 / a1
|
|
45
|
+
const a2 = a0 % a1
|
|
46
|
+
a0 = a1
|
|
47
|
+
a1 = a2
|
|
48
|
+
const f2 = sub(f0)(mul(f1)(q))
|
|
49
|
+
f0 = f1
|
|
50
|
+
f1 = f2
|
|
51
|
+
}
|
|
52
|
+
return f1
|
|
53
|
+
}
|
|
54
|
+
const middle = p >> 1n
|
|
55
|
+
if ((p & 3n) !== 3n) { throw 'sqrt' }
|
|
56
|
+
const sqrt_k = (p + 1n) >> 2n
|
|
57
|
+
/** @type {(a: bigint) => (n: bigint) => bigint} */
|
|
58
|
+
const pow = a => n => {
|
|
59
|
+
let result = 1n
|
|
60
|
+
while (true) {
|
|
61
|
+
if ((n & 1n) === 1n) {
|
|
62
|
+
result = mul(result)(a)
|
|
63
|
+
}
|
|
64
|
+
n >>= 1n
|
|
65
|
+
if (n === 0n) {
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
68
|
+
a = mul(a)(a)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
middle,
|
|
73
|
+
max: p - 1n,
|
|
74
|
+
neg: a => a === 0n ? 0n : p - a,
|
|
75
|
+
sub,
|
|
76
|
+
add: a => b => {
|
|
77
|
+
const r = a + b
|
|
78
|
+
return r < p ? r : r - p
|
|
79
|
+
},
|
|
80
|
+
abs: a => middle < a ? p - a : a,
|
|
81
|
+
mul,
|
|
82
|
+
reciprocal,
|
|
83
|
+
div: a => b => mul(a)(reciprocal(b)),
|
|
84
|
+
pow,
|
|
85
|
+
sqrt: a => {
|
|
86
|
+
const result = pow(a)(sqrt_k)
|
|
87
|
+
return mul(result)(result) === a ? result : null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
prime_field
|
|
94
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const { prime_field } = require('./module.f.cjs')
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
prime_field_test: () => {
|
|
5
|
+
const p = 0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_fffffffe_fffffc2fn;
|
|
6
|
+
const f = prime_field(p)
|
|
7
|
+
return {
|
|
8
|
+
neg: () => {
|
|
9
|
+
if (f.neg(0n) !== 0n) { throw '-0' }
|
|
10
|
+
if (f.neg(1n) !== p - 1n) { throw '-1' }
|
|
11
|
+
},
|
|
12
|
+
sub: () => {
|
|
13
|
+
if (f.sub(10n)(4n) !== 6n) { throw '10 - 4'}
|
|
14
|
+
if (f.sub(11n)(14n) !== p - 3n) { throw '11 - 14' }
|
|
15
|
+
},
|
|
16
|
+
add: () => {
|
|
17
|
+
if (f.add(13n)(24n) !== 37n) { throw '13 + 24' }
|
|
18
|
+
if (f.add(77n)(f.neg(12n)) !== 65n) { throw '77 + (-12)' }
|
|
19
|
+
},
|
|
20
|
+
mul: () => {
|
|
21
|
+
if (f.mul(100n)(0n) !== 0n) { throw '100 * 0' }
|
|
22
|
+
if (f.mul(101n)(205n) !== 20_705n) { throw '101 * 205' }
|
|
23
|
+
if (f.mul(304n)(f.neg(1n)) !== f.neg(304n)) { throw '304 * -1' }
|
|
24
|
+
if (f.mul(f.neg(507n))(609n) !== f.neg(308_763n)) { throw '-507 * 609' }
|
|
25
|
+
if (f.mul(f.neg(713n))(f.neg(825n)) !== 588_225n) { throw '-713 * -825' }
|
|
26
|
+
},
|
|
27
|
+
reciprocal: () => {
|
|
28
|
+
let i = 1n
|
|
29
|
+
while (i < 10_000n) {
|
|
30
|
+
const x = f.reciprocal(i)
|
|
31
|
+
if (f.mul(x)(i) !== 1n) { throw i }
|
|
32
|
+
++i
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
pow: () => {
|
|
36
|
+
/** @type {(a: bigint) => void} */
|
|
37
|
+
const test = a => {
|
|
38
|
+
if (f.pow(a)(0n) !== 1n) { throw '**0'}
|
|
39
|
+
if (f.pow(a)(1n) !== a) { throw '**1' }
|
|
40
|
+
// https://en.wikipedia.org/wiki/Fermat%27s_little_theorem
|
|
41
|
+
// a^(p-1) % p = 1
|
|
42
|
+
if (f.abs(f.pow(a)(f.middle)) !== 1n) { throw '**middle' }
|
|
43
|
+
if (f.pow(a)(f.sub(f.max)(1n)) !== f.reciprocal(a)) { throw '**(max-1)' }
|
|
44
|
+
if (f.pow(a)(f.max) !== 1n) { throw '**max-1' }
|
|
45
|
+
}
|
|
46
|
+
// 0
|
|
47
|
+
if (f.pow(0n)(0n) !== 1n) { throw '0**0'}
|
|
48
|
+
if (f.pow(0n)(f.max) !== 0n) { throw '0**max' }
|
|
49
|
+
// 1
|
|
50
|
+
test(1n)
|
|
51
|
+
// 2
|
|
52
|
+
test(2n)
|
|
53
|
+
if (f.pow(2n)(2n) !== 4n) { throw '2**2' }
|
|
54
|
+
if (f.pow(2n)(3n) !== 8n) { throw '2**3' }
|
|
55
|
+
if (f.pow(2n)(128n) !== 1n << 128n) { throw '2**128' }
|
|
56
|
+
// 3
|
|
57
|
+
test(3n)
|
|
58
|
+
if (f.pow(3n)(2n) !== 9n) { throw '3**2' }
|
|
59
|
+
if (f.pow(3n)(3n) !== 27n) { throw '3**3' }
|
|
60
|
+
if (f.pow(3n)(100n) !== 3n ** 100n) { throw '3**100' }
|
|
61
|
+
if (f.pow(3n)(110n) !== 3n ** 110n) { throw '3**110' }
|
|
62
|
+
if (f.pow(3n)(120n) !== 3n ** 120n) { throw '3**120' }
|
|
63
|
+
if (f.pow(3n)(121n) !== 3n ** 121n) { throw '3**121' }
|
|
64
|
+
//
|
|
65
|
+
test(f.middle)
|
|
66
|
+
test(f.max - 1n)
|
|
67
|
+
test(f.max)
|
|
68
|
+
},
|
|
69
|
+
sqrt: () => {
|
|
70
|
+
/** @type {(a: bigint) => void} */
|
|
71
|
+
const test = a => {
|
|
72
|
+
const a2 = f.mul(a)(a)
|
|
73
|
+
const s = f.sqrt(a2)
|
|
74
|
+
if (s !== null && f.abs(s) !== f.abs(a)) { throw 'sqrt' }
|
|
75
|
+
}
|
|
76
|
+
let i = 1n
|
|
77
|
+
while (i < 1000n) {
|
|
78
|
+
test(i)
|
|
79
|
+
++i;
|
|
80
|
+
}
|
|
81
|
+
test(f.middle);
|
|
82
|
+
test(f.max);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|