1 package ff
2
3 import (
4 "crypto/rand"
5 "fmt"
6 "testing"
7
8 "github.com/cloudflare/circl/internal/test"
9 )
10
11 func randomFp(t testing.TB) *Fp {
12 t.Helper()
13 f := new(Fp)
14 err := f.Random(rand.Reader)
15 if err != nil {
16 t.Error(err)
17 }
18 return f
19 }
20
21 func TestFp(t *testing.T) {
22 const testTimes = 1 << 10
23 t.Run("no_alias", func(t *testing.T) {
24 var want, got Fp
25 x := randomFp(t)
26 got = *x
27 got.Sqr(&got)
28 want = *x
29 want.Mul(&want, &want)
30 if got.IsEqual(&want) == 0 {
31 test.ReportError(t, got, want, x)
32 }
33 })
34 t.Run("mul_inv", func(t *testing.T) {
35 var z Fp
36 for i := 0; i < testTimes; i++ {
37 x := randomFp(t)
38 y := randomFp(t)
39
40
41 z.Inv(x)
42 z.Mul(&z, y)
43 z.Mul(&z, x)
44 z.Sub(&z, y)
45 got := z.IsZero()
46 want := 1
47 if got != want {
48 test.ReportError(t, got, want, x, y)
49 }
50 }
51 })
52 t.Run("mul_sqr", func(t *testing.T) {
53 var l0, l1, r0, r1 Fp
54 for i := 0; i < testTimes; i++ {
55 x := randomFp(t)
56 y := randomFp(t)
57
58
59 l0.Add(x, y)
60 l1.Sub(x, y)
61 l0.Mul(&l0, &l1)
62 r0.Sqr(x)
63 r1.Sqr(y)
64 r0.Sub(&r0, &r1)
65 got := &l0
66 want := &r0
67 if got.IsEqual(want) == 0 {
68 test.ReportError(t, got, want, x, y)
69 }
70 }
71 })
72 t.Run("sqrt", func(t *testing.T) {
73 var r, notRoot, got Fp
74
75 for i := 0; i < testTimes; i++ {
76 x := randomFp(t)
77 x.Sqr(x)
78
79
80 isQR := r.Sqrt(x)
81 test.CheckOk(isQR == 1, fmt.Sprintf("should be a QR: %v", x), t)
82 rNeg := r
83 rNeg.Neg()
84
85 want := x
86 for _, root := range []*Fp{&r, &rNeg} {
87 got.Sqr(root)
88 if got.IsEqual(want) == 0 {
89 test.ReportError(t, got, want, x, root)
90 }
91 }
92 }
93
94 for i := 0; i < testTimes; i++ {
95 want := randomFp(t)
96 x := randomFp(t)
97 x.Sqr(x)
98 x.Add(x, x)
99
100
101 got := want
102 isQR := got.Sqrt(x)
103 test.CheckOk(isQR == 0, fmt.Sprintf("shouldn't be a QR: %v", x), t)
104
105 if got.IsEqual(want) != 1 {
106 test.ReportError(t, got, want, x, notRoot)
107 }
108 }
109 })
110 t.Run("marshal", func(t *testing.T) {
111 var b Fp
112 for i := 0; i < testTimes; i++ {
113 a := randomFp(t)
114 s, err := a.MarshalBinary()
115 test.CheckNoErr(t, err, "MarshalBinary failed")
116 err = b.UnmarshalBinary(s)
117 test.CheckNoErr(t, err, "UnmarshalBinary failed")
118 if b.IsEqual(a) == 0 {
119 test.ReportError(t, a, b)
120 }
121 }
122 })
123 }
124
125 func BenchmarkFp(b *testing.B) {
126 x := randomFp(b)
127 y := randomFp(b)
128 z := randomFp(b)
129 b.Run("Add", func(b *testing.B) {
130 for i := 0; i < b.N; i++ {
131 z.Add(x, y)
132 }
133 })
134 b.Run("Mul", func(b *testing.B) {
135 for i := 0; i < b.N; i++ {
136 z.Mul(x, y)
137 }
138 })
139 b.Run("Sqr", func(b *testing.B) {
140 for i := 0; i < b.N; i++ {
141 z.Sqr(x)
142 }
143 })
144 b.Run("Inv", func(b *testing.B) {
145 for i := 0; i < b.N; i++ {
146 z.Inv(x)
147 }
148 })
149 }
150
View as plain text