-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathnum3072_test.go
154 lines (144 loc) · 4.51 KB
/
num3072_test.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package muhash
import (
"math/rand"
"runtime"
"sync"
"testing"
)
func TestNum3072_GetInverse(t *testing.T) {
t.Parallel()
r := rand.New(rand.NewSource(0))
var element num3072
for i := 0; i < 5; i++ {
for i := range element.limbs {
element.limbs[i] = word(r.Uint64())
}
inv := element.GetInverse()
again := inv.GetInverse()
if *again != element {
t.Fatalf("Expected double inverting to be equal, found: %v != %v", again, element)
}
}
}
func num3072equalToWord(a *num3072, b word) bool {
if a.limbs[0] != b {
return false
}
for j := 1; j < len(a.limbs); j++ {
if a.limbs[j] != 0 {
return false
}
}
return true
}
func TestNum3072_IsOverflow(t *testing.T) {
var n num3072
if n.IsOverflow() {
t.Fatal("zeroed Num3072 isn't overflown")
}
n.limbs[0] = maxLimb
if n.IsOverflow() {
t.Fatalf("a %d num3072 isn't overflown", maxLimb)
}
for i := range n.limbs {
n.limbs[i] = maxLimb
}
if !n.IsOverflow() {
t.Fatal("maxed out num3072 is defenitely an overflow")
}
n.limbs[0] -= primeDiff - 1
if !n.IsOverflow() {
t.Fatal("The prime itself is considered an overflow(=0)")
}
}
func TestNum3072_DivOverflow(t *testing.T) {
tests := make([]byte, primeDiff)
var max num3072
for i := range max.limbs {
max.limbs[i] = maxLimb
}
regularOne := oneNum3072()
var wg sync.WaitGroup
step := word(primeDiff / runtime.NumCPU())
for c := word(0); c < word(runtime.NumCPU()); c++ {
wg.Add(1)
go func(c word) {
defer wg.Done()
start := c * step
end := start + step
if end > (primeDiff - step) {
end = primeDiff
}
for i := end; i > start; i-- {
expected := word(primeDiff - i)
overflown := max
overflown.limbs[0] = maxLimb - i + 1
overflownCopy := overflown
overflownCopy.Divide(®ularOne)
tests[expected]++
if !num3072equalToWord(&overflownCopy, expected) {
t.Errorf("Expected %v to be %d", overflownCopy, expected)
return
}
// Zero doesn't have a modular inverse
if i != primeDiff {
lhs := overflown
rhs := overflown
lhs.Divide(&rhs)
if !num3072equalToWord(&lhs, 1) {
t.Errorf("Expected %v to be %d", overflownCopy, 1)
return
}
}
}
}(c)
}
wg.Wait()
for i, n := range tests {
if n != 1 {
t.Fatalf("Expected all the integers 0..%d to be checked once, but %d was checked %d times", primeDiff, i, n)
}
}
}
func TestNum3072_MulMax(t *testing.T) {
t.Parallel()
var max num3072
for i := range max.limbs {
max.limbs[i] = word(maxUint)
}
max.limbs[0] -= primeDiff
copyMax := max
max.Mul(©Max)
if !num3072equalToWord(&max, 1) {
t.Fatalf("(p-1)*(p-1) mod p should equal 1, instead got: %v", max)
}
}
func TestNum3072MulDiv(t *testing.T) {
t.Parallel()
r := rand.New(rand.NewSource(1))
var list [loopsN]num3072
start := oneNum3072()
for i := 0; i < loopsN; i++ {
for n := range list[i].limbs {
list[i].limbs[n] = word(r.Uint64())
}
start.Mul(&list[i])
}
if start == oneNum3072() {
t.Errorf("start is 1 even though it shouldn't be: start '%x', one: %x\n", start, one())
}
for i := 0; i < loopsN; i++ {
start.Divide(&list[i])
}
if start != oneNum3072() {
t.Errorf("start should be 1 but it isn't: start: '%x', one: '%x'\n", start, one())
}
}
// This specifically tests the zeroing loop at the end of num3072.GetInverse.
func TestNum3072_GetInverse_EdgeCase(t *testing.T) {
orig := num3072{limbs: [limbs]word{7122228832992001076, 984226626229791276, 7630161757215403889, 6284986028532537849, 8045609952094061025, 11960578682873843289, 13746438324198032094, 13918942278011779234, 17733507388171786846, 10563242470999117317, 17037155475664456442, 17937456968131788544, 12599342294785769540, 13386260146859547870, 2817582499516127913, 652557987984108933, 9669847560665129471, 17711760030167214508, 5376140856964249866, 18051557786492143716, 2482926987284881227, 8605482545261324676, 7878786448874819977, 1266815984192471985, 2678516262590404672, 14004775981272003760, 10357003870690124643, 2730710396948079405, 4635754375072562978, 13656184258619915136, 803512205739688286, 11844116904145642840, 5760653310472302601, 15069027324939031326, 14913021043324743434, 17567013163360751106, 6302557725767759643, 17458497366820989801, 3410551217786514778, 14182717432968305815, 12471950523812677269, 2294197765573979691, 3220941588656114052, 605606616684921311, 1440136155000853957, 16361481774333736133, 11385241783616172231, 13968855456762740410}}
inverse := orig.GetInverse()
if *inverse.GetInverse() != orig {
t.Fatalf("Double inverting resulted in different varaible than the original: %v", orig)
}
}