functionalscript
Version:
FunctionalScript is a purely functional subset of JavaScript
78 lines (77 loc) • 1.89 kB
JavaScript
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;
};
};