Tonelli-Shanks algorithm: Difference between revisions

m
(Replaced deprecated "ArithmeticError" with "ValueError". Added some spaces to improve readability.)
m (→‎{{header|Wren}}: Minor tidy)
 
(15 intermediate revisions by 9 users not shown)
Line 1:
{{task}}
{{wikipedia}}
'''Tonelli–Shanks algorithm'''
In computational number theory, the [https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm Tonelli–Shanks algorithm] is a technique for solving an equation of the form:
 
<big><big>
::: x<sup>2</sup> ≡ n (mod p)
</big></big>
 
─── where &nbsp; '''n''' &nbsp; is an integer which is a quadratic residue (mod p), &nbsp; '''p''' &nbsp; is an odd prime, &nbsp; and
 
<big><big>
::: x,n &nbsp; Є &nbsp; Fp = {0, 1, ... p-1}
</big></big>
 
In computational number theory, the [[wp:Tonelli–Shanks algorithm|Tonelli–Shanks algorithm]] is a technique for solving for '''x''' in a congruence of the form:
<big>
:: x<sup>2</sup> ≡ n (mod p)
</big>
where '''n''' is an integer which is a quadratic residue (mod p), '''p''' is an odd prime, and '''x,n ∈ F<sub>p</sub>''' where F<sub>p</sub> = {0, 1, ..., p - 1}.
 
It is used in [https://en.wikipedia.org/wiki/Rabin_cryptosystem cryptography] techniques.
 
 
To apply the algorithm, we need the Legendre symbol.:
 
The Legendre symbol '''(a | p)''' denotes the value of a<sup>(p-1)/2</sup> (mod p).
Legendre symbol
* '''(a | p) ≡ 1''' &nbsp;&nbsp; if '''a''' is a square (mod p)
* '''(a | p) ≡ -1''' &nbsp;&nbsp; if '''a''' is not a square (mod p)
* '''(a | p) ≡ 0''' &nbsp;&nbsp; if '''a''' ≡ 0 (mod p)
 
* The Legendre symbol ( a | p) denotes the value of a ^ ((p-1)/2) (mod p)
* (a | p) ≡ &nbsp; 1 &nbsp; &nbsp; if a is a square (mod p)
* (a | p) ≡ -1 &nbsp; &nbsp; if a is not a square (mod p)
* (a | p) ≡ &nbsp; 0 &nbsp; &nbsp; if a ≡ 0
 
;Algorithm pseudo-code:
<big>
All ≡ are taken to mean (mod p) unless stated otherwise.
 
* Input: '''p''' an odd prime, and an integer '''n''' .
;Algorithm pseudo-code: (copied from Wikipedia):
* Step 0: Check that '''n''' is indeed a square: (n | p) must be ≡ 1 .
 
* Step 1: By factoring out powers of 2 from p - 1, find '''q''' and '''s''' such that p - 1 = q2<sup>s</sup> with '''q''' odd .
All &nbsp; ≡ &nbsp; are taken to mean &nbsp; (mod p) &nbsp; unless stated otherwise.
** If p ≡ 3 (mod 4) (i.e. s = 1), output the two solutions r ≡ ± n<sup>(p+1)/4</sup> .
 
* Step 2: Select a non-square '''z''' such that (z | p) ≡ -1 and set c ≡ z<sup>q</sup> .
* Input : p an odd prime, and an integer n .
* Step 3: Set r ≡ n<sup>(q+1)/2</sup>, t ≡ n<sup>q</sup>, m = s .
* Step 0. Check that n is indeed a square : (n | p) must be ≡ 1
* Step 4: Loop the following:
* Step 1. [Factors out powers of 2 from p-1] Define q -odd- and s such as p-1 = q * 2^s
** ifIf st = 1 , i.e p ≡ 3 (mod 4) , output the two solutions '''r''' and '''p +/- n^((p+1)/4)r''' .
** StepOtherwise 2.find, Selectby arepeated non-squaresquaring, zthe suchlowest as'''i''', (z0 |< p)i =< -1m , andsuch setthat ct<sup>2<sup>i</sup></sup> z^q1 .
** StepLet 3.b Set rc<sup>2<sup>(m - i n- ^((q+1)</2)sup></sup>, and set r ≡ rb, t ≡ n^qtb<sup>2</sup>, c ≡ b<sup>2</sup> and m = si .
</big>
* Step 4. Loop.
** if t ≡ 1 output r, p-r .
** Otherwise find, by repeated squaring, the lowest i , 0 < i< m , such as t^(2^i) ≡ 1
** Let b ≡ c^(2^(m-i-1)), and set r ≡ r*b, t ≡ t*b^2 , c ≡ b^2 and m = i.
 
 
;Numerical Example:
* n=10, p= 13. &nbsp; See [https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm Wikipedia]
 
 
;Task:
Implement the above algorithm.
 
Find solutions (if any) for
Line 57 ⟶ 46:
* n = 1032 p = 10009
* n = 44402 p = 100049
 
;Extra credit:
Line 69 ⟶ 57:
* [[Cipolla's algorithm]]
<br><br>
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F legendre(a, p)
R pow(a, (p - 1) I/ 2, p)
 
F tonelli(n, p)
assert(legendre(n, p) == 1, ‘not a square (mod p)’)
V q = p - 1
V s = 0
L q % 2 == 0
q I/= 2
s++
I s == 1
R pow(n, (p + 1) I/ 4, p)
V z = 2
L
I p - 1 == legendre(z, p)
L.break
z++
V c = pow(z, q, p)
V r = pow(n, (q + 1) I/ 2, p)
V t = pow(n, q, p)
V m = s
V t2 = BigInt(0)
L (t - 1) % p != 0
t2 = (t * t) % p
V i = 1
L(ii) 1 .< m
I (t2 - 1) % p == 0
i = ii
L.break
t2 = (t2 * t2) % p
V b = pow(c, Int64(1 << (m - i - 1)), p)
r = (r * b) % p
c = (b * b) % p
t = (t * c) % p
m = i
R r
 
V ttest = [(BigInt(10), BigInt(13)), (BigInt(56), BigInt(101)), (BigInt(1030), BigInt(10009)), (BigInt(44402), BigInt(100049)),
(BigInt(665820697), BigInt(1000000009)), (BigInt(881398088036), BigInt(1000000000039)),
(BigInt(‘41660815127637347468140745042827704103445750172002’), BigInt(10) ^ 50 + 577)]
L(n, p) ttest
V r = tonelli(n, p)
assert((r * r - n) % p == 0)
print(‘n = #. p = #.’.format(n, p))
print("\t roots : #. #.".format(r, p - r))</syntaxhighlight>
 
{{out}}
<pre>
n = 10 p = 13
roots : 7 6
n = 56 p = 101
roots : 37 64
n = 1030 p = 10009
roots : 1632 8377
n = 44402 p = 100049
roots : 30468 69581
n = 665820697 p = 1000000009
roots : 378633312 621366697
n = 881398088036 p = 1000000000039
roots : 791399408049 208600591990
n = 41660815127637347468140745042827704103445750172002 p = 100000000000000000000000000000000000000000000000577
roots : 32102985369940620849741983987300038903725266634508 67897014630059379150258016012699961096274733366069
</pre>
 
=={{header|AArch64 Assembly}}==
{{works with|as|Raspberry Pi 3B version Buster 64 bits <br> or android 64 bits with application Termux }}
<syntaxhighlight lang="aarch64 assembly">
<lang AArch64 Assembly>
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
/* program tonshan64.s */
Line 513 ⟶ 568:
/* for this file see task include a file in language AArch64 assembly */
.include "../includeARM64.inc"
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 524 ⟶ 579:
Program normal end.
</pre>
 
=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<syntaxhighlight lang="arm assembly">
<lang ARM Assembly>
/* ARM assembly Raspberry PI or android 32 bits */
/* program tonshan.s */
Line 947 ⟶ 1,003:
/***************************************************/
.include "../affichage.inc"
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 959 ⟶ 1,015:
</pre>
=={{header|C}}==
=== Version 1 ===
{{trans|C#}}
<langsyntaxhighlight lang="c">#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
Line 1,061 ⟶ 1,118:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>n = 10
Line 1,086 ⟶ 1,143:
root1 = 30468
root2 = 69581</pre>
 
=== Version 2 ===
<syntaxhighlight lang="c">
// return (a * b) % mod, avoiding overflow errors while doing modular multiplication.
static unsigned multiplication_modulo(unsigned a, unsigned b, const unsigned mod) {
unsigned res = 0, tmp;
for (b %= mod; a; a & 1 ? b >= mod - res ? res -= mod : 0, res += b : 0, a >>= 1, (tmp = b) >= mod - b ? tmp -= mod : 0, b += tmp);
return res % mod;
}
 
// return (n ^ exp) % mod
static unsigned mod_pow(unsigned n, unsigned exp, const unsigned mod) {
unsigned res = 1;
for (n %= mod; exp; exp & 1 ? res = multiplication_modulo(res, n, mod) : 0, n = multiplication_modulo(n, n, mod), exp >>= 1);
return res;
}
 
static unsigned tonelli_shanks_1(const unsigned n, const unsigned mod) {
// return root such that (root * root) % mod congruent to n % mod.
// return 0 if no solution to the congruence exists.
// mod is assumed odd prime.
const unsigned a = n % mod;
unsigned res, b, c, d, e, f, g, h;
if (mod_pow(a, (mod - 1) >> 1, mod) != 1)
res = 0;
else
switch (mod & 7) {
case 3 : case 7 :
res = mod_pow(a, (mod + 1) >> 2, mod);
break;
case 5 :
res = mod_pow(a, (mod + 3) >> 3, mod);
if (multiplication_modulo(res, res, mod) != a){
b = mod_pow(2, (mod - 1) >> 2, mod);
res = multiplication_modulo(res, b, mod);
}
break;
default :
if (a == 1)
res = 1;
else {
for (c = mod - 1, d = 2; d < mod && mod_pow(d, c >> 1, mod) != c; ++d);
for (e = 0; !(c & 1); ++e, c >>= 1);
f = mod_pow(a, c, mod);
b = mod_pow(d, c, mod);
for (h = 0, g = 0; h < e; h++) {
d = mod_pow(b, g, mod);
d = multiplication_modulo(d, f, mod);
d = mod_pow(d, 1 << (e - 1 - h), mod);
if (d == mod - 1)
g += 1 << h;
}
f = mod_pow(a, (c + 1) >> 1, mod);
b = mod_pow(b, g >> 1, mod);
res = multiplication_modulo(f, b, mod);
}
}
return res;
}
 
// return root such that (root * root) % mod congruent to n % mod.
// return 0 (the default value of a) if no solution to the congruence exists.
static unsigned tonelli_shanks_2(unsigned n, const unsigned mod) {
unsigned a = 0, b = mod - 1, c, d = b, e = 0, f = 2, g;
if (mod_pow(n, b >> 1, mod) == 1) {
for (; !(d & 1); ++e, d >>= 1);
if (e == 1)
a = mod_pow(n, (mod + 1) >> 2, mod);
else {
for (; b != mod_pow(f, b >> 1, mod); ++f);
for (b = mod_pow(f, d, mod), a = mod_pow(n, (d + 1) >> 1, mod), c = mod_pow(n, d, mod), g = e; c != 1; g = d) {
for (d = 0, e = c, --g; e != 1 && d < g; ++d)
e = multiplication_modulo(e, e, mod);
for (f = b, n = g - d; n--;)
f = multiplication_modulo(f, f, mod);
a = multiplication_modulo(a, f, mod);
b = multiplication_modulo(f, f, mod);
c = multiplication_modulo(c, b, mod);
}
}
}
return a;
}
 
#include <assert.h>
int main() {
unsigned n, mod, root ; /* root_2 = mod - root */
 
n = 27875, mod = 26371, root = tonelli_shanks_1(n, mod);
assert(root == 14320); // 14320 * 14320 mod 26371 = 1504 and 1504 = 27875 mod 26371
 
n = 1111111111, mod = 1111111121, root = tonelli_shanks_1(n, mod);
assert(root == 88664850);
 
n = 5258, mod = 3851, root = tonelli_shanks_1(n, mod);
assert(root == 0); // no solution to the congruence exists.
}
</syntaxhighlight>
 
A is assumed odd prime, the algorithm requires O(log A + r * r) multiplications modulo A, where r is the power of 2 dividing A − 1.
 
=={{header|C sharp|C#}}==
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Numerics;
Line 1,204 ⟶ 1,361:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>n = 10
Line 1,244 ⟶ 1,401:
root1 = 32102985369940620849741983987300038903725266634508
root2 = 67897014630059379150258016012699961096274733366069</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cstdint>
#include <iostream>
#include <vector>
 
struct Pair {
uint64_t n;
uint64_t p;
};
 
struct Solution {
uint64_t root1;
uint64_t root2;
bool is_square;
};
 
uint64_t multiply_modulus(uint64_t a, uint64_t b, const uint64_t& modulus) {
a %= modulus; b %= modulus;
if ( b < a ) {
uint64_t temp = a; a = b; b = temp;
}
 
uint64_t result = 0;
while ( a > 0 ) {
if ( a % 2 == 1 ) {
result = ( result + b ) % modulus;
};
b = ( b << 1 ) % modulus;
a >>= 1;
}
return result;
}
 
uint64_t power_modulus(uint64_t base, uint64_t exponent, const uint64_t& modulus) {
if ( modulus == 1 ) {
return 0;
}
 
base %= modulus;
uint64_t result = 1;
while ( exponent > 0 ) {
if ( ( exponent & 1 ) == 1 ) {
result = multiply_modulus(result, base, modulus);
}
base = multiply_modulus(base, base, modulus);
exponent >>= 1;
}
return result;
}
 
uint64_t legendre(const uint64_t& a, const uint64_t& p) {
return power_modulus(a, ( p - 1 ) / 2, p);
}
 
Solution tonelli_shanks(const uint64_t& n, const uint64_t& p) {
if ( legendre(n, p) != 1 ) {
return Solution(0, 0, false);
}
 
// Factor out powers of 2 from p - 1
uint64_t q = p - 1;
uint64_t s = 0;
while ( q % 2 == 0 ) {
q /= 2;
s += 1;
}
 
if ( s == 1 ) {
uint64_t result = power_modulus(n, ( p + 1 ) / 4, p);
return Solution(result, p - result, true);
}
 
// Find a non-square z such as ( z | p ) = -1
uint64_t z = 2;
while ( legendre(z, p) != p - 1 ) {
z += 1;
}
 
uint64_t c = power_modulus(z, q, p);
uint64_t t = power_modulus(n, q, p);
uint64_t m = s;
uint64_t result = power_modulus(n, ( q + 1 ) >> 1, p);
 
while ( t != 1 ) {
uint64_t i = 1;
z = multiply_modulus(t, t, p);
while ( z != 1 && i < m - 1 ) {
i += 1;
z = multiply_modulus(z, z, p);
}
uint64_t 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);
}
return Solution(result, p - result, true);
}
 
int main() {
const std::vector<Pair> tests = { Pair(10, 13), Pair(56, 101), Pair(1030, 1009), Pair(1032, 1009),
Pair(44402, 100049), Pair(665820697, 1000000009), Pair(881398088036, 1000000000039) };
 
for ( const Pair& test : tests ) {
Solution solution = tonelli_shanks(test.n, test.p);
std::cout << "n = " << test.n << ", p = " << test.p;
if ( solution.is_square == true ) {
std::cout << " has solutions: " << solution.root1 << " and " << solution.root2 << std::endl << std::endl;
} else {
std::cout << " has no solutions because n is not a square modulo p" << std::endl << std::endl;
}
}
}
</syntaxhighlight>
{{ out }}
<pre>
n = 10, p = 13 has solutions: 7 and 6
 
n = 56, p = 101 has solutions: 37 and 64
 
n = 1030, p = 1009 has solutions: 651 and 358
 
n = 1032, p = 1009 has no solutions because n is not a square modulo p
 
n = 44402, p = 100049 has solutions: 30468 and 69581
 
n = 665820697, p = 1000000009 has solutions: 378633312 and 621366697
 
n = 881398088036, p = 1000000000039 has solutions: 791399408049 and 208600591990
</pre>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">
(defn find-first
" Finds first element of collection that satisifies predicate function pred "
Line 1,303 ⟶ 1,592:
(println (format "n: %5d p: %d \n\troots: %5d %5d" (biginteger n) (biginteger p) (biginteger r) (biginteger (- p r)))))
 
</syntaxhighlight>
</lang>
{{out}}
n: 10 p: 13
Line 1,322 ⟶ 1,611:
=={{header|D}}==
{{trans|Kotlin}}
<langsyntaxhighlight Dlang="d">import std.bigint;
import std.stdio;
import std.typecons;
Line 1,441 ⟶ 1,730:
}
else writeln("No solution exists");
}</langsyntaxhighlight>
 
{{out}}
Line 1,484 ⟶ 1,773:
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
(require 'bigint)
;; test equality mod p
Line 1,526 ⟶ 1,815:
(mod:≡ t (* t c) p)
(set! m i)))))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,567 ⟶ 1,856:
=={{header|FreeBASIC}}==
===LongInt version===
<langsyntaxhighlight FreeBASIClang="freebasic">' version 11-04-2017
' compile with: fbc -s console
' maximum for p is 17 digits to be on the save side
Line 1,729 ⟶ 2,018:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>Find solution for n = 10 and p = 13
Line 1,753 ⟶ 2,042:
===GMP version===
{{libheader|GMP}}
<langsyntaxhighlight lang="freebasic">' version 12-04-2017
' compile with: fbc -s console
 
Line 1,883 ⟶ 2,172:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>Find solution for n = 10 and p = 13
Line 1,912 ⟶ 2,201:
===int===
Implementation following Wikipedia, using similar variable names, and using the int type for simplicity.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,988 ⟶ 2,277:
fmt.Println(ts(1032, 10009))
fmt.Println(ts(44402, 100049))
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,999 ⟶ 2,288:
===big.Int===
For the extra credit, we use big.Int from the math/big package of the Go standard library. While the method call syntax is not as easy on the eyes as operator syntax, the package provides modular exponentiation and even the Legendre symbol as the Jacobi function.
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,070 ⟶ 2,359:
fmt.Println(&R1)
fmt.Println(&R2)
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,080 ⟶ 2,369:
===Library===
It gets better; the library has a ModSqrt function that uses Tonelli-Shanks internally. Output is same as above.
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,107 ⟶ 2,396:
fmt.Println(&R1)
fmt.Println(&R2)
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
{{trans|Python}}
<langsyntaxhighlight lang="haskell">import Data.List (genericTake, genericLength)
import Data.Bits (shiftR)
 
Line 2,152 ⟶ 2,441:
c' = (b*b) `mod` p
t' = (t*c') `mod` p
in loop i c' r' t'</langsyntaxhighlight>
 
<pre>λ> tonelli 10 13
Line 2,176 ⟶ 2,465:
Implementation:
 
<langsyntaxhighlight Jlang="j">leg=: dyad define
x (y&|)@^ (y-1)%2
)
Line 2,204 ⟶ 2,493:
end.
y|(,-)r
)</langsyntaxhighlight>
 
Task examples:
 
<langsyntaxhighlight Jlang="j"> 10 tosh 13
7 6
56 tosh 101
Line 2,224 ⟶ 2,513:
791399408049 208600591990
41660815127637347468140745042827704103445750172002x tosh (10^50x)+577
32102985369940620849741983987300038903725266634508 67897014630059379150258016012699961096274733366069</langsyntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
{{works with|Java|9}}
<langsyntaxhighlight Javalang="java">import java.math.BigInteger;
import java.util.List;
import java.util.Map;
Line 2,340 ⟶ 2,629:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>n = 10
Line 2,380 ⟶ 2,669:
root1 = 32102985369940620849741983987300038903725266634508
root2 = 67897014630059379150258016012699961096274733366069</pre>
 
=={{header|jq}}==
'''Works with gojq and fq, two Go implementations of jq'''
 
'''Adapted from [[#Wren|Wren]]'''
 
The Go implementations of jq provide indefinite-precision integer
arithmetic.
 
See [[Modular_exponentiation]] for suitable jq definitions of `power/1` and `modPow/2` as used here.
<syntaxhighlight lang=jq>
include "rc-modular-exponentiation"; # see remark above
 
# If $j is 0, then an error condition is raised;
# otherwise, assuming infinite-precision integer arithmetic,
# if the input and $j are integers, then the result will be an integer.
def idivide($j):
. as $i
| ($i % $j) as $mod
| ($i - $mod) / $j ;
 
def Solution(a;b;c):
{"root1": a, "root2": b, "exists": c};
 
# pretty print a Solution
def pp:
if .exists
then "root1 = \(.root1)",
"root2 = \(.root2)"
else "No solution exists"
end;
 
# Tonelli-Shanks
def ts($n; $p):
def powModP($a; $e): $a | modPow($e; $p);
 
def ls($a): powModP($a; ($p - 1) | idivide(2));
 
if ls($n) != 1 then Solution(0; 0; false)
else { q: ($p - 1), ss: 0}
| until (.q % 2 != 0;
.ss += 1
| .q |= idivide(2) )
| if .ss == 1
then powModP(n; ($p+1) | idivide(4)) as $r1
| Solution($r1; $p - $r1; true)
else .z = 2
| until ( ls(.z) == ($p - 1); .z += 1 )
| .c = powModP(.z; .q)
| .r = powModP($n; (.q+1) | idivide(2))
| .t = powModP($n; .q)
| .m = .ss
| until (.emit;
if .t == 1 then .emit = Solution(.r; $p - .r; true)
else .i = 0
| .zz = .t
| until (.zz == 1 or .i >= (.m - 1);
.zz = (.zz * .zz) % p
| .i += 1 )
| .b = .c
| .e = .m - (1 + .i)
| until (.e <= 0;
.b = (.b * .b) % $p
| .e += -1 )
| .r = (.r * .b) % $p
| .c = (.b * .b) % $p
| .t = (.t * .c) % $p
| .m = .i
end )
| .emit
end
end;
def pairs: [
[10, 13], [56, 101], [1030, 10009], [1032, 10009], [44402, 100049],
[665820697, 1000000009], [881398088036, 1000000000039]
];
 
def task:
pairs[] as [$n, $p]
| ts($n; $p) as $sol
| "n = \($n)",
"p = \($p)",
($sol | pp),
"";
 
def task2:
def bn: 41660815127637347468140745042827704103445750172002;
def bp: (10 | power(50)) + 577;
ts(bn; bp) as $bsol
| "n = \(bn)",
"p = \(bp)",
( $bsol | pp );
 
task, task2
</syntaxhighlight>
{{output}}
See [[#Wren|Wren]].
 
=={{header|Julia}}==
Line 2,385 ⟶ 2,772:
 
'''Module''':
<langsyntaxhighlight lang="julia">module TonelliShanks
 
legendre(a, p) = powermod(a, (p - 1) ÷ 2, p)
Line 2,426 ⟶ 2,813:
end
 
end # module TonelliShanks</langsyntaxhighlight>
 
'''Main''':
<langsyntaxhighlight lang="julia">@show TonelliShanks.solve(10, 13)
@show TonelliShanks.solve(56, 101)
@show TonelliShanks.solve(1030, 10009)
Line 2,435 ⟶ 2,822:
@show TonelliShanks.solve(665820697, 1000000009)
@show TonelliShanks.solve(881398088036, 1000000000039)
@show TonelliShanks.solve(41660815127637347468140745042827704103445750172002, big"10" ^ 50 + 577)</langsyntaxhighlight>
 
{{out}}
Line 2,448 ⟶ 2,835:
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
import java.math.BigInteger
Line 2,543 ⟶ 2,930:
}
else println("No solution exists")
}</langsyntaxhighlight>
 
{{out}}
Line 2,591 ⟶ 2,978:
Based algorithm pseudo-code, referencing python 3.
 
<langsyntaxhighlight Nimlang="nim">proc pow*[T: SomeInteger](x, n, p: T): T =
var t = x mod p
var e = n
Line 2,655 ⟶ 3,042:
run(1032, 10009)
run(44402, 100049)
run(665820697, 1000000009)</langsyntaxhighlight>
 
output:
Line 2,664 ⟶ 3,051:
30468 69581
378633312 621366697</pre>
 
=={{header|OCaml}}==
{{trans|Java}}
{{libheader|zarith}}
An extra test case has been added for the `s = 1` branch.
<syntaxhighlight lang="ocaml">let tonelli n p =
let open Z in
let two = ~$2 in
let pp = pred p in
let pph = pred p / two in
let pow_mod_p a e = powm a e p in
let legendre_p a = pow_mod_p a pph in
 
if legendre_p n <> one then None
else
let s = trailing_zeros pp in
if s = 1 then
let r = pow_mod_p n (succ p / ~$4) in
Some (r, p - r)
else
let q = pp asr s in
let z =
let rec find_non_square z =
if legendre_p z = pp then z else find_non_square (succ z)
in
find_non_square two
in
let rec loop c r t m =
if t = one then (r, p - r)
else
let mp = pred m in
let rec find_i n i =
if n = one || i >= mp then i else find_i (n * n mod p) (succ i)
in
let rec exp_pow2 b e =
if e <= zero then b else exp_pow2 (b * b mod p) (pred e)
in
let i = find_i t zero in
let b = exp_pow2 c (mp - i) in
let c = b * b mod p in
loop c (r * b mod p) (t * c mod p) i
in
Some
(loop (pow_mod_p z q) (pow_mod_p n (succ q / two)) (pow_mod_p n q) ~$s)
 
let () =
let open Z in
[
(~$9, ~$11);
(~$10, ~$13);
(~$56, ~$101);
(~$1030, ~$10009);
(~$1032, ~$10009);
(~$44402, ~$100049);
(~$665820697, ~$1000000009);
(~$881398088036, ~$1000000000039);
( of_string "41660815127637347468140745042827704103445750172002",
pow ~$10 50 + ~$577 );
]
|> List.iter (fun (n, p) ->
Printf.printf "n = %s\np = %s\n%!" (to_string n) (to_string p);
match tonelli n p with
| Some (r1, r2) ->
Printf.printf "root1 = %s\nroot2 = %s\n\n%!" (to_string r1)
(to_string r2)
| None -> print_endline "No solution exists\n")
</syntaxhighlight>
 
{{out}}
<pre>
n = 9
p = 11
root1 = 3
root2 = 8
 
n = 10
p = 13
root1 = 7
root2 = 6
 
n = 56
p = 101
root1 = 37
root2 = 64
 
n = 1030
p = 10009
root1 = 1632
root2 = 8377
 
n = 1032
p = 10009
No solution exists
 
n = 44402
p = 100049
root1 = 30468
root2 = 69581
 
n = 665820697
p = 1000000009
root1 = 378633312
root2 = 621366697
 
n = 881398088036
p = 1000000000039
root1 = 791399408049
root2 = 208600591990
 
n = 41660815127637347468140745042827704103445750172002
p = 100000000000000000000000000000000000000000000000577
root1 = 32102985369940620849741983987300038903725266634508
root2 = 67897014630059379150258016012699961096274733366069
 
</pre>
 
=={{header|Perl}}==
{{trans|Raku}}
{{libheader|ntheory}}
<langsyntaxhighlight lang="perl">use bigint;
use ntheory qw(is_prime powmod kronecker);
 
Line 2,725 ⟶ 3,227:
printf "Roots of %d are (%d, %d) mod %d\n", $n, $t, $p-$t, $p;
}
}</langsyntaxhighlight>
{{out}}
<pre>Roots of 10 are (7, 6) mod 13
Line 2,738 ⟶ 3,240:
{{trans|C#}}
{{libheader|Phix/mpfr}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>include mpfr.e
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
function ts(string ns, ps)
mpz n = mpz_init(ns),
<span style="color: #008080;">function</span> <span style="color: #000000;">ts</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">ns</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ps</span><span style="color: #0000FF;">)</span>
p = mpz_init(ps),
<span style="color: #004080;">mpz</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ns</span><span style="color: #0000FF;">),</span>
t = mpz_init(),
<span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ps</span><span style="color: #0000FF;">),</span>
r = mpz_init(),
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
pm1 = mpz_init(),
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
pm2 = mpz_init()
<span style="color: #000000;">pm1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(),</span>
mpz_sub_ui(pm1,p,1) -- pm1 = p-1
<span style="color: #000000;">pm2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
mpz_fdiv_q_2exp(pm2,pm1,1) -- pm2 = pm1/2
<span style="color: #7060A8;">mpz_sub_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pm1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- pm1 = p-1</span>
mpz_powm(t,n,pm2,p) -- t = mod(n^pm2,p)
<span style="color: #7060A8;">mpz_fdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pm2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pm1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- pm2 = pm1/2</span>
if mpz_cmp_si(t,1)!=0 then
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pm2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- t = mod(n^pm2,p)</span>
return "No solution exists"
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #008000;">"No solution exists"</span>
mpz q = mpz_init_set(pm1)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer ss = 0
<span style="color: #004080;">mpz</span> <span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pm1</span><span style="color: #0000FF;">)</span>
while mpz_even(q) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">ss</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
ss += 1
<span style="color: #008080;">while</span> <span style="color: #7060A8;">mpz_even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
mpz_fdiv_q_2exp(q,q,1) -- q/=2
<span style="color: #000000;">ss</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
end while
<span style="color: #7060A8;">mpz_fdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- q/=2</span>
if ss=1 then
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
mpz_add_ui(t,p,1)
<span style="color: #008080;">if</span> <span style="color: #000000;">ss</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
mpz_fdiv_q_2exp(t,t,2)
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
mpz_powm(r,n,t,p) -- r = mod(n^((p+1)/4),p)
<span style="color: #7060A8;">mpz_fdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
else
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- r = mod(n^((p+1)/4),p)</span>
mpz z = mpz_init(2)
<span style="color: #008080;">else</span>
while true do
<span style="color: #004080;">mpz</span> <span style="color: #000000;">z</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
mpz_powm(t,z,pm2,p) -- t = mod(z^pm2,p)
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
if mpz_cmp(t,pm1)=0 then exit end if
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pm2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- t = mod(z^pm2,p)</span>
mpz_add_ui(z,z,1) -- z+= 1
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mpz_cmp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pm1</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- z+= 1</span>
mpz {b,c,zz} = mpz_inits(3)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
mpz_powm(c,z,q,p) -- c = mod(z^q,p)
<span style="color: #004080;">mpz</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zz</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
mpz_add_ui(t,q,1)
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">z</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- c = mod(z^q,p)</span>
mpz_fdiv_q_2exp(t,t,1)
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
mpz_powm(r,n,t,p) -- r = mod(n^((q+1)/2),p)
<span style="color: #7060A8;">mpz_fdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
mpz_powm(t,n,q,p) -- t = mod(n^q,p)
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- r = mod(n^((q+1)/2),p)</span>
integer m = ss
<span style="color: #7060A8;">mpz_powm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- t = mod(n^q,p)</span>
while mpz_cmp_si(t,1) do -- t!=1
<span style="color: #004080;">integer</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ss</span>
integer i = 0
<span style="color: #008080;">while</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- t!=1</span>
mpz_set(zz,t)
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
while mpz_cmp_si(zz,1)!=0 and i<m-1 do
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">)</span>
mpz_powm_ui(zz,zz,2,p) -- zz = mod(zz^2,p)
<span style="color: #008080;">while</span> <span style="color: #7060A8;">mpz_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><</span><span style="color: #000000;">m</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
i += 1
<span style="color: #7060A8;">mpz_powm_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">zz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">zz</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- zz = mod(zz^2,p)</span>
end while
<span style="color: #000000;">i</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
mpz_set(b,c)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer e = m-i-1
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
while e>0 do
<span style="color: #004080;">integer</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
mpz_powm_ui(b,b,2,p) -- b = mod(b^2,p)
<span style="color: #008080;">while</span> <span style="color: #000000;">e</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
e -= 1
<span style="color: #7060A8;">mpz_powm_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- b = mod(b^2,p)</span>
end while
<span style="color: #000000;">e</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
mpz_mul(r,r,b)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
mpz_mod(r,r,p) -- r = mod(r*b,p)
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
mpz_powm_ui(c,b,2,p) -- c = mod(b^2,p)
<span style="color: #7060A8;">mpz_mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- r = mod(r*b,p)</span>
mpz_mul(t,t,c)
<span style="color: #7060A8;">mpz_powm_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- c = mod(b^2,p)</span>
mpz_mod(t,t,p) -- t = mod(t*c,p)
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
m = i
<span style="color: #7060A8;">mpz_mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- t = mod(t*c,p)</span>
end while
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
mpz_sub(p,p,r)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return mpz_get_str(r)&" and "&mpz_get_str(p)
<span style="color: #7060A8;">mpz_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" and "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant tests = {{"10","13"},
{"56","101"},
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"10"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"13"</span><span style="color: #0000FF;">},</span>
{"1030","10009"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"56"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"101"</span><span style="color: #0000FF;">},</span>
{"1032","10009"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"1030"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"10009"</span><span style="color: #0000FF;">},</span>
{"44402","100049"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"1032"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"10009"</span><span style="color: #0000FF;">},</span>
{"665820697","1000000009"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"44402"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"100049"</span><span style="color: #0000FF;">},</span>
{"881398088036","1000000000039"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"665820697"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1000000009"</span><span style="color: #0000FF;">},</span>
{"41660815127637347468140745042827704103445750172002",
<span style="color: #0000FF;">{</span><span style="color: #008000;">"881398088036"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1000000000039"</span><span style="color: #0000FF;">},</span>
sprintf("1%s577",repeat('0',47))}} -- 10^50+577
<span style="color: #0000FF;">{</span><span style="color: #008000;">"41660815127637347468140745042827704103445750172002"</span><span style="color: #0000FF;">,</span>
<span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1%s577"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">47</span><span style="color: #0000FF;">))}}</span> <span style="color: #000080;font-style:italic;">-- 10^50+577</span>
for i=1 to length(tests) do
string {p1,p2} = tests[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
printf(1,"For n = %s and p = %s, %s\n",{p1,p2,ts(p1,p2)})
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end for</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"For n = %s and p = %s, %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,831 ⟶ 3,336:
=={{header|PicoLisp}}==
{{trans|Go}}
<langsyntaxhighlight PicoLisplang="picolisp"># from @lib/rsa.l
(de **Mod (X Y N)
(let M 1
Line 2,898 ⟶ 3,403:
(println (ts 665820697 1000000009))
(println (ts 881398088036 1000000000039))
(println (ts 41660815127637347468140745042827704103445750172002 (+ (** 10 50) 577)))</langsyntaxhighlight>
 
{{out}}
Line 2,910 ⟶ 3,415:
(791399408049 208600591990)
(32102985369940620849741983987300038903725266634508 67897014630059379150258016012699961096274733366069)
</pre>
 
=={{header|Powershell}}==
{{trans|Python}}
{{works with|Powershell|7}}
<syntaxhighlight lang="powershell">Function Invoke-ModuloExponentiation ([BigInt]$Base, [BigInt]$Exponent, $Modulo) {
$Result = 1
$Base = $Base % $Modulo
If ($Base -eq 0) {return 0}
While ($Exponent -gt 0) {
If (($Exponent -band 1) -eq 1) {$Result = ($Result * $Base) % $Modulo}
$Exponent = $Exponent -shr 1
$Base = ($Base * $Base) % $Modulo
}
return ($Result % $Modulo)
}
 
Function Get-Legendre ([BigInt]$Integer, [BigInt]$Prime) {
return (Invoke-ModuloExponentiation -Base $Integer -Exponent (($Prime - 1) / 2) -Modulo $Prime)
}
 
Function Invoke-TonelliShanks ([BigInt]$Integer, [BigInt]$Prime) {
If ((Get-Legendre $Integer $Prime) -ne 1) {throw "$Integer not a square (mod $Prime)"}
[bigint]$q = $Prime - 1
$s = 0
While (($q % 2) -eq 0) {
$q = $q / 2
$s++
}
If ($s -eq 1) {
return (Invoke-ModuloExponentiation $Integer -Exponent (($Prime + 1) / 4) -Modulo $Prime)
}
For ($z = 2; [Bigint]::Compare($z, $Prime) -lt 0; $z++) {
If ([BigInt]::Compare(($Prime - 1), (Get-Legendre $z $Prime)) -eq 0) {
break
}
}
$c = Invoke-ModuloExponentiation -Base $z -Exponent $q -Modulo $Prime
$r = Invoke-ModuloExponentiation -Base $Integer -Exponent (($q + 1) / 2) -Modulo $Prime
$t = Invoke-ModuloExponentiation -Base $Integer -Exponent $q -Modulo $Prime
$m = $s
$t2 = 0
While ((($t - 1) % $Prime) -ne 0) {
$t2 = $t * $t % $Prime
Foreach ($i in (1..$m)) {
If ((($t2 -1) % $Prime) -eq 0) {
break
}
$t2 = Invoke-ModuloExponentiation -Base $t2 -Exponent 2 -Modulo $Prime
}
$b = Invoke-ModuloExponentiation -Base $c -Exponent ([Math]::Pow(2, ($m - $i - 1))) -Modulo $Prime
$r = ($r * $b) % $Prime
$c = ($b * $b) % $Prime
$t = ($t * $c) % $Prime
$m = $i
}
return $r
}
 
$TonelliTests = @(
@{Integer = [BigInt]::Parse('10'); Prime = [BigInt]::Parse('13')},
@{Integer = [BigInt]::Parse('56'); Prime = [BigInt]::Parse('101')},
@{Integer = [BigInt]::Parse('1030'); Prime = [BigInt]::Parse('10009')},
@{Integer = [BigInt]::Parse('44402'); Prime = [BigInt]::Parse('100049')},
@{Integer = [BigInt]::Parse('665820697'); Prime = [BigInt]::Parse('1000000009')},
@{Integer = [BigInt]::Parse('881398088036'); Prime = [BigInt]::Parse('1000000000039')},
@{Integer = [BigInt]::Parse('41660815127637347468140745042827704103445750172002'); Prime = [BigInt]::Parse('100000000000000000000000000000000000000000000000577')}
)
 
$TonelliTests | Foreach-Object {
$Result = Invoke-TonelliShanks @_
[PSCustomObject]@{
n = $_['Integer']
p = $_['Prime']
Roots = @($Result, ($_['Prime'] - $Result))
}
} | Format-List</syntaxhighlight>
 
{{out}}
<pre>
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
 
n : 41660815127637347468140745042827704103445750172002
p : 100000000000000000000000000000000000000000000000577
Roots : {32102985369940620849741983987300038903725266634508, 67897014630059379150258016012699961096274733366069}
</pre>
 
Line 2,915 ⟶ 3,529:
{{trans|EchoLisp}}
{{works with|Python|3}}
<langsyntaxhighlight lang="python">def legendre(a, p):
return pow(a, (p - 1) // 2, p)
 
Line 2,956 ⟶ 3,570:
assert (r * r - n) % p == 0
print("n = %d p = %d" % (n, p))
print("\t roots : %d %d" % (r, p - r))</langsyntaxhighlight>
{{out}}
<pre>
Line 2,977 ⟶ 3,591:
=={{header|Racket}}==
{{trans|EchoLisp}}
<langsyntaxhighlight lang="racket">#lang racket
 
(require math/number-theory)
Line 3,036 ⟶ 3,650:
(task ttest)
 
(check-exn exn:fail? (λ () (Tonelli 1032 1009))))</langsyntaxhighlight>
 
{{out}}
Line 3,060 ⟶ 3,674:
Translation of the Wikipedia pseudocode, heavily influenced by Sidef and Python.
 
<syntaxhighlight lang="raku" perl6line># Legendre operator (𝑛│𝑝)
sub infix:<│> (Int \𝑛, Int \𝑝 where 𝑝.is-prime && (𝑝 != 2)) {
given 𝑛.expmod( (𝑝-1) div 2, 𝑝 ) {
Line 3,111 ⟶ 3,725:
say "No solution for ({$n}, {$p})." and next if !$t or ($t² - $n) % $p;
say "Roots of $n are ($t, {$p-$t}) mod $p";
}</langsyntaxhighlight>
 
{{out}}
Line 3,126 ⟶ 3,740:
{{trans|Python}}
The large numbers cannot reasonably be handled by the pow function shown here.
<langsyntaxhighlight lang="rexx">/* REXX (required by some interpreters) */
Numeric Digits 1000000
ttest ='[(10, 13), (56, 101), (1030, 10009), (44402, 100049)]'
Line 3,183 ⟶ 3,797:
If z>'' Then
p=p//z
Return p</langsyntaxhighlight>
{{out}}
<pre>n = 10 p = 13
Line 3,196 ⟶ 3,810:
=={{header|Sidef}}==
{{trans|Python}}
<langsyntaxhighlight lang="ruby">func tonelli(n, p) {
legendre(n, p) == 1 || die "not a square (mod p)"
var q = p-1
Line 3,235 ⟶ 3,849:
assert((r*r - n) % p == 0)
say "Roots of #{n} are (#{r}, #{p-r}) mod #{p}"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,249 ⟶ 3,863:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Imports System.Numerics
 
Module Module1
Line 3,363 ⟶ 3,977:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>n = 10
Line 3,408 ⟶ 4,022:
{{libheader|Wren-dynamic}}
{{libheader|Wren-big}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Tuple
import "./big" for BigInt
 
var Solution = Tuple.create("Solution", ["root1", "root2", "exists"])
Line 3,489 ⟶ 4,103:
} else {
System.print("No solution exists")
}</langsyntaxhighlight>
 
{{out}}
Line 3,535 ⟶ 4,149:
=={{header|zkl}}==
{{trans|EchoLisp}}
<langsyntaxhighlight lang="zkl">var BN=Import("zklBigNum");
fcn modEq(a,b,p) { (a-b)%p==0 }
fcn legendre(a,p){ a.powm((p - 1)/2,p) }
Line 3,553 ⟶ 4,167:
}
r
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">ttest:=T(T(10,13), T(56,101), T(1030,10009), T(44402,100049),
T(665820697,1000000009), T(881398088036,1000000000039),
T("41660815127637347468140745042827704103445750172002", BN(10).pow(50) + 577),
Line 3,563 ⟶ 4,177:
println("n=%d p=%d".fmt(n,p));
println(" roots: %d %d".fmt(r, p-r));
}</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits