MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / sqrtModPrime

Function sqrtModPrime

src/compute-engine/numerics/diophantine.ts:427–469  ·  view source on GitHub ↗

* Tonelli–Shanks: a single square root of `a` modulo an ODD PRIME `p`, in * `[0, p)`, or `null` if `a` is a quadratic non-residue. The other root is * `p − r`.

(a: bigint, p: bigint)

Source from the content-addressed store, hash-verified

425 * `p − r`.
426 */
427function sqrtModPrime(a: bigint, p: bigint): bigint | null {
428 a = ((a % p) + p) % p;
429 if (a === 0n) return 0n;
430 if (p === 2n) return a & 1n;
431 // Euler's criterion.
432 if (modPow(a, (p - 1n) / 2n, p) !== 1n) return null;
433 if (p % 4n === 3n) return modPow(a, (p + 1n) / 4n, p);
434
435 // Factor p − 1 = q·2^s with q odd.
436 let q = p - 1n;
437 let s = 0n;
438 while (q % 2n === 0n) {
439 q /= 2n;
440 s += 1n;
441 }
442 // Find a quadratic non-residue z.
443 let z = 2n;
444 while (modPow(z, (p - 1n) / 2n, p) !== p - 1n) z += 1n;
445
446 let m = s;
447 let cc = modPow(z, q, p);
448 let t = modPow(a, q, p);
449 let r = modPow(a, (q + 1n) / 2n, p);
450 let guard = 0;
451 while (t !== 1n) {
452 if (++guard > MAX_ITERATIONS) throw new DiophantineBudgetError();
453 // Least i, 0 < i < m, with t^(2^i) = 1.
454 let i = 0n;
455 let t2 = t;
456 while (t2 !== 1n) {
457 t2 = (t2 * t2) % p;
458 i += 1n;
459 if (i === m) return null; // should not happen for a QR
460 }
461 let b = cc;
462 for (let j = 0n; j < m - i - 1n; j++) b = (b * b) % p;
463 m = i;
464 cc = (b * b) % p;
465 t = (t * cc) % p;
466 r = (r * b) % p;
467 }
468 return r;
469}
470
471/**
472 * All roots of `x² ≡ a (mod pᵏ)` for an ODD prime `p`, `k ≥ 1`, sorted

Callers 1

sqrtUnitOddPrimePowerFunction · 0.85

Calls 1

modPowFunction · 0.90

Tested by

no test coverage detected