|
|
@ -1,6 +1,7 @@ |
|
|
|
#![recursion_limit = "1024"] |
|
|
|
#![recursion_limit = "1024"] |
|
|
|
|
|
|
|
|
|
|
|
extern crate proc_macro; |
|
|
|
extern crate proc_macro; |
|
|
|
|
|
|
|
extern crate proc_macro2; |
|
|
|
extern crate syn; |
|
|
|
extern crate syn; |
|
|
|
#[macro_use] |
|
|
|
#[macro_use] |
|
|
|
extern crate quote; |
|
|
|
extern crate quote; |
|
|
@ -12,18 +13,16 @@ extern crate num_traits; |
|
|
|
use num_bigint::BigUint; |
|
|
|
use num_bigint::BigUint; |
|
|
|
use num_integer::Integer; |
|
|
|
use num_integer::Integer; |
|
|
|
use num_traits::{One, ToPrimitive, Zero}; |
|
|
|
use num_traits::{One, ToPrimitive, Zero}; |
|
|
|
|
|
|
|
use quote::TokenStreamExt; |
|
|
|
use std::str::FromStr; |
|
|
|
use std::str::FromStr; |
|
|
|
|
|
|
|
|
|
|
|
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] |
|
|
|
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus, PrimeFieldGenerator))] |
|
|
|
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { |
|
|
|
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { |
|
|
|
// Construct a string representation of the type definition
|
|
|
|
// Parse the type definition
|
|
|
|
let s = input.to_string(); |
|
|
|
let ast: syn::DeriveInput = syn::parse(input).unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
// Parse the string representation
|
|
|
|
|
|
|
|
let ast = syn::parse_derive_input(&s).unwrap(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The struct we're deriving for is a wrapper around a "Repr" type we must construct.
|
|
|
|
// The struct we're deriving for is a wrapper around a "Repr" type we must construct.
|
|
|
|
let repr_ident = fetch_wrapped_ident(&ast.body) |
|
|
|
let repr_ident = fetch_wrapped_ident(&ast.data) |
|
|
|
.expect("PrimeField derive only operates over tuple structs of a single item"); |
|
|
|
.expect("PrimeField derive only operates over tuple structs of a single item"); |
|
|
|
|
|
|
|
|
|
|
|
// We're given the modulus p of the prime field
|
|
|
|
// We're given the modulus p of the prime field
|
|
|
@ -51,38 +50,40 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut gen = quote::Tokens::new(); |
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(prime_field_repr_impl(&repr_ident, limbs)); |
|
|
|
gen.extend(prime_field_repr_impl(&repr_ident, limbs)); |
|
|
|
gen.append(prime_field_constants_and_sqrt( |
|
|
|
gen.extend(prime_field_constants_and_sqrt( |
|
|
|
&ast.ident, |
|
|
|
&ast.ident, |
|
|
|
&repr_ident, |
|
|
|
&repr_ident, |
|
|
|
modulus, |
|
|
|
modulus, |
|
|
|
limbs, |
|
|
|
limbs, |
|
|
|
generator, |
|
|
|
generator, |
|
|
|
)); |
|
|
|
)); |
|
|
|
gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs)); |
|
|
|
gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs)); |
|
|
|
|
|
|
|
|
|
|
|
// Return the generated impl
|
|
|
|
// Return the generated impl
|
|
|
|
gen.parse().unwrap() |
|
|
|
gen.into() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Fetches the ident being wrapped by the type we're deriving.
|
|
|
|
/// Fetches the ident being wrapped by the type we're deriving.
|
|
|
|
fn fetch_wrapped_ident(body: &syn::Body) -> Option<syn::Ident> { |
|
|
|
fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> { |
|
|
|
match body { |
|
|
|
match body { |
|
|
|
&syn::Body::Struct(ref variant_data) => { |
|
|
|
&syn::Data::Struct(ref variant_data) => match variant_data.fields { |
|
|
|
let fields = variant_data.fields(); |
|
|
|
syn::Fields::Unnamed(ref fields) => { |
|
|
|
if fields.len() == 1 { |
|
|
|
if fields.unnamed.len() == 1 { |
|
|
|
match fields[0].ty { |
|
|
|
match fields.unnamed[0].ty { |
|
|
|
syn::Ty::Path(_, ref path) => { |
|
|
|
syn::Type::Path(ref path) => { |
|
|
|
if path.segments.len() == 1 { |
|
|
|
if path.path.segments.len() == 1 { |
|
|
|
return Some(path.segments[0].ident.clone()); |
|
|
|
return Some(path.path.segments[0].ident.clone()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_ => {} |
|
|
|
} |
|
|
|
} |
|
|
|
_ => {} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
_ => {} |
|
|
|
|
|
|
|
}, |
|
|
|
_ => {} |
|
|
|
_ => {} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -92,14 +93,18 @@ fn fetch_wrapped_ident(body: &syn::Body) -> Option<syn::Ident> { |
|
|
|
/// Fetch an attribute string from the derived struct.
|
|
|
|
/// Fetch an attribute string from the derived struct.
|
|
|
|
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> { |
|
|
|
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> { |
|
|
|
for attr in attrs { |
|
|
|
for attr in attrs { |
|
|
|
if attr.name() == name { |
|
|
|
if let Some(meta) = attr.interpret_meta() { |
|
|
|
match attr.value { |
|
|
|
match meta { |
|
|
|
syn::MetaItem::NameValue(_, ref val) => match val { |
|
|
|
syn::Meta::NameValue(nv) => { |
|
|
|
&syn::Lit::Str(ref s, _) => return Some(s.clone()), |
|
|
|
if nv.ident.to_string() == name { |
|
|
|
_ => { |
|
|
|
match nv.lit { |
|
|
|
panic!("attribute {} should be a string", name); |
|
|
|
syn::Lit::Str(ref s) => return Some(s.value()), |
|
|
|
|
|
|
|
_ => { |
|
|
|
|
|
|
|
panic!("attribute {} should be a string", name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
} |
|
|
|
_ => { |
|
|
|
_ => { |
|
|
|
panic!("attribute {} should be a string", name); |
|
|
|
panic!("attribute {} should be a string", name); |
|
|
|
} |
|
|
|
} |
|
|
@ -111,7 +116,7 @@ fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
|
|
|
|
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
|
|
|
|
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { |
|
|
|
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream { |
|
|
|
quote! { |
|
|
|
quote! { |
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Default)] |
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Default)] |
|
|
|
pub struct #repr(pub [u64; #limbs]); |
|
|
|
pub struct #repr(pub [u64; #limbs]); |
|
|
@ -253,7 +258,7 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> quote::Tokens { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Convert BigUint into a vector of 64-bit limbs.
|
|
|
|
/// Convert BigUint into a vector of 64-bit limbs.
|
|
|
|
fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> { |
|
|
|
fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> { |
|
|
|
let m = BigUint::one() << 64; |
|
|
|
let m = BigUint::one() << 64; |
|
|
|
let mut ret = vec![]; |
|
|
|
let mut ret = vec![]; |
|
|
|
|
|
|
|
|
|
|
@ -271,6 +276,12 @@ fn biguint_to_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> { |
|
|
|
ret |
|
|
|
ret |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Convert BigUint into a tokenized vector of 64-bit limbs.
|
|
|
|
|
|
|
|
fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream { |
|
|
|
|
|
|
|
let ret = biguint_to_real_u64_vec(v, limbs); |
|
|
|
|
|
|
|
quote!([#(#ret,)*]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn biguint_num_bits(mut v: BigUint) -> u32 { |
|
|
|
fn biguint_num_bits(mut v: BigUint) -> u32 { |
|
|
|
let mut bits = 0; |
|
|
|
let mut bits = 0; |
|
|
|
|
|
|
|
|
|
|
@ -321,7 +332,7 @@ fn prime_field_constants_and_sqrt( |
|
|
|
modulus: BigUint, |
|
|
|
modulus: BigUint, |
|
|
|
limbs: usize, |
|
|
|
limbs: usize, |
|
|
|
generator: BigUint, |
|
|
|
generator: BigUint, |
|
|
|
) -> quote::Tokens { |
|
|
|
) -> proc_macro2::TokenStream { |
|
|
|
let modulus_num_bits = biguint_num_bits(modulus.clone()); |
|
|
|
let modulus_num_bits = biguint_num_bits(modulus.clone()); |
|
|
|
|
|
|
|
|
|
|
|
// The number of bits we should "shave" from a randomly sampled reputation, i.e.,
|
|
|
|
// The number of bits we should "shave" from a randomly sampled reputation, i.e.,
|
|
|
@ -437,7 +448,7 @@ fn prime_field_constants_and_sqrt( |
|
|
|
let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); |
|
|
|
let r2 = biguint_to_u64_vec((&r * &r) % &modulus, limbs); |
|
|
|
|
|
|
|
|
|
|
|
let r = biguint_to_u64_vec(r, limbs); |
|
|
|
let r = biguint_to_u64_vec(r, limbs); |
|
|
|
let modulus = biguint_to_u64_vec(modulus, limbs); |
|
|
|
let modulus = biguint_to_real_u64_vec(modulus, limbs); |
|
|
|
|
|
|
|
|
|
|
|
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
|
|
|
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
|
|
|
let mut inv = 1u64; |
|
|
|
let mut inv = 1u64; |
|
|
@ -449,7 +460,7 @@ fn prime_field_constants_and_sqrt( |
|
|
|
|
|
|
|
|
|
|
|
quote! { |
|
|
|
quote! { |
|
|
|
/// This is the modulus m of the prime field
|
|
|
|
/// This is the modulus m of the prime field
|
|
|
|
const MODULUS: #repr = #repr(#modulus); |
|
|
|
const MODULUS: #repr = #repr([#(#modulus,)*]); |
|
|
|
|
|
|
|
|
|
|
|
/// The number of bits needed to represent the modulus.
|
|
|
|
/// The number of bits needed to represent the modulus.
|
|
|
|
const MODULUS_BITS: u32 = #modulus_num_bits; |
|
|
|
const MODULUS_BITS: u32 = #modulus_num_bits; |
|
|
@ -482,15 +493,19 @@ fn prime_field_constants_and_sqrt( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Implement PrimeField for the derived type.
|
|
|
|
/// Implement PrimeField for the derived type.
|
|
|
|
fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote::Tokens { |
|
|
|
fn prime_field_impl( |
|
|
|
|
|
|
|
name: &syn::Ident, |
|
|
|
|
|
|
|
repr: &syn::Ident, |
|
|
|
|
|
|
|
limbs: usize, |
|
|
|
|
|
|
|
) -> proc_macro2::TokenStream { |
|
|
|
// Returns r{n} as an ident.
|
|
|
|
// Returns r{n} as an ident.
|
|
|
|
fn get_temp(n: usize) -> syn::Ident { |
|
|
|
fn get_temp(n: usize) -> syn::Ident { |
|
|
|
syn::Ident::from(format!("r{}", n)) |
|
|
|
syn::Ident::new(&format!("r{}", n), proc_macro2::Span::call_site()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// The parameter list for the mont_reduce() internal method.
|
|
|
|
// The parameter list for the mont_reduce() internal method.
|
|
|
|
// r0: u64, mut r1: u64, mut r2: u64, ...
|
|
|
|
// r0: u64, mut r1: u64, mut r2: u64, ...
|
|
|
|
let mut mont_paramlist = quote::Tokens::new(); |
|
|
|
let mut mont_paramlist = proc_macro2::TokenStream::new(); |
|
|
|
mont_paramlist.append_separated( |
|
|
|
mont_paramlist.append_separated( |
|
|
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { |
|
|
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { |
|
|
|
if i != 0 { |
|
|
|
if i != 0 { |
|
|
@ -499,17 +514,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
quote!{#x: u64} |
|
|
|
quote!{#x: u64} |
|
|
|
} |
|
|
|
} |
|
|
|
}), |
|
|
|
}), |
|
|
|
",", |
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// Implement montgomery reduction for some number of limbs
|
|
|
|
// Implement montgomery reduction for some number of limbs
|
|
|
|
fn mont_impl(limbs: usize) -> quote::Tokens { |
|
|
|
fn mont_impl(limbs: usize) -> proc_macro2::TokenStream { |
|
|
|
let mut gen = quote::Tokens::new(); |
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
|
|
for i in 0..limbs { |
|
|
|
for i in 0..limbs { |
|
|
|
{ |
|
|
|
{ |
|
|
|
let temp = get_temp(i); |
|
|
|
let temp = get_temp(i); |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let k = #temp.wrapping_mul(INV); |
|
|
|
let k = #temp.wrapping_mul(INV); |
|
|
|
let mut carry = 0; |
|
|
|
let mut carry = 0; |
|
|
|
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); |
|
|
|
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); |
|
|
@ -518,7 +533,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
|
|
|
|
|
|
|
|
for j in 1..limbs { |
|
|
|
for j in 1..limbs { |
|
|
|
let temp = get_temp(i + j); |
|
|
|
let temp = get_temp(i + j); |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); |
|
|
|
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -526,17 +541,17 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
|
|
if i == 0 { |
|
|
|
if i == 0 { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
#temp = ::ff::adc(#temp, 0, &mut carry); |
|
|
|
#temp = ::ff::adc(#temp, 0, &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
#temp = ::ff::adc(#temp, carry2, &mut carry); |
|
|
|
#temp = ::ff::adc(#temp, carry2, &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if i != (limbs - 1) { |
|
|
|
if i != (limbs - 1) { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let carry2 = carry; |
|
|
|
let carry2 = carry; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -545,7 +560,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
for i in 0..limbs { |
|
|
|
for i in 0..limbs { |
|
|
|
let temp = get_temp(limbs + i); |
|
|
|
let temp = get_temp(limbs + i); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
(self.0).0[#i] = #temp; |
|
|
|
(self.0).0[#i] = #temp; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -553,22 +568,22 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
gen |
|
|
|
gen |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn sqr_impl(a: quote::Tokens, limbs: usize) -> quote::Tokens { |
|
|
|
fn sqr_impl(a: proc_macro2::TokenStream, limbs: usize) -> proc_macro2::TokenStream { |
|
|
|
let mut gen = quote::Tokens::new(); |
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
|
|
for i in 0..(limbs - 1) { |
|
|
|
for i in 0..(limbs - 1) { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let mut carry = 0; |
|
|
|
let mut carry = 0; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
for j in (i + 1)..limbs { |
|
|
|
for j in (i + 1)..limbs { |
|
|
|
let temp = get_temp(i + j); |
|
|
|
let temp = get_temp(i + j); |
|
|
|
if i == 0 { |
|
|
|
if i == 0 { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); |
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry); |
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#a.0).0[#j], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -576,7 +591,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = carry; |
|
|
|
let #temp = carry; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -585,16 +600,16 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
let k = get_temp(i); |
|
|
|
let k = get_temp(i); |
|
|
|
|
|
|
|
|
|
|
|
if i == 1 { |
|
|
|
if i == 1 { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let tmp0 = #k >> 63; |
|
|
|
let tmp0 = #k >> 63; |
|
|
|
let #k = #k << 1; |
|
|
|
let #k = #k << 1; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else if i == (limbs * 2 - 1) { |
|
|
|
} else if i == (limbs * 2 - 1) { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #k = tmp0; |
|
|
|
let #k = tmp0; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let tmp1 = #k >> 63; |
|
|
|
let tmp1 = #k >> 63; |
|
|
|
let #k = #k << 1; |
|
|
|
let #k = #k << 1; |
|
|
|
let #k = #k | tmp0; |
|
|
|
let #k = #k | tmp0; |
|
|
@ -603,7 +618,7 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let mut carry = 0; |
|
|
|
let mut carry = 0; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -611,35 +626,42 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
let temp0 = get_temp(i * 2); |
|
|
|
let temp0 = get_temp(i * 2); |
|
|
|
let temp1 = get_temp(i * 2 + 1); |
|
|
|
let temp1 = get_temp(i * 2 + 1); |
|
|
|
if i == 0 { |
|
|
|
if i == 0 { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); |
|
|
|
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); |
|
|
|
let #temp0 = ::ff::mac_with_carry(#temp0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp1 = ::ff::adc(#temp1, 0, &mut carry); |
|
|
|
let #temp1 = ::ff::adc(#temp1, 0, &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut mont_calling = quote::Tokens::new(); |
|
|
|
let mut mont_calling = proc_macro2::TokenStream::new(); |
|
|
|
mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); |
|
|
|
mont_calling.append_separated( |
|
|
|
|
|
|
|
(0..(limbs * 2)).map(|i| get_temp(i)), |
|
|
|
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
gen |
|
|
|
gen |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens { |
|
|
|
fn mul_impl( |
|
|
|
let mut gen = quote::Tokens::new(); |
|
|
|
a: proc_macro2::TokenStream, |
|
|
|
|
|
|
|
b: proc_macro2::TokenStream, |
|
|
|
|
|
|
|
limbs: usize, |
|
|
|
|
|
|
|
) -> proc_macro2::TokenStream { |
|
|
|
|
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
|
|
for i in 0..limbs { |
|
|
|
for i in 0..limbs { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let mut carry = 0; |
|
|
|
let mut carry = 0; |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -647,11 +669,11 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
let temp = get_temp(i + j); |
|
|
|
let temp = get_temp(i + j); |
|
|
|
|
|
|
|
|
|
|
|
if i == 0 { |
|
|
|
if i == 0 { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); |
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry); |
|
|
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
@ -659,15 +681,18 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
let #temp = carry; |
|
|
|
let #temp = carry; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let mut mont_calling = quote::Tokens::new(); |
|
|
|
let mut mont_calling = proc_macro2::TokenStream::new(); |
|
|
|
mont_calling.append_separated((0..(limbs * 2)).map(|i| get_temp(i)), ","); |
|
|
|
mont_calling.append_separated( |
|
|
|
|
|
|
|
(0..(limbs * 2)).map(|i| get_temp(i)), |
|
|
|
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
gen.append(quote!{ |
|
|
|
gen.extend(quote!{ |
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -679,12 +704,12 @@ fn prime_field_impl(name: &syn::Ident, repr: &syn::Ident, limbs: usize) -> quote |
|
|
|
let montgomery_impl = mont_impl(limbs); |
|
|
|
let montgomery_impl = mont_impl(limbs); |
|
|
|
|
|
|
|
|
|
|
|
// (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
|
|
|
|
// (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
|
|
|
|
let mut into_repr_params = quote::Tokens::new(); |
|
|
|
let mut into_repr_params = proc_macro2::TokenStream::new(); |
|
|
|
into_repr_params.append_separated( |
|
|
|
into_repr_params.append_separated( |
|
|
|
(0..limbs) |
|
|
|
(0..limbs) |
|
|
|
.map(|i| quote!{ (self.0).0[#i] }) |
|
|
|
.map(|i| quote!{ (self.0).0[#i] }) |
|
|
|
.chain((0..limbs).map(|_| quote!{0})), |
|
|
|
.chain((0..limbs).map(|_| quote!{0})), |
|
|
|
",", |
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
quote!{ |
|
|
|
quote!{ |
|
|
|