field_derive/
lib.rs

1#![recursion_limit = "1024"]
2
3extern crate proc_macro;
4#[macro_use]
5extern crate quote;
6
7use num_bigint::BigUint;
8use num_integer::Integer;
9use num_traits::{One, ToPrimitive, Zero};
10use quote::TokenStreamExt;
11use std::str::FromStr;
12
13#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))]
14pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
15    // Parse the type definition
16    let ast: syn::DeriveInput = syn::parse(input).unwrap();
17
18    // The struct we're deriving for is a wrapper around a "Repr" type we must construct.
19    let repr_ident =
20        fetch_wrapped_ident(&ast.data).expect("PrimeField derive only operates over tuple structs of a single item");
21
22    // We're given the modulus p of the prime field
23    let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs)
24        .expect("Please supply a PrimeFieldModulus attribute")
25        .parse()
26        .expect("PrimeFieldModulus should be a number");
27
28    // We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
29    // nonresidue.
30    let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
31        .expect("Please supply a PrimeFieldGenerator attribute")
32        .parse()
33        .expect("PrimeFieldGenerator should be a number");
34
35    // The arithmetic in this library only works if the modulus*2 is smaller than the backing
36    // representation. Compute the number of limbs we need.
37    let mut limbs = 1;
38    {
39        let mod2 = (&modulus) << 1; // modulus * 2
40        let mut cur = BigUint::one() << 64; // always 64-bit limbs for now
41        while cur < mod2 {
42            limbs += 1;
43            cur = cur << 64;
44        }
45    }
46
47    let mut gen = proc_macro2::TokenStream::new();
48
49    let (constants_impl, sqrt_impl) =
50        prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator);
51
52    gen.extend(constants_impl);
53    gen.extend(prime_field_repr_impl(&repr_ident, limbs));
54    gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs));
55    gen.extend(sqrt_impl);
56
57    // Return the generated impl
58    gen.into()
59}
60
61/// Fetches the ident being wrapped by the type we're deriving.
62fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
63    match body {
64        &syn::Data::Struct(ref variant_data) => match variant_data.fields {
65            syn::Fields::Unnamed(ref fields) => {
66                if fields.unnamed.len() == 1 {
67                    match fields.unnamed[0].ty {
68                        syn::Type::Path(ref path) => {
69                            if path.path.segments.len() == 1 {
70                                return Some(path.path.segments[0].ident.clone());
71                            }
72                        }
73                        _ => {}
74                    }
75                }
76            }
77            _ => {}
78        },
79        _ => {}
80    };
81
82    None
83}
84
85/// Fetch an attribute string from the derived struct.
86fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
87    for attr in attrs {
88        if let Some(meta) = attr.interpret_meta() {
89            match meta {
90                syn::Meta::NameValue(nv) => {
91                    if nv.ident.to_string() == name {
92                        match nv.lit {
93                            syn::Lit::Str(ref s) => return Some(s.value()),
94                            _ => {
95                                panic!("attribute {} should be a string", name);
96                            }
97                        }
98                    }
99                }
100                _ => {
101                    panic!("attribute {} should be a string", name);
102                }
103            }
104        }
105    }
106
107    None
108}
109
110// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
111fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
112    quote! {
113        #[derive(Copy, Clone, PartialEq, Eq, Default)]
114        pub struct #repr(pub [u64; #limbs]);
115
116        impl ::std::fmt::Debug for #repr
117        {
118            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
119                write!(f, "0x")?;
120                for i in self.0.iter().rev() {
121                    write!(f, "{:016x}", *i)?;
122                }
123
124                Ok(())
125            }
126        }
127
128        impl ::std::fmt::Display for #repr {
129            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
130                write!(f, "0x")?;
131                for i in self.0.iter().rev() {
132                    write!(f, "{:016x}", *i)?;
133                }
134
135                Ok(())
136            }
137        }
138
139        impl AsRef<[u64]> for #repr {
140            #[inline(always)]
141            fn as_ref(&self) -> &[u64] {
142                &self.0
143            }
144        }
145
146        impl AsMut<[u64]> for #repr {
147            #[inline(always)]
148            fn as_mut(&mut self) -> &mut [u64] {
149                &mut self.0
150            }
151        }
152
153        impl From<u64> for #repr {
154            #[inline(always)]
155            fn from(val: u64) -> #repr {
156                use std::default::Default;
157
158                let mut repr = Self::default();
159                repr.0[0] = val;
160                repr
161            }
162        }
163
164        impl Ord for #repr {
165            #[inline(always)]
166            fn cmp(&self, other: &#repr) -> ::std::cmp::Ordering {
167                for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
168                    if a < b {
169                        return ::std::cmp::Ordering::Less
170                    } else if a > b {
171                        return ::std::cmp::Ordering::Greater
172                    }
173                }
174
175                ::std::cmp::Ordering::Equal
176            }
177        }
178
179        impl PartialOrd for #repr {
180            #[inline(always)]
181            fn partial_cmp(&self, other: &#repr) -> Option<::std::cmp::Ordering> {
182                Some(self.cmp(other))
183            }
184        }
185
186        impl crate::librustzcash::algebra::field::PrimeFieldRepr for #repr {
187            #[inline(always)]
188            fn is_odd(&self) -> bool {
189                self.0[0] & 1 == 1
190            }
191
192            #[inline(always)]
193            fn is_even(&self) -> bool {
194                !self.is_odd()
195            }
196
197            #[inline(always)]
198            fn is_zero(&self) -> bool {
199                self.0.iter().all(|&e| e == 0)
200            }
201
202            #[inline(always)]
203            fn shr(&mut self, mut n: u32) {
204                if n as usize >= 64 * #limbs {
205                    *self = Self::from(0);
206                    return;
207                }
208
209                while n >= 64 {
210                    let mut t = 0;
211                    for i in self.0.iter_mut().rev() {
212                        ::std::mem::swap(&mut t, i);
213                    }
214                    n -= 64;
215                }
216
217                if n > 0 {
218                    let mut t = 0;
219                    for i in self.0.iter_mut().rev() {
220                        let t2 = *i << (64 - n);
221                        *i >>= n;
222                        *i |= t;
223                        t = t2;
224                    }
225                }
226            }
227
228            #[inline(always)]
229            fn div2(&mut self) {
230                let mut t = 0;
231                for i in self.0.iter_mut().rev() {
232                    let t2 = *i << 63;
233                    *i >>= 1;
234                    *i |= t;
235                    t = t2;
236                }
237            }
238
239            #[inline(always)]
240            fn mul2(&mut self) {
241                let mut last = 0;
242                for i in &mut self.0 {
243                    let tmp = *i >> 63;
244                    *i <<= 1;
245                    *i |= last;
246                    last = tmp;
247                }
248            }
249
250            #[inline(always)]
251            fn shl(&mut self, mut n: u32) {
252                if n as usize >= 64 * #limbs {
253                    *self = Self::from(0);
254                    return;
255                }
256
257                while n >= 64 {
258                    let mut t = 0;
259                    for i in &mut self.0 {
260                        ::std::mem::swap(&mut t, i);
261                    }
262                    n -= 64;
263                }
264
265                if n > 0 {
266                    let mut t = 0;
267                    for i in &mut self.0 {
268                        let t2 = *i >> (64 - n);
269                        *i <<= n;
270                        *i |= t;
271                        t = t2;
272                    }
273                }
274            }
275
276            #[inline(always)]
277            fn num_bits(&self) -> u32 {
278                let mut ret = (#limbs as u32) * 64;
279                for i in self.0.iter().rev() {
280                    let leading = i.leading_zeros();
281                    ret -= leading;
282                    if leading != 64 {
283                        break;
284                    }
285                }
286
287                ret
288            }
289
290            #[inline(always)]
291            fn add_nocarry(&mut self, other: &#repr) {
292                let mut carry = 0;
293
294                for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
295                    *a = crate::librustzcash::algebra::field::adc(*a, *b, &mut carry);
296                }
297            }
298
299            #[inline(always)]
300            fn sub_noborrow(&mut self, other: &#repr) {
301                let mut borrow = 0;
302
303                for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
304                    *a = crate::librustzcash::algebra::field::sbb(*a, *b, &mut borrow);
305                }
306            }
307        }
308    }
309}
310
311/// Convert BigUint into a vector of 64-bit limbs.
312fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> {
313    let m = BigUint::one() << 64;
314    let mut ret = vec![];
315
316    while v > BigUint::zero() {
317        ret.push((&v % &m).to_u64().unwrap());
318        v = v >> 64;
319    }
320
321    while ret.len() < limbs {
322        ret.push(0);
323    }
324
325    assert!(ret.len() == limbs);
326
327    ret
328}
329
330/// Convert BigUint into a tokenized vector of 64-bit limbs.
331fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream {
332    let ret = biguint_to_real_u64_vec(v, limbs);
333    quote!([#(#ret,)*])
334}
335
336fn biguint_num_bits(mut v: BigUint) -> u32 {
337    let mut bits = 0;
338
339    while v != BigUint::zero() {
340        v = v >> 1;
341        bits += 1;
342    }
343
344    bits
345}
346
347/// BigUint modular exponentiation by square-and-multiply.
348fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
349    let mut ret = BigUint::one();
350
351    for i in exp
352        .to_bytes_be()
353        .into_iter()
354        .flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd()))
355    {
356        ret = (&ret * &ret) % modulus;
357        if i {
358            ret = (ret * &base) % modulus;
359        }
360    }
361
362    ret
363}
364
365#[test]
366fn test_exp() {
367    assert_eq!(
368        exp(
369            BigUint::from_str("4398572349857239485729348572983472345").unwrap(),
370            &BigUint::from_str("5489673498567349856734895").unwrap(),
371            &BigUint::from_str("52435875175126190479447740508185965837690552500527637822603658699938581184513")
372                .unwrap()
373        ),
374        BigUint::from_str("4371221214068404307866768905142520595925044802278091865033317963560480051536").unwrap()
375    );
376}
377
378fn prime_field_constants_and_sqrt(
379    name: &syn::Ident,
380    repr: &syn::Ident,
381    modulus: BigUint,
382    limbs: usize,
383    generator: BigUint,
384) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) {
385    let modulus_num_bits = biguint_num_bits(modulus.clone());
386
387    // The number of bits we should "shave" from a randomly sampled reputation, i.e.,
388    // if our modulus is 381 bits and our representation is 384 bits, we should shave
389    // 3 bits from the beginning of a randomly sampled 384 bit representation to
390    // reduce the cost of rejection sampling.
391    let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone());
392
393    // Compute R = 2**(64 * limbs) mod m
394    let r = (BigUint::one() << (limbs * 64)) % &modulus;
395
396    // modulus - 1 = 2^s * t
397    let mut s: u32 = 0;
398    let mut t = &modulus - BigUint::from_str("1").unwrap();
399    while t.is_even() {
400        t = t >> 1;
401        s += 1;
402    }
403
404    // Compute 2^s root of unity given the generator
405    let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus, limbs);
406    let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs);
407
408    let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
409    let legendre_impl = quote! {
410        fn legendre(&self) -> crate::librustzcash::algebra::field::LegendreSymbol {
411            // s = self^((modulus - 1) // 2)
412            let s = self.pow(#mod_minus_1_over_2);
413            if s == Self::zero() {
414                crate::librustzcash::algebra::field::LegendreSymbol::Zero
415            } else if s == Self::one() {
416                crate::librustzcash::algebra::field::LegendreSymbol::QuadraticResidue
417            } else {
418                crate::librustzcash::algebra::field::LegendreSymbol::QuadraticNonResidue
419            }
420        }
421    };
422
423    let sqrt_impl = if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
424        let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs);
425
426        // Compute -R as (m - r)
427        let rneg = biguint_to_u64_vec(&modulus - &r, limbs);
428
429        quote! {
430            impl crate::librustzcash::algebra::field::SqrtField for #name {
431                #legendre_impl
432
433                fn sqrt(&self) -> Option<Self> {
434                    // Shank's algorithm for q mod 4 = 3
435                    // https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
436
437                    let mut a1 = self.pow(#mod_minus_3_over_4);
438
439                    let mut a0 = a1;
440                    a0.square();
441                    a0.mul_assign(self);
442
443                    if a0.0 == #repr(#rneg) {
444                        None
445                    } else {
446                        a1.mul_assign(self);
447                        Some(a1)
448                    }
449                }
450            }
451        }
452    } else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
453        let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs);
454        let t = biguint_to_u64_vec(t.clone(), limbs);
455
456        quote! {
457            impl crate::librustzcash::algebra::field::SqrtField for #name {
458                #legendre_impl
459
460                fn sqrt(&self) -> Option<Self> {
461                    // Tonelli-Shank's algorithm for q mod 16 = 1
462                    // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
463
464                    match self.legendre() {
465                        crate::librustzcash::algebra::field::LegendreSymbol::Zero => Some(*self),
466                        crate::librustzcash::algebra::field::LegendreSymbol::QuadraticNonResidue => None,
467                        crate::librustzcash::algebra::field::LegendreSymbol::QuadraticResidue => {
468                            let mut c = #name(ROOT_OF_UNITY);
469                            let mut r = self.pow(#t_plus_1_over_2);
470                            let mut t = self.pow(#t);
471                            let mut m = S;
472
473                            while t != Self::one() {
474                                let mut i = 1;
475                                {
476                                    let mut t2i = t;
477                                    t2i.square();
478                                    loop {
479                                        if t2i == Self::one() {
480                                            break;
481                                        }
482                                        t2i.square();
483                                        i += 1;
484                                    }
485                                }
486
487                                for _ in 0..(m - i - 1) {
488                                    c.square();
489                                }
490                                r.mul_assign(&c);
491                                c.square();
492                                t.mul_assign(&c);
493                                m = i;
494                            }
495
496                            Some(r)
497                        }
498                    }
499                }
500            }
501        }
502    } else {
503        quote! {}
504    };
505
506    // Compute R^2 mod m
507    let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs);
508
509    let r = biguint_to_u64_vec(r, limbs);
510    let modulus = biguint_to_real_u64_vec(modulus, limbs);
511
512    // Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
513    let mut inv = 1u64;
514    for _ in 0..63 {
515        inv = inv.wrapping_mul(inv);
516        inv = inv.wrapping_mul(modulus[0]);
517    }
518    inv = inv.wrapping_neg();
519
520    (
521        quote! {
522            /// This is the modulus m of the prime field
523            const MODULUS: #repr = #repr([#(#modulus,)*]);
524
525            /// The number of bits needed to represent the modulus.
526            const MODULUS_BITS: u32 = #modulus_num_bits;
527
528            /// The number of bits that must be shaved from the beginning of
529            /// the representation when randomly sampling.
530            const REPR_SHAVE_BITS: u32 = #repr_shave_bits;
531
532            /// 2^{limbs*64} mod m
533            const R: #repr = #repr(#r);
534
535            /// 2^{limbs*64*2} mod m
536            const R2: #repr = #repr(#r2);
537
538            /// -(m^{-1} mod m) mod m
539            const INV: u64 = #inv;
540
541            /// Multiplicative generator of `MODULUS` - 1 order, also quadratic
542            /// nonresidue.
543            const GENERATOR: #repr = #repr(#generator);
544
545            /// 2^s * t = MODULUS - 1 with t odd
546            const S: u32 = #s;
547
548            /// 2^s root of unity computed by GENERATOR^t
549            const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
550        },
551        sqrt_impl,
552    )
553}
554
555/// Implement PrimeField for the derived type.
556fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
557    // Returns r{n} as an ident.
558    fn get_temp(n: usize) -> syn::Ident {
559        syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site())
560    }
561
562    // The parameter list for the mont_reduce() internal method.
563    // r0: u64, mut r1: u64, mut r2: u64, ...
564    let mut mont_paramlist = proc_macro2::TokenStream::new();
565    mont_paramlist.append_separated(
566        (0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
567            if i != 0 {
568                quote! {mut #x: u64}
569            } else {
570                quote! {#x: u64}
571            }
572        }),
573        proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
574    );
575
576    // Implement montgomery reduction for some number of limbs
577    fn mont_impl(limbs: usize) -> proc_macro2::TokenStream {
578        let mut gen = proc_macro2::TokenStream::new();
579
580        for i in 0..limbs {
581            {
582                let temp = get_temp(i);
583                gen.extend(quote! {
584                    let k = #temp.wrapping_mul(INV);
585                    let mut carry = 0;
586                    crate::librustzcash::algebra::field::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry);
587                });
588            }
589
590            for j in 1..limbs {
591                let temp = get_temp(i + j);
592                gen.extend(quote! {
593                    #temp = crate::librustzcash::algebra::field::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry);
594                });
595            }
596
597            let temp = get_temp(i + limbs);
598
599            if i == 0 {
600                gen.extend(quote! {
601                    #temp = crate::librustzcash::algebra::field::adc(#temp, 0, &mut carry);
602                });
603            } else {
604                gen.extend(quote! {
605                    #temp = crate::librustzcash::algebra::field::adc(#temp, carry2, &mut carry);
606                });
607            }
608
609            if i != (limbs - 1) {
610                gen.extend(quote! {
611                    let carry2 = carry;
612                });
613            }
614        }
615
616        for i in 0..limbs {
617            let temp = get_temp(limbs + i);
618
619            gen.extend(quote! {
620                (self.0).0[#i] = #temp;
621            });
622        }
623
624        gen
625    }
626
627    fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream {
628        let mut gen = proc_macro2::TokenStream::new();
629
630        for i in 0..(limbs - 1) {
631            gen.extend(quote! {
632                let mut carry = 0;
633            });
634
635            for j in (i + 1)..limbs {
636                let temp = get_temp(i + j);
637                if i == 0 {
638                    gen.extend(quote!{
639                        let #temp = crate::librustzcash::algebra::field::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
640                    });
641                } else {
642                    gen.extend(quote!{
643                        let #temp = crate::librustzcash::algebra::field::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry);
644                    });
645                }
646            }
647
648            let temp = get_temp(i + limbs);
649
650            gen.extend(quote! {
651                let #temp = carry;
652            });
653        }
654
655        for i in 1..(limbs * 2) {
656            let temp0 = get_temp(limbs * 2 - i);
657            let temp1 = get_temp(limbs * 2 - i - 1);
658
659            if i == 1 {
660                gen.extend(quote! {
661                    let #temp0 = #temp1 >> 63;
662                });
663            } else if i == (limbs * 2 - 1) {
664                gen.extend(quote! {
665                    let #temp0 = #temp0 << 1;
666                });
667            } else {
668                gen.extend(quote! {
669                    let #temp0 = (#temp0 << 1) | (#temp1 >> 63);
670                });
671            }
672        }
673
674        gen.extend(quote! {
675            let mut carry = 0;
676        });
677
678        for i in 0..limbs {
679            let temp0 = get_temp(i * 2);
680            let temp1 = get_temp(i * 2 + 1);
681            if i == 0 {
682                gen.extend(quote!{
683                    let #temp0 = crate::librustzcash::algebra::field::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
684                });
685            } else {
686                gen.extend(quote!{
687                    let #temp0 = crate::librustzcash::algebra::field::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry);
688                });
689            }
690
691            gen.extend(quote! {
692                let #temp1 = crate::librustzcash::algebra::field::adc(#temp1, 0, &mut carry);
693            });
694        }
695
696        let mut mont_calling = proc_macro2::TokenStream::new();
697        mont_calling.append_separated(
698            (0..(limbs * 2)).map(|i| get_temp(i)),
699            proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
700        );
701
702        gen.extend(quote! {
703            self.mont_reduce(#mont_calling);
704        });
705
706        gen
707    }
708
709    fn mul_impl(a: proc_macro2::TokenStream, b: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream {
710        let mut gen = proc_macro2::TokenStream::new();
711
712        for i in 0..limbs {
713            gen.extend(quote! {
714                let mut carry = 0;
715            });
716
717            for j in 0..limbs {
718                let temp = get_temp(i + j);
719
720                if i == 0 {
721                    gen.extend(quote!{
722                        let #temp = crate::librustzcash::algebra::field::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
723                    });
724                } else {
725                    gen.extend(quote!{
726                        let #temp = crate::librustzcash::algebra::field::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
727                    });
728                }
729            }
730
731            let temp = get_temp(i + limbs);
732
733            gen.extend(quote! {
734                let #temp = carry;
735            });
736        }
737
738        let mut mont_calling = proc_macro2::TokenStream::new();
739        mont_calling.append_separated(
740            (0..(limbs * 2)).map(|i| get_temp(i)),
741            proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
742        );
743
744        gen.extend(quote! {
745            self.mont_reduce(#mont_calling);
746        });
747
748        gen
749    }
750
751    let squaring_impl = sqr_impl(quote! {self}, limbs);
752    let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs);
753    let montgomery_impl = mont_impl(limbs);
754
755    // (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
756    let mut into_repr_params = proc_macro2::TokenStream::new();
757    into_repr_params.append_separated(
758        (0..limbs)
759            .map(|i| quote! { (self.0).0[#i] })
760            .chain((0..limbs).map(|_| quote! {0})),
761        proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
762    );
763
764    let top_limb_index = limbs - 1;
765
766    quote! {
767        impl ::std::marker::Copy for #name { }
768
769        impl ::std::clone::Clone for #name {
770            fn clone(&self) -> #name {
771                *self
772            }
773        }
774
775        impl ::std::cmp::PartialEq for #name {
776            fn eq(&self, other: &#name) -> bool {
777                self.0 == other.0
778            }
779        }
780
781        impl ::std::cmp::Eq for #name { }
782
783        impl ::std::fmt::Debug for #name
784        {
785            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
786                write!(f, "{}({:?})", stringify!(#name), self.into_repr())
787            }
788        }
789
790        /// Elements are ordered lexicographically.
791        impl Ord for #name {
792            #[inline(always)]
793            fn cmp(&self, other: &#name) -> ::std::cmp::Ordering {
794                self.into_repr().cmp(&other.into_repr())
795            }
796        }
797
798        impl PartialOrd for #name {
799            #[inline(always)]
800            fn partial_cmp(&self, other: &#name) -> Option<::std::cmp::Ordering> {
801                Some(self.cmp(other))
802            }
803        }
804
805        impl ::std::fmt::Display for #name {
806            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
807                write!(f, "{}({})", stringify!(#name), self.into_repr())
808            }
809        }
810
811        impl From<#name> for #repr {
812            fn from(e: #name) -> #repr {
813                e.into_repr()
814            }
815        }
816
817        impl crate::librustzcash::algebra::field::PrimeField for #name {
818            type Repr = #repr;
819
820            fn from_repr(r: #repr) -> Result<#name, PrimeFieldDecodingError> {
821                let mut r = #name(r);
822                if r.is_valid() {
823                    r.mul_assign(&#name(R2));
824
825                    Ok(r)
826                } else {
827                    Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
828                }
829            }
830
831            fn into_repr(&self) -> #repr {
832                let mut r = *self;
833                r.mont_reduce(
834                    #into_repr_params
835                );
836
837                r.0
838            }
839
840            fn char() -> #repr {
841                MODULUS
842            }
843
844            const NUM_BITS: u32 = MODULUS_BITS;
845
846            const CAPACITY: u32 = Self::NUM_BITS - 1;
847
848            fn multiplicative_generator() -> Self {
849                #name(GENERATOR)
850            }
851
852            const S: u32 = S;
853
854            fn root_of_unity() -> Self {
855                #name(ROOT_OF_UNITY)
856            }
857        }
858
859        impl crate::librustzcash::algebra::field::Field for #name {
860            /// Computes a uniformly random element using rejection sampling.
861            fn random<R: ::rand_core::RngCore>(rng: &mut R) -> Self {
862                loop {
863                    let mut tmp = {
864                        let mut repr = [0u64; #limbs];
865                        for i in 0..#limbs {
866                            repr[i] = rng.next_u64();
867                        }
868                        #name(#repr(repr))
869                    };
870
871                    // Mask away the unused most-significant bits.
872                    tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
873
874                    if tmp.is_valid() {
875                        return tmp
876                    }
877                }
878            }
879
880            #[inline]
881            fn zero() -> Self {
882                #name(#repr::from(0))
883            }
884
885            #[inline]
886            fn one() -> Self {
887                #name(R)
888            }
889
890            #[inline]
891            fn is_zero(&self) -> bool {
892                self.0.is_zero()
893            }
894
895            #[inline]
896            fn add_assign(&mut self, other: &#name) {
897                // This cannot exceed the backing capacity.
898                self.0.add_nocarry(&other.0);
899
900                // However, it may need to be reduced.
901                self.reduce();
902            }
903
904            #[inline]
905            fn double(&mut self) {
906                // This cannot exceed the backing capacity.
907                self.0.mul2();
908
909                // However, it may need to be reduced.
910                self.reduce();
911            }
912
913            #[inline]
914            fn sub_assign(&mut self, other: &#name) {
915                // If `other` is larger than `self`, we'll need to add the modulus to self first.
916                if other.0 > self.0 {
917                    self.0.add_nocarry(&MODULUS);
918                }
919
920                self.0.sub_noborrow(&other.0);
921            }
922
923            #[inline]
924            fn negate(&mut self) {
925                if !self.is_zero() {
926                    let mut tmp = MODULUS;
927                    tmp.sub_noborrow(&self.0);
928                    self.0 = tmp;
929                }
930            }
931
932            fn inverse(&self) -> Option<Self> {
933                if self.is_zero() {
934                    None
935                } else {
936                    // Guajardo Kumar Paar Pelzl
937                    // Efficient Software-Implementation of Finite Fields with Applications to Cryptography
938                    // Algorithm 16 (BEA for Inversion in Fp)
939
940                    let one = #repr::from(1);
941
942                    let mut u = self.0;
943                    let mut v = MODULUS;
944                    let mut b = #name(R2); // Avoids unnecessary reduction step.
945                    let mut c = Self::zero();
946
947                    while u != one && v != one {
948                        while u.is_even() {
949                            u.div2();
950
951                            if b.0.is_even() {
952                                b.0.div2();
953                            } else {
954                                b.0.add_nocarry(&MODULUS);
955                                b.0.div2();
956                            }
957                        }
958
959                        while v.is_even() {
960                            v.div2();
961
962                            if c.0.is_even() {
963                                c.0.div2();
964                            } else {
965                                c.0.add_nocarry(&MODULUS);
966                                c.0.div2();
967                            }
968                        }
969
970                        if v < u {
971                            u.sub_noborrow(&v);
972                            b.sub_assign(&c);
973                        } else {
974                            v.sub_noborrow(&u);
975                            c.sub_assign(&b);
976                        }
977                    }
978
979                    if u == one {
980                        Some(b)
981                    } else {
982                        Some(c)
983                    }
984                }
985            }
986
987            #[inline(always)]
988            fn frobenius_map(&mut self, _: usize) {
989                // This has no effect in a prime field.
990            }
991
992            #[inline]
993            fn mul_assign(&mut self, other: &#name)
994            {
995                #multiply_impl
996            }
997
998            #[inline]
999            fn square(&mut self)
1000            {
1001                #squaring_impl
1002            }
1003        }
1004
1005        impl #name {
1006            /// Determines if the element is really in the field. This is only used
1007            /// internally.
1008            #[inline(always)]
1009            fn is_valid(&self) -> bool {
1010                self.0 < MODULUS
1011            }
1012
1013            /// Subtracts the modulus from this element if this element is not in the
1014            /// field. Only used interally.
1015            #[inline(always)]
1016            fn reduce(&mut self) {
1017                if !self.is_valid() {
1018                    self.0.sub_noborrow(&MODULUS);
1019                }
1020            }
1021
1022            #[inline(always)]
1023            fn mont_reduce(
1024                &mut self,
1025                #mont_paramlist
1026            )
1027            {
1028                // The Montgomery reduction here is based on Algorithm 14.32 in
1029                // Handbook of Applied Cryptography
1030                // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
1031
1032                #montgomery_impl
1033
1034                self.reduce();
1035            }
1036        }
1037    }
1038}