forked from TheAlgorithms/Go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
exponentiation.go
56 lines (45 loc) · 1.37 KB
/
exponentiation.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
// exponentiation.go
// description: Implementation of Modular Exponentiation Algorithm
// details:
// A simple implementation of Modular Exponentiation - [Modular Exponenetation wiki](https://en.wikipedia.org/wiki/Modular_exponentiation)
// author(s) [Taj](https://github.com/tjgurwara99)
// see exponentiation_test.go
package modular
import (
"errors"
"math"
)
// ErrorIntOverflow For asserting that the values do not overflow in Int64
var ErrorIntOverflow = errors.New("integer overflow")
// ErrorNegativeExponent for asserting that the exponent we receive is positive
var ErrorNegativeExponent = errors.New("negative Exponent provided")
// Exponentiation returns base^exponent % mod
func Exponentiation(base, exponent, mod int64) (int64, error) {
if mod == 1 {
return 0, nil
}
if exponent < 0 {
return -1, ErrorNegativeExponent
}
_, err := Multiply64BitInt(mod-1, mod-1)
if err != nil {
return -1, err
}
var result int64 = 1
base = base % mod
for exponent > 0 {
if exponent%2 == 1 {
result = (result * base) % mod
}
exponent = exponent >> 1
base = (base * base) % mod
}
return result, nil
}
// Multiply64BitInt Checking if the integer multiplication overflows
func Multiply64BitInt(left, right int64) (int64, error) {
if math.Abs(float64(left)) > float64(math.MaxInt64)/math.Abs(float64(right)) {
return 0, ErrorIntOverflow
}
return left * right, nil
}