UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

78 lines (77 loc) 1.89 kB
import { repeat } from "../../types/monoid/module.f.js"; /** * Creates a prime field with the specified prime modulus and associated operations. * * @param p - A prime number to define the field. * @returns The prime field object. */ export const prime_field = (p) => { const sub = a => b => { const r = a - b; return r < 0 ? r + p : r; }; const mul = a => b => a * b % p; const reciprocal = a => { if (a === 0n) { throw '1/0'; } let a1 = a; let a0 = p; let f0 = 0n; let f1 = 1n; while (a1 !== 1n) { const q = a0 / a1; const a2 = a0 % a1; a0 = a1; a1 = a2; const f2 = sub(f0)(mul(f1)(q)); f0 = f1; f1 = f2; } return f1; }; const middle = p >> 1n; const pow2 = a => mul(a)(a); const pow = repeat({ identity: 1n, operation: mul }); return { p, middle, max: p - 1n, neg: a => a === 0n ? 0n : p - a, sub, add: a => b => { const r = a + b; return r < p ? r : r - p; }, abs: a => middle < a ? p - a : a, mul, reciprocal, div: a => b => mul(a)(reciprocal(b)), pow, pow2, pow3: a => mul(a)(pow2(a)) }; }; /** * Computes the square root of a number in a prime field. * * @throws If the prime modulus `p` does not satisfy `p % 4 == 3`. * * @example * * ```js * const field = prime_field(7n); * const root = sqrt(field)(4n); * if (root !== 2n) { throw root } * ``` */ export const sqrt = ({ p, mul, pow }) => { if ((p & 3n) !== 3n) { throw 'sqrt'; } const sqrt_k = (p + 1n) >> 2n; return a => { const result = pow(a)(sqrt_k); return mul(result)(result) === a ? result : null; }; };