Data update
This commit is contained in:
parent
72eb4943cb
commit
4d5544505c
2347 changed files with 62432 additions and 16731 deletions
|
|
@ -0,0 +1,113 @@
|
|||
class TonelliShanks {
|
||||
static ts(n, p) {
|
||||
// Convert to BigInt if not already
|
||||
n = typeof n === 'bigint' ? n : BigInt(n);
|
||||
p = typeof p === 'bigint' ? p : BigInt(p);
|
||||
|
||||
const ZERO = BigInt(0);
|
||||
const ONE = BigInt(1);
|
||||
const TWO = BigInt(2);
|
||||
|
||||
// Helper function for modular exponentiation
|
||||
const powModP = (a, e) => {
|
||||
let result = BigInt(1);
|
||||
a = a % p;
|
||||
while (e > ZERO) {
|
||||
if (e % TWO === ONE) {
|
||||
result = (result * a) % p;
|
||||
}
|
||||
e = e / TWO;
|
||||
a = (a * a) % p;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// Legendre symbol calculation
|
||||
const ls = (a) => powModP(a, (p - ONE) / TWO);
|
||||
|
||||
if (ls(n) !== ONE) return { root1: ZERO, root2: ZERO, exists: false };
|
||||
|
||||
let q = p - ONE;
|
||||
let ss = ZERO;
|
||||
while (q % TWO === ZERO) {
|
||||
ss += ONE;
|
||||
q /= TWO;
|
||||
}
|
||||
|
||||
if (ss === ONE) {
|
||||
const r1 = powModP(n, (p + ONE) / BigInt(4));
|
||||
return { root1: r1, root2: p - r1, exists: true };
|
||||
}
|
||||
|
||||
let z = TWO;
|
||||
while (ls(z) !== p - ONE) z += ONE;
|
||||
|
||||
let c = powModP(z, q);
|
||||
let r = powModP(n, (q + ONE) / TWO);
|
||||
let t = powModP(n, q);
|
||||
let m = ss;
|
||||
|
||||
while (true) {
|
||||
if (t === ONE) return { root1: r, root2: p - r, exists: true };
|
||||
|
||||
let i = ZERO;
|
||||
let zz = t;
|
||||
while (zz !== ONE && i < m - ONE) {
|
||||
zz = (zz * zz) % p;
|
||||
i += ONE;
|
||||
}
|
||||
|
||||
let b = c;
|
||||
let e = m - i - ONE;
|
||||
while (e > ZERO) {
|
||||
b = (b * b) % p;
|
||||
e -= ONE;
|
||||
}
|
||||
|
||||
r = (r * b) % p;
|
||||
c = (b * b) % p;
|
||||
t = (t * c) % p;
|
||||
m = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main function
|
||||
function main() {
|
||||
const pairs = [
|
||||
[10n, 13n],
|
||||
[56n, 101n],
|
||||
[1030n, 10009n],
|
||||
[1032n, 10009n],
|
||||
[44402n, 100049n],
|
||||
[665820697n, 1000000009n],
|
||||
[881398088036n, 1000000000039n]
|
||||
];
|
||||
|
||||
for (const [n, p] of pairs) {
|
||||
const sol = TonelliShanks.ts(n, p);
|
||||
console.log(`n = ${n}`);
|
||||
console.log(`p = ${p}`);
|
||||
if (sol.exists) {
|
||||
console.log(`root1 = ${sol.root1}`);
|
||||
console.log(`root2 = ${sol.root2}`);
|
||||
} else {
|
||||
console.log("No solution exists");
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
const bn = 41660815127637347468140745042827704103445750172002n;
|
||||
const bp = BigInt(10) ** 50n + 577n;
|
||||
const sol = TonelliShanks.ts(bn, bp);
|
||||
console.log(`n = ${bn}`);
|
||||
console.log(`p = ${bp}`);
|
||||
if (sol.exists) {
|
||||
console.log(`root1 = ${sol.root1}`);
|
||||
console.log(`root2 = ${sol.root2}`);
|
||||
} else {
|
||||
console.log("No solution exists");
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
120
Task/Tonelli-Shanks-algorithm/Rust/tonelli-shanks-algorithm.rs
Normal file
120
Task/Tonelli-Shanks-algorithm/Rust/tonelli-shanks-algorithm.rs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
struct Pair {
|
||||
n: u64,
|
||||
p: u64,
|
||||
}
|
||||
|
||||
struct Solution {
|
||||
root1: u64,
|
||||
root2: u64,
|
||||
is_square: bool,
|
||||
}
|
||||
|
||||
fn multiply_modulus(a: u64, b: u64, modulus: u64) -> u64 {
|
||||
let mut a = a % modulus;
|
||||
let mut b = b % modulus;
|
||||
|
||||
if b < a {
|
||||
std::mem::swap(&mut a, &mut b);
|
||||
}
|
||||
|
||||
let mut result = 0;
|
||||
while a > 0 {
|
||||
if a % 2 == 1 {
|
||||
result = (result + b) % modulus;
|
||||
}
|
||||
b = (b << 1) % modulus;
|
||||
a >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn power_modulus(base: u64, exponent: u64, modulus: u64) -> u64 {
|
||||
if modulus == 1 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut base = base % modulus;
|
||||
let mut result = 1;
|
||||
let mut exponent = exponent;
|
||||
|
||||
while exponent > 0 {
|
||||
if (exponent & 1) == 1 {
|
||||
result = multiply_modulus(result, base, modulus);
|
||||
}
|
||||
base = multiply_modulus(base, base, modulus);
|
||||
exponent >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn legendre(a: u64, p: u64) -> u64 {
|
||||
power_modulus(a, (p - 1) / 2, p)
|
||||
}
|
||||
|
||||
fn tonelli_shanks(n: u64, p: u64) -> Solution {
|
||||
if legendre(n, p) != 1 {
|
||||
return Solution { root1: 0, root2: 0, is_square: false };
|
||||
}
|
||||
|
||||
// Factor out powers of 2 from p - 1
|
||||
let mut q = p - 1;
|
||||
let mut s = 0;
|
||||
while q % 2 == 0 {
|
||||
q /= 2;
|
||||
s += 1;
|
||||
}
|
||||
|
||||
if s == 1 {
|
||||
let result = power_modulus(n, (p + 1) / 4, p);
|
||||
return Solution { root1: result, root2: p - result, is_square: true };
|
||||
}
|
||||
|
||||
// Find a non-square z such as ( z | p ) = -1
|
||||
let mut z = 2;
|
||||
while legendre(z, p) != p - 1 {
|
||||
z += 1;
|
||||
}
|
||||
|
||||
let mut c = power_modulus(z, q, p);
|
||||
let mut t = power_modulus(n, q, p);
|
||||
let mut m = s;
|
||||
let mut result = power_modulus(n, (q + 1) >> 1, p);
|
||||
|
||||
while t != 1 {
|
||||
let mut i = 1;
|
||||
let mut z = multiply_modulus(t, t, p);
|
||||
while z != 1 && i < m - 1 {
|
||||
i += 1;
|
||||
z = multiply_modulus(z, z, p);
|
||||
}
|
||||
let b = power_modulus(c, 1 << (m - i - 1), p);
|
||||
c = multiply_modulus(b, b, p);
|
||||
t = multiply_modulus(t, c, p);
|
||||
m = i;
|
||||
result = multiply_modulus(result, b, p);
|
||||
}
|
||||
|
||||
Solution { root1: result, root2: p - result, is_square: true }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let tests = vec![
|
||||
Pair { n: 10, p: 13 },
|
||||
Pair { n: 56, p: 101 },
|
||||
Pair { n: 1030, p: 1009 },
|
||||
Pair { n: 1032, p: 1009 },
|
||||
Pair { n: 44402, p: 100049 },
|
||||
Pair { n: 665820697, p: 1000000009 },
|
||||
Pair { n: 881398088036, p: 1000000000039 },
|
||||
];
|
||||
|
||||
for test in tests {
|
||||
let solution = tonelli_shanks(test.n, test.p);
|
||||
print!("n = {}, p = {}", test.n, test.p);
|
||||
if solution.is_square {
|
||||
println!(" has solutions: {} and {}\n", solution.root1, solution.root2);
|
||||
} else {
|
||||
println!(" has no solutions because n is not a square modulo p\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
128
Task/Tonelli-Shanks-algorithm/Zig/tonelli-shanks-algorithm.zig
Normal file
128
Task/Tonelli-Shanks-algorithm/Zig/tonelli-shanks-algorithm.zig
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
const std = @import("std");
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
const Pair = struct {
|
||||
n: u64,
|
||||
p: u64,
|
||||
};
|
||||
|
||||
const Solution = struct {
|
||||
root1: u64,
|
||||
root2: u64,
|
||||
is_square: bool,
|
||||
};
|
||||
|
||||
fn multiplyModulus(a: u64, b: u64, modulus: u64) u64 {
|
||||
var a_mod = a % modulus;
|
||||
var b_mod = b % modulus;
|
||||
|
||||
if (b_mod < a_mod) {
|
||||
const temp = a_mod;
|
||||
a_mod = b_mod;
|
||||
b_mod = temp;
|
||||
}
|
||||
|
||||
var result: u64 = 0;
|
||||
var a_temp = a_mod;
|
||||
var b_temp = b_mod;
|
||||
|
||||
while (a_temp > 0) {
|
||||
if (a_temp % 2 == 1) {
|
||||
result = (result + b_temp) % modulus;
|
||||
}
|
||||
b_temp = (b_temp << 1) % modulus;
|
||||
a_temp >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn powerModulus(base: u64, exponent: u64, modulus: u64) u64 {
|
||||
if (modulus == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var base_mod = base % modulus;
|
||||
var result: u64 = 1;
|
||||
var exp = exponent;
|
||||
|
||||
while (exp > 0) {
|
||||
if ((exp & 1) == 1) {
|
||||
result = multiplyModulus(result, base_mod, modulus);
|
||||
}
|
||||
base_mod = multiplyModulus(base_mod, base_mod, modulus);
|
||||
exp >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn legendre(a: u64, p: u64) u64 {
|
||||
return powerModulus(a, (p - 1) / 2, p);
|
||||
}
|
||||
|
||||
fn tonelliShanks(n: u64, p: u64) Solution {
|
||||
if (legendre(n, p) != 1) {
|
||||
return Solution{ .root1 = 0, .root2 = 0, .is_square = false };
|
||||
}
|
||||
|
||||
// Factor out powers of 2 from p - 1
|
||||
var q = p - 1;
|
||||
var s: u64 = 0;
|
||||
while (q % 2 == 0) {
|
||||
q /= 2;
|
||||
s += 1;
|
||||
}
|
||||
|
||||
if (s == 1) {
|
||||
const result = powerModulus(n, (p + 1) / 4, p);
|
||||
return Solution{ .root1 = result, .root2 = p - result, .is_square = true };
|
||||
}
|
||||
|
||||
// Find a non-square z such as ( z | p ) = -1
|
||||
var z: u64 = 2;
|
||||
while (legendre(z, p) != p - 1) {
|
||||
z += 1;
|
||||
}
|
||||
|
||||
var c = powerModulus(z, q, p);
|
||||
var t = powerModulus(n, q, p);
|
||||
var m = s;
|
||||
var result = powerModulus(n, (q + 1) >> 1, p);
|
||||
|
||||
while (t != 1) {
|
||||
var i: u64 = 1;
|
||||
var z_temp = multiplyModulus(t, t, p);
|
||||
while (z_temp != 1 and i < m - 1) {
|
||||
i += 1;
|
||||
z_temp = multiplyModulus(z_temp, z_temp, p);
|
||||
}
|
||||
const b = powerModulus(c, @as(u64, 1) << @as( u6, @intCast(m - i - 1)), p);
|
||||
c = multiplyModulus(b, b, p);
|
||||
t = multiplyModulus(t, c, p);
|
||||
m = i;
|
||||
result = multiplyModulus(result, b, p);
|
||||
}
|
||||
|
||||
return Solution{ .root1 = result, .root2 = p - result, .is_square = true };
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
const tests = [_]Pair{
|
||||
.{ .n = 10, .p = 13 },
|
||||
.{ .n = 56, .p = 101 },
|
||||
.{ .n = 1030, .p = 1009 },
|
||||
.{ .n = 1032, .p = 1009 },
|
||||
.{ .n = 44402, .p = 100049 },
|
||||
.{ .n = 665820697, .p = 1000000009 },
|
||||
.{ .n = 881398088036, .p = 1000000000039 },
|
||||
};
|
||||
|
||||
for (tests) |my_test| {
|
||||
const solution = tonelliShanks(my_test.n, my_test.p);
|
||||
try stdout.print("n = {}, p = {}", .{ my_test.n, my_test.p });
|
||||
if (solution.is_square) {
|
||||
try stdout.print(" has solutions: {} and {}\n\n", .{ solution.root1, solution.root2 });
|
||||
} else {
|
||||
try stdout.print(" has no solutions because n is not a square modulo p\n\n", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue