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.
@@ -29,7 +29,7 @@ jobs:
29
29
 
30
30
  strategy:
31
31
  matrix:
32
- node-version: [16.x, 18.x, 20.x, 21.x]
32
+ node-version: [16.x, 18.x, 20.x, 22.x]
33
33
  # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
34
34
 
35
35
  steps:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.547",
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": "NatFoam",
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": "^20.5.1",
34
- "typescript": "^5.1.6"
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
+ }