-
Notifications
You must be signed in to change notification settings - Fork 11
/
millerrabinprimalitytest.go
81 lines (71 loc) · 1.7 KB
/
millerrabinprimalitytest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// millerrabinprimalitytest.go
// description: An implementation of Miller-Rabin primality test
// details:
// A simple implementation of Miller-Rabin Primality Test
// [Miller-Rabin primality test Wiki](https://en.wikipedia.org/wiki/Miller–Rabin_primality_test)
// author(s) [Taj](https://github.com/tjgurwara99)
// see millerrabinprimalitytest_test.go
package prime
import (
"math/rand"
"github.com/TheAlgorithms/Go/math/modular"
)
// findD accepts a number and returns the
// odd number d such that num = 2^r * d - 1
func findRD(num int64) (int64, int64) {
r := int64(0)
d := num - 1
for num%2 == 0 {
d /= 2
r++
}
return d, r
}
// MillerTest This is the intermediate step that repeats within the
// miller rabin primality test for better probabilitic chances of
// receiving the correct result.
func MillerTest(d, num int64) (bool, error) {
random := rand.Int63n(num-1) + 2
res, err := modular.Exponentiation(random, d, num)
if err != nil {
return false, err
}
// miller conditions checks
if res == 1 || res == num-1 {
return true, nil
}
for d != num-1 {
res = (res * res) % num
d *= 2
if res == 1 {
return false, nil
}
if res == num-1 {
return true, nil
}
}
return false, nil
}
// MillerRabinTest Probabilistic test for primality of an integer based of the algorithm devised by Miller and Rabin.
func MillerRabinTest(num, rounds int64) (bool, error) {
if num <= 4 {
if num == 2 || num == 3 {
return true, nil
}
return false, nil
}
if num%2 == 0 {
return false, nil
}
d, _ := findRD(num)
for i := int64(0); i < rounds; i++ {
val, err := MillerTest(d, num)
if err != nil {
return false, err
}
if !val {
return false, nil
}
}
return true, nil
}