functionalscript 0.0.549 → 0.0.550

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.549",
3
+ "version": "0.0.550",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "module.f.cjs",
6
6
  "scripts": {
@@ -1,39 +1,54 @@
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
- */
1
+ const op = require('../types/function/operator/module.f.cjs')
2
+
3
+ /** @typedef {op.Reduce<bigint>} Reduce */
4
+
5
+ /** @typedef {op.Unary<bigint, bigint>} Unary*/
10
6
 
11
7
  /**
12
8
  * @typedef {{
9
+ * readonly p: bigint
13
10
  * readonly middle: bigint
14
11
  * 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
12
+ * readonly neg: Unary
13
+ * readonly sub: Reduce
14
+ * readonly add: Reduce
15
+ * readonly abs: Unary
16
+ * readonly mul: Reduce
17
+ * readonly reciprocal: Unary
18
+ * readonly div: Reduce
19
+ * readonly pow: Reduce
20
+ * readonly pow2: Unary
21
+ * readonly pow3: Unary
24
22
  * }} PrimeField
25
23
  */
26
24
 
25
+ /** @type {<T>(zero: T, add: op.Reduce<T>) => (a: T) => (n: bigint) => T} */
26
+ const scalar_mul = (zero, add) => a => n => {
27
+ let ai = a
28
+ let ni = n
29
+ let result = zero
30
+ while (true) {
31
+ if ((ni & 1n) === 1n) {
32
+ result = add(result)(ai)
33
+ }
34
+ ni >>= 1n
35
+ if (ni === 0n) {
36
+ return result
37
+ }
38
+ ai = add(ai)(ai)
39
+ }
40
+ }
41
+
27
42
  /** @type {(p: bigint) => PrimeField} */
28
43
  const prime_field = p => {
29
- /** @type {(a: bigint) => (b: bigint) => bigint} */
44
+ /** @type {Reduce} */
30
45
  const sub = a => b => {
31
46
  const r = a - b
32
47
  return r < 0 ? r + p : r
33
48
  }
34
- /** @type {(a: bigint) => (b: bigint) => bigint} */
49
+ /** @type {Reduce} */
35
50
  const mul = a => b => a * b % p
36
- /** @type {(a: bigint) => bigint} */
51
+ /** @type {Unary} */
37
52
  const reciprocal = a => {
38
53
  if (a === 0n) { throw '1/0' }
39
54
  let a1 = a
@@ -52,23 +67,12 @@ const prime_field = p => {
52
67
  return f1
53
68
  }
54
69
  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
- }
70
+ /** @type {Unary} */
71
+ const pow2 = a => mul(a)(a)
72
+ /** @type {Reduce} */
73
+ const pow = scalar_mul(1n, mul)
71
74
  return {
75
+ p,
72
76
  middle,
73
77
  max: p - 1n,
74
78
  neg: a => a === 0n ? 0n : p - a,
@@ -82,13 +86,21 @@ const prime_field = p => {
82
86
  reciprocal,
83
87
  div: a => b => mul(a)(reciprocal(b)),
84
88
  pow,
85
- sqrt: a => {
86
- const result = pow(a)(sqrt_k)
87
- return mul(result)(result) === a ? result : null
88
- }
89
+ pow2,
90
+ pow3: a => mul(a)(pow2(a))
89
91
  }
90
92
  }
91
93
 
92
94
  module.exports = {
93
- prime_field
95
+ scalar_mul,
96
+ prime_field,
97
+ /** @type {(f: PrimeField) => (a: bigint) => bigint|null} */
98
+ sqrt: ({p, mul, pow }) => {
99
+ if ((p & 3n) !== 3n) { throw 'sqrt' }
100
+ const sqrt_k = (p + 1n) >> 2n
101
+ return a => {
102
+ const result = pow(a)(sqrt_k)
103
+ return mul(result)(result) === a ? result : null
104
+ }
105
+ }
94
106
  }
@@ -1,9 +1,10 @@
1
- const { prime_field } = require('./module.f.cjs')
1
+ const { prime_field, sqrt } = require('./module.f.cjs')
2
2
 
3
3
  module.exports = {
4
4
  prime_field_test: () => {
5
5
  const p = 0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_fffffffe_fffffc2fn;
6
6
  const f = prime_field(p)
7
+ const sqrt_f = sqrt(f)
7
8
  return {
8
9
  neg: () => {
9
10
  if (f.neg(0n) !== 0n) { throw '-0' }
@@ -41,7 +42,7 @@ module.exports = {
41
42
  // a^(p-1) % p = 1
42
43
  if (f.abs(f.pow(a)(f.middle)) !== 1n) { throw '**middle' }
43
44
  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
+ if (f.pow(a)(f.max) !== 1n) { throw '**max' }
45
46
  }
46
47
  // 0
47
48
  if (f.pow(0n)(0n) !== 1n) { throw '0**0'}
@@ -70,7 +71,7 @@ module.exports = {
70
71
  /** @type {(a: bigint) => void} */
71
72
  const test = a => {
72
73
  const a2 = f.mul(a)(a)
73
- const s = f.sqrt(a2)
74
+ const s = sqrt_f(a2)
74
75
  if (s !== null && f.abs(s) !== f.abs(a)) { throw 'sqrt' }
75
76
  }
76
77
  let i = 1n
@@ -0,0 +1,119 @@
1
+ const op = require('../types/function/operator/module.f.cjs')
2
+ const pf = require('../prime_field/module.f.cjs')
3
+ const { scalar_mul, prime_field, sqrt } = pf
4
+
5
+ /** @typedef {readonly[bigint, bigint]} Point2D */
6
+
7
+ /** @typedef {Point2D|null} Point */
8
+
9
+ /**
10
+ * @typedef {{
11
+ * readonly p: bigint
12
+ * readonly a: readonly[bigint, bigint]
13
+ * readonly g: readonly[bigint, bigint]
14
+ * readonly n: bigint
15
+ * }} Init
16
+ */
17
+
18
+ /**
19
+ * @typedef {{
20
+ * readonly pf: pf.PrimeField
21
+ * readonly nf: pf.PrimeField
22
+ * readonly y2: (x: bigint) => bigint
23
+ * readonly y: (x: bigint) => bigint|null
24
+ * readonly neg: (a: Point) => Point
25
+ * readonly add: op.Reduce<Point>
26
+ * readonly mul: (a: Point) => (n: bigint) => Point
27
+ * }} Curve
28
+ */
29
+
30
+ /** @type {(i: Init) => Curve} */
31
+ const curve = ({ p, a: [a0, a1], n }) => {
32
+ const pf = prime_field(p)
33
+ const { pow2, pow3, sub, add, mul, neg, div } = pf
34
+ const mul3 = mul(3n)
35
+ const mul2 = mul(2n)
36
+ const addA1 = add(a1)
37
+ const mulA1 = mul(a1)
38
+ const addA0 = add(a0)
39
+ // y**2 = a1*x**3 + a0
40
+ /** @type {(x: bigint) => bigint} */
41
+ const y2 = x => addA0(add(pow3(x))(mulA1(x)))
42
+ /** @type {op.Reduce<Point>} */
43
+ const addPoint = p => q => {
44
+ if (p === null) {
45
+ return q
46
+ }
47
+ if (q === null) {
48
+ return p
49
+ }
50
+ const [px, py] = p
51
+ const [qx, qy] = q
52
+ const md = px === qx
53
+ // (3 * px ** 2 + a1) / (2 * py)
54
+ ? py !== qy || py === 0n ? null : [addA1(mul3(pow2(px))), mul2(py)]
55
+ // (py - qy) / (px - qx)
56
+ : [sub(py)(qy), sub(px)(qx)]
57
+ if (md === null) {
58
+ return null
59
+ }
60
+ const [ma, mb] = md
61
+ const m = div(ma)(mb)
62
+ // m ** 2 - px - qx
63
+ const rx = sub(pow2(m))(add(px)(qx))
64
+ // [rx, m * (px - rx) - py]
65
+ return [rx, sub(mul(m)(sub(px)(rx)))(py)]
66
+ }
67
+ const sqrt_p = sqrt(pf)
68
+ return {
69
+ pf,
70
+ nf: prime_field(n),
71
+ y2,
72
+ y: x => sqrt_p(y2(x)),
73
+ neg: p => {
74
+ if (p === null) {
75
+ return null
76
+ }
77
+ const [x, y] = p
78
+ return [x, neg(y)]
79
+ },
80
+ add: addPoint,
81
+ mul: scalar_mul(null, addPoint)
82
+ }
83
+ }
84
+
85
+ module.exports = {
86
+ curve,
87
+ /** @type {(a: Point) => (b: Point) => boolean} */
88
+ eq: a => b => {
89
+ if (a === null || b === null) {
90
+ return a === b
91
+ }
92
+ const [ax, ay] = a
93
+ const [bx, by] = b
94
+ return ax === bx && ay === by
95
+ },
96
+ /** @type {Init} */
97
+ secp256k1: {
98
+ p: 0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_fffffffe_fffffc2fn,
99
+ a: [7n, 0n],
100
+ g: [
101
+ 0x79be667e_f9dcbbac_55a06295_ce870b07_029bfcdb_2dce28d9_59f2815b_16f81798n,
102
+ 0x483ada77_26a3c465_5da4fbfc_0e1108a8_fd17b448_a6855419_9c47d08f_fb10d4b8n
103
+ ],
104
+ n: 0xffffffff_ffffffff_ffffffff_fffffffe_baaedce6_af48a03b_bfd25e8c_d0364141n,
105
+ },
106
+ /** @type {Init} */
107
+ secp192r1: {
108
+ p: 0xffffffff_ffffffff_ffffffff_fffffffe_ffffffff_ffffffffn,
109
+ a: [
110
+ 0x64210519_e59c80e7_0fa7e9ab_72243049_feb8deec_c146b9b1n,
111
+ 0xffffffff_ffffffff_ffffffff_fffffffe_ffffffff_fffffffcn
112
+ ],
113
+ g: [
114
+ 0x188da80e_b03090f6_7cbf20eb_43a18800_f4ff0afd_82ff1012n,
115
+ 0x07192b95_ffc8da78_631011ed_6b24cdd5_73f977a1_1e794811n
116
+ ],
117
+ n: 0xffffffff_ffffffff_ffffffff_99def836_146bc9b1_b4d22831n,
118
+ },
119
+ }
@@ -0,0 +1,48 @@
1
+ const m = require('./module.f.cjs')
2
+ const { curve, secp256k1, secp192r1, eq } = m
3
+
4
+ module.exports = {
5
+ test: () => {
6
+ /** @type {(c: m.Init) => void} */
7
+ const test_curve = c => {
8
+ const { g } = c
9
+ const { mul, neg, pf: { abs }, y: yf, nf: { p: n } } = curve(c)
10
+ /** @type {(p: m.Point) => void} */
11
+ const point_check = p => {
12
+ if (p === null) { throw 'null' }
13
+ const [x, y] = p
14
+ const ye = yf(x)
15
+ if (ye === null) { throw 'null' }
16
+ if (abs(ye) !== abs(y)) { throw 'ye' }
17
+ }
18
+ point_check(g)
19
+ point_check(neg(g))
20
+ /** @type {(p: m.Point) => void} */
21
+ const test_mul = p => {
22
+ if (mul(p)(0n) !== null) { throw 'O' }
23
+ if (mul(p)(1n) !== p) { throw 'p' }
24
+ if (mul(p)(n) !== null) { throw 'n' }
25
+ const pn = neg(p)
26
+ if (!eq(mul(p)(n - 1n))(pn)) { throw 'n - 1' }
27
+ /** @type {(s: bigint) => void} */
28
+ const f = s => {
29
+ const r = mul(p)(s)
30
+ point_check(r)
31
+ const rn = mul(pn)(s)
32
+ point_check(rn)
33
+ if (!eq(r)(neg(rn))) { throw 'r != -rn' }
34
+ }
35
+ f(2n)
36
+ f(3n)
37
+ f(4n << 128n)
38
+ f((5n << 128n) + 6n)
39
+ f(7n << 128n)
40
+ f((8n << 128n) + 9n)
41
+ }
42
+ test_mul(g)
43
+ test_mul(neg(g))
44
+ }
45
+ test_curve(secp256k1)
46
+ test_curve(secp192r1)
47
+ }
48
+ }