Merge pull request #1 from str4d/updates

Update dependencies and traits
This commit is contained in:
ebfull
2018-07-02 08:28:36 -06:00
committed by GitHub
4 changed files with 673 additions and 345 deletions

View File

@@ -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 = []

View File

@@ -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"

File diff suppressed because it is too large Load Diff

View File

@@ -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) {
res.square(); if found_one {
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)]
pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
let tmp = (1u128 << 64) + (a as u128) - (b as u128) - (*borrow as u128);
*borrow = if tmp >> 64 == 0 { 1 } else { 0 }; #[cfg(feature = "u128-support")]
mod arith_impl {
/// 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);
tmp as u64 *borrow = if tmp >> 64 == 0 { 1 } else { 0 };
tmp as u64
}
/// 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 tmp = u128::from(a) + u128::from(b) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
/// 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 {
let tmp = (u128::from(a)) + u128::from(b) * u128::from(c) + u128::from(*carry);
*carry = (tmp >> 64) as u64;
tmp as u64
}
} }
/// Calculate a + b + carry, returning the sum and modifying the #[cfg(not(feature = "u128-support"))]
/// carry value. mod arith_impl {
#[inline(always)] #[inline(always)]
pub fn adc(a: u64, b: u64, carry: &mut u64) -> u64 { fn split_u64(i: u64) -> (u64, u64) {
let tmp = (a as u128) + (b as u128) + (*carry as u128); (i >> 32, i & 0xFFFFFFFF)
}
*carry = (tmp >> 64) as u64; #[inline(always)]
fn combine_u64(hi: u64, lo: u64) -> u64 {
(hi << 32) | lo
}
tmp as u64 /// Calculate a - b - borrow, returning the result and modifying
} /// the borrow value.
#[inline(always)]
/// Calculate a + (b * c) + carry, returning the least significant digit pub fn sbb(a: u64, b: u64, borrow: &mut u64) -> u64 {
/// and setting carry to the most significant digit. let (a_hi, a_lo) = split_u64(a);
#[inline(always)] let (b_hi, b_lo) = split_u64(b);
pub fn mac_with_carry(a: u64, b: u64, c: u64, carry: &mut u64) -> u64 { let (b, r0) = split_u64((1 << 32) + a_lo - b_lo - *borrow);
let tmp = (a as u128) + (b as u128) * (c as u128) + (*carry as u128); let (b, r1) = split_u64((1 << 32) + a_hi - b_hi - ((b == 0) as u64));
*carry = (tmp >> 64) as u64; *borrow = (b == 0) as u64;
tmp 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)
}
} }