Skip to content

Commit

Permalink
merge: Consolidate Primality Algorithm testing into single suite (The…
Browse files Browse the repository at this point in the history
…Algorithms#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
  • Loading branch information
raklaptudirm authored May 2, 2022
1 parent d00ee5e commit d696a49
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 129 deletions.
57 changes: 0 additions & 57 deletions math/prime/millerrabinprimalitytest_test.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func MillerTest(num, witness int64) (bool, error) {
// miller rabin primality test for better probabilitic chances of
// receiving the correct result with random witnesses.
func MillerRandomTest(num int64) (bool, error) {
random := rand.Int63n(num-1) + 2
random := rand.Int63n(num-2) + 2
return MillerTest(num, random)
}

Expand Down
95 changes: 95 additions & 0 deletions math/prime/prime_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package prime

import (
"fmt"
"testing"
)

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}
var testLimit = 127

type primalityTest func(int64) bool

func primalityTestTestingHelper(t *testing.T, name string, f primalityTest) {
arrayIndex := 0
for i := 1; i <= testLimit; i++ {
isPrime := i == primeList[arrayIndex]

testName := fmt.Sprintf("%s(%d)", name, i)
t.Run(testName, func(t *testing.T) {
result := f(int64(i))

if isPrime {
arrayIndex++
}

if result != isPrime {
t.Errorf("%d: %s function returned %v\n", i, name, result)
}
})
}
}

func primalityTestBenchmarkHelper(b *testing.B, f primalityTest) {
for i := 0; i < b.N; i++ {
f(104729)
}
}

// Miller-Rabin Probabilistic test

func millerRabinProbabilisticTester(n int64) bool {
result, err := MillerRabinProbabilistic(n, 40)
if err != nil {
panic(err)
}

return result
}

func TestMillerRabinProbabilistic(t *testing.T) {
primalityTestTestingHelper(t, "Miller-Rabin Probabilistic", millerRabinProbabilisticTester)
}

func BenchmarkMillerRabinProbabilistic(b *testing.B) {
primalityTestBenchmarkHelper(b, millerRabinProbabilisticTester)
}

// Miller-Rabin deterministic test

func millerRabinDeterministicTester(n int64) bool {
result, err := MillerRabinDeterministic(n)
if err != nil {
panic(err)
}

return result
}

func TestMillerRabinDeterministic(t *testing.T) {
primalityTestTestingHelper(t, "Miller-Rabin Deterministic", millerRabinDeterministicTester)
}

func BenchmarkMillerRabinDeterministic(b *testing.B) {
primalityTestBenchmarkHelper(b, millerRabinDeterministicTester)
}

// Trial Division test

func TestTrialDivision(t *testing.T) {
primalityTestTestingHelper(t, "Trial Division", TrialDivision)
}

func BenchmarkTrialDivision(b *testing.B) {
primalityTestBenchmarkHelper(b, TrialDivision)
}

// Trial Division (optimized)

func TestOptimizedTrialDivision(t *testing.T) {
primalityTestTestingHelper(t, "Trial Division (optimized)", OptimizedTrialDivision)
}

func BenchmarkOptimizedTrialDivision(b *testing.B) {
primalityTestBenchmarkHelper(b, OptimizedTrialDivision)
}
34 changes: 25 additions & 9 deletions math/prime/primecheck.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package prime

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

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

for i := int64(2); i < n; i++ {

if n%i == 0 {
return false
Expand All @@ -18,12 +20,26 @@ func NaiveApproach(n int) bool {
return true
}

// PairApproach checks primality of an integer and returns a bool. More efficient than the naive approach as number of iterations are less.
func PairApproach(n int) bool {
// OptimizedTrialDivision checks primality of an integer using an optimized trial division method.
// The optimizations include not checking divisibility by the even numbers and only checking up to
// the square root of the given number.
func OptimizedTrialDivision(n int64) bool {
// 0 and 1 are not prime
if n < 2 {
return false
}
for i := 2; i*i <= n; i++ {

// 2 and 3 are prime
if n < 4 {
return true
}

// all numbers divisible by 2 except 2 are not prime
if n%2 == 0 {
return false
}

for i := int64(3); i*i <= n; i += 2 {
if n%i == 0 {
return false
}
Expand Down
62 changes: 0 additions & 62 deletions math/prime/primecheck_test.go

This file was deleted.

0 comments on commit d696a49

Please sign in to comment.