mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-02-07 14:54:10 +00:00
Add auto-derivation of prime fields, and modify the traits a little bit.
This commit is contained in:
parent
e97f0df3df
commit
13a822f994
@ -1,20 +1,22 @@
|
|||||||
|
#![recursion_limit="1024"]
|
||||||
|
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
//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_traits;
|
||||||
|
|
||||||
//use num_traits::{Zero, One, ToPrimitive};
|
use num_traits::{Zero, One, ToPrimitive};
|
||||||
//use num_bigint::BigUint;
|
use num_bigint::BigUint;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus))]
|
#[proc_macro_derive(PrimeField, attributes(PrimeFieldModulus))]
|
||||||
pub fn prime_field(
|
pub fn prime_field(
|
||||||
_: proc_macro::TokenStream
|
input: proc_macro::TokenStream
|
||||||
) -> proc_macro::TokenStream
|
) -> proc_macro::TokenStream
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// Construct a string representation of the type definition
|
// Construct a string representation of the type definition
|
||||||
let s = input.to_string();
|
let s = input.to_string();
|
||||||
|
|
||||||
@ -32,7 +34,6 @@ pub fn prime_field(
|
|||||||
|
|
||||||
// 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.
|
||||||
|
|
||||||
let mut limbs = 1;
|
let mut limbs = 1;
|
||||||
{
|
{
|
||||||
let mod2 = (&modulus) << 1; // modulus * 2
|
let mod2 = (&modulus) << 1; // modulus * 2
|
||||||
@ -42,20 +43,18 @@ pub fn prime_field(
|
|||||||
cur = cur << 64;
|
cur = cur << 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
let gen = quote::Tokens::new();
|
let mut gen = quote::Tokens::new();
|
||||||
|
|
||||||
//gen.append(prime_field_repr_impl(&repr_ident, limbs));
|
gen.append(prime_field_repr_impl(&repr_ident, limbs));
|
||||||
//gen.append(prime_field_constants(&repr_ident, modulus, limbs));
|
gen.append(prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs));
|
||||||
//gen.append(prime_field_impl(&ast.ident, &repr_ident));
|
gen.append(prime_field_impl(&ast.ident, &repr_ident, limbs));
|
||||||
//gen.append(prime_field_arith_impl(&ast.ident, &repr_ident, limbs));
|
//gen.append(prime_field_arith_impl(&ast.ident, &repr_ident, limbs));
|
||||||
|
|
||||||
// Return the generated impl
|
// Return the generated impl
|
||||||
gen.parse().unwrap()
|
gen.parse().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
fn fetch_wrapped_ident(
|
fn fetch_wrapped_ident(
|
||||||
body: &syn::Body
|
body: &syn::Body
|
||||||
) -> Option<syn::Ident>
|
) -> Option<syn::Ident>
|
||||||
@ -108,4 +107,610 @@ fn fetch_attr(
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
fn prime_field_repr_impl(
|
||||||
|
repr: &syn::Ident,
|
||||||
|
limbs: usize
|
||||||
|
) -> quote::Tokens
|
||||||
|
{
|
||||||
|
quote! {
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct #repr(pub [u64; #limbs]);
|
||||||
|
|
||||||
|
impl ::rand::Rand for #repr {
|
||||||
|
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
||||||
|
#repr(rng.gen())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 AsRef<[u64]> for #repr {
|
||||||
|
fn as_ref(&self) -> &[u64] {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u64> for #repr {
|
||||||
|
#[inline(always)]
|
||||||
|
fn from(val: u64) -> #repr {
|
||||||
|
use std::default::Default;
|
||||||
|
|
||||||
|
let mut repr = Self::default();
|
||||||
|
repr.0[0] = val;
|
||||||
|
repr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for #repr {
|
||||||
|
fn cmp(&self, other: &#repr) -> ::std::cmp::Ordering {
|
||||||
|
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
|
||||||
|
if a < b {
|
||||||
|
return ::std::cmp::Ordering::Less
|
||||||
|
} else if a > b {
|
||||||
|
return ::std::cmp::Ordering::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::std::cmp::Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for #repr {
|
||||||
|
fn partial_cmp(&self, other: &#repr) -> Option<::std::cmp::Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::ff::PrimeFieldRepr for #repr {
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_odd(&self) -> bool {
|
||||||
|
self.0[0] & 1 == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_even(&self) -> bool {
|
||||||
|
!self.is_odd()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0.iter().all(|&e| e == 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn div2(&mut self) {
|
||||||
|
let mut t = 0;
|
||||||
|
for i in self.0.iter_mut().rev() {
|
||||||
|
let t2 = *i << 63;
|
||||||
|
*i >>= 1;
|
||||||
|
*i |= t;
|
||||||
|
t = t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mul2(&mut self) {
|
||||||
|
let mut last = 0;
|
||||||
|
for i in self.0.iter_mut() {
|
||||||
|
let tmp = *i >> 63;
|
||||||
|
*i <<= 1;
|
||||||
|
*i |= last;
|
||||||
|
last = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn num_bits(&self) -> u32 {
|
||||||
|
let mut ret = (#limbs as u32) * 64;
|
||||||
|
for i in self.0.iter().rev() {
|
||||||
|
let leading = i.leading_zeros();
|
||||||
|
ret -= leading;
|
||||||
|
if leading != 64 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn add_nocarry(&mut self, other: &#repr) -> bool {
|
||||||
|
let mut carry = 0;
|
||||||
|
|
||||||
|
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
||||||
|
*a = ::ff::adc(*a, *b, &mut carry);
|
||||||
|
}
|
||||||
|
|
||||||
|
carry != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn sub_noborrow(&mut self, other: &#repr) -> bool {
|
||||||
|
let mut borrow = 0;
|
||||||
|
|
||||||
|
for (a, b) in self.0.iter_mut().zip(other.0.iter()) {
|
||||||
|
*a = ::ff::sbb(*a, *b, &mut borrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
borrow != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn biguint_to_u64_vec(
|
||||||
|
mut v: BigUint
|
||||||
|
) -> Vec<u64>
|
||||||
|
{
|
||||||
|
let m = BigUint::one() << 64;
|
||||||
|
let mut ret = vec![];
|
||||||
|
|
||||||
|
while v > BigUint::zero() {
|
||||||
|
ret.push((&v % &m).to_u64().unwrap());
|
||||||
|
v = v >> 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn biguint_num_bits(
|
||||||
|
mut v: BigUint
|
||||||
|
) -> u32
|
||||||
|
{
|
||||||
|
let mut bits = 0;
|
||||||
|
|
||||||
|
while v != BigUint::zero() {
|
||||||
|
v = v >> 1;
|
||||||
|
bits += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prime_field_constants_and_sqrt(
|
||||||
|
name: &syn::Ident,
|
||||||
|
repr: &syn::Ident,
|
||||||
|
modulus: BigUint,
|
||||||
|
limbs: usize
|
||||||
|
) -> quote::Tokens
|
||||||
|
{
|
||||||
|
let modulus_num_bits = biguint_num_bits(modulus.clone());
|
||||||
|
let repr_shave_bits = (64 * limbs as u32) - biguint_num_bits(modulus.clone());
|
||||||
|
|
||||||
|
// Compute R = 2**(64 * limbs) mod m
|
||||||
|
let r = (BigUint::one() << (limbs * 64)) % &modulus;
|
||||||
|
|
||||||
|
let sqrt_impl =
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Compute -R as (m - r)
|
||||||
|
let rneg = biguint_to_u64_vec(&modulus - &r);
|
||||||
|
|
||||||
|
quote!{
|
||||||
|
impl ::ff::SqrtField for #name {
|
||||||
|
fn sqrt(&self) -> Option<Self> {
|
||||||
|
// Shank's algorithm for q mod 4 = 3
|
||||||
|
// https://eprint.iacr.org/2012/685.pdf (page 9, algorithm 2)
|
||||||
|
|
||||||
|
let mut a1 = self.pow(#mod_minus_3_over_4);
|
||||||
|
|
||||||
|
let mut a0 = a1;
|
||||||
|
a0.square();
|
||||||
|
a0.mul_assign(self);
|
||||||
|
|
||||||
|
if a0.0 == #repr(#rneg) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
a1.mul_assign(self);
|
||||||
|
Some(a1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote!{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute R^2 mod m
|
||||||
|
let r2 = biguint_to_u64_vec((&r * &r) % &modulus);
|
||||||
|
|
||||||
|
let r = biguint_to_u64_vec(r);
|
||||||
|
let modulus = biguint_to_u64_vec(modulus);
|
||||||
|
|
||||||
|
// Compute -m^-1 mod 2**64 by exponentiating by totient(2**64) - 1
|
||||||
|
let mut inv = 1u64;
|
||||||
|
for _ in 0..63 {
|
||||||
|
inv = inv.wrapping_mul(inv);
|
||||||
|
inv = inv.wrapping_mul(modulus[0]);
|
||||||
|
}
|
||||||
|
inv = inv.wrapping_neg();
|
||||||
|
|
||||||
|
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 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*2} mod m
|
||||||
|
const R2: #repr = #repr(#r2);
|
||||||
|
|
||||||
|
/// -(m^{-1} mod m) mod m
|
||||||
|
const INV: u64 = #inv;
|
||||||
|
|
||||||
|
#sqrt_impl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prime_field_impl(
|
||||||
|
name: &syn::Ident,
|
||||||
|
repr: &syn::Ident,
|
||||||
|
limbs: usize
|
||||||
|
) -> quote::Tokens
|
||||||
|
{
|
||||||
|
fn get_temp(n: usize) -> syn::Ident {
|
||||||
|
syn::Ident::from(format!("r{}", n))
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mont_paramlist = quote::Tokens::new();
|
||||||
|
mont_paramlist.append_separated(
|
||||||
|
(0..(limbs*2)).map(|i| (i, get_temp(i)))
|
||||||
|
.map(|(i, x)| {
|
||||||
|
if i != 0 {
|
||||||
|
quote!{mut #x: u64}
|
||||||
|
} else {
|
||||||
|
quote!{#x: u64}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
","
|
||||||
|
); // r0: u64, mut r1: u64, mut r2: u64, ...
|
||||||
|
|
||||||
|
let mut mont_impl = quote::Tokens::new();
|
||||||
|
for i in 0..limbs {
|
||||||
|
{
|
||||||
|
let temp = get_temp(i);
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
let k = #temp.wrapping_mul(INV);
|
||||||
|
let mut carry = 0;
|
||||||
|
::ff::mac_with_carry(#temp, k, MODULUS.0[0], &mut carry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for j in 1..limbs {
|
||||||
|
let temp = get_temp(i + j);
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
#temp = ::ff::mac_with_carry(#temp, k, MODULUS.0[#j], &mut carry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
#temp = ::ff::adc(#temp, 0, &mut carry);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
#temp = ::ff::adc(#temp, carry2, &mut carry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if i != (limbs - 1) {
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
let carry2 = carry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..limbs {
|
||||||
|
let temp = get_temp(limbs + i);
|
||||||
|
|
||||||
|
mont_impl.append(quote!{
|
||||||
|
(self.0).0[#i] = #temp;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mul_impl(a: quote::Tokens, b: quote::Tokens, limbs: usize) -> quote::Tokens
|
||||||
|
{
|
||||||
|
let mut gen = quote::Tokens::new();
|
||||||
|
|
||||||
|
for i in 0..limbs {
|
||||||
|
gen.append(quote!{
|
||||||
|
let mut carry = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for j in 0..limbs {
|
||||||
|
let temp = get_temp(i + j);
|
||||||
|
|
||||||
|
if i == 0 {
|
||||||
|
gen.append(quote!{
|
||||||
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
gen.append(quote!{
|
||||||
|
let #temp = ::ff::mac_with_carry(#temp, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
|
gen.append(quote!{
|
||||||
|
let #temp = carry;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut mont_calling = quote::Tokens::new();
|
||||||
|
mont_calling.append_separated((0..(limbs*2)).map(|i| get_temp(i)), ",");
|
||||||
|
|
||||||
|
gen.append(quote!{
|
||||||
|
self.mont_reduce(#mont_calling);
|
||||||
|
});
|
||||||
|
|
||||||
|
gen
|
||||||
|
}
|
||||||
|
|
||||||
|
let squaring_impl = mul_impl(quote!{self}, quote!{self}, limbs);
|
||||||
|
let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs);
|
||||||
|
|
||||||
|
let mut into_repr_params = quote::Tokens::new();
|
||||||
|
into_repr_params.append_separated(
|
||||||
|
(0..limbs).map(|i| quote!{ (self.0).0[#i] })
|
||||||
|
.chain((0..limbs).map(|_| quote!{0})),
|
||||||
|
","
|
||||||
|
);
|
||||||
|
|
||||||
|
quote!{
|
||||||
|
impl Copy for #name { }
|
||||||
|
|
||||||
|
impl Clone for #name {
|
||||||
|
fn clone(&self) -> #name {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for #name {
|
||||||
|
fn eq(&self, other: &#name) -> bool {
|
||||||
|
self.0 == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for #name { }
|
||||||
|
|
||||||
|
impl ::std::fmt::Debug for #name
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||||
|
write!(f, "{}({:?})", stringify!(#name), self.into_repr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rand for #name {
|
||||||
|
/// Computes a uniformly random element using rejection sampling.
|
||||||
|
fn rand<R: Rng>(rng: &mut R) -> Self {
|
||||||
|
loop {
|
||||||
|
let mut tmp = #name(#repr::rand(rng));
|
||||||
|
for _ in 0..REPR_SHAVE_BITS {
|
||||||
|
tmp.0.div2();
|
||||||
|
}
|
||||||
|
if tmp.is_valid() {
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::ff::PrimeField for #name {
|
||||||
|
type Repr = #repr;
|
||||||
|
|
||||||
|
fn from_repr(r: #repr) -> Result<#name, ()> {
|
||||||
|
let mut r = #name(r);
|
||||||
|
if r.is_valid() {
|
||||||
|
r.mul_assign(&#name(R2));
|
||||||
|
|
||||||
|
Ok(r)
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_repr(&self) -> #repr {
|
||||||
|
let mut r = *self;
|
||||||
|
r.mont_reduce(
|
||||||
|
#into_repr_params
|
||||||
|
);
|
||||||
|
|
||||||
|
r.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char() -> #repr {
|
||||||
|
MODULUS
|
||||||
|
}
|
||||||
|
|
||||||
|
fn num_bits() -> u32 {
|
||||||
|
MODULUS_BITS
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capacity() -> u32 {
|
||||||
|
Self::num_bits() - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::ff::Field for #name {
|
||||||
|
#[inline]
|
||||||
|
fn zero() -> Self {
|
||||||
|
#name(#repr::from(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn one() -> Self {
|
||||||
|
#name(R)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_zero(&self) -> bool {
|
||||||
|
self.0.is_zero()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: &#name) {
|
||||||
|
// This cannot exceed the backing capacity.
|
||||||
|
self.0.add_nocarry(&other.0);
|
||||||
|
|
||||||
|
// However, it may need to be reduced.
|
||||||
|
self.reduce();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn double(&mut self) {
|
||||||
|
// This cannot exceed the backing capacity.
|
||||||
|
self.0.mul2();
|
||||||
|
|
||||||
|
// However, it may need to be reduced.
|
||||||
|
self.reduce();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, other: &#name) {
|
||||||
|
// If `other` is larger than `self`, we'll need to add the modulus to self first.
|
||||||
|
if other.0 > self.0 {
|
||||||
|
self.0.add_nocarry(&MODULUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.0.sub_noborrow(&other.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn negate(&mut self) {
|
||||||
|
if !self.is_zero() {
|
||||||
|
let mut tmp = MODULUS;
|
||||||
|
tmp.sub_noborrow(&self.0);
|
||||||
|
self.0 = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inverse(&self) -> Option<Self> {
|
||||||
|
if self.is_zero() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
// Guajardo Kumar Paar Pelzl
|
||||||
|
// Efficient Software-Implementation of Finite Fields with Applications to Cryptography
|
||||||
|
// Algorithm 16 (BEA for Inversion in Fp)
|
||||||
|
|
||||||
|
let one = #repr::from(1);
|
||||||
|
|
||||||
|
let mut u = self.0;
|
||||||
|
let mut v = MODULUS;
|
||||||
|
let mut b = #name(R2); // Avoids unnecessary reduction step.
|
||||||
|
let mut c = Self::zero();
|
||||||
|
|
||||||
|
while u != one && v != one {
|
||||||
|
while u.is_even() {
|
||||||
|
u.div2();
|
||||||
|
|
||||||
|
if b.0.is_even() {
|
||||||
|
b.0.div2();
|
||||||
|
} else {
|
||||||
|
b.0.add_nocarry(&MODULUS);
|
||||||
|
b.0.div2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while v.is_even() {
|
||||||
|
v.div2();
|
||||||
|
|
||||||
|
if c.0.is_even() {
|
||||||
|
c.0.div2();
|
||||||
|
} else {
|
||||||
|
c.0.add_nocarry(&MODULUS);
|
||||||
|
c.0.div2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < u {
|
||||||
|
u.sub_noborrow(&v);
|
||||||
|
b.sub_assign(&c);
|
||||||
|
} else {
|
||||||
|
v.sub_noborrow(&u);
|
||||||
|
c.sub_assign(&b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if u == one {
|
||||||
|
Some(b)
|
||||||
|
} else {
|
||||||
|
Some(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn frobenius_map(&mut self, _: usize) {
|
||||||
|
// This has no effect in a prime field.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, other: &#name)
|
||||||
|
{
|
||||||
|
#multiply_impl
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn square(&mut self)
|
||||||
|
{
|
||||||
|
#squaring_impl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #name {
|
||||||
|
/// Determines if the element is really in the field. This is only used
|
||||||
|
/// internally.
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_valid(&self) -> bool {
|
||||||
|
self.0 < MODULUS
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subtracts the modulus from this element if this element is not in the
|
||||||
|
/// field. Only used interally.
|
||||||
|
#[inline(always)]
|
||||||
|
fn reduce(&mut self) {
|
||||||
|
if !self.is_valid() {
|
||||||
|
self.0.sub_noborrow(&MODULUS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn mont_reduce(
|
||||||
|
&mut self,
|
||||||
|
#mont_paramlist
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// The Montgomery reduction here is based on Algorithm 14.32 in
|
||||||
|
// Handbook of Applied Cryptography
|
||||||
|
// <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
|
||||||
|
|
||||||
|
#mont_impl
|
||||||
|
|
||||||
|
self.reduce();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
26
src/lib.rs
26
src/lib.rs
@ -1,11 +1,12 @@
|
|||||||
#![feature(i128_type)]
|
#![feature(i128_type)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
|
||||||
//#[macro_use]
|
#[macro_use]
|
||||||
//extern crate ff_derive;
|
extern crate ff_derive;
|
||||||
|
|
||||||
//pub use ff_derive::*;
|
pub use ff_derive::*;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@ -50,7 +51,8 @@ pub trait Field: Sized +
|
|||||||
/// Computes the multiplicative inverse of this element, if nonzero.
|
/// Computes the multiplicative inverse of this element, if nonzero.
|
||||||
fn inverse(&self) -> Option<Self>;
|
fn inverse(&self) -> Option<Self>;
|
||||||
|
|
||||||
/// Exponentiates this element by a power of the modulus.
|
/// Exponentiates this element by a power of the base prime modulus via
|
||||||
|
/// the Frobenius automorphism.
|
||||||
fn frobenius_map(&mut self, power: usize);
|
fn frobenius_map(&mut self, power: usize);
|
||||||
|
|
||||||
/// Exponentiates this element by a number represented with `u64` limbs,
|
/// Exponentiates this element by a number represented with `u64` limbs,
|
||||||
@ -94,14 +96,14 @@ pub trait PrimeFieldRepr: Sized +
|
|||||||
AsRef<[u64]> +
|
AsRef<[u64]> +
|
||||||
From<u64>
|
From<u64>
|
||||||
{
|
{
|
||||||
/// Subtract another reprensetation from this one. Underflow is ignored.
|
/// Subtract another reprensetation from this one, returning the borrow bit.
|
||||||
fn sub_noborrow(&mut self, other: &Self);
|
fn sub_noborrow(&mut self, other: &Self) -> bool;
|
||||||
|
|
||||||
/// Add another representation to this one. Overflow is ignored.
|
/// Add another representation to this one, returning the carry bit.
|
||||||
fn add_nocarry(&mut self, other: &Self);
|
fn add_nocarry(&mut self, other: &Self) -> bool;
|
||||||
|
|
||||||
/// Compute the number of bits needed to encode this number.
|
/// Compute the number of bits needed to encode this number.
|
||||||
fn num_bits(&self) -> usize;
|
fn num_bits(&self) -> u32;
|
||||||
|
|
||||||
/// Returns true iff this number is zero.
|
/// Returns true iff this number is zero.
|
||||||
fn is_zero(&self) -> bool;
|
fn is_zero(&self) -> bool;
|
||||||
@ -122,7 +124,7 @@ pub trait PrimeFieldRepr: Sized +
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This represents an element of a prime field.
|
/// This represents an element of a prime field.
|
||||||
pub trait PrimeField: SqrtField
|
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.
|
||||||
@ -140,11 +142,11 @@ pub trait PrimeField: SqrtField
|
|||||||
|
|
||||||
/// Returns how many bits are needed to represent an element of this
|
/// Returns how many bits are needed to represent an element of this
|
||||||
/// field.
|
/// field.
|
||||||
fn num_bits() -> usize;
|
fn num_bits() -> u32;
|
||||||
|
|
||||||
/// Returns how many bits of information can be reliably stored in the
|
/// Returns how many bits of information can be reliably stored in the
|
||||||
/// field element.
|
/// field element.
|
||||||
fn capacity() -> usize;
|
fn capacity() -> u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BitIterator<E> {
|
pub struct BitIterator<E> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user