Merge pull request #1 from str4d/updates
Update dependencies and traits
This commit is contained in:
@@ -9,5 +9,10 @@ license = "MIT/Apache-2.0"
|
|||||||
repository = "https://github.com/ebfull/ff"
|
repository = "https://github.com/ebfull/ff"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.3"
|
byteorder = "1"
|
||||||
|
rand = "0.4"
|
||||||
ff_derive = { version = "0.2.0", path = "ff_derive" }
|
ff_derive = { version = "0.2.0", path = "ff_derive" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
u128-support = []
|
||||||
|
default = []
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ repository = "https://github.com/ebfull/ff"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = "0.11"
|
num-bigint = "0.2"
|
||||||
quote = "0.3"
|
num-traits = "0.2"
|
||||||
num-bigint = "0.1"
|
|
||||||
num-traits = "0.1"
|
|
||||||
num-integer = "0.1"
|
num-integer = "0.1"
|
||||||
|
proc-macro2 = "0.4"
|
||||||
|
quote = "0.6"
|
||||||
|
syn = "0.14"
|
||||||
|
|||||||
@@ -1,44 +1,42 @@
|
|||||||
#![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;
|
||||||
|
|
||||||
extern crate num_bigint;
|
extern crate num_bigint;
|
||||||
extern crate num_traits;
|
|
||||||
extern crate num_integer;
|
extern crate num_integer;
|
||||||
|
extern crate num_traits;
|
||||||
|
|
||||||
use num_integer::Integer;
|
|
||||||
use num_traits::{Zero, One, ToPrimitive};
|
|
||||||
use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
|
use num_integer::Integer;
|
||||||
|
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(
|
pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
input: proc_macro::TokenStream
|
// Parse the type definition
|
||||||
) -> proc_macro::TokenStream
|
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
||||||
{
|
|
||||||
// Construct a string representation of the type definition
|
|
||||||
let s = input.to_string();
|
|
||||||
|
|
||||||
// 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
|
||||||
let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs)
|
let modulus: BigUint = fetch_attr("PrimeFieldModulus", &ast.attrs)
|
||||||
.expect("Please supply a PrimeFieldModulus attribute")
|
.expect("Please supply a PrimeFieldModulus attribute")
|
||||||
.parse().expect("PrimeFieldModulus should be a number");
|
.parse()
|
||||||
|
.expect("PrimeFieldModulus should be a number");
|
||||||
|
|
||||||
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
|
// We may be provided with a generator of p - 1 order. It is required that this generator be quadratic
|
||||||
// nonresidue.
|
// nonresidue.
|
||||||
let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
|
let generator: BigUint = fetch_attr("PrimeFieldGenerator", &ast.attrs)
|
||||||
.expect("Please supply a PrimeFieldGenerator attribute")
|
.expect("Please supply a PrimeFieldGenerator attribute")
|
||||||
.parse().expect("PrimeFieldGenerator should be a number");
|
.parse()
|
||||||
|
.expect("PrimeFieldGenerator should be a number");
|
||||||
|
|
||||||
// The arithmetic in this library only works if the modulus*2 is smaller than the backing
|
// The arithmetic in this library only works if the modulus*2 is smaller than the backing
|
||||||
// representation. Compute the number of limbs we need.
|
// representation. Compute the number of limbs we need.
|
||||||
@@ -52,34 +50,42 @@ pub fn prime_field(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut gen = quote::Tokens::new();
|
let mut gen = proc_macro2::TokenStream::new();
|
||||||
|
|
||||||
gen.append(prime_field_repr_impl(&repr_ident, limbs));
|
let (constants_impl, sqrt_impl) = prime_field_constants_and_sqrt(
|
||||||
gen.append(prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator));
|
&ast.ident,
|
||||||
gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs));
|
&repr_ident,
|
||||||
|
modulus,
|
||||||
|
limbs,
|
||||||
|
generator,
|
||||||
|
);
|
||||||
|
|
||||||
|
gen.extend(constants_impl);
|
||||||
|
gen.extend(prime_field_repr_impl(&repr_ident, limbs));
|
||||||
|
gen.extend(prime_field_impl(&ast.ident, &repr_ident, limbs));
|
||||||
|
gen.extend(sqrt_impl);
|
||||||
|
|
||||||
// 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(
|
fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
|
||||||
body: &syn::Body
|
|
||||||
) -> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
@@ -88,24 +94,20 @@ fn fetch_wrapped_ident(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch an attribute string from the derived struct.
|
/// Fetch an attribute string from the derived struct.
|
||||||
fn fetch_attr(
|
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
|
||||||
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) => {
|
syn::Meta::NameValue(nv) => {
|
||||||
match val {
|
if nv.ident.to_string() == name {
|
||||||
&syn::Lit::Str(ref s, _) => {
|
match nv.lit {
|
||||||
return Some(s.clone())
|
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);
|
panic!("attribute {} should be a string", name);
|
||||||
}
|
}
|
||||||
@@ -117,15 +119,23 @@ fn fetch_attr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(
|
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
|
||||||
repr: &syn::Ident,
|
|
||||||
limbs: usize
|
|
||||||
) -> quote::Tokens
|
|
||||||
{
|
|
||||||
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]);
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for #repr
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
try!(write!(f, "0x"));
|
||||||
|
for i in self.0.iter().rev() {
|
||||||
|
try!(write!(f, "{:016x}", *i));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::rand::Rand for #repr {
|
impl ::rand::Rand for #repr {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
||||||
@@ -133,8 +143,7 @@ fn prime_field_repr_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::fmt::Debug for #repr
|
impl ::std::fmt::Display for #repr {
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
try!(write!(f, "0x"));
|
try!(write!(f, "0x"));
|
||||||
for i in self.0.iter().rev() {
|
for i in self.0.iter().rev() {
|
||||||
@@ -152,6 +161,13 @@ fn prime_field_repr_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsMut<[u64]> for #repr {
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_mut(&mut self) -> &mut [u64] {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<u64> for #repr {
|
impl From<u64> for #repr {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(val: u64) -> #repr {
|
fn from(val: u64) -> #repr {
|
||||||
@@ -201,6 +217,32 @@ fn prime_field_repr_impl(
|
|||||||
self.0.iter().all(|&e| e == 0)
|
self.0.iter().all(|&e| e == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn shr(&mut self, mut n: u32) {
|
||||||
|
if n as usize >= 64 * #limbs {
|
||||||
|
*self = Self::from(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while n >= 64 {
|
||||||
|
let mut t = 0;
|
||||||
|
for i in self.0.iter_mut().rev() {
|
||||||
|
::std::mem::swap(&mut t, i);
|
||||||
|
}
|
||||||
|
n -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if n > 0 {
|
||||||
|
let mut t = 0;
|
||||||
|
for i in self.0.iter_mut().rev() {
|
||||||
|
let t2 = *i << (64 - n);
|
||||||
|
*i >>= n;
|
||||||
|
*i |= t;
|
||||||
|
t = t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn div2(&mut self) {
|
fn div2(&mut self) {
|
||||||
let mut t = 0;
|
let mut t = 0;
|
||||||
@@ -215,7 +257,7 @@ fn prime_field_repr_impl(
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn mul2(&mut self) {
|
fn mul2(&mut self) {
|
||||||
let mut last = 0;
|
let mut last = 0;
|
||||||
for i in self.0.iter_mut() {
|
for i in &mut self.0 {
|
||||||
let tmp = *i >> 63;
|
let tmp = *i >> 63;
|
||||||
*i <<= 1;
|
*i <<= 1;
|
||||||
*i |= last;
|
*i |= last;
|
||||||
@@ -223,6 +265,32 @@ fn prime_field_repr_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn shl(&mut self, mut n: u32) {
|
||||||
|
if n as usize >= 64 * #limbs {
|
||||||
|
*self = Self::from(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while n >= 64 {
|
||||||
|
let mut t = 0;
|
||||||
|
for i in &mut self.0 {
|
||||||
|
::std::mem::swap(&mut t, i);
|
||||||
|
}
|
||||||
|
n -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if n > 0 {
|
||||||
|
let mut t = 0;
|
||||||
|
for i in &mut self.0 {
|
||||||
|
let t2 = *i >> (64 - n);
|
||||||
|
*i <<= n;
|
||||||
|
*i |= t;
|
||||||
|
t = t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn num_bits(&self) -> u32 {
|
fn num_bits(&self) -> u32 {
|
||||||
let mut ret = (#limbs as u32) * 64;
|
let mut ret = (#limbs as u32) * 64;
|
||||||
@@ -238,36 +306,28 @@ fn prime_field_repr_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn add_nocarry(&mut self, other: &#repr) -> bool {
|
fn add_nocarry(&mut self, other: &#repr) {
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
|
|
||||||
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
||||||
*a = ::ff::adc(*a, *b, &mut carry);
|
*a = ::ff::adc(*a, *b, &mut carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
carry != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn sub_noborrow(&mut self, other: &#repr) -> bool {
|
fn sub_noborrow(&mut self, other: &#repr) {
|
||||||
let mut borrow = 0;
|
let mut borrow = 0;
|
||||||
|
|
||||||
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
||||||
*a = ::ff::sbb(*a, *b, &mut borrow);
|
*a = ::ff::sbb(*a, *b, &mut borrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
borrow != 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert BigUint into a vector of 64-bit limbs.
|
/// Convert BigUint into a vector of 64-bit limbs.
|
||||||
fn biguint_to_u64_vec(
|
fn biguint_to_real_u64_vec(mut v: BigUint, limbs: usize) -> Vec<u64> {
|
||||||
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![];
|
||||||
|
|
||||||
@@ -285,10 +345,13 @@ fn biguint_to_u64_vec(
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
fn biguint_num_bits(
|
/// Convert BigUint into a tokenized vector of 64-bit limbs.
|
||||||
mut v: BigUint
|
fn biguint_to_u64_vec(v: BigUint, limbs: usize) -> proc_macro2::TokenStream {
|
||||||
) -> u32
|
let ret = biguint_to_real_u64_vec(v, limbs);
|
||||||
{
|
quote!([#(#ret,)*])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn biguint_num_bits(mut v: BigUint) -> u32 {
|
||||||
let mut bits = 0;
|
let mut bits = 0;
|
||||||
|
|
||||||
while v != BigUint::zero() {
|
while v != BigUint::zero() {
|
||||||
@@ -300,12 +363,7 @@ fn biguint_num_bits(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// BigUint modular exponentiation by square-and-multiply.
|
/// BigUint modular exponentiation by square-and-multiply.
|
||||||
fn exp(
|
fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
||||||
base: BigUint,
|
|
||||||
exp: &BigUint,
|
|
||||||
modulus: &BigUint
|
|
||||||
) -> BigUint
|
|
||||||
{
|
|
||||||
let mut ret = BigUint::one();
|
let mut ret = BigUint::one();
|
||||||
|
|
||||||
for i in exp.to_bytes_be()
|
for i in exp.to_bytes_be()
|
||||||
@@ -327,9 +385,13 @@ fn test_exp() {
|
|||||||
exp(
|
exp(
|
||||||
BigUint::from_str("4398572349857239485729348572983472345").unwrap(),
|
BigUint::from_str("4398572349857239485729348572983472345").unwrap(),
|
||||||
&BigUint::from_str("5489673498567349856734895").unwrap(),
|
&BigUint::from_str("5489673498567349856734895").unwrap(),
|
||||||
&BigUint::from_str("52435875175126190479447740508185965837690552500527637822603658699938581184513").unwrap()
|
&BigUint::from_str(
|
||||||
|
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
|
||||||
|
).unwrap()
|
||||||
),
|
),
|
||||||
BigUint::from_str("4371221214068404307866768905142520595925044802278091865033317963560480051536").unwrap()
|
BigUint::from_str(
|
||||||
|
"4371221214068404307866768905142520595925044802278091865033317963560480051536"
|
||||||
|
).unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,9 +400,8 @@ fn prime_field_constants_and_sqrt(
|
|||||||
repr: &syn::Ident,
|
repr: &syn::Ident,
|
||||||
modulus: BigUint,
|
modulus: BigUint,
|
||||||
limbs: usize,
|
limbs: usize,
|
||||||
generator: BigUint
|
generator: BigUint,
|
||||||
) -> quote::Tokens
|
) -> (proc_macro2::TokenStream, 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.,
|
||||||
@@ -353,7 +414,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
||||||
|
|
||||||
// modulus - 1 = 2^s * t
|
// modulus - 1 = 2^s * t
|
||||||
let mut s: usize = 0;
|
let mut s: u32 = 0;
|
||||||
let mut t = &modulus - BigUint::from_str("1").unwrap();
|
let mut t = &modulus - BigUint::from_str("1").unwrap();
|
||||||
while t.is_even() {
|
while t.is_even() {
|
||||||
t = t >> 1;
|
t = t >> 1;
|
||||||
@@ -361,18 +422,40 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute 2^s root of unity given the generator
|
// Compute 2^s root of unity given the generator
|
||||||
let root_of_unity = biguint_to_u64_vec((exp(generator.clone(), &t, &modulus) * &r) % &modulus, limbs);
|
let root_of_unity = biguint_to_u64_vec(
|
||||||
|
(exp(generator.clone(), &t, &modulus) * &r) % &modulus,
|
||||||
|
limbs,
|
||||||
|
);
|
||||||
let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs);
|
let generator = biguint_to_u64_vec((generator.clone() * &r) % &modulus, limbs);
|
||||||
|
|
||||||
|
let mod_minus_1_over_2 =
|
||||||
|
biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
|
||||||
|
let legendre_impl = quote!{
|
||||||
|
fn legendre(&self) -> ::ff::LegendreSymbol {
|
||||||
|
// s = self^((modulus - 1) // 2)
|
||||||
|
let s = self.pow(#mod_minus_1_over_2);
|
||||||
|
if s == Self::zero() {
|
||||||
|
::ff::LegendreSymbol::Zero
|
||||||
|
} else if s == Self::one() {
|
||||||
|
::ff::LegendreSymbol::QuadraticResidue
|
||||||
|
} else {
|
||||||
|
::ff::LegendreSymbol::QuadraticNonResidue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let sqrt_impl =
|
let sqrt_impl =
|
||||||
if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
|
if (&modulus % BigUint::from_str("4").unwrap()) == BigUint::from_str("3").unwrap() {
|
||||||
let mod_minus_3_over_4 = biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs);
|
let mod_minus_3_over_4 =
|
||||||
|
biguint_to_u64_vec((&modulus - BigUint::from_str("3").unwrap()) >> 2, limbs);
|
||||||
|
|
||||||
// Compute -R as (m - r)
|
// Compute -R as (m - r)
|
||||||
let rneg = biguint_to_u64_vec(&modulus - &r, limbs);
|
let rneg = biguint_to_u64_vec(&modulus - &r, limbs);
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
impl ::ff::SqrtField for #name {
|
impl ::ff::SqrtField for #name {
|
||||||
|
#legendre_impl
|
||||||
|
|
||||||
fn sqrt(&self) -> Option<Self> {
|
fn sqrt(&self) -> Option<Self> {
|
||||||
// Shank's algorithm for q mod 4 = 3
|
// Shank's algorithm for q mod 4 = 3
|
||||||
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
|
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
|
||||||
@@ -393,27 +476,25 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
|
} else if (&modulus % BigUint::from_str("16").unwrap()) == BigUint::from_str("1").unwrap() {
|
||||||
let mod_minus_1_over_2 = biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
|
|
||||||
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs);
|
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs);
|
||||||
let t = biguint_to_u64_vec(t.clone(), limbs);
|
let t = biguint_to_u64_vec(t.clone(), limbs);
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
impl ::ff::SqrtField for #name {
|
impl ::ff::SqrtField for #name {
|
||||||
|
#legendre_impl
|
||||||
|
|
||||||
fn sqrt(&self) -> Option<Self> {
|
fn sqrt(&self) -> Option<Self> {
|
||||||
// Tonelli-Shank's algorithm for q mod 16 = 1
|
// Tonelli-Shank's algorithm for q mod 16 = 1
|
||||||
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
// https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5)
|
||||||
|
|
||||||
if self.is_zero() {
|
match self.legendre() {
|
||||||
return Some(*self);
|
::ff::LegendreSymbol::Zero => Some(*self),
|
||||||
}
|
::ff::LegendreSymbol::QuadraticNonResidue => None,
|
||||||
|
::ff::LegendreSymbol::QuadraticResidue => {
|
||||||
if self.pow(#mod_minus_1_over_2) != Self::one() {
|
let mut c = #name(ROOT_OF_UNITY);
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let mut c = #name(#repr(#root_of_unity));
|
|
||||||
let mut r = self.pow(#t_plus_1_over_2);
|
let mut r = self.pow(#t_plus_1_over_2);
|
||||||
let mut t = self.pow(#t);
|
let mut t = self.pow(#t);
|
||||||
let mut m = #s;
|
let mut m = S;
|
||||||
|
|
||||||
while t != Self::one() {
|
while t != Self::one() {
|
||||||
let mut i = 1;
|
let mut i = 1;
|
||||||
@@ -443,6 +524,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
quote!{}
|
quote!{}
|
||||||
};
|
};
|
||||||
@@ -451,7 +533,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;
|
||||||
@@ -461,9 +543,9 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
inv = inv.wrapping_neg();
|
inv = inv.wrapping_neg();
|
||||||
|
|
||||||
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;
|
||||||
@@ -486,51 +568,46 @@ fn prime_field_constants_and_sqrt(
|
|||||||
const GENERATOR: #repr = #repr(#generator);
|
const GENERATOR: #repr = #repr(#generator);
|
||||||
|
|
||||||
/// 2^s * t = MODULUS - 1 with t odd
|
/// 2^s * t = MODULUS - 1 with t odd
|
||||||
const S: usize = #s;
|
const S: u32 = #s;
|
||||||
|
|
||||||
/// 2^s root of unity computed by GENERATOR^t
|
/// 2^s root of unity computed by GENERATOR^t
|
||||||
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
|
const ROOT_OF_UNITY: #repr = #repr(#root_of_unity);
|
||||||
|
}, sqrt_impl)
|
||||||
#sqrt_impl
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implement PrimeField for the derived type.
|
/// Implement PrimeField for the derived type.
|
||||||
fn prime_field_impl(
|
fn prime_field_impl(
|
||||||
name: &syn::Ident,
|
name: &syn::Ident,
|
||||||
repr: &syn::Ident,
|
repr: &syn::Ident,
|
||||||
limbs: usize
|
limbs: usize,
|
||||||
) -> quote::Tokens
|
) -> 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)))
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
|
||||||
.map(|(i, x)| {
|
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
quote!{mut #x: u64}
|
quote!{mut #x: u64}
|
||||||
} else {
|
} else {
|
||||||
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 = proc_macro2::TokenStream::new();
|
||||||
let mut gen = quote::Tokens::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);
|
||||||
@@ -539,7 +616,7 @@ fn prime_field_impl(
|
|||||||
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -547,17 +624,17 @@ fn prime_field_impl(
|
|||||||
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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -566,7 +643,7 @@ fn prime_field_impl(
|
|||||||
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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -574,23 +651,22 @@ fn prime_field_impl(
|
|||||||
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 = proc_macro2::TokenStream::new();
|
||||||
let mut gen = quote::Tokens::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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -598,34 +674,31 @@ fn prime_field_impl(
|
|||||||
|
|
||||||
let temp = get_temp(i + limbs);
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
gen.append(quote!{
|
gen.extend(quote!{
|
||||||
let #temp = carry;
|
let #temp = carry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 1..(limbs*2) {
|
for i in 1..(limbs * 2) {
|
||||||
let k = get_temp(i);
|
let temp0 = get_temp(limbs * 2 - i);
|
||||||
|
let temp1 = get_temp(limbs * 2 - i - 1);
|
||||||
|
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
gen.append(quote!{
|
gen.extend(quote!{
|
||||||
let tmp0 = #k >> 63;
|
let #temp0 = #temp1 >> 63;
|
||||||
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 #temp0 = #temp0 << 1;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gen.append(quote!{
|
gen.extend(quote!{
|
||||||
let tmp1 = #k >> 63;
|
let #temp0 = (#temp0 << 1) | (#temp1 >> 63);
|
||||||
let #k = #k << 1;
|
|
||||||
let #k = #k | tmp0;
|
|
||||||
let tmp0 = tmp1;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gen.append(quote!{
|
gen.extend(quote!{
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -633,36 +706,42 @@ fn prime_field_impl(
|
|||||||
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(
|
||||||
{
|
a: proc_macro2::TokenStream,
|
||||||
let mut gen = quote::Tokens::new();
|
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;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -670,11 +749,11 @@ fn prime_field_impl(
|
|||||||
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -682,15 +761,18 @@ fn prime_field_impl(
|
|||||||
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -702,29 +784,32 @@ fn prime_field_impl(
|
|||||||
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).map(|i| quote!{ (self.0).0[#i] })
|
(0..limbs)
|
||||||
|
.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!{
|
let top_limb_index = limbs - 1;
|
||||||
impl Copy for #name { }
|
|
||||||
|
|
||||||
impl Clone for #name {
|
quote!{
|
||||||
|
impl ::std::marker::Copy for #name { }
|
||||||
|
|
||||||
|
impl ::std::clone::Clone for #name {
|
||||||
fn clone(&self) -> #name {
|
fn clone(&self) -> #name {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for #name {
|
impl ::std::cmp::PartialEq for #name {
|
||||||
fn eq(&self, other: &#name) -> bool {
|
fn eq(&self, other: &#name) -> bool {
|
||||||
self.0 == other.0
|
self.0 == other.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for #name { }
|
impl ::std::cmp::Eq for #name { }
|
||||||
|
|
||||||
impl ::std::fmt::Debug for #name
|
impl ::std::fmt::Debug for #name
|
||||||
{
|
{
|
||||||
@@ -733,14 +818,36 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Elements are ordered lexicographically.
|
||||||
|
impl Ord for #name {
|
||||||
|
#[inline(always)]
|
||||||
|
fn cmp(&self, other: &#name) -> ::std::cmp::Ordering {
|
||||||
|
self.into_repr().cmp(&other.into_repr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for #name {
|
||||||
|
#[inline(always)]
|
||||||
|
fn partial_cmp(&self, other: &#name) -> Option<::std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::std::fmt::Display for #name {
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
write!(f, "{}({})", stringify!(#name), self.into_repr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::rand::Rand for #name {
|
impl ::rand::Rand for #name {
|
||||||
/// Computes a uniformly random element using rejection sampling.
|
/// Computes a uniformly random element using rejection sampling.
|
||||||
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
||||||
loop {
|
loop {
|
||||||
let mut tmp = #name(#repr::rand(rng));
|
let mut tmp = #name(#repr::rand(rng));
|
||||||
for _ in 0..REPR_SHAVE_BITS {
|
|
||||||
tmp.0.div2();
|
// Mask away the unused bits at the beginning.
|
||||||
}
|
tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
|
||||||
|
|
||||||
if tmp.is_valid() {
|
if tmp.is_valid() {
|
||||||
return tmp
|
return tmp
|
||||||
}
|
}
|
||||||
@@ -748,17 +855,23 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<#name> for #repr {
|
||||||
|
fn from(e: #name) -> #repr {
|
||||||
|
e.into_repr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ::ff::PrimeField for #name {
|
impl ::ff::PrimeField for #name {
|
||||||
type Repr = #repr;
|
type Repr = #repr;
|
||||||
|
|
||||||
fn from_repr(r: #repr) -> Result<#name, ()> {
|
fn from_repr(r: #repr) -> Result<#name, PrimeFieldDecodingError> {
|
||||||
let mut r = #name(r);
|
let mut r = #name(r);
|
||||||
if r.is_valid() {
|
if r.is_valid() {
|
||||||
r.mul_assign(&#name(R2));
|
r.mul_assign(&#name(R2));
|
||||||
|
|
||||||
Ok(r)
|
Ok(r)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(PrimeFieldDecodingError::NotInField(format!("{}", r.0)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -775,21 +888,15 @@ fn prime_field_impl(
|
|||||||
MODULUS
|
MODULUS
|
||||||
}
|
}
|
||||||
|
|
||||||
fn num_bits() -> u32 {
|
const NUM_BITS: u32 = MODULUS_BITS;
|
||||||
MODULUS_BITS
|
|
||||||
}
|
|
||||||
|
|
||||||
fn capacity() -> u32 {
|
const CAPACITY: u32 = Self::NUM_BITS - 1;
|
||||||
Self::num_bits() - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiplicative_generator() -> Self {
|
fn multiplicative_generator() -> Self {
|
||||||
#name(GENERATOR)
|
#name(GENERATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn s() -> usize {
|
const S: u32 = S;
|
||||||
S
|
|
||||||
}
|
|
||||||
|
|
||||||
fn root_of_unity() -> Self {
|
fn root_of_unity() -> Self {
|
||||||
#name(ROOT_OF_UNITY)
|
#name(ROOT_OF_UNITY)
|
||||||
|
|||||||
351
src/lib.rs
351
src/lib.rs
@@ -1,6 +1,6 @@
|
|||||||
#![feature(i128_type)]
|
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
|
extern crate byteorder;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -8,18 +8,13 @@ extern crate ff_derive;
|
|||||||
|
|
||||||
pub use ff_derive::*;
|
pub use ff_derive::*;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
/// This trait represents an element of a field.
|
/// This trait represents an element of a field.
|
||||||
pub trait Field: Sized +
|
pub trait Field:
|
||||||
Eq +
|
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand
|
||||||
Copy +
|
|
||||||
Clone +
|
|
||||||
Send +
|
|
||||||
Sync +
|
|
||||||
fmt::Debug +
|
|
||||||
'static +
|
|
||||||
rand::Rand
|
|
||||||
{
|
{
|
||||||
/// Returns the zero element of the field, the additive identity.
|
/// Returns the zero element of the field, the additive identity.
|
||||||
fn zero() -> Self;
|
fn zero() -> Self;
|
||||||
@@ -57,12 +52,18 @@ pub trait Field: Sized +
|
|||||||
|
|
||||||
/// Exponentiates this element by a number represented with `u64` limbs,
|
/// Exponentiates this element by a number represented with `u64` limbs,
|
||||||
/// least significant digit first.
|
/// least significant digit first.
|
||||||
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self
|
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
|
||||||
{
|
|
||||||
let mut res = Self::one();
|
let mut res = Self::one();
|
||||||
|
|
||||||
|
let mut found_one = false;
|
||||||
|
|
||||||
for i in BitIterator::new(exp) {
|
for i in BitIterator::new(exp) {
|
||||||
|
if found_one {
|
||||||
res.square();
|
res.square();
|
||||||
|
} else {
|
||||||
|
found_one = i;
|
||||||
|
}
|
||||||
|
|
||||||
if i {
|
if i {
|
||||||
res.mul_assign(self);
|
res.mul_assign(self);
|
||||||
}
|
}
|
||||||
@@ -73,8 +74,10 @@ pub trait Field: Sized +
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This trait represents an element of a field that has a square root operation described for it.
|
/// This trait represents an element of a field that has a square root operation described for it.
|
||||||
pub trait SqrtField: Field
|
pub trait SqrtField: Field {
|
||||||
{
|
/// Returns the Legendre symbol of the field element.
|
||||||
|
fn legendre(&self) -> LegendreSymbol;
|
||||||
|
|
||||||
/// Returns the square root of the field element, if it is
|
/// Returns the square root of the field element, if it is
|
||||||
/// quadratic residue.
|
/// quadratic residue.
|
||||||
fn sqrt(&self) -> Option<Self>;
|
fn sqrt(&self) -> Option<Self>;
|
||||||
@@ -83,26 +86,31 @@ pub trait SqrtField: Field
|
|||||||
/// This trait represents a wrapper around a biginteger which can encode any element of a particular
|
/// This trait represents a wrapper around a biginteger which can encode any element of a particular
|
||||||
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
|
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
|
||||||
/// first.
|
/// first.
|
||||||
pub trait PrimeFieldRepr: Sized +
|
pub trait PrimeFieldRepr:
|
||||||
Copy +
|
Sized
|
||||||
Clone +
|
+ Copy
|
||||||
Eq +
|
+ Clone
|
||||||
Ord +
|
+ Eq
|
||||||
Send +
|
+ Ord
|
||||||
Sync +
|
+ Send
|
||||||
fmt::Debug +
|
+ Sync
|
||||||
'static +
|
+ Default
|
||||||
rand::Rand +
|
+ fmt::Debug
|
||||||
AsRef<[u64]> +
|
+ fmt::Display
|
||||||
From<u64>
|
+ 'static
|
||||||
|
+ rand::Rand
|
||||||
|
+ AsRef<[u64]>
|
||||||
|
+ AsMut<[u64]>
|
||||||
|
+ From<u64>
|
||||||
{
|
{
|
||||||
/// Subtract another reprensetation from this one, returning the borrow bit.
|
/// Subtract another represetation from this one.
|
||||||
fn sub_noborrow(&mut self, other: &Self) -> bool;
|
fn sub_noborrow(&mut self, other: &Self);
|
||||||
|
|
||||||
/// Add another representation to this one, returning the carry bit.
|
/// Add another representation to this one.
|
||||||
fn add_nocarry(&mut self, other: &Self) -> bool;
|
fn add_nocarry(&mut self, other: &Self);
|
||||||
|
|
||||||
/// Compute the number of bits needed to encode this number.
|
/// Compute the number of bits needed to encode this number. Always a
|
||||||
|
/// multiple of 64.
|
||||||
fn num_bits(&self) -> u32;
|
fn num_bits(&self) -> u32;
|
||||||
|
|
||||||
/// Returns true iff this number is zero.
|
/// Returns true iff this number is zero.
|
||||||
@@ -118,61 +126,179 @@ pub trait PrimeFieldRepr: Sized +
|
|||||||
/// it by 2.
|
/// it by 2.
|
||||||
fn div2(&mut self);
|
fn div2(&mut self);
|
||||||
|
|
||||||
|
/// Performs a rightwise bitshift of this number by some amount.
|
||||||
|
fn shr(&mut self, amt: u32);
|
||||||
|
|
||||||
/// Performs a leftwise bitshift of this number, effectively multiplying
|
/// Performs a leftwise bitshift of this number, effectively multiplying
|
||||||
/// it by 2. Overflow is ignored.
|
/// it by 2. Overflow is ignored.
|
||||||
fn mul2(&mut self);
|
fn mul2(&mut self);
|
||||||
|
|
||||||
|
/// Performs a leftwise bitshift of this number by some amount.
|
||||||
|
fn shl(&mut self, amt: u32);
|
||||||
|
|
||||||
|
/// Writes this `PrimeFieldRepr` as a big endian integer.
|
||||||
|
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
|
|
||||||
|
for digit in self.as_ref().iter().rev() {
|
||||||
|
writer.write_u64::<BigEndian>(*digit)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a big endian integer into this representation.
|
||||||
|
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
|
||||||
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
|
|
||||||
|
for digit in self.as_mut().iter_mut().rev() {
|
||||||
|
*digit = reader.read_u64::<BigEndian>()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes this `PrimeFieldRepr` as a little endian integer.
|
||||||
|
fn write_le<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
|
use byteorder::{LittleEndian, WriteBytesExt};
|
||||||
|
|
||||||
|
for digit in self.as_ref().iter() {
|
||||||
|
writer.write_u64::<LittleEndian>(*digit)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads a little endian integer into this representation.
|
||||||
|
fn read_le<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
|
||||||
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
|
|
||||||
|
for digit in self.as_mut().iter_mut() {
|
||||||
|
*digit = reader.read_u64::<LittleEndian>()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum LegendreSymbol {
|
||||||
|
Zero = 0,
|
||||||
|
QuadraticResidue = 1,
|
||||||
|
QuadraticNonResidue = -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a
|
||||||
|
/// `PrimeField` element.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PrimeFieldDecodingError {
|
||||||
|
/// The encoded value is not in the field
|
||||||
|
NotInField(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for PrimeFieldDecodingError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
PrimeFieldDecodingError::NotInField(..) => "not an element of the field",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PrimeFieldDecodingError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
match *self {
|
||||||
|
PrimeFieldDecodingError::NotInField(ref repr) => {
|
||||||
|
write!(f, "{} is not an element of the field", repr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This represents an element of a prime field.
|
/// This represents an element of a prime field.
|
||||||
pub trait PrimeField: Field
|
pub trait PrimeField: Field {
|
||||||
{
|
|
||||||
/// The prime field can be converted back and forth into this biginteger
|
/// The prime field can be converted back and forth into this biginteger
|
||||||
/// representation.
|
/// representation.
|
||||||
type Repr: PrimeFieldRepr;
|
type Repr: PrimeFieldRepr + From<Self>;
|
||||||
|
|
||||||
|
/// Interpret a string of numbers as a (congruent) prime field element.
|
||||||
|
/// Does not accept unnecessary leading zeroes or a blank string.
|
||||||
|
fn from_str(s: &str) -> Option<Self> {
|
||||||
|
if s.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if s == "0" {
|
||||||
|
return Some(Self::zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut res = Self::zero();
|
||||||
|
|
||||||
|
let ten = Self::from_repr(Self::Repr::from(10)).unwrap();
|
||||||
|
|
||||||
|
let mut first_digit = true;
|
||||||
|
|
||||||
|
for c in s.chars() {
|
||||||
|
match c.to_digit(10) {
|
||||||
|
Some(c) => {
|
||||||
|
if first_digit {
|
||||||
|
if c == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_digit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.mul_assign(&ten);
|
||||||
|
res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap());
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert this prime field element into a biginteger representation.
|
/// Convert this prime field element into a biginteger representation.
|
||||||
fn from_repr(Self::Repr) -> Result<Self, ()>;
|
fn from_repr(Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
|
||||||
|
|
||||||
/// Convert a biginteger reprensentation into a prime field element, if
|
/// Convert a biginteger representation into a prime field element, if
|
||||||
/// the number is an element of the field.
|
/// the number is an element of the field.
|
||||||
fn into_repr(&self) -> Self::Repr;
|
fn into_repr(&self) -> Self::Repr;
|
||||||
|
|
||||||
/// Returns the field characteristic; the modulus.
|
/// Returns the field characteristic; the modulus.
|
||||||
fn char() -> Self::Repr;
|
fn char() -> Self::Repr;
|
||||||
|
|
||||||
/// Returns how many bits are needed to represent an element of this
|
/// How many bits are needed to represent an element of this field.
|
||||||
/// field.
|
const NUM_BITS: u32;
|
||||||
fn num_bits() -> u32;
|
|
||||||
|
|
||||||
/// Returns how many bits of information can be reliably stored in the
|
/// How many bits of information can be reliably stored in the field element.
|
||||||
/// field element.
|
const CAPACITY: u32;
|
||||||
fn capacity() -> u32;
|
|
||||||
|
|
||||||
/// Returns the multiplicative generator of `char()` - 1 order. This element
|
/// Returns the multiplicative generator of `char()` - 1 order. This element
|
||||||
/// must also be quadratic nonresidue.
|
/// must also be quadratic nonresidue.
|
||||||
fn multiplicative_generator() -> Self;
|
fn multiplicative_generator() -> Self;
|
||||||
|
|
||||||
/// Returns s such that 2^s * t = `char()` - 1 with t odd.
|
/// 2^s * t = `char()` - 1 with t odd.
|
||||||
fn s() -> usize;
|
const S: u32;
|
||||||
|
|
||||||
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
|
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
|
||||||
/// by t.
|
/// by t.
|
||||||
fn root_of_unity() -> Self;
|
fn root_of_unity() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct BitIterator<E> {
|
pub struct BitIterator<E> {
|
||||||
t: E,
|
t: E,
|
||||||
n: usize
|
n: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: AsRef<[u64]>> BitIterator<E> {
|
impl<E: AsRef<[u64]>> BitIterator<E> {
|
||||||
fn new(t: E) -> Self {
|
pub fn new(t: E) -> Self {
|
||||||
let n = t.as_ref().len() * 64;
|
let n = t.as_ref().len() * 64;
|
||||||
|
|
||||||
BitIterator {
|
BitIterator { t, n }
|
||||||
t: t,
|
|
||||||
n: n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +331,12 @@ fn test_bit_iterator() {
|
|||||||
|
|
||||||
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
|
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
|
||||||
|
|
||||||
let mut a = BitIterator::new([0x429d5f3ac3a3b759, 0xb10f4c66768b1c92, 0x92368b6d16ecd3b4, 0xa57ea85ae8775219]);
|
let mut a = BitIterator::new([
|
||||||
|
0x429d5f3ac3a3b759,
|
||||||
|
0xb10f4c66768b1c92,
|
||||||
|
0x92368b6d16ecd3b4,
|
||||||
|
0xa57ea85ae8775219,
|
||||||
|
]);
|
||||||
|
|
||||||
for e in expected.chars() {
|
for e in expected.chars() {
|
||||||
assert!(a.next().unwrap() == (e == '1'));
|
assert!(a.next().unwrap() == (e == '1'));
|
||||||
@@ -214,35 +345,119 @@ fn test_bit_iterator() {
|
|||||||
assert!(a.next().is_none());
|
assert!(a.next().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a - b - borrow, returning the result and modifying
|
pub use self::arith_impl::*;
|
||||||
/// the borrow value.
|
|
||||||
#[inline(always)]
|
#[cfg(feature = "u128-support")]
|
||||||
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
|
mod arith_impl {
|
||||||
let tmp = (1u128 << 64) + (a as u128) - (b as u128) - (*borrow as u128);
|
/// Calculate a - b - borrow, returning the result and modifying
|
||||||
|
/// the borrow value.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
|
||||||
|
let tmp = (1u128 << 64) + u128::from(a) - u128::from(b) - u128::from(*borrow);
|
||||||
|
|
||||||
*borrow = if tmp >> 64 == 0 { 1 } else { 0 };
|
*borrow = if tmp >> 64 == 0 { 1 } else { 0 };
|
||||||
|
|
||||||
tmp as u64
|
tmp as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a + b + carry, returning the sum and modifying the
|
/// Calculate a + b + carry, returning the sum and modifying the
|
||||||
/// carry value.
|
/// carry value.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
|
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
|
||||||
let tmp = (a as u128) + (b as u128) + (*carry as u128);
|
let tmp = u128::from(a) + u128::from(b) + u128::from(*carry);
|
||||||
|
|
||||||
*carry = (tmp >> 64) as u64;
|
*carry = (tmp >> 64) as u64;
|
||||||
|
|
||||||
tmp as u64
|
tmp as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate a + (b * c) + carry, returning the least significant digit
|
/// Calculate a + (b * c) + carry, returning the least significant digit
|
||||||
/// and setting carry to the most significant digit.
|
/// and setting carry to the most significant digit.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
|
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
|
||||||
let tmp = (a as u128) + (b as u128) * (c as u128) + (*carry as u128);
|
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry);
|
||||||
|
|
||||||
*carry = (tmp >> 64) as u64;
|
*carry = (tmp >> 64) as u64;
|
||||||
|
|
||||||
tmp as u64
|
tmp as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "u128-support"))]
|
||||||
|
mod arith_impl {
|
||||||
|
#[inline(always)]
|
||||||
|
fn split_u64(i: u64) -> (u64, u64) {
|
||||||
|
(i >> 32, i & 0xFFFFFFFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn combine_u64(hi: u64, lo: u64) -> u64 {
|
||||||
|
(hi << 32) | lo
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate a - b - borrow, returning the result and modifying
|
||||||
|
/// the borrow value.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
|
||||||
|
let (a_hi, a_lo) = split_u64(a);
|
||||||
|
let (b_hi, b_lo) = split_u64(b);
|
||||||
|
let (b, r0) = split_u64((1 << 32) + a_lo - b_lo - *borrow);
|
||||||
|
let (b, r1) = split_u64((1 << 32) + a_hi - b_hi - ((b == 0) as u64));
|
||||||
|
|
||||||
|
*borrow = (b == 0) as u64;
|
||||||
|
|
||||||
|
combine_u64(r1, r0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate a + b + carry, returning the sum and modifying the
|
||||||
|
/// carry value.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 {
|
||||||
|
let (a_hi, a_lo) = split_u64(a);
|
||||||
|
let (b_hi, b_lo) = split_u64(b);
|
||||||
|
let (carry_hi, carry_lo) = split_u64(*carry);
|
||||||
|
|
||||||
|
let (t, r0) = split_u64(a_lo + b_lo + carry_lo);
|
||||||
|
let (t, r1) = split_u64(t + a_hi + b_hi + carry_hi);
|
||||||
|
|
||||||
|
*carry = t;
|
||||||
|
|
||||||
|
combine_u64(r1, r0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculate a + (b * c) + carry, returning the least significant digit
|
||||||
|
/// and setting carry to the most significant digit.
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 {
|
||||||
|
/*
|
||||||
|
[ b_hi | b_lo ]
|
||||||
|
[ c_hi | c_lo ] *
|
||||||
|
-------------------------------------------
|
||||||
|
[ b_lo * c_lo ] <-- w
|
||||||
|
[ b_hi * c_lo ] <-- x
|
||||||
|
[ b_lo * c_hi ] <-- y
|
||||||
|
[ b_hi * c_lo ] <-- z
|
||||||
|
[ a_hi | a_lo ]
|
||||||
|
[ C_hi | C_lo ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
let (a_hi, a_lo) = split_u64(a);
|
||||||
|
let (b_hi, b_lo) = split_u64(b);
|
||||||
|
let (c_hi, c_lo) = split_u64(c);
|
||||||
|
let (carry_hi, carry_lo) = split_u64(*carry);
|
||||||
|
|
||||||
|
let (w_hi, w_lo) = split_u64(b_lo * c_lo);
|
||||||
|
let (x_hi, x_lo) = split_u64(b_hi * c_lo);
|
||||||
|
let (y_hi, y_lo) = split_u64(b_lo * c_hi);
|
||||||
|
let (z_hi, z_lo) = split_u64(b_hi * c_hi);
|
||||||
|
|
||||||
|
let (t, r0) = split_u64(w_lo + a_lo + carry_lo);
|
||||||
|
let (t, r1) = split_u64(t + w_hi + x_lo + y_lo + a_hi + carry_hi);
|
||||||
|
let (t, r2) = split_u64(t + x_hi + y_hi + z_lo);
|
||||||
|
let (_, r3) = split_u64(t + z_hi);
|
||||||
|
|
||||||
|
*carry = combine_u64(r3, r2);
|
||||||
|
|
||||||
|
combine_u64(r1, r0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user