Cipolla's algorithm: Difference between revisions
Content added Content deleted
(add PicoLisp) |
(Added Kotlin) |
||
Line 739: | Line 739: | ||
34035243914635549601583369544560650254325084643201x cipolla (10^50x) + 151 |
34035243914635549601583369544560650254325084643201x cipolla (10^50x) + 151 |
||
17436881171909637738621006042549786426312886309400 82563118828090362261378993957450213573687113690751</lang> |
17436881171909637738621006042549786426312886309400 82563118828090362261378993957450213573687113690751</lang> |
||
=={{header|Kotlin}}== |
|||
{{trans|Go}} |
|||
<lang scala>// version 1.2.0 |
|||
import java.math.BigInteger |
|||
class Point(val x: BigInteger, val y: BigInteger) |
|||
val bigZero = BigInteger.ZERO |
|||
val bigOne = BigInteger.ONE |
|||
val bigTwo = BigInteger.valueOf(2L) |
|||
val bigBig = BigInteger.TEN.pow(50) + BigInteger.valueOf(151L) |
|||
fun c(ns: String, ps: String): Triple<BigInteger, BigInteger, Boolean> { |
|||
val n = BigInteger(ns) |
|||
val p = if (!ps.isEmpty()) BigInteger(ps) else bigBig |
|||
// Legendre symbol, returns 1, 0 or p - 1 |
|||
fun ls(a: BigInteger) = a.modPow((p - bigOne) / bigTwo, p) |
|||
// Step 0, validate arguments |
|||
if (ls(n) != bigOne) return Triple(bigZero, bigZero, false) |
|||
// Step 1, find a, omega2 |
|||
var a = bigZero |
|||
var omega2: BigInteger |
|||
while (true) { |
|||
omega2 = (a * a + p - n) % p |
|||
if (ls(omega2) == p - bigOne) break |
|||
a++ |
|||
} |
|||
// multiplication in Fp2 |
|||
fun mul(aa: Point, bb: Point) = |
|||
Point( |
|||
(aa.x * bb.x + aa.y * bb.y * omega2) % p, |
|||
(aa.x * bb.y + bb.x * aa.y) % p |
|||
) |
|||
// Step 2, compute power |
|||
var r = Point(bigOne, bigZero) |
|||
var s = Point(a, bigOne) |
|||
var nn = ((p + bigOne) shr 1) % p |
|||
while (nn > bigZero) { |
|||
if ((nn and bigOne) == bigOne) r = mul(r, s) |
|||
s = mul(s, s) |
|||
nn = nn shr 1 |
|||
} |
|||
// Step 3, check x in Fp |
|||
if (r.y != bigZero) return Triple(bigZero, bigZero, false) |
|||
// Step 5, check x * x = n |
|||
if (r.x * r.x % p != n) return Triple(bigZero, bigZero, false) |
|||
// Step 4, solutions |
|||
return Triple(r.x, p - r.x, true) |
|||
} |
|||
fun main(args: Array<String>) { |
|||
println(c("10", "13")) |
|||
println(c("56", "101")) |
|||
println(c("8218", "10007")) |
|||
println(c("8219", "10007")) |
|||
println(c("331575", "1000003")) |
|||
println(c("665165880", "1000000007")) |
|||
println(c("881398088036", "1000000000039")) |
|||
println(c("34035243914635549601583369544560650254325084643201", "")) |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
(6, 7, true) |
|||
(37, 64, true) |
|||
(9872, 135, true) |
|||
(0, 0, false) |
|||
(855842, 144161, true) |
|||
(475131702, 524868305, true) |
|||
(791399408049, 208600591990, true) |
|||
(82563118828090362261378993957450213573687113690751, 17436881171909637738621006042549786426312886309400, true) |
|||
</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |