Data update

This commit is contained in:
Ingy döt Net 2025-08-11 18:05:26 -07:00
parent 4d5544505c
commit 4924dd0264
3073 changed files with 55820 additions and 4408 deletions

View file

@ -0,0 +1,122 @@
class Pair {
final int n;
final int p;
Pair(this.n, this.p);
}
class Solution {
final int root1;
final int root2;
final bool isSquare;
Solution(this.root1, this.root2, this.isSquare);
}
int multiplyModulus(int a, int b, int modulus) {
a %= modulus;
b %= modulus;
if (b < a) {
var temp = a;
a = b;
b = temp;
}
int result = 0;
while (a > 0) {
if (a % 2 == 1) {
result = (result + b) % modulus;
}
b = (b << 1) % modulus;
a >>= 1;
}
return result;
}
int powerModulus(int base, int exponent, int modulus) {
if (modulus == 1) return 0;
base %= modulus;
int result = 1;
while (exponent > 0) {
if ((exponent & 1) == 1) {
result = multiplyModulus(result, base, modulus);
}
base = multiplyModulus(base, base, modulus);
exponent >>= 1;
}
return result;
}
int legendre(int a, int p) {
return powerModulus(a, (p - 1) ~/ 2, p);
}
Solution tonelliShanks(int n, int p) {
if (legendre(n, p) != 1) {
return Solution(0, 0, false);
}
// Factor out powers of 2 from p - 1
int q = p - 1;
int s = 0;
while (q % 2 == 0) {
q ~/= 2;
s += 1;
}
if (s == 1) {
int result = powerModulus(n, (p + 1) ~/ 4, p);
return Solution(result, p - result, true);
}
// Find a non-square z such that (z | p) = -1
int z = 2;
while (legendre(z, p) != p - 1) {
z += 1;
}
int c = powerModulus(z, q, p);
int t = powerModulus(n, q, p);
int m = s;
int result = powerModulus(n, (q + 1) ~/ 2, p);
while (t != 1) {
int i = 1;
int zTemp = multiplyModulus(t, t, p);
while (zTemp != 1 && i < m - 1) {
i += 1;
zTemp = multiplyModulus(zTemp, zTemp, p);
}
int b = powerModulus(c, 1 << (m - i - 1), p);
c = multiplyModulus(b, b, p);
t = multiplyModulus(t, c, p);
m = i;
result = multiplyModulus(result, b, p);
}
return Solution(result, p - result, true);
}
void main() {
final List<Pair> tests = [
Pair(10, 13),
Pair(56, 101),
Pair(1030, 1009),
Pair(1032, 1009),
Pair(44402, 100049),
Pair(665820697, 1000000009),
Pair(881398088036, 1000000000039),
];
for (final test in tests) {
final solution = tonelliShanks(test.n, test.p);
print('n = ${test.n}, p = ${test.p}');
if (solution.isSquare) {
print('has solutions: ${solution.root1} and ${solution.root2}\n');
} else {
print('has no solutions because n is not a square modulo p\n');
}
}
}

View file

@ -0,0 +1,67 @@
(* Legendre symbol *)
LegendreSymbol[a_, p_] := PowerMod[a, (p - 1)/2, p]
(* Tonelli-Shanks Algorithm *)
Tonelli[n_, p_] := Module[
{q, s, z, c, r, t, m, t2, i, b},
(* Check that n is a quadratic residue mod p *)
If[LegendreSymbol[n, p] =!= 1,
Message[Tonelli::notsquare, n, p]; Abort[]];
(* Step 1: Factor out powers of 2 from p - 1 *)
q = p - 1;
s = 0;
While[EvenQ[q], q = q/2; s++];
(* Special case when s == 1 *)
If[s == 1,
Return[PowerMod[n, (p + 1)/4, p]]
];
(* Find a non-residue z *)
For[z = 2, z < p, z++,
If[LegendreSymbol[z, p] == p - 1, Break[]]
];
(* Initialize variables *)
c = PowerMod[z, q, p];
r = PowerMod[n, (q + 1)/2, p];
t = PowerMod[n, q, p];
m = s;
(* Main loop *)
While[Mod[t - 1, p] =!= 0,
t2 = Mod[t^2, p];
For[i = 1, i < m, i++,
If[Mod[t2 - 1, p] === 0, Break[]];
t2 = Mod[t2^2, p];
];
b = PowerMod[c, 2^(m - i - 1), p];
r = Mod[r*b, p];
c = Mod[b^2, p];
t = Mod[t*c, p];
m = i;
];
r
]
(* Test cases *)
ttest = {
{10, 13},
{56, 101},
{1030, 10009},
{44402, 100049},
{665820697, 1000000009},
{881398088036, 1000000000039},
{41660815127637347468140745042827704103445750172002, 10^50 + 577}
};
Do[
n = ttest[[i, 1]];
p = ttest[[i, 2]];
r = Tonelli[n, p];
Assert[Mod[r^2 - n, p] == 0];
Print["n = ", n, ", p = ", p];
Print["\troots : ", r, " ", p - r],
{i, Length[ttest]}
]

View file

@ -0,0 +1,123 @@
/* Legendre symbol */
legendresymbol(a, p) =
{
lift(Mod(a, p)^((p-1)/2));
}
/* Tonelli-Shanks Algorithm */
tonelli(n, p) =
{
local(q, s, z, c, r, t, m, t2, i, b);
/* Check that n is a quadratic residue mod p */
if(legendresymbol(n, p) != 1,
error("n is not a quadratic residue mod p"));
/* Step 1: Factor out powers of 2 from p - 1 */
q = p - 1;
s = 0;
while(q % 2 == 0,
q = q/2;
s++
);
/* Special case when s == 1 */
if(s == 1,
return(lift(Mod(n, p)^((p+1)/4)))
);
/* Find a non-residue z */
z = 2;
while(z < p,
if(legendresymbol(z, p) == p - 1, break());
z++
);
/* Initialize variables */
c = lift(Mod(z, p)^q);
r = lift(Mod(n, p)^((q+1)/2));
t = lift(Mod(n, p)^q);
m = s;
/* Main loop */
while((t - 1) % p != 0,
t2 = t^2 % p;
i = 1;
while(i < m,
if((t2 - 1) % p == 0, break());
t2 = t2^2 % p;
i++
);
b = lift(Mod(c, p)^(2^(m - i - 1)));
r = (r * b) % p;
c = b^2 % p;
t = (t * c) % p;
m = i
);
return(r);
}
/* Test the functions */
print("Testing Tonelli-Shanks algorithm:");
print();
/* Test case 1 */
n = 10; p = 13;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 2 */
n = 56; p = 101;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 3 */
n = 1030; p = 10009;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 4 */
n = 44402; p = 100049;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 5 */
n = 665820697; p = 1000000009;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 6 */
n = 881398088036; p = 1000000000039;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();
/* Test case 7 */
n = 41660815127637347468140745042827704103445750172002; p = 100000000000000000000000000000000000000000000000577;
r = tonelli(n, p);
print("n = ", n, ", p = ", p);
print("roots: ", r, ", ", p - r);
print("verification: ", r, "^2 mod ", p, " = ", r^2 % p);
print();

View file

@ -0,0 +1,98 @@
library(gmp) # For handling large integers and modular arithmetic
# Legendre symbol: a^((p-1)/2) mod p
legendre <- function(a, p) {
a <- as.bigz(a)
p <- as.bigz(p)
e <- div.bigz(sub.bigz(p, 1), 2)
result <- powm(a, e, p)
return(result)
}
# Tonelli-Shanks algorithm to find square root of n mod p
tonelli <- function(n, p) {
n <- as.bigz(n)
p <- as.bigz(p)
# Check that n is a quadratic residue
leg <- legendre(n, p)
if (!identical(as.character(leg), "1")) {
stop("not a square (mod p)")
}
q <- sub.bigz(p, 1)
s <- 0
while (mod.bigz(q, 2) == 0) {
q <- div.bigz(q, 2)
s <- s + 1
}
if (s == 1) {
e <- div.bigz(add.bigz(p, 1), 4)
return(powm(n, e, p))
}
z <- as.bigz(2)
p_minus_1 <- sub.bigz(p, 1)
while (z < p) {
if (identical(as.character(legendre(z, p)), as.character(p_minus_1))) {
break
}
z <- add.bigz(z, 1)
}
c <- powm(z, q, p)
r <- powm(n, div.bigz(add.bigz(q, 1), 2), p)
t <- powm(n, q, p)
m <- s
one <- as.bigz(1)
two <- as.bigz(2)
while (!identical(mod.bigz(sub.bigz(t, one), p), as.bigz(0))) {
t2 <- mod.bigz(mul.bigz(t, t), p)
i <- 1
while (i < m) {
if (identical(mod.bigz(sub.bigz(t2, one), p), as.bigz(0))) {
break
}
t2 <- mod.bigz(mul.bigz(t2, t2), p)
i <- i + 1
}
b_exp <- pow.bigz(two, m - i - 1)
b <- powm(c, b_exp, p)
r <- mod.bigz(mul.bigz(r, b), p)
c <- mod.bigz(mul.bigz(b, b), p)
t <- mod.bigz(mul.bigz(t, c), p)
m <- i
}
return(r)
}
# Test cases
ttest <- list(
c("10", "13"),
c("56", "101"),
c("1030", "10009"),
c("44402", "100049"),
c("665820697", "1000000009"),
c("881398088036", "1000000000039"),
c("41660815127637347468140745042827704103445750172002", "100000000000000000000000000000000000000000000000577")
)
for (case in ttest) {
n <- as.bigz(case[1])
p <- as.bigz(case[2])
r <- tonelli(n, p)
check <- mod.bigz(sub.bigz(mul.bigz(r, r), n), p)
# Verify the result
if (!identical(as.character(check), "0")) {
stop("Verification failed")
}
cat("n =", as.character(n), "p =", as.character(p), "\n")
cat("\troots :", as.character(r), as.character(sub.bigz(p, r)), "\n")
}

View file

@ -0,0 +1,106 @@
import java.math.BigInteger
import scala.collection.immutable.List
import scala.annotation.tailrec
object TonelliShanks {
private val ZERO = BigInteger.ZERO
private val ONE = BigInteger.ONE
private val TEN = BigInteger.TEN
private val TWO = BigInteger.valueOf(2)
private val FOUR = BigInteger.valueOf(4)
private case class Solution(root1: BigInteger, root2: BigInteger, exists: Boolean)
private def ts(n: Long, p: Long): Solution = ts(BigInteger.valueOf(n), BigInteger.valueOf(p))
private def ts(n: BigInteger, p: BigInteger): Solution = {
val powModP: (BigInteger, BigInteger) => BigInteger = (a, e) => a.modPow(e, p)
val ls: BigInteger => BigInteger = a => powModP(a, p.subtract(ONE).divide(TWO))
if (!ls(n).equals(ONE)) return Solution(ZERO, ZERO, false)
var q = p.subtract(ONE)
var ss = ZERO
while (q.and(ONE).equals(ZERO)) {
ss = ss.add(ONE)
q = q.shiftRight(1)
}
if (ss.equals(ONE)) {
val r1 = powModP(n, p.add(ONE).divide(FOUR))
return Solution(r1, p.subtract(r1), true)
}
var z = TWO
while (!ls(z).equals(p.subtract(ONE))) z = z.add(ONE)
var c = powModP(z, q)
var r = powModP(n, q.add(ONE).divide(TWO))
var t = powModP(n, q)
var m = ss
// Convert the while(true) loop to a tail-recursive function
@tailrec
def loop(r: BigInteger, c: BigInteger, t: BigInteger, m: BigInteger): Solution = {
if (t.equals(ONE)) {
Solution(r, p.subtract(r), true)
} else {
var i = ZERO
var zz = t
while (!zz.equals(BigInteger.ONE) && i.compareTo(m.subtract(ONE)) < 0) {
zz = zz.multiply(zz).mod(p)
i = i.add(ONE)
}
var b = c
var e = m.subtract(i).subtract(ONE)
while (e.compareTo(ZERO) > 0) {
b = b.multiply(b).mod(p)
e = e.subtract(ONE)
}
val newR = r.multiply(b).mod(p)
val newC = b.multiply(b).mod(p)
val newT = t.multiply(newC).mod(p)
val newM = i
loop(newR, newC, newT, newM)
}
}
loop(r, c, t, m)
}
def main(args: Array[String]): Unit = {
val pairs = List(
(10L, 13L),
(56L, 101L),
(1030L, 10009L),
(1032L, 10009L),
(44402L, 100049L),
(665820697L, 1000000009L),
(881398088036L, 1000000000039L)
)
for ((n, p) <- pairs) {
val sol = ts(n, p)
println(s"n = $n")
println(s"p = $p")
if (sol.exists) {
println(s"root1 = ${sol.root1}")
println(s"root2 = ${sol.root2}")
} else {
println("No solution exists")
}
println()
}
val bn = new BigInteger("41660815127637347468140745042827704103445750172002")
val bp = TEN.pow(50).add(BigInteger.valueOf(577))
val sol = ts(bn, bp)
println(s"n = $bn")
println(s"p = $bp")
if (sol.exists) {
println(s"root1 = ${sol.root1}")
println(s"root2 = ${sol.root2}")
} else {
println("No solution exists")
}
}
}