/rust/registry/src/index.crates.io-1949cf8c6b5b557f/primeorder-0.13.6/src/field.rs
Line | Count | Source |
1 | | /// Implements a field element type whose internal representation is in |
2 | | /// Montgomery form, providing a combination of trait impls and inherent impls |
3 | | /// which are `const fn` where possible. |
4 | | /// |
5 | | /// Accepts a set of `const fn` arithmetic operation functions as arguments. |
6 | | /// |
7 | | /// # Inherent impls |
8 | | /// - `const ZERO: Self` |
9 | | /// - `const ONE: Self` (multiplicative identity) |
10 | | /// - `pub fn from_bytes` |
11 | | /// - `pub fn from_slice` |
12 | | /// - `pub fn from_uint` |
13 | | /// - `fn from_uint_unchecked` |
14 | | /// - `pub fn to_bytes` |
15 | | /// - `pub fn to_canonical` |
16 | | /// - `pub fn is_odd` |
17 | | /// - `pub fn is_zero` |
18 | | /// - `pub fn double` |
19 | | /// |
20 | | /// NOTE: field implementations must provide their own inherent impls of |
21 | | /// the following methods in order for the code generated by this macro to |
22 | | /// compile: |
23 | | /// |
24 | | /// - `pub fn invert` |
25 | | /// - `pub fn sqrt` |
26 | | /// |
27 | | /// # Trait impls |
28 | | /// - `AsRef<$arr>` |
29 | | /// - `ConditionallySelectable` |
30 | | /// - `ConstantTimeEq` |
31 | | /// - `ConstantTimeGreater` |
32 | | /// - `ConstantTimeLess` |
33 | | /// - `Default` |
34 | | /// - `DefaultIsZeroes` |
35 | | /// - `Eq` |
36 | | /// - `Field` |
37 | | /// - `PartialEq` |
38 | | /// |
39 | | /// ## Ops |
40 | | /// - `Add` |
41 | | /// - `AddAssign` |
42 | | /// - `Sub` |
43 | | /// - `SubAssign` |
44 | | /// - `Mul` |
45 | | /// - `MulAssign` |
46 | | /// - `Neg` |
47 | | #[macro_export] |
48 | | macro_rules! impl_mont_field_element { |
49 | | ( |
50 | | $curve:tt, |
51 | | $fe:tt, |
52 | | $bytes:ty, |
53 | | $uint:ty, |
54 | | $modulus:expr, |
55 | | $arr:ty, |
56 | | $from_mont:ident, |
57 | | $to_mont:ident, |
58 | | $add:ident, |
59 | | $sub:ident, |
60 | | $mul:ident, |
61 | | $neg:ident, |
62 | | $square:ident |
63 | | ) => { |
64 | | impl $fe { |
65 | | /// Zero element. |
66 | | pub const ZERO: Self = Self(<$uint>::ZERO); |
67 | | |
68 | | /// Multiplicative identity. |
69 | | pub const ONE: Self = Self::from_uint_unchecked(<$uint>::ONE); |
70 | | |
71 | | /// Create a [` |
72 | | #[doc = stringify!($fe)] |
73 | | /// `] from a canonical big-endian representation. |
74 | 112 | pub fn from_bytes(repr: &$bytes) -> $crate::elliptic_curve::subtle::CtOption<Self> { |
75 | | use $crate::elliptic_curve::FieldBytesEncoding; |
76 | 112 | Self::from_uint(FieldBytesEncoding::<$curve>::decode_field_bytes(repr)) |
77 | 112 | } |
78 | | |
79 | | /// Decode [` |
80 | | #[doc = stringify!($fe)] |
81 | | /// `] from a big endian byte slice. |
82 | 0 | pub fn from_slice(slice: &[u8]) -> $crate::elliptic_curve::Result<Self> { |
83 | | use $crate::elliptic_curve::generic_array::{typenum::Unsigned, GenericArray}; |
84 | | |
85 | 0 | if slice.len() != <$curve as $crate::elliptic_curve::Curve>::FieldBytesSize::USIZE { |
86 | 0 | return Err($crate::elliptic_curve::Error); |
87 | 0 | } |
88 | | |
89 | 0 | Option::from(Self::from_bytes(GenericArray::from_slice(slice))) |
90 | 0 | .ok_or($crate::elliptic_curve::Error) |
91 | 0 | } |
92 | | |
93 | | /// Decode [` |
94 | | #[doc = stringify!($fe)] |
95 | | /// `] |
96 | | /// from [` |
97 | | #[doc = stringify!($uint)] |
98 | | /// `] converting it into Montgomery form: |
99 | | /// |
100 | | /// ```text |
101 | | /// w * R^2 * R^-1 mod p = wR mod p |
102 | | /// ``` |
103 | 112 | pub fn from_uint(uint: $uint) -> $crate::elliptic_curve::subtle::CtOption<Self> { |
104 | | use $crate::elliptic_curve::subtle::ConstantTimeLess as _; |
105 | 112 | let is_some = uint.ct_lt(&$modulus); |
106 | 112 | $crate::elliptic_curve::subtle::CtOption::new( |
107 | 112 | Self::from_uint_unchecked(uint), |
108 | 112 | is_some, |
109 | | ) |
110 | 112 | } |
111 | | |
112 | | /// Parse a [` |
113 | | #[doc = stringify!($fe)] |
114 | | /// `] from big endian hex-encoded bytes. |
115 | | /// |
116 | | /// Does *not* perform a check that the field element does not overflow the order. |
117 | | /// |
118 | | /// This method is primarily intended for defining internal constants. |
119 | | #[allow(dead_code)] |
120 | 0 | pub(crate) const fn from_hex(hex: &str) -> Self { |
121 | 0 | Self::from_uint_unchecked(<$uint>::from_be_hex(hex)) |
122 | 0 | } |
123 | | |
124 | | /// Convert a `u64` into a [` |
125 | | #[doc = stringify!($fe)] |
126 | | /// `]. |
127 | 0 | pub const fn from_u64(w: u64) -> Self { |
128 | 0 | Self::from_uint_unchecked(<$uint>::from_u64(w)) |
129 | 0 | } |
130 | | |
131 | | /// Decode [` |
132 | | #[doc = stringify!($fe)] |
133 | | /// `] from [` |
134 | | #[doc = stringify!($uint)] |
135 | | /// `] converting it into Montgomery form. |
136 | | /// |
137 | | /// Does *not* perform a check that the field element does not overflow the order. |
138 | | /// |
139 | | /// Used incorrectly this can lead to invalid results! |
140 | 112 | pub(crate) const fn from_uint_unchecked(w: $uint) -> Self { |
141 | 112 | Self(<$uint>::from_words($to_mont(w.as_words()))) |
142 | 112 | } |
143 | | |
144 | | /// Returns the big-endian encoding of this [` |
145 | | #[doc = stringify!($fe)] |
146 | | /// `]. |
147 | 15.8k | pub fn to_bytes(self) -> $bytes { |
148 | | use $crate::elliptic_curve::FieldBytesEncoding; |
149 | 15.8k | FieldBytesEncoding::<$curve>::encode_field_bytes(&self.to_canonical()) |
150 | 15.8k | } |
151 | | |
152 | | /// Translate [` |
153 | | #[doc = stringify!($fe)] |
154 | | /// `] out of the Montgomery domain, returning a [` |
155 | | #[doc = stringify!($uint)] |
156 | | /// `] in canonical form. |
157 | | #[inline] |
158 | 19.0k | pub const fn to_canonical(self) -> $uint { |
159 | 19.0k | <$uint>::from_words($from_mont(self.0.as_words())) |
160 | 19.0k | } |
161 | | |
162 | | /// Determine if this [` |
163 | | #[doc = stringify!($fe)] |
164 | | /// `] is odd in the SEC1 sense: `self mod 2 == 1`. |
165 | | /// |
166 | | /// # Returns |
167 | | /// |
168 | | /// If odd, return `Choice(1)`. Otherwise, return `Choice(0)`. |
169 | 3.19k | pub fn is_odd(&self) -> Choice { |
170 | | use $crate::elliptic_curve::bigint::Integer; |
171 | 3.19k | self.to_canonical().is_odd() |
172 | 3.19k | } |
173 | | |
174 | | /// Determine if this [` |
175 | | #[doc = stringify!($fe)] |
176 | | /// `] is even in the SEC1 sense: `self mod 2 == 0`. |
177 | | /// |
178 | | /// # Returns |
179 | | /// |
180 | | /// If even, return `Choice(1)`. Otherwise, return `Choice(0)`. |
181 | 0 | pub fn is_even(&self) -> Choice { |
182 | 0 | !self.is_odd() |
183 | 0 | } |
184 | | |
185 | | /// Determine if this [` |
186 | | #[doc = stringify!($fe)] |
187 | | /// `] is zero. |
188 | | /// |
189 | | /// # Returns |
190 | | /// |
191 | | /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. |
192 | 8.27k | pub fn is_zero(&self) -> Choice { |
193 | 8.27k | self.ct_eq(&Self::ZERO) |
194 | 8.27k | } |
195 | | |
196 | | /// Add elements. |
197 | 21.6M | pub const fn add(&self, rhs: &Self) -> Self { |
198 | 21.6M | Self(<$uint>::from_words($add( |
199 | 21.6M | self.0.as_words(), |
200 | 21.6M | rhs.0.as_words(), |
201 | 21.6M | ))) |
202 | 21.6M | } |
203 | | |
204 | | /// Double element (add it to itself). |
205 | | #[must_use] |
206 | 21.6M | pub const fn double(&self) -> Self { |
207 | 21.6M | self.add(self) |
208 | 21.6M | } |
209 | | |
210 | | /// Subtract elements. |
211 | 0 | pub const fn sub(&self, rhs: &Self) -> Self { |
212 | 0 | Self(<$uint>::from_words($sub( |
213 | 0 | self.0.as_words(), |
214 | 0 | rhs.0.as_words(), |
215 | 0 | ))) |
216 | 0 | } |
217 | | |
218 | | /// Multiply elements. |
219 | 99.3k | pub const fn multiply(&self, rhs: &Self) -> Self { |
220 | 99.3k | Self(<$uint>::from_words($mul( |
221 | 99.3k | self.0.as_words(), |
222 | 99.3k | rhs.0.as_words(), |
223 | 99.3k | ))) |
224 | 99.3k | } |
225 | | |
226 | | /// Negate element. |
227 | 0 | pub const fn neg(&self) -> Self { |
228 | 0 | Self(<$uint>::from_words($neg(self.0.as_words()))) |
229 | 0 | } |
230 | | |
231 | | /// Compute modular square. |
232 | | #[must_use] |
233 | 8.54M | pub const fn square(&self) -> Self { |
234 | 8.54M | Self(<$uint>::from_words($square(self.0.as_words()))) |
235 | 8.54M | } |
236 | | |
237 | | /// Returns `self^exp`, where `exp` is a little-endian integer exponent. |
238 | | /// |
239 | | /// **This operation is variable time with respect to the exponent.** |
240 | | /// |
241 | | /// If the exponent is fixed, this operation is effectively constant time. |
242 | 0 | pub const fn pow_vartime(&self, exp: &[u64]) -> Self { |
243 | 0 | let mut res = Self::ONE; |
244 | 0 | let mut i = exp.len(); |
245 | | |
246 | 0 | while i > 0 { |
247 | 0 | i -= 1; |
248 | | |
249 | 0 | let mut j = 64; |
250 | 0 | while j > 0 { |
251 | 0 | j -= 1; |
252 | 0 | res = res.square(); |
253 | | |
254 | 0 | if ((exp[i] >> j) & 1) == 1 { |
255 | 0 | res = res.multiply(self); |
256 | 0 | } |
257 | | } |
258 | | } |
259 | | |
260 | 0 | res |
261 | 0 | } |
262 | | } |
263 | | |
264 | | $crate::impl_mont_field_element_arithmetic!( |
265 | | $fe, $bytes, $uint, $arr, $add, $sub, $mul, $neg |
266 | | ); |
267 | | }; |
268 | | } |
269 | | |
270 | | /// Add arithmetic impls to the given field element. |
271 | | #[macro_export] |
272 | | macro_rules! impl_mont_field_element_arithmetic { |
273 | | ( |
274 | | $fe:tt, |
275 | | $bytes:ty, |
276 | | $uint:ty, |
277 | | $arr:ty, |
278 | | $add:ident, |
279 | | $sub:ident, |
280 | | $mul:ident, |
281 | | $neg:ident |
282 | | ) => { |
283 | | impl AsRef<$arr> for $fe { |
284 | 140M | fn as_ref(&self) -> &$arr { |
285 | 140M | self.0.as_ref() |
286 | 140M | } |
287 | | } |
288 | | |
289 | | impl Default for $fe { |
290 | 8.38k | fn default() -> Self { |
291 | 8.38k | Self::ZERO |
292 | 8.38k | } |
293 | | } |
294 | | |
295 | | impl Eq for $fe {} |
296 | | impl PartialEq for $fe { |
297 | 0 | fn eq(&self, rhs: &Self) -> bool { |
298 | 0 | self.0.ct_eq(&(rhs.0)).into() |
299 | 0 | } |
300 | | } |
301 | | |
302 | | impl From<u32> for $fe { |
303 | 0 | fn from(n: u32) -> $fe { |
304 | 0 | Self::from_uint_unchecked(<$uint>::from(n)) |
305 | 0 | } |
306 | | } |
307 | | |
308 | | impl From<u64> for $fe { |
309 | 0 | fn from(n: u64) -> $fe { |
310 | 0 | Self::from_uint_unchecked(<$uint>::from(n)) |
311 | 0 | } |
312 | | } |
313 | | |
314 | | impl From<u128> for $fe { |
315 | 0 | fn from(n: u128) -> $fe { |
316 | 0 | Self::from_uint_unchecked(<$uint>::from(n)) |
317 | 0 | } |
318 | | } |
319 | | |
320 | | impl $crate::elliptic_curve::subtle::ConditionallySelectable for $fe { |
321 | 23.8M | fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { |
322 | 23.8M | Self(<$uint>::conditional_select(&a.0, &b.0, choice)) |
323 | 23.8M | } |
324 | | } |
325 | | |
326 | | impl $crate::elliptic_curve::subtle::ConstantTimeEq for $fe { |
327 | 8.33k | fn ct_eq(&self, other: &Self) -> $crate::elliptic_curve::subtle::Choice { |
328 | 8.33k | self.0.ct_eq(&other.0) |
329 | 8.33k | } |
330 | | } |
331 | | |
332 | | impl $crate::elliptic_curve::subtle::ConstantTimeGreater for $fe { |
333 | 0 | fn ct_gt(&self, other: &Self) -> $crate::elliptic_curve::subtle::Choice { |
334 | 0 | self.0.ct_gt(&other.0) |
335 | 0 | } |
336 | | } |
337 | | |
338 | | impl $crate::elliptic_curve::subtle::ConstantTimeLess for $fe { |
339 | 0 | fn ct_lt(&self, other: &Self) -> $crate::elliptic_curve::subtle::Choice { |
340 | 0 | self.0.ct_lt(&other.0) |
341 | 0 | } |
342 | | } |
343 | | |
344 | | impl $crate::elliptic_curve::zeroize::DefaultIsZeroes for $fe {} |
345 | | |
346 | | impl $crate::elliptic_curve::ff::Field for $fe { |
347 | | const ZERO: Self = Self::ZERO; |
348 | | const ONE: Self = Self::ONE; |
349 | | |
350 | 0 | fn random(mut rng: impl $crate::elliptic_curve::rand_core::RngCore) -> Self { |
351 | | // NOTE: can't use ScalarPrimitive::random due to CryptoRng bound |
352 | 0 | let mut bytes = <$bytes>::default(); |
353 | | |
354 | | loop { |
355 | 0 | rng.fill_bytes(&mut bytes); |
356 | 0 | if let Some(fe) = Self::from_bytes(&bytes).into() { |
357 | 0 | return fe; |
358 | 0 | } |
359 | | } |
360 | 0 | } |
361 | | |
362 | 0 | fn is_zero(&self) -> Choice { |
363 | 0 | Self::ZERO.ct_eq(self) |
364 | 0 | } |
365 | | |
366 | | #[must_use] |
367 | 6.43M | fn square(&self) -> Self { |
368 | 6.43M | self.square() |
369 | 6.43M | } |
370 | | |
371 | | #[must_use] |
372 | 21.6M | fn double(&self) -> Self { |
373 | 21.6M | self.double() |
374 | 21.6M | } |
375 | | |
376 | 8.27k | fn invert(&self) -> CtOption<Self> { |
377 | 8.27k | self.invert() |
378 | 8.27k | } |
379 | | |
380 | 0 | fn sqrt(&self) -> CtOption<Self> { |
381 | 0 | self.sqrt() |
382 | 0 | } |
383 | | |
384 | 0 | fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { |
385 | 0 | $crate::elliptic_curve::ff::helpers::sqrt_ratio_generic(num, div) |
386 | 0 | } |
387 | | } |
388 | | |
389 | | $crate::impl_field_op!($fe, Add, add, $add); |
390 | | $crate::impl_field_op!($fe, Sub, sub, $sub); |
391 | | $crate::impl_field_op!($fe, Mul, mul, $mul); |
392 | | |
393 | | impl AddAssign<$fe> for $fe { |
394 | | #[inline] |
395 | 0 | fn add_assign(&mut self, other: $fe) { |
396 | 0 | *self = *self + other; |
397 | 0 | } |
398 | | } |
399 | | |
400 | | impl AddAssign<&$fe> for $fe { |
401 | | #[inline] |
402 | 0 | fn add_assign(&mut self, other: &$fe) { |
403 | 0 | *self = *self + other; |
404 | 0 | } |
405 | | } |
406 | | |
407 | | impl SubAssign<$fe> for $fe { |
408 | | #[inline] |
409 | 0 | fn sub_assign(&mut self, other: $fe) { |
410 | 0 | *self = *self - other; |
411 | 0 | } |
412 | | } |
413 | | |
414 | | impl SubAssign<&$fe> for $fe { |
415 | | #[inline] |
416 | 0 | fn sub_assign(&mut self, other: &$fe) { |
417 | 0 | *self = *self - other; |
418 | 0 | } |
419 | | } |
420 | | |
421 | | impl MulAssign<&$fe> for $fe { |
422 | | #[inline] |
423 | 0 | fn mul_assign(&mut self, other: &$fe) { |
424 | 0 | *self = *self * other; |
425 | 0 | } |
426 | | } |
427 | | |
428 | | impl MulAssign for $fe { |
429 | | #[inline] |
430 | 0 | fn mul_assign(&mut self, other: $fe) { |
431 | 0 | *self = *self * other; |
432 | 0 | } |
433 | | } |
434 | | |
435 | | impl Neg for $fe { |
436 | | type Output = $fe; |
437 | | |
438 | | #[inline] |
439 | 0 | fn neg(self) -> $fe { |
440 | 0 | Self($neg(self.as_ref()).into()) |
441 | 0 | } Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Neg>::neg Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Neg>::neg |
442 | | } |
443 | | |
444 | | impl Sum for $fe { |
445 | 0 | fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { |
446 | 0 | iter.reduce(core::ops::Add::add).unwrap_or(Self::ZERO) |
447 | 0 | } |
448 | | } |
449 | | |
450 | | impl<'a> Sum<&'a $fe> for $fe { |
451 | 0 | fn sum<I: Iterator<Item = &'a $fe>>(iter: I) -> Self { |
452 | 0 | iter.copied().sum() |
453 | 0 | } |
454 | | } |
455 | | |
456 | | impl Product for $fe { |
457 | 0 | fn product<I: Iterator<Item = Self>>(iter: I) -> Self { |
458 | 0 | iter.reduce(core::ops::Mul::mul).unwrap_or(Self::ONE) |
459 | 0 | } |
460 | | } |
461 | | |
462 | | impl<'a> Product<&'a $fe> for $fe { |
463 | 0 | fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { |
464 | 0 | iter.copied().product() |
465 | 0 | } |
466 | | } |
467 | | }; |
468 | | } |
469 | | |
470 | | /// Emit impls for a `core::ops` trait for all combinations of reference types, |
471 | | /// which thunk to the given function. |
472 | | #[macro_export] |
473 | | macro_rules! impl_field_op { |
474 | | ($fe:tt, $op:tt, $op_fn:ident, $func:ident) => { |
475 | | impl ::core::ops::$op for $fe { |
476 | | type Output = $fe; |
477 | | |
478 | | #[inline] |
479 | 70.0M | fn $op_fn(self, rhs: $fe) -> $fe { |
480 | 70.0M | $fe($func(self.as_ref(), rhs.as_ref()).into()) |
481 | 70.0M | } <p256::arithmetic::field::FieldElement as core::ops::arith::Add>::add Line | Count | Source | 479 | 24.9M | fn $op_fn(self, rhs: $fe) -> $fe { | 480 | 24.9M | $fe($func(self.as_ref(), rhs.as_ref()).into()) | 481 | 24.9M | } |
<p256::arithmetic::field::FieldElement as core::ops::arith::Sub>::sub Line | Count | Source | 479 | 15.4M | fn $op_fn(self, rhs: $fe) -> $fe { | 480 | 15.4M | $fe($func(self.as_ref(), rhs.as_ref()).into()) | 481 | 15.4M | } |
<p256::arithmetic::field::FieldElement as core::ops::arith::Mul>::mul Line | Count | Source | 479 | 29.6M | fn $op_fn(self, rhs: $fe) -> $fe { | 480 | 29.6M | $fe($func(self.as_ref(), rhs.as_ref()).into()) | 481 | 29.6M | } |
Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Mul>::mul Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Add>::add Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Sub>::sub |
482 | | } |
483 | | |
484 | | impl ::core::ops::$op<&$fe> for $fe { |
485 | | type Output = $fe; |
486 | | |
487 | | #[inline] |
488 | 16.8k | fn $op_fn(self, rhs: &$fe) -> $fe { |
489 | 16.8k | $fe($func(self.as_ref(), rhs.as_ref()).into()) |
490 | 16.8k | } <p256::arithmetic::field::FieldElement as core::ops::arith::Add<&p256::arithmetic::field::FieldElement>>::add Line | Count | Source | 488 | 112 | fn $op_fn(self, rhs: &$fe) -> $fe { | 489 | 112 | $fe($func(self.as_ref(), rhs.as_ref()).into()) | 490 | 112 | } |
<p256::arithmetic::field::FieldElement as core::ops::arith::Mul<&p256::arithmetic::field::FieldElement>>::mul Line | Count | Source | 488 | 16.7k | fn $op_fn(self, rhs: &$fe) -> $fe { | 489 | 16.7k | $fe($func(self.as_ref(), rhs.as_ref()).into()) | 490 | 16.7k | } |
Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Mul<&p256::arithmetic::field::FieldElement>>::mul Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Add<&p256::arithmetic::field::FieldElement>>::add Unexecuted instantiation: <p256::arithmetic::field::FieldElement as core::ops::arith::Sub<&p256::arithmetic::field::FieldElement>>::sub |
491 | | } |
492 | | |
493 | | impl ::core::ops::$op<&$fe> for &$fe { |
494 | | type Output = $fe; |
495 | | |
496 | | #[inline] |
497 | 0 | fn $op_fn(self, rhs: &$fe) -> $fe { |
498 | 0 | $fe($func(self.as_ref(), rhs.as_ref()).into()) |
499 | 0 | } Unexecuted instantiation: <&p256::arithmetic::field::FieldElement as core::ops::arith::Mul>::mul Unexecuted instantiation: <&p256::arithmetic::field::FieldElement as core::ops::arith::Add>::add Unexecuted instantiation: <&p256::arithmetic::field::FieldElement as core::ops::arith::Sub>::sub |
500 | | } |
501 | | }; |
502 | | } |
503 | | |
504 | | /// Implement Bernstein-Yang field element inversion. |
505 | | #[macro_export] |
506 | | macro_rules! impl_bernstein_yang_invert { |
507 | | ( |
508 | | $a:expr, |
509 | | $one:expr, |
510 | | $d:expr, |
511 | | $nlimbs:expr, |
512 | | $word:ty, |
513 | | $from_mont:ident, |
514 | | $mul:ident, |
515 | | $neg:ident, |
516 | | $divstep_precomp:ident, |
517 | | $divstep:ident, |
518 | | $msat:ident, |
519 | | $selectznz:ident, |
520 | | ) => {{ |
521 | | // See Bernstein-Yang 2019 p.366 |
522 | | const ITERATIONS: usize = (49 * $d + 57) / 17; |
523 | | |
524 | | let a = $from_mont($a); |
525 | | let mut d = 1; |
526 | | let mut f = $msat(); |
527 | | let mut g = [0; $nlimbs + 1]; |
528 | | let mut v = [0; $nlimbs]; |
529 | | let mut r = $one; |
530 | | let mut i = 0; |
531 | | let mut j = 0; |
532 | | |
533 | | while j < $nlimbs { |
534 | | g[j] = a[j]; |
535 | | j += 1; |
536 | | } |
537 | | |
538 | | while i < ITERATIONS - ITERATIONS % 2 { |
539 | | let (out1, out2, out3, out4, out5) = $divstep(d, &f, &g, &v, &r); |
540 | | let (out1, out2, out3, out4, out5) = $divstep(out1, &out2, &out3, &out4, &out5); |
541 | | d = out1; |
542 | | f = out2; |
543 | | g = out3; |
544 | | v = out4; |
545 | | r = out5; |
546 | | i += 2; |
547 | | } |
548 | | |
549 | | if ITERATIONS % 2 != 0 { |
550 | | let (_out1, out2, _out3, out4, _out5) = $divstep(d, &f, &g, &v, &r); |
551 | | v = out4; |
552 | | f = out2; |
553 | | } |
554 | | |
555 | | let s = ((f[f.len() - 1] >> <$word>::BITS - 1) & 1) as u8; |
556 | | let v = $selectznz(s, &v, &$neg(&v)); |
557 | | $mul(&v, &$divstep_precomp()) |
558 | | }}; |
559 | | } |
560 | | |
561 | | /// Implement field element identity tests. |
562 | | #[macro_export] |
563 | | macro_rules! impl_field_identity_tests { |
564 | | ($fe:tt) => { |
565 | | #[test] |
566 | | fn zero_is_additive_identity() { |
567 | | let zero = $fe::ZERO; |
568 | | let one = $fe::ONE; |
569 | | assert_eq!(zero.add(&zero), zero); |
570 | | assert_eq!(one.add(&zero), one); |
571 | | } |
572 | | |
573 | | #[test] |
574 | | fn one_is_multiplicative_identity() { |
575 | | let one = $fe::ONE; |
576 | | assert_eq!(one.multiply(&one), one); |
577 | | } |
578 | | }; |
579 | | } |
580 | | |
581 | | /// Implement field element inversion tests. |
582 | | #[macro_export] |
583 | | macro_rules! impl_field_invert_tests { |
584 | | ($fe:tt) => { |
585 | | #[test] |
586 | | fn invert() { |
587 | | let one = $fe::ONE; |
588 | | assert_eq!(one.invert().unwrap(), one); |
589 | | |
590 | | let three = one + &one + &one; |
591 | | let inv_three = three.invert().unwrap(); |
592 | | assert_eq!(three * &inv_three, one); |
593 | | |
594 | | let minus_three = -three; |
595 | | let inv_minus_three = minus_three.invert().unwrap(); |
596 | | assert_eq!(inv_minus_three, -inv_three); |
597 | | assert_eq!(three * &inv_minus_three, -one); |
598 | | } |
599 | | }; |
600 | | } |
601 | | |
602 | | /// Implement field element square root tests. |
603 | | #[macro_export] |
604 | | macro_rules! impl_field_sqrt_tests { |
605 | | ($fe:tt) => { |
606 | | #[test] |
607 | | fn sqrt() { |
608 | | for &n in &[1u64, 4, 9, 16, 25, 36, 49, 64] { |
609 | | let fe = $fe::from(n); |
610 | | let sqrt = fe.sqrt().unwrap(); |
611 | | assert_eq!(sqrt.square(), fe); |
612 | | } |
613 | | } |
614 | | }; |
615 | | } |
616 | | |
617 | | /// Implement tests for the `PrimeField` trait. |
618 | | #[macro_export] |
619 | | macro_rules! impl_primefield_tests { |
620 | | ($fe:tt, $t:expr) => { |
621 | | #[test] |
622 | | fn two_inv_constant() { |
623 | | assert_eq!($fe::from(2u32) * $fe::TWO_INV, $fe::ONE); |
624 | | } |
625 | | |
626 | | #[test] |
627 | | fn root_of_unity_constant() { |
628 | | assert!($fe::S < 128); |
629 | | let two_to_s = 1u128 << $fe::S; |
630 | | |
631 | | // ROOT_OF_UNITY^{2^s} mod m == 1 |
632 | | assert_eq!( |
633 | | $fe::ROOT_OF_UNITY.pow_vartime(&[ |
634 | | (two_to_s & 0xFFFFFFFFFFFFFFFF) as u64, |
635 | | (two_to_s >> 64) as u64, |
636 | | 0, |
637 | | 0 |
638 | | ]), |
639 | | $fe::ONE |
640 | | ); |
641 | | |
642 | | // MULTIPLICATIVE_GENERATOR^{t} mod m == ROOT_OF_UNITY |
643 | | assert_eq!( |
644 | | $fe::MULTIPLICATIVE_GENERATOR.pow_vartime(&$t), |
645 | | $fe::ROOT_OF_UNITY |
646 | | ) |
647 | | } |
648 | | |
649 | | #[test] |
650 | | fn root_of_unity_inv_constant() { |
651 | | assert_eq!($fe::ROOT_OF_UNITY * $fe::ROOT_OF_UNITY_INV, $fe::ONE); |
652 | | } |
653 | | |
654 | | #[test] |
655 | | fn delta_constant() { |
656 | | // DELTA^{t} mod m == 1 |
657 | | assert_eq!($fe::DELTA.pow_vartime(&$t), $fe::ONE); |
658 | | } |
659 | | }; |
660 | | } |