functionalscript 0.0.549 → 0.0.551

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