|
|
|
@ -52,13 +52,8 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
|
|
|
|
|
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
let (constants_impl, sqrt_impl) = prime_field_constants_and_sqrt( |
|
|
|
|
&ast.ident, |
|
|
|
|
&repr_ident, |
|
|
|
|
modulus, |
|
|
|
|
limbs, |
|
|
|
|
generator, |
|
|
|
|
); |
|
|
|
|
let (constants_impl, sqrt_impl) = |
|
|
|
|
prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator); |
|
|
|
|
|
|
|
|
|
gen.extend(constants_impl); |
|
|
|
|
gen.extend(prime_field_repr_impl(&repr_ident, limbs)); |
|
|
|
@ -359,7 +354,8 @@ fn biguint_num_bits(mut v: BigUint) -> u32 {
|
|
|
|
|
fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { |
|
|
|
|
let mut ret = BigUint::one(); |
|
|
|
|
|
|
|
|
|
for i in exp.to_bytes_be() |
|
|
|
|
for i in exp |
|
|
|
|
.to_bytes_be() |
|
|
|
|
.into_iter() |
|
|
|
|
.flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd())) |
|
|
|
|
{ |
|
|
|
@ -380,11 +376,13 @@ fn test_exp() {
|
|
|
|
|
&BigUint::from_str("5489673498567349856734895").unwrap(), |
|
|
|
|
&BigUint::from_str( |
|
|
|
|
"52435875175126190479447740508185965837690552500527637822603658699938581184513" |
|
|
|
|
).unwrap() |
|
|
|
|
) |
|
|
|
|
.unwrap() |
|
|
|
|
), |
|
|
|
|
BigUint::from_str( |
|
|
|
|
"4371221214068404307866768905142520595925044802278091865033317963560480051536" |
|
|
|
|
).unwrap() |
|
|
|
|
) |
|
|
|
|
.unwrap() |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -423,7 +421,7 @@ fn prime_field_constants_and_sqrt(
|
|
|
|
|
|
|
|
|
|
let mod_minus_1_over_2 = |
|
|
|
|
biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs); |
|
|
|
|
let legendre_impl = quote!{ |
|
|
|
|
let legendre_impl = quote! { |
|
|
|
|
fn legendre(&self) -> ::ff::LegendreSymbol { |
|
|
|
|
// s = self^((modulus - 1) // 2)
|
|
|
|
|
let s = self.pow(#mod_minus_1_over_2); |
|
|
|
@ -445,7 +443,7 @@ fn prime_field_constants_and_sqrt(
|
|
|
|
|
// Compute -R as (m - r)
|
|
|
|
|
let rneg = biguint_to_u64_vec(&modulus - &r, limbs); |
|
|
|
|
|
|
|
|
|
quote!{ |
|
|
|
|
quote! { |
|
|
|
|
impl ::ff::SqrtField for #name { |
|
|
|
|
#legendre_impl |
|
|
|
|
|
|
|
|
@ -472,7 +470,7 @@ fn prime_field_constants_and_sqrt(
|
|
|
|
|
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs); |
|
|
|
|
let t = biguint_to_u64_vec(t.clone(), limbs); |
|
|
|
|
|
|
|
|
|
quote!{ |
|
|
|
|
quote! { |
|
|
|
|
impl ::ff::SqrtField for #name { |
|
|
|
|
#legendre_impl |
|
|
|
|
|
|
|
|
@ -519,7 +517,7 @@ fn prime_field_constants_and_sqrt(
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
quote!{} |
|
|
|
|
quote! {} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Compute R^2 mod m
|
|
|
|
@ -536,36 +534,39 @@ fn prime_field_constants_and_sqrt(
|
|
|
|
|
} |
|
|
|
|
inv = inv.wrapping_neg(); |
|
|
|
|
|
|
|
|
|
(quote! { |
|
|
|
|
/// This is the modulus m of the prime field
|
|
|
|
|
const MODULUS: #repr = #repr([#(#modulus,)*]); |
|
|
|
|
( |
|
|
|
|
quote! { |
|
|
|
|
/// This is the modulus m of the prime field
|
|
|
|
|
const MODULUS: #repr = #repr([#(#modulus,)*]); |
|
|
|
|
|
|
|
|
|
/// The number of bits needed to represent the modulus.
|
|
|
|
|
const MODULUS_BITS: u32 = #modulus_num_bits; |
|
|
|
|
/// The number of bits needed to represent the modulus.
|
|
|
|
|
const MODULUS_BITS: u32 = #modulus_num_bits; |
|
|
|
|
|
|
|
|
|
/// The number of bits that must be shaved from the beginning of
|
|
|
|
|
/// the representation when randomly sampling.
|
|
|
|
|
const REPR_SHAVE_BITS: u32 = #repr_shave_bits; |
|
|
|
|
/// The number of bits that must be shaved from the beginning of
|
|
|
|
|
/// the representation when randomly sampling.
|
|
|
|
|
const REPR_SHAVE_BITS: u32 = #repr_shave_bits; |
|
|
|
|
|
|
|
|
|
/// 2^{limbs*64} mod m
|
|
|
|
|
const R: #repr = #repr(#r); |
|
|
|
|
/// 2^{limbs*64} mod m
|
|
|
|
|
const R: #repr = #repr(#r); |
|
|
|
|
|
|
|
|
|
/// 2^{limbs*64*2} mod m
|
|
|
|
|
const R2: #repr = #repr(#r2); |
|
|
|
|
/// 2^{limbs*64*2} mod m
|
|
|
|
|
const R2: #repr = #repr(#r2); |
|
|
|
|
|
|
|
|
|
/// -(m^{-1} mod m) mod m
|
|
|
|
|
const INV: u64 = #inv; |
|
|
|
|
/// -(m^{-1} mod m) mod m
|
|
|
|
|
const INV: u64 = #inv; |
|
|
|
|
|
|
|
|
|
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
|
|
|
|
/// nonresidue.
|
|
|
|
|
const GENERATOR: #repr = #repr(#generator); |
|
|
|
|
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
|
|
|
|
/// nonresidue.
|
|
|
|
|
const GENERATOR: #repr = #repr(#generator); |
|
|
|
|
|
|
|
|
|
/// 2^s * t = MODULUS - 1 with t odd
|
|
|
|
|
const S: u32 = #s; |
|
|
|
|
/// 2^s * t = MODULUS - 1 with t odd
|
|
|
|
|
const S: u32 = #s; |
|
|
|
|
|
|
|
|
|
/// 2^s root of unity computed by GENERATOR^t
|
|
|
|
|
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); |
|
|
|
|
}, sqrt_impl) |
|
|
|
|
/// 2^s root of unity computed by GENERATOR^t
|
|
|
|
|
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity); |
|
|
|
|
}, |
|
|
|
|
sqrt_impl, |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Implement PrimeField for the derived type.
|
|
|
|
@ -585,9 +586,9 @@ fn prime_field_impl(
|
|
|
|
|
mont_paramlist.append_separated( |
|
|
|
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| { |
|
|
|
|
if i != 0 { |
|
|
|
|
quote!{mut #x: u64} |
|
|
|
|
quote! {mut #x: u64} |
|
|
|
|
} else { |
|
|
|
|
quote!{#x: u64} |
|
|
|
|
quote! {#x: u64} |
|
|
|
|
} |
|
|
|
|
}), |
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
@ -600,7 +601,7 @@ fn prime_field_impl(
|
|
|
|
|
for i in 0..limbs { |
|
|
|
|
{ |
|
|
|
|
let temp = get_temp(i); |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let k = #temp.wrapping_mul(INV); |
|
|
|
|
let mut carry = 0; |
|
|
|
|
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry); |
|
|
|
@ -609,7 +610,7 @@ fn prime_field_impl(
|
|
|
|
|
|
|
|
|
|
for j in 1..limbs { |
|
|
|
|
let temp = get_temp(i + j); |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -617,17 +618,17 @@ fn prime_field_impl(
|
|
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
if i == 0 { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
#temp = ::ff::adc(#temp, 0, &mut carry); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
#temp = ::ff::adc(#temp, carry2, &mut carry); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if i != (limbs - 1) { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let carry2 = carry; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -636,7 +637,7 @@ fn prime_field_impl(
|
|
|
|
|
for i in 0..limbs { |
|
|
|
|
let temp = get_temp(limbs + i); |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
(self.0).0[#i] = #temp; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -648,14 +649,14 @@ fn prime_field_impl(
|
|
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
for i in 0..(limbs - 1) { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let mut carry = 0; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
for j in (i + 1)..limbs { |
|
|
|
|
let temp = get_temp(i + j); |
|
|
|
|
if i == 0 { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#j], &mut carry); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
@ -667,7 +668,7 @@ fn prime_field_impl(
|
|
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp = carry; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -677,21 +678,21 @@ fn prime_field_impl(
|
|
|
|
|
let temp1 = get_temp(limbs * 2 - i - 1); |
|
|
|
|
|
|
|
|
|
if i == 1 { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp0 = #temp1 >> 63; |
|
|
|
|
}); |
|
|
|
|
} else if i == (limbs * 2 - 1) { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp0 = #temp0 << 1; |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp0 = (#temp0 << 1) | (#temp1 >> 63); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let mut carry = 0; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -699,7 +700,7 @@ fn prime_field_impl(
|
|
|
|
|
let temp0 = get_temp(i * 2); |
|
|
|
|
let temp1 = get_temp(i * 2 + 1); |
|
|
|
|
if i == 0 { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp0 = ::ff::mac_with_carry(0, (#a.0).0[#i], (#a.0).0[#i], &mut carry); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
@ -708,7 +709,7 @@ fn prime_field_impl(
|
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp1 = ::ff::adc(#temp1, 0, &mut carry); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -719,7 +720,7 @@ fn prime_field_impl(
|
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -734,7 +735,7 @@ fn prime_field_impl(
|
|
|
|
|
let mut gen = proc_macro2::TokenStream::new(); |
|
|
|
|
|
|
|
|
|
for i in 0..limbs { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let mut carry = 0; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -742,7 +743,7 @@ fn prime_field_impl(
|
|
|
|
|
let temp = get_temp(i + j); |
|
|
|
|
|
|
|
|
|
if i == 0 { |
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry); |
|
|
|
|
}); |
|
|
|
|
} else { |
|
|
|
@ -754,7 +755,7 @@ fn prime_field_impl(
|
|
|
|
|
|
|
|
|
|
let temp = get_temp(i + limbs); |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
let #temp = carry; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
@ -765,29 +766,29 @@ fn prime_field_impl(
|
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
gen.extend(quote!{ |
|
|
|
|
gen.extend(quote! { |
|
|
|
|
self.mont_reduce(#mont_calling); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
gen |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let squaring_impl = sqr_impl(quote!{self}, limbs); |
|
|
|
|
let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs); |
|
|
|
|
let squaring_impl = sqr_impl(quote! {self}, limbs); |
|
|
|
|
let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs); |
|
|
|
|
let montgomery_impl = mont_impl(limbs); |
|
|
|
|
|
|
|
|
|
// (self.0).0[0], (self.0).0[1], ..., 0, 0, 0, 0, ...
|
|
|
|
|
let mut into_repr_params = proc_macro2::TokenStream::new(); |
|
|
|
|
into_repr_params.append_separated( |
|
|
|
|
(0..limbs) |
|
|
|
|
.map(|i| quote!{ (self.0).0[#i] }) |
|
|
|
|
.chain((0..limbs).map(|_| quote!{0})), |
|
|
|
|
.map(|i| quote! { (self.0).0[#i] }) |
|
|
|
|
.chain((0..limbs).map(|_| quote! {0})), |
|
|
|
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
let top_limb_index = limbs - 1; |
|
|
|
|
|
|
|
|
|
quote!{ |
|
|
|
|
quote! { |
|
|
|
|
impl ::std::marker::Copy for #name { } |
|
|
|
|
|
|
|
|
|
impl ::std::clone::Clone for #name { |
|
|
|
|