@@ -43,21 +43,22 @@ export Fp, Fr, FF
43
43
44
44
# No exceptions allowed
45
45
{.push raises : [].}
46
+ {.push inline .}
46
47
47
48
# ############################################################
48
49
#
49
50
# Conversion
50
51
#
51
52
# ############################################################
52
53
53
- func fromBig * (dst: var FF , src: BigInt ) {. inline .} =
54
+ func fromBig * (dst: var FF , src: BigInt ) =
54
55
# # Convert a BigInt to its Montgomery form
55
56
when nimvm :
56
57
dst.mres.montyResidue_precompute (src, FF .fieldMod (), FF .getR2modP (), FF .getNegInvModWord ())
57
58
else :
58
59
dst.mres.montyResidue (src, FF .fieldMod (), FF .getR2modP (), FF .getNegInvModWord (), FF .canUseNoCarryMontyMul ())
59
60
60
- func fromBig * [C: static Curve ](T: type FF [C], src: BigInt ): FF [C] {.noInit , inline .} =
61
+ func fromBig * [C: static Curve ](T: type FF [C], src: BigInt ): FF [C] {.noInit .} =
61
62
# # Convert a BigInt to its Montgomery form
62
63
result .fromBig (src)
63
64
@@ -70,14 +71,14 @@ func toBig*(src: FF): auto {.noInit, inline.} =
70
71
# Copy
71
72
# ------------------------------------------------------------
72
73
73
- func ccopy * (a: var FF , b: FF , ctl: SecretBool ) {.inline , meter .} =
74
+ func ccopy * (a: var FF , b: FF , ctl: SecretBool ) {.meter .} =
74
75
# # Constant-time conditional copy
75
76
# # If ctl is true: b is copied into a
76
77
# # if ctl is false: b is not copied and a is unmodified
77
78
# # Time and memory accesses are the same whether a copy occurs or not
78
79
ccopy (a.mres, b.mres, ctl)
79
80
80
- func cswap * (a, b: var FF , ctl: CTBool ) {.inline , meter .} =
81
+ func cswap * (a, b: var FF , ctl: CTBool ) {.meter .} =
81
82
# # Swap ``a`` and ``b`` if ``ctl`` is true
82
83
# #
83
84
# # Constant-time:
@@ -105,34 +106,34 @@ func cswap*(a, b: var FF, ctl: CTBool) {.inline, meter.} =
105
106
# In practice I'm not aware of such prime being using in elliptic curves.
106
107
# 2^127 - 1 and 2^521 - 1 are used but 127 and 521 are not multiple of 32/64
107
108
108
- func `==` * (a, b: FF ): SecretBool {. inline .} =
109
+ func `==` * (a, b: FF ): SecretBool =
109
110
# # Constant-time equality check
110
111
a.mres == b.mres
111
112
112
- func isZero * (a: FF ): SecretBool {. inline .} =
113
+ func isZero * (a: FF ): SecretBool =
113
114
# # Constant-time check if zero
114
115
a.mres.isZero ()
115
116
116
- func isOne * (a: FF ): SecretBool {. inline .} =
117
+ func isOne * (a: FF ): SecretBool =
117
118
# # Constant-time check if one
118
119
a.mres == FF .getMontyOne ()
119
120
120
- func isMinusOne * (a: FF ): SecretBool {. inline .} =
121
+ func isMinusOne * (a: FF ): SecretBool =
121
122
# # Constant-time check if -1 (mod p)
122
123
a.mres == FF .getMontyPrimeMinus1 ()
123
124
124
- func setZero * (a: var FF ) {. inline .} =
125
+ func setZero * (a: var FF ) =
125
126
# # Set ``a`` to zero
126
127
a.mres.setZero ()
127
128
128
- func setOne * (a: var FF ) {. inline .} =
129
+ func setOne * (a: var FF ) =
129
130
# # Set ``a`` to one
130
131
# Note: we need 1 in Montgomery residue form
131
132
# TODO : Nim codegen is not optimal it uses a temporary
132
133
# Check if the compiler optimizes it away
133
134
a.mres = FF .getMontyOne ()
134
135
135
- func `+=` * (a: var FF , b: FF ) {.inline , meter .} =
136
+ func `+=` * (a: var FF , b: FF ) {.meter .} =
136
137
# # In-place addition modulo p
137
138
when UseASM_X86_64 and a.mres.limbs.len <= 6 : # TODO : handle spilling
138
139
addmod_asm (a.mres.limbs, a.mres.limbs, b.mres.limbs, FF .fieldMod ().limbs)
@@ -141,15 +142,15 @@ func `+=`*(a: var FF, b: FF) {.inline, meter.} =
141
142
overflowed = overflowed or not (a.mres < FF .fieldMod ())
142
143
discard csub (a.mres, FF .fieldMod (), overflowed)
143
144
144
- func `-=` * (a: var FF , b: FF ) {.inline , meter .} =
145
+ func `-=` * (a: var FF , b: FF ) {.meter .} =
145
146
# # In-place substraction modulo p
146
147
when UseASM_X86_64 and a.mres.limbs.len <= 6 : # TODO : handle spilling
147
148
submod_asm (a.mres.limbs, a.mres.limbs, b.mres.limbs, FF .fieldMod ().limbs)
148
149
else :
149
150
let underflowed = sub (a.mres, b.mres)
150
151
discard cadd (a.mres, FF .fieldMod (), underflowed)
151
152
152
- func double * (a: var FF ) {.inline , meter .} =
153
+ func double * (a: var FF ) {.meter .} =
153
154
# # Double ``a`` modulo p
154
155
when UseASM_X86_64 and a.mres.limbs.len <= 6 : # TODO : handle spilling
155
156
addmod_asm (a.mres.limbs, a.mres.limbs, a.mres.limbs, FF .fieldMod ().limbs)
@@ -158,7 +159,7 @@ func double*(a: var FF) {.inline, meter.} =
158
159
overflowed = overflowed or not (a.mres < FF .fieldMod ())
159
160
discard csub (a.mres, FF .fieldMod (), overflowed)
160
161
161
- func sum * (r: var FF , a, b: FF ) {.inline , meter .} =
162
+ func sum * (r: var FF , a, b: FF ) {.meter .} =
162
163
# # Sum ``a`` and ``b`` into ``r`` modulo p
163
164
# # r is initialized/overwritten
164
165
when UseASM_X86_64 and a.mres.limbs.len <= 6 : # TODO : handle spilling
@@ -168,11 +169,11 @@ func sum*(r: var FF, a, b: FF) {.inline, meter.} =
168
169
overflowed = overflowed or not (r.mres < FF .fieldMod ())
169
170
discard csub (r.mres, FF .fieldMod (), overflowed)
170
171
171
- func sumNoReduce * (r: var FF , a, b: FF ) {.inline , meter .} =
172
+ func sumNoReduce * (r: var FF , a, b: FF ) {.meter .} =
172
173
# # Sum ``a`` and ``b`` into ``r`` without reduction
173
174
discard r.mres.sum (a.mres, b.mres)
174
175
175
- func diff * (r: var FF , a, b: FF ) {.inline , meter .} =
176
+ func diff * (r: var FF , a, b: FF ) {.meter .} =
176
177
# # Substract `b` from `a` and store the result into `r`.
177
178
# # `r` is initialized/overwritten
178
179
# # Requires r != b
@@ -182,12 +183,12 @@ func diff*(r: var FF, a, b: FF) {.inline, meter.} =
182
183
var underflowed = r.mres.diff (a.mres, b.mres)
183
184
discard cadd (r.mres, FF .fieldMod (), underflowed)
184
185
185
- func diffNoReduce * (r: var FF , a, b: FF ) {.inline , meter .} =
186
+ func diffNoReduce * (r: var FF , a, b: FF ) {.meter .} =
186
187
# # Substract `b` from `a` and store the result into `r`
187
188
# # without reduction
188
189
discard r.mres.diff (a.mres, b.mres)
189
190
190
- func double * (r: var FF , a: FF ) {.inline , meter .} =
191
+ func double * (r: var FF , a: FF ) {.meter .} =
191
192
# # Double ``a`` into ``r``
192
193
# # `r` is initialized/overwritten
193
194
when UseASM_X86_64 and a.mres.limbs.len <= 6 : # TODO : handle spilling
@@ -197,16 +198,16 @@ func double*(r: var FF, a: FF) {.inline, meter.} =
197
198
overflowed = overflowed or not (r.mres < FF .fieldMod ())
198
199
discard csub (r.mres, FF .fieldMod (), overflowed)
199
200
200
- func prod * (r: var FF , a, b: FF ) {.inline , meter .} =
201
+ func prod * (r: var FF , a, b: FF ) {.meter .} =
201
202
# # Store the product of ``a`` by ``b`` modulo p into ``r``
202
203
# # ``r`` is initialized / overwritten
203
204
r.mres.montyMul (a.mres, b.mres, FF .fieldMod (), FF .getNegInvModWord (), FF .canUseNoCarryMontyMul ())
204
205
205
- func square * (r: var FF , a: FF ) {.inline , meter .} =
206
+ func square * (r: var FF , a: FF ) {.meter .} =
206
207
# # Squaring modulo p
207
208
r.mres.montySquare (a.mres, FF .fieldMod (), FF .getNegInvModWord (), FF .canUseNoCarryMontySquare ())
208
209
209
- func neg * (r: var FF , a: FF ) {.inline , meter .} =
210
+ func neg * (r: var FF , a: FF ) {.meter .} =
210
211
# # Negate modulo p
211
212
when UseASM_X86_64:
212
213
negmod_asm (r.mres.limbs, a.mres.limbs, FF .fieldMod ().limbs)
@@ -221,11 +222,11 @@ func neg*(r: var FF, a: FF) {.inline, meter.} =
221
222
t.mres.czero (isZero)
222
223
r = t
223
224
224
- func neg * (a: var FF ) {.inline , meter .} =
225
+ func neg * (a: var FF ) {.meter .} =
225
226
# # Negate modulo p
226
227
a.neg (a)
227
228
228
- func div2 * (a: var FF ) {.inline , meter .} =
229
+ func div2 * (a: var FF ) {.meter .} =
229
230
# # Modular division by 2
230
231
a.mres.div2_modular (FF .getPrimePlus1div2 ())
231
232
@@ -269,7 +270,7 @@ func csub*(a: var FF, b: FF, ctl: SecretBool) {.meter.} =
269
270
#
270
271
# Internally those procedures will allocate extra scratchspace on the stack
271
272
272
- func pow * (a: var FF , exponent: BigInt ) {. inline .} =
273
+ func pow * (a: var FF , exponent: BigInt ) =
273
274
# # Exponentiation modulo p
274
275
# # ``a``: a field element to be exponentiated
275
276
# # ``exponent``: a big integer
@@ -282,7 +283,7 @@ func pow*(a: var FF, exponent: BigInt) {.inline.} =
282
283
FF .canUseNoCarryMontySquare ()
283
284
)
284
285
285
- func pow * (a: var FF , exponent: openarray [byte ]) {. inline .} =
286
+ func pow * (a: var FF , exponent: openarray [byte ]) =
286
287
# # Exponentiation modulo p
287
288
# # ``a``: a field element to be exponentiated
288
289
# # ``exponent``: a big integer in canonical big endian representation
@@ -295,7 +296,7 @@ func pow*(a: var FF, exponent: openarray[byte]) {.inline.} =
295
296
FF .canUseNoCarryMontySquare ()
296
297
)
297
298
298
- func powUnsafeExponent * (a: var FF , exponent: BigInt ) {. inline .} =
299
+ func powUnsafeExponent * (a: var FF , exponent: BigInt ) =
299
300
# # Exponentiation modulo p
300
301
# # ``a``: a field element to be exponentiated
301
302
# # ``exponent``: a big integer
@@ -315,7 +316,7 @@ func powUnsafeExponent*(a: var FF, exponent: BigInt) {.inline.} =
315
316
FF .canUseNoCarryMontySquare ()
316
317
)
317
318
318
- func powUnsafeExponent * (a: var FF , exponent: openarray [byte ]) {. inline .} =
319
+ func powUnsafeExponent * (a: var FF , exponent: openarray [byte ]) =
319
320
# # Exponentiation modulo p
320
321
# # ``a``: a field element to be exponentiated
321
322
# # ``exponent``: a big integer a big integer in canonical big endian representation
@@ -342,47 +343,27 @@ func powUnsafeExponent*(a: var FF, exponent: openarray[byte]) {.inline.} =
342
343
# ############################################################
343
344
#
344
345
# This implements extra primitives for ergonomics.
345
- # The in-place ones should be preferred as they avoid copies on assignment
346
- # Two kinds:
347
- # - Those that return a field element
348
- # - Those that internally allocate a temporary field element
349
346
350
- func `+` * (a, b: FF ): FF {.noInit , inline , meter .} =
351
- # # Addition modulo p
352
- result .sum (a, b)
353
-
354
- func `-` * (a, b: FF ): FF {.noInit , inline , meter .} =
355
- # # Substraction modulo p
356
- result .diff (a, b)
357
-
358
- func `*` * (a, b: FF ): FF {.noInit , inline , meter .} =
359
- # # Multiplication modulo p
360
- # #
361
- # # It is recommended to assign with {.noInit.}
362
- # # as FF elements are usually large and this
363
- # # routine will zero init internally the result.
364
- result .prod (a, b)
365
-
366
- func `*=` * (a: var FF , b: FF ) {.inline , meter .} =
347
+ func `*=` * (a: var FF , b: FF ) {.meter .} =
367
348
# # Multiplication modulo p
368
349
a.prod (a, b)
369
350
370
- func square * (a: var FF ) {.inline , meter .} =
351
+ func square * (a: var FF ) {.meter .} =
371
352
# # Squaring modulo p
372
353
a.mres.montySquare (a.mres, FF .fieldMod (), FF .getNegInvModWord (), FF .canUseNoCarryMontySquare ())
373
354
374
- func square_repeated * (r: var FF , num: int ) {.inline , meter .} =
355
+ func square_repeated * (r: var FF , num: int ) {.meter .} =
375
356
# # Repeated squarings
376
357
for _ in 0 ..< num:
377
358
r.square ()
378
359
379
- func square_repeated * (r: var FF , a: FF , num: int ) {.inline , meter .} =
360
+ func square_repeated * (r: var FF , a: FF , num: int ) {.meter .} =
380
361
# # Repeated squarings
381
362
r.square (a)
382
363
for _ in 1 ..< num:
383
364
r.square ()
384
365
385
- func `*=` * (a: var FF , b: static int ) {. inline .} =
366
+ func `*=` * (a: var FF , b: static int ) =
386
367
# # Multiplication by a small integer known at compile-time
387
368
# Implementation:
388
369
# We don't want to go convert the integer to the Montgomery domain (O(n²))
@@ -464,7 +445,27 @@ func `*=`*(a: var FF, b: static int) {.inline.} =
464
445
else :
465
446
{.error : " Multiplication by this small int not implemented" .}
466
447
467
- func `*` * (b: static int , a: FF ): FF {. noinit , inline .} =
448
+ func prod * (r: var FF , a: FF , b: static int ) =
468
449
# # Multiplication by a small integer known at compile-time
469
- result = a
470
- result *= b
450
+ const negate = b < 0
451
+ const b = if negate: - b
452
+ else : b
453
+ when negate:
454
+ r.neg (a)
455
+ else :
456
+ r = a
457
+ r *= b
458
+
459
+ template mulCheckSparse * (a: var Fp , b: Fp ) =
460
+ # # Multiplication with optimization for sparse inputs
461
+ when b.isOne ().bool :
462
+ discard
463
+ elif b.isZero ().bool :
464
+ a.setZero ()
465
+ elif b.isMinusOne ().bool :
466
+ a.neg ()
467
+ else :
468
+ a *= b
469
+
470
+ {.pop .} # inline
471
+ {.pop .} # raises no exceptions
0 commit comments