modnscalar_bench_test.go raw
1 // Copyright (c) 2020-2022 The Decred developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package secp256k1
6
7 import (
8 "math/big"
9 "testing"
10 )
11
12 // benchmarkVals returns the raw bytes for a couple of unsigned 256-bit
13 // big-endian integers used throughout the benchmarks.
14 func benchmarkVals() [2][]byte {
15 return [2][]byte{
16 hexToBytes("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364143"),
17 hexToBytes("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364144"),
18 }
19 }
20
21 // BenchmarkBigIntModN benchmarks setting and reducing an unsigned 256-bit
22 // big-endian integer modulo the group order with stdlib big integers.
23 func BenchmarkBigIntModN(b *testing.B) {
24 buf := benchmarkVals()[0]
25 b.ReportAllocs()
26 b.ResetTimer()
27 for i := 0; i < b.N; i++ {
28 v := new(big.Int).SetBytes(buf)
29 v.Mod(v, curveParams.N)
30 }
31 }
32
33 // BenchmarkModNScalar benchmarks setting and reducing an unsigned 256-bit
34 // big-endian integer modulo the group order with the specialized type.
35 func BenchmarkModNScalar(b *testing.B) {
36 slice := benchmarkVals()[0]
37 var buf [32]byte
38 copy(buf[:], slice)
39 b.ReportAllocs()
40 b.ResetTimer()
41 for i := 0; i < b.N; i++ {
42 var s ModNScalar
43 s.SetBytes(&buf)
44 }
45 }
46
47 // BenchmarkBigIntZero benchmarks zeroing an unsigned 256-bit big-endian
48 // integer modulo the group order with stdlib big integers.
49 func BenchmarkBigIntZero(b *testing.B) {
50 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
51 b.ReportAllocs()
52 b.ResetTimer()
53 for i := 0; i < b.N; i++ {
54 v1.SetUint64(0)
55 }
56 }
57
58 // BenchmarkModNScalarZero benchmarks zeroing an unsigned 256-bit big-endian
59 // integer modulo the group order with the specialized type.
60 func BenchmarkModNScalarZero(b *testing.B) {
61 var s1 ModNScalar
62 s1.SetByteSlice(benchmarkVals()[0])
63 b.ReportAllocs()
64 b.ResetTimer()
65 for i := 0; i < b.N; i++ {
66 s1.Zero()
67 }
68 }
69
70 // BenchmarkBigIntIsZero benchmarks determining if an unsigned 256-bit
71 // big-endian integer modulo the group order is zero with stdlib big integers.
72 func BenchmarkBigIntIsZero(b *testing.B) {
73 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
74 b.ReportAllocs()
75 b.ResetTimer()
76 for i := 0; i < b.N; i++ {
77 _ = v1.Sign() == 0
78 }
79 }
80
81 // BenchmarkModNScalarIsZero benchmarks determining if an unsigned 256-bit
82 // big-endian integer modulo the group order is zero with the specialized type.
83 func BenchmarkModNScalarIsZero(b *testing.B) {
84 var s1 ModNScalar
85 s1.SetByteSlice(benchmarkVals()[0])
86 b.ReportAllocs()
87 b.ResetTimer()
88 for i := 0; i < b.N; i++ {
89 _ = s1.IsZero()
90 }
91 }
92
93 // BenchmarkBigIntEquals benchmarks determining equality between two unsigned
94 // 256-bit big-endian integers modulo the group order with stdlib big integers.
95 func BenchmarkBigIntEquals(b *testing.B) {
96 bufs := benchmarkVals()
97 v1 := new(big.Int).SetBytes(bufs[0])
98 v2 := new(big.Int).SetBytes(bufs[1])
99 b.ReportAllocs()
100 b.ResetTimer()
101 for i := 0; i < b.N; i++ {
102 v1.Cmp(v2)
103 }
104 }
105
106 // BenchmarkModNScalarEquals benchmarks determining equality between two
107 // unsigned 256-bit big-endian integers modulo the group order with the
108 // specialized type.
109 func BenchmarkModNScalarEquals(b *testing.B) {
110 bufs := benchmarkVals()
111 var s1, s2 ModNScalar
112 s1.SetByteSlice(bufs[0])
113 s2.SetByteSlice(bufs[1])
114 b.ReportAllocs()
115 b.ResetTimer()
116 for i := 0; i < b.N; i++ {
117 s1.Equals(&s2)
118 }
119 }
120
121 // BenchmarkBigIntAddModN benchmarks adding two unsigned 256-bit big-endian
122 // integers modulo the group order with stdlib big integers.
123 func BenchmarkBigIntAddModN(b *testing.B) {
124 bufs := benchmarkVals()
125 v1 := new(big.Int).SetBytes(bufs[0])
126 v2 := new(big.Int).SetBytes(bufs[1])
127 b.ReportAllocs()
128 b.ResetTimer()
129 for i := 0; i < b.N; i++ {
130 result := new(big.Int).Add(v1, v2)
131 result.Mod(result, curveParams.N)
132 }
133 }
134
135 // BenchmarkModNScalarAdd benchmarks adding two unsigned 256-bit big-endian
136 // integers modulo the group order with the specialized type.
137 func BenchmarkModNScalarAdd(b *testing.B) {
138 bufs := benchmarkVals()
139 var s1, s2 ModNScalar
140 s1.SetByteSlice(bufs[0])
141 s2.SetByteSlice(bufs[1])
142 b.ReportAllocs()
143 b.ResetTimer()
144 for i := 0; i < b.N; i++ {
145 _ = new(ModNScalar).Add2(&s1, &s2)
146 }
147 }
148
149 // BenchmarkBigIntMulModN benchmarks multiplying two unsigned 256-bit big-endian
150 // integers modulo the group order with stdlib big integers.
151 func BenchmarkBigIntMulModN(b *testing.B) {
152 bufs := benchmarkVals()
153 v1 := new(big.Int).SetBytes(bufs[0])
154 v2 := new(big.Int).SetBytes(bufs[1])
155 b.ReportAllocs()
156 b.ResetTimer()
157 for i := 0; i < b.N; i++ {
158 result := new(big.Int).Mul(v1, v2)
159 result.Mod(result, curveParams.N)
160 }
161 }
162
163 // BenchmarkModNScalarMul benchmarks multiplying two unsigned 256-bit big-endian
164 // integers modulo the group order with the specialized type.
165 func BenchmarkModNScalarMul(b *testing.B) {
166 bufs := benchmarkVals()
167 var s1, s2 ModNScalar
168 s1.SetByteSlice(bufs[0])
169 s2.SetByteSlice(bufs[1])
170 b.ReportAllocs()
171 b.ResetTimer()
172 for i := 0; i < b.N; i++ {
173 _ = new(ModNScalar).Mul2(&s1, &s2)
174 }
175 }
176
177 // BenchmarkBigIntSquareModN benchmarks squaring an unsigned 256-bit big-endian
178 // integer modulo the group order is zero with stdlib big integers.
179 func BenchmarkBigIntSquareModN(b *testing.B) {
180 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
181 b.ReportAllocs()
182 b.ResetTimer()
183 for i := 0; i < b.N; i++ {
184 result := new(big.Int).Mul(v1, v1)
185 result.Mod(result, curveParams.N)
186 }
187 }
188
189 // BenchmarkModNScalarSquare benchmarks squaring an unsigned 256-bit big-endian
190 // integer modulo the group order is zero with the specialized type.
191 func BenchmarkModNScalarSquare(b *testing.B) {
192 var s1 ModNScalar
193 s1.SetByteSlice(benchmarkVals()[0])
194 b.ReportAllocs()
195 b.ResetTimer()
196 for i := 0; i < b.N; i++ {
197 _ = new(ModNScalar).SquareVal(&s1)
198 }
199 }
200
201 // BenchmarkBigIntNegateModN benchmarks negating an unsigned 256-bit big-endian
202 // integer modulo the group order is zero with stdlib big integers.
203 func BenchmarkBigIntNegateModN(b *testing.B) {
204 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
205 b.ReportAllocs()
206 b.ResetTimer()
207 for i := 0; i < b.N; i++ {
208 result := new(big.Int).Neg(v1)
209 result.Mod(result, curveParams.N)
210 }
211 }
212
213 // BenchmarkModNScalarNegate benchmarks negating an unsigned 256-bit big-endian
214 // integer modulo the group order is zero with the specialized type.
215 func BenchmarkModNScalarNegate(b *testing.B) {
216 var s1 ModNScalar
217 s1.SetByteSlice(benchmarkVals()[0])
218 b.ReportAllocs()
219 b.ResetTimer()
220 for i := 0; i < b.N; i++ {
221 _ = new(ModNScalar).NegateVal(&s1)
222 }
223 }
224
225 // BenchmarkBigIntInverseModN benchmarks calculating the multiplicative inverse
226 // of an unsigned 256-bit big-endian integer modulo the group order is zero with
227 // stdlib big integers.
228 func BenchmarkBigIntInverseModN(b *testing.B) {
229 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
230 b.ReportAllocs()
231 b.ResetTimer()
232 for i := 0; i < b.N; i++ {
233 new(big.Int).ModInverse(v1, curveParams.N)
234 }
235 }
236
237 // BenchmarkModNScalarInverse benchmarks calculating the multiplicative inverse
238 // of an unsigned 256-bit big-endian integer modulo the group order is zero with
239 // the specialized type.
240 func BenchmarkModNScalarInverse(b *testing.B) {
241 var s1 ModNScalar
242 s1.SetByteSlice(benchmarkVals()[0])
243 b.ReportAllocs()
244 b.ResetTimer()
245 for i := 0; i < b.N; i++ {
246 _ = new(ModNScalar).InverseValNonConst(&s1)
247 }
248 }
249
250 // BenchmarkBigIntIsOverHalfOrder benchmarks determining if an unsigned 256-bit
251 // big-endian integer modulo the group order exceeds half the group order with
252 // stdlib big integers.
253 func BenchmarkBigIntIsOverHalfOrder(b *testing.B) {
254 v1 := new(big.Int).SetBytes(benchmarkVals()[0])
255 bigHalfOrder := new(big.Int).Rsh(curveParams.N, 1)
256 b.ReportAllocs()
257 b.ResetTimer()
258 for i := 0; i < b.N; i++ {
259 _ = v1.Cmp(bigHalfOrder)
260 }
261 }
262
263 // BenchmarkModNScalarIsOverHalfOrder benchmarks determining if an unsigned
264 // 256-bit big-endian integer modulo the group order exceeds half the group
265 // order with the specialized type.
266 func BenchmarkModNScalarIsOverHalfOrder(b *testing.B) {
267 var s1 ModNScalar
268 s1.SetByteSlice(benchmarkVals()[0])
269 b.ReportAllocs()
270 b.ResetTimer()
271 for i := 0; i < b.N; i++ {
272 s1.IsOverHalfOrder()
273 }
274 }
275