github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/math/big/prime.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package big 6 7 import "math/rand" 8 9 // ProbablyPrime performs n Miller-Rabin tests to check whether x is prime. 10 // If x is prime, it returns true. 11 // If x is not prime, it returns false with probability at least 1 - ¼ⁿ. 12 // 13 // It is not suitable for judging primes that an adversary may have crafted 14 // to fool this test. 15 func (x *Int) ProbablyPrime(n int) bool { 16 if n <= 0 { 17 panic("non-positive n for ProbablyPrime") 18 } 19 return !x.neg && x.abs.probablyPrime(n) 20 } 21 22 // probablyPrime performs n Miller-Rabin tests to check whether x is prime. 23 // If x is prime, it returns true. 24 // If x is not prime, it returns false with probability at least 1 - ¼ⁿ. 25 // 26 // It is not suitable for judging primes that an adversary may have crafted 27 // to fool this test. 28 func (n nat) probablyPrime(reps int) bool { 29 if len(n) == 0 { 30 return false 31 } 32 33 if len(n) == 1 { 34 if n[0] < 2 { 35 return false 36 } 37 38 if n[0]%2 == 0 { 39 return n[0] == 2 40 } 41 42 // We have to exclude these cases because we reject all 43 // multiples of these numbers below. 44 switch n[0] { 45 case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53: 46 return true 47 } 48 } 49 50 if n[0]&1 == 0 { 51 return false // n is even 52 } 53 54 const primesProduct32 = 0xC0CFD797 // Π {p ∈ primes, 2 < p <= 29} 55 const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53} 56 57 var r Word 58 switch _W { 59 case 32: 60 r = n.modW(primesProduct32) 61 case 64: 62 r = n.modW(primesProduct64 & _M) 63 default: 64 panic("Unknown word size") 65 } 66 67 if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 || 68 r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 { 69 return false 70 } 71 72 if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 || 73 r%43 == 0 || r%47 == 0 || r%53 == 0) { 74 return false 75 } 76 77 nm1 := nat(nil).sub(n, natOne) 78 // determine q, k such that nm1 = q << k 79 k := nm1.trailingZeroBits() 80 q := nat(nil).shr(nm1, k) 81 82 nm3 := nat(nil).sub(nm1, natTwo) 83 rand := rand.New(rand.NewSource(int64(n[0]))) 84 85 var x, y, quotient nat 86 nm3Len := nm3.bitLen() 87 88 NextRandom: 89 for i := 0; i < reps; i++ { 90 x = x.random(rand, nm3, nm3Len) 91 x = x.add(x, natTwo) 92 y = y.expNN(x, q, n) 93 if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 { 94 continue 95 } 96 for j := uint(1); j < k; j++ { 97 y = y.mul(y, y) 98 quotient, y = quotient.div(y, y, n) 99 if y.cmp(nm1) == 0 { 100 continue NextRandom 101 } 102 if y.cmp(natOne) == 0 { 103 return false 104 } 105 } 106 return false 107 } 108 109 return true 110 }