download
raw
2.27 kB
export function euclideanMod(x, y) {
const r = x % y;
if (r < 0n) {
return r + y;
}
return r;
}
export function inverseMod(a, n) {
if (n < 0) {
n = n * -1n;
}
if (a < 0) {
a = euclideanMod(a, n);
}
let dividend = a;
let divisor = n;
let remainder = dividend % divisor;
let quotient = dividend / divisor;
let s1 = 1n;
let s2 = 0n;
let s3 = s1 - quotient * s2;
while (remainder !== 0n) {
dividend = divisor;
divisor = remainder;
s1 = s2;
s2 = s3;
remainder = dividend % divisor;
quotient = dividend / divisor;
s3 = s1 - quotient * s2;
}
if (divisor !== 1n) {
throw new Error("a and n is not relatively prime");
}
if (s2 < 0) {
return s2 + n;
}
return s2;
}
export function powmod(x, y, p) {
let res = 1n; // Initialize result
x = x % p;
while (y > 0) {
if (y % 2n === 1n) {
res = euclideanMod(res * x, p);
}
y = y >> 1n;
x = euclideanMod(x * x, p);
}
return res;
}
// assumes p is prime
// https://en.wikipedia.org/wiki/Tonelli–Shanks_algorithm#The_algorithm
export function tonelliShanks(n, p) {
if (p % 4n === 3n) {
return powmod(n, (p + 1n) / 4n, p);
}
if (powmod(n, (p - 1n) / 2n, p) === p - 1n) {
throw new Error("Cannot find square root");
}
let q = p - 1n;
let s = 0n;
while (q % 2n === 0n) {
q = q / 2n;
s++;
}
let z = 2n;
while (powmod(z, (p - 1n) / 2n, p) !== p - 1n) {
z++;
}
let r = powmod(n, (q + 1n) / 2n, p);
let t = powmod(n, q, p);
let c = powmod(z, q, p);
let m = s;
// eslint-disable-next-line no-constant-condition
while (true) {
if (t === 1n) {
return r;
}
let i = 1n;
while (i <= m) {
if (i === m) {
throw new Error("Cannot find square root");
}
if (powmod(t, 2n ** i, p) === 1n) {
break;
}
i++;
}
const b = c ** (2n ** (m - i - 1n));
m = i;
c = b ** 2n % p;
t = (t * b ** 2n) % p;
r = (r * b) % p;
}
}

Xet Storage Details

Size:
2.27 kB
·
Xet hash:
f05162773ed435269c788ac45ab608f586f0228b85a3455f11c6484b5ed7a505

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.