Skip to content

Commit d696a49

Browse files
authored
merge: Consolidate Primality Algorithm testing into single suite (#504)
* chore: add testing interface * chore: add benchmark helper * chore: remove individual tests (1) * chore: remove individual tests (2) * chore: add miller rabin test suite * refactor: trial division primality tests * chore: add trial division test suite * refactor: trial division tests now accept `int64` * chore: remove `error` return from `primalityTest` * fix: remove redundant identifier * chore: add function names for debug * chore: fix typo * chore: add explicit type conversions * fix: index out of range in tests * fix: random witness generation
1 parent d00ee5e commit d696a49

File tree

5 files changed

+121
-129
lines changed

5 files changed

+121
-129
lines changed

math/prime/millerrabinprimalitytest_test.go

-57
This file was deleted.

math/prime/millerrabinprimalitytest.go renamed to math/prime/millerrabintest.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func MillerTest(num, witness int64) (bool, error) {
7575
// miller rabin primality test for better probabilitic chances of
7676
// receiving the correct result with random witnesses.
7777
func MillerRandomTest(num int64) (bool, error) {
78-
random := rand.Int63n(num-1) + 2
78+
random := rand.Int63n(num-2) + 2
7979
return MillerTest(num, random)
8080
}
8181

math/prime/prime_test.go

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package prime
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
var primeList = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127}
9+
var testLimit = 127
10+
11+
type primalityTest func(int64) bool
12+
13+
func primalityTestTestingHelper(t *testing.T, name string, f primalityTest) {
14+
arrayIndex := 0
15+
for i := 1; i <= testLimit; i++ {
16+
isPrime := i == primeList[arrayIndex]
17+
18+
testName := fmt.Sprintf("%s(%d)", name, i)
19+
t.Run(testName, func(t *testing.T) {
20+
result := f(int64(i))
21+
22+
if isPrime {
23+
arrayIndex++
24+
}
25+
26+
if result != isPrime {
27+
t.Errorf("%d: %s function returned %v\n", i, name, result)
28+
}
29+
})
30+
}
31+
}
32+
33+
func primalityTestBenchmarkHelper(b *testing.B, f primalityTest) {
34+
for i := 0; i < b.N; i++ {
35+
f(104729)
36+
}
37+
}
38+
39+
// Miller-Rabin Probabilistic test
40+
41+
func millerRabinProbabilisticTester(n int64) bool {
42+
result, err := MillerRabinProbabilistic(n, 40)
43+
if err != nil {
44+
panic(err)
45+
}
46+
47+
return result
48+
}
49+
50+
func TestMillerRabinProbabilistic(t *testing.T) {
51+
primalityTestTestingHelper(t, "Miller-Rabin Probabilistic", millerRabinProbabilisticTester)
52+
}
53+
54+
func BenchmarkMillerRabinProbabilistic(b *testing.B) {
55+
primalityTestBenchmarkHelper(b, millerRabinProbabilisticTester)
56+
}
57+
58+
// Miller-Rabin deterministic test
59+
60+
func millerRabinDeterministicTester(n int64) bool {
61+
result, err := MillerRabinDeterministic(n)
62+
if err != nil {
63+
panic(err)
64+
}
65+
66+
return result
67+
}
68+
69+
func TestMillerRabinDeterministic(t *testing.T) {
70+
primalityTestTestingHelper(t, "Miller-Rabin Deterministic", millerRabinDeterministicTester)
71+
}
72+
73+
func BenchmarkMillerRabinDeterministic(b *testing.B) {
74+
primalityTestBenchmarkHelper(b, millerRabinDeterministicTester)
75+
}
76+
77+
// Trial Division test
78+
79+
func TestTrialDivision(t *testing.T) {
80+
primalityTestTestingHelper(t, "Trial Division", TrialDivision)
81+
}
82+
83+
func BenchmarkTrialDivision(b *testing.B) {
84+
primalityTestBenchmarkHelper(b, TrialDivision)
85+
}
86+
87+
// Trial Division (optimized)
88+
89+
func TestOptimizedTrialDivision(t *testing.T) {
90+
primalityTestTestingHelper(t, "Trial Division (optimized)", OptimizedTrialDivision)
91+
}
92+
93+
func BenchmarkOptimizedTrialDivision(b *testing.B) {
94+
primalityTestBenchmarkHelper(b, OptimizedTrialDivision)
95+
}

math/prime/primecheck.go

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package prime
22

3-
// A primality test is an algorithm for determining whether an input number is prime.Among other fields of mathematics, it is used for cryptography.
4-
//Unlike integer factorization, primality tests do not generally give prime factors, only stating whether the input number is prime or not.
5-
//Source - Wikipedia https://en.wikipedia.org/wiki/Primality_test
3+
// A primality test is an algorithm for determining whether an input number is prime. Among other
4+
// fields of mathematics, it is used for cryptography. Unlike integer factorization, primality
5+
// tests do not generally give prime factors, only stating whether the input number is prime or not.
6+
// Source - Wikipedia https://en.wikipedia.org/wiki/Primality_test
67

7-
// NaiveApproach checks if an integer is prime or not. Returns a bool.
8-
func NaiveApproach(n int) bool {
8+
// TrialDivision tests whether a number is prime by trying to divide it by the numbers less than it.
9+
func TrialDivision(n int64) bool {
910
if n < 2 {
1011
return false
1112
}
12-
for i := 2; i < n; i++ {
13+
14+
for i := int64(2); i < n; i++ {
1315

1416
if n%i == 0 {
1517
return false
@@ -18,12 +20,26 @@ func NaiveApproach(n int) bool {
1820
return true
1921
}
2022

21-
// PairApproach checks primality of an integer and returns a bool. More efficient than the naive approach as number of iterations are less.
22-
func PairApproach(n int) bool {
23+
// OptimizedTrialDivision checks primality of an integer using an optimized trial division method.
24+
// The optimizations include not checking divisibility by the even numbers and only checking up to
25+
// the square root of the given number.
26+
func OptimizedTrialDivision(n int64) bool {
27+
// 0 and 1 are not prime
2328
if n < 2 {
2429
return false
2530
}
26-
for i := 2; i*i <= n; i++ {
31+
32+
// 2 and 3 are prime
33+
if n < 4 {
34+
return true
35+
}
36+
37+
// all numbers divisible by 2 except 2 are not prime
38+
if n%2 == 0 {
39+
return false
40+
}
41+
42+
for i := int64(3); i*i <= n; i += 2 {
2743
if n%i == 0 {
2844
return false
2945
}

math/prime/primecheck_test.go

-62
This file was deleted.

0 commit comments

Comments
 (0)