Skip to content

Commit 8bc4e86

Browse files
tjgurwara99github-actions
andauthored
feat: added a few algorithms that will be used for rewriting RSA algorithm that currently fails the tests (#288)
* feat: added a few algorithms that will be used for rsa algorithm * fix: renamed the directory for better import string organisation * fix: rename of a file * updating DIRECTORY.md * fix: corrected the mistakes in the documetation comments of some code * fix: missplelling * fix: spelling errors * fix: reduced cyclomatic complexity Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
1 parent e701407 commit 8bc4e86

File tree

14 files changed

+175
-77
lines changed

14 files changed

+175
-77
lines changed

DIRECTORY.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,19 @@
104104
* Gcd
105105
* [Gcd](https://github.com/TheAlgorithms/Go/blob/master/math/gcd/gcd.go)
106106
* [Gcd Test](https://github.com/TheAlgorithms/Go/blob/master/math/gcd/gcd_test.go)
107+
* [Gcditerative](https://github.com/TheAlgorithms/Go/blob/master/math/gcd/gcditerative.go)
108+
* Lcm
109+
* [Lcm](https://github.com/TheAlgorithms/Go/blob/master/math/lcm/lcm.go)
107110
* Modulararithmetic
108111
* [Modularexponentiation](https://github.com/TheAlgorithms/Go/blob/master/math/modulararithmetic/modularexponentiation.go)
109112
* [Modularexponentiation Test](https://github.com/TheAlgorithms/Go/blob/master/math/modulararithmetic/modularexponentiation_test.go)
110113
* Power
111114
* [Fastexponent](https://github.com/TheAlgorithms/Go/blob/master/math/power/fastexponent.go)
112115
* [Fastexponent Test](https://github.com/TheAlgorithms/Go/blob/master/math/power/fastexponent_test.go)
113-
* Primecheck
114-
* [Primecheck](https://github.com/TheAlgorithms/Go/blob/master/math/primecheck/primecheck.go)
115-
* [Primecheck Test](https://github.com/TheAlgorithms/Go/blob/master/math/primecheck/primecheck_test.go)
116+
* Prime
117+
* [Millerrabinprimalitytest](https://github.com/TheAlgorithms/Go/blob/master/math/prime/millerrabinprimalitytest.go)
118+
* [Prime Test](https://github.com/TheAlgorithms/Go/blob/master/math/prime/prime_test.go)
119+
* [Primecheck](https://github.com/TheAlgorithms/Go/blob/master/math/prime/primecheck.go)
116120
* Pythagoras
117121
* [Pythagoras](https://github.com/TheAlgorithms/Go/blob/master/math/pythagoras/pythagoras.go)
118122
* [Pythagoras Test](https://github.com/TheAlgorithms/Go/blob/master/math/pythagoras/pythagoras_test.go)

ciphers/polybius/polybius_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func TestNewPolybius(t *testing.T) {
4545
wantErr string
4646
}{
4747
{
48-
name: "correct initalization", size: 5, characters: "HogeF", key: "abcdefghijklmnopqrstuvwxy", wantErr: "",
48+
name: "correct initialization", size: 5, characters: "HogeF", key: "abcdefghijklmnopqrstuvwxy", wantErr: "",
4949
},
5050
{
5151
name: "truncate characters", size: 5, characters: "HogeFuga", key: "abcdefghijklmnopqrstuvwxy", wantErr: "",

math/gcd/gcd.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package gcd
22

3-
// Gcd finds and returns the greatest common divisor of a given integer.
4-
func Gcd(a, b int) int {
3+
// Recursive finds and returns the greatest common divisor of a given integer.
4+
func Recursive(a, b int64) int64 {
55
if b == 0 {
66
return a
77
}
8-
return Gcd(b, a%b)
8+
return Recursive(b, a%b)
99
}

math/gcd/gcd_test.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,48 @@ package gcd
22

33
import "testing"
44

5+
type testFunction func(int64, int64) int64
6+
57
var testCases = []struct {
68
name string
7-
a int
8-
b int
9-
output int
9+
a int64
10+
b int64
11+
output int64
1012
}{
1113
{"gcd of 10 and 0", 10, 0, 10},
1214
{"gcd of 98 and 56", 98, 56, 14},
1315
{"gcd of 0 and 10", 0, 10, 10},
1416
}
1517

16-
func TestGCD(t *testing.T) {
18+
func TemplateTestGCD(t *testing.T, f testFunction) {
1719
for _, tc := range testCases {
1820
t.Run(tc.name, func(t *testing.T) {
19-
actual := Gcd(tc.a, tc.b)
21+
actual := f(tc.a, tc.b)
2022
if actual != tc.output {
2123
t.Errorf("Expected GCD of %d and %d to be: %v, but got: %d", tc.a, tc.b, tc.output, actual)
2224
}
2325
})
2426
}
2527
}
2628

27-
func BenchmarkGCD(b *testing.B) {
29+
func TestGCDRecursive(t *testing.T) {
30+
TemplateTestGCD(t, Recursive)
31+
}
32+
33+
func TestGCDIterative(t *testing.T) {
34+
TemplateTestGCD(t, Iterative)
35+
}
36+
37+
func TemplateBenchmarkGCD(b *testing.B, f testFunction) {
2838
for i := 0; i < b.N; i++ {
29-
Gcd(98, 56)
39+
f(98, 56)
3040
}
3141
}
42+
43+
func BenchmarkGCDRecursive(b *testing.B) {
44+
TemplateBenchmarkGCD(b, Recursive)
45+
}
46+
47+
func BenchmarkGCDIterative(b *testing.B) {
48+
TemplateBenchmarkGCD(b, Iterative)
49+
}

math/gcd/gcditerative.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package gcd
2+
3+
// Iterative Faster iterative version of GcdRecursive without holding up too much of the stack
4+
func Iterative(a, b int64) int64 {
5+
for b != 0 {
6+
a, b = b, a%b
7+
}
8+
return a
9+
}

math/lcm/lcm.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package lcm
2+
3+
import (
4+
"math"
5+
6+
"github.com/TheAlgorithms/Go/math/gcd"
7+
)
8+
9+
// Lcm returns the lcm of two numbers using the fact that lcm(a,b) * gcd(a,b) = | a * b |
10+
func Lcm(a, b int64) int64 {
11+
return int64(math.Abs(float64(a*b)) / float64(gcd.Iterative(a, b)))
12+
}

math/modulararithmetic/modularexponentiation_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ func TestModularExponentiation(t *testing.T) {
6666
result, err := ModularExponentiation(test.base, test.exponent, test.mod)
6767
if err != test.expectedError {
6868
t.Logf("Test Failed for %s", test.name)
69-
t.Logf("Unexpected error occured")
70-
t.Errorf("Expected error: %v, Recieved error: %v", test.expectedError, err)
69+
t.Logf("Unexpected error occurred")
70+
t.Errorf("Expected error: %v, Received error: %v", test.expectedError, err)
7171
}
7272
if result != test.expected {
7373
t.Logf("Test Failed for %s", test.description)
74-
t.Fatalf("Expected: %d, Recieved: %d", test.expected, result)
74+
t.Fatalf("Expected: %d, Received: %d", test.expected, result)
7575
}
7676
})
7777
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package prime
2+
3+
import (
4+
"math/rand"
5+
6+
"github.com/TheAlgorithms/Go/math/modulararithmetic"
7+
)
8+
9+
// findD accepts a number and returns the
10+
// odd number d such that num = 2^r * d - 1
11+
func findRD(num int64) (int64, int64) {
12+
r := int64(0)
13+
d := num - 1
14+
for num%2 == 0 {
15+
d /= 2
16+
r++
17+
}
18+
return d, r
19+
}
20+
21+
// MillerTest This is the intermediate step that repeats within the
22+
// miller rabin primality test for better probabilitic chances of
23+
// receiving the correct result.
24+
func MillerTest(d, num int64) (bool, error) {
25+
random := rand.Int63n(num-1) + 2
26+
27+
res, err := modulararithmetic.ModularExponentiation(random, d, num)
28+
29+
if err != nil {
30+
return false, err
31+
}
32+
// miller conditions checks
33+
if res == 1 || res == num-1 {
34+
return true, nil
35+
}
36+
37+
for d != num-1 {
38+
res = (res * res) % num
39+
d *= 2
40+
if res == 1 {
41+
return false, nil
42+
}
43+
if res == num-1 {
44+
return true, nil
45+
}
46+
}
47+
return false, nil
48+
}
49+
50+
// MillerRabinTest Probabilistic test for primality of an integer based of the algorithm devised by Miller and Rabin.
51+
func MillerRabinTest(num, rounds int64) (bool, error) {
52+
if num <= 4 {
53+
if num == 2 || num == 3 {
54+
return true, nil
55+
}
56+
return false, nil
57+
}
58+
if num%2 == 0 {
59+
return false, nil
60+
}
61+
d, _ := findRD(num)
62+
63+
for i := int64(0); i < rounds; i++ {
64+
val, err := MillerTest(d, num)
65+
if err != nil {
66+
return false, err
67+
}
68+
if !val {
69+
return false, nil
70+
}
71+
}
72+
return true, nil
73+
}

math/primecheck/primecheck_test.go renamed to math/prime/prime_test.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package primecheck
1+
package prime
22

33
import (
44
"testing"
@@ -49,6 +49,33 @@ func TestTablePairApproach(t *testing.T) {
4949

5050
}
5151

52+
func TestMillerRabinTest(t *testing.T) {
53+
var tests = []struct {
54+
name string
55+
input int64
56+
expected bool
57+
rounds int64
58+
err error
59+
}{
60+
{"smallest prime", 2, true, 5, nil},
61+
{"random prime", 3, true, 5, nil},
62+
{"neither prime nor composite", 1, false, 5, nil},
63+
{"random non-prime", 10, false, 5, nil},
64+
{"another random prime", 23, true, 5, nil},
65+
}
66+
for _, test := range tests {
67+
t.Run(test.name, func(t *testing.T) {
68+
output, err := MillerRabinTest(test.input, test.rounds)
69+
if err != test.err {
70+
t.Errorf("For input: %d, unexpected error: %v, expected error: %v", test.input, err, test.err)
71+
}
72+
if output != test.expected {
73+
t.Errorf("For input: %d, expected: %v", test.input, output)
74+
}
75+
})
76+
}
77+
}
78+
5279
func BenchmarkNaiveApproach(b *testing.B) {
5380
for i := 0; i < b.N; i++ {
5481
NaiveApproach(23)

math/primecheck/primecheck.go renamed to math/prime/primecheck.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package primecheck
1+
package prime
22

33
// A primality test is an algorithm for determining whether an input number is prime.Among other fields of mathematics, it is used for cryptography.
44
//Unlike integer factorization, primality tests do not generally give prime factors, only stating whether the input number is prime or not.

0 commit comments

Comments
 (0)