mirror of
https://github.com/Qortal/pirate-librustzcash.git
synced 2025-07-31 12:31:22 +00:00
Squashed 'ff/' changes from 661558e..ddff465
ddff465 Bump version and dependency on ff_derive 25d11d6 Bump version 95e2723 Bump version to 0.5.1 f76872a Add ?Sized to RngCore trait bounds (#14) 09a32b1 ff 0.5.0 32543ab Crate docs 22031dc Update READMEs 658fe6d CI: Check intra-doc links 35f5026 Add READMEs to Cargo.toml files 6804225 Migrate ff_derive to proc-macro2 1.0 b9a79ce cargo fmt 82574c2 cargo fix --edition-idioms for ff 3b0cf72 Add edition = 2018 8a2b51b Replace try! macro 40fc9ba cargo fix --edition for ff 22c67f3 cargo fmt 312141c Clarify masking of bits in Field::random impls 89a68e1 Migrate to rand 0.7 58415fb Migrate ff, group, pairing, and bellman to rand 0.6 8b6e6b1 Migrate ff to rand_core 0.3 (used by rand 0.5) git-subtree-dir: ff git-subtree-split: ddff4658ddd7496bb29cc636c391b7aaaca24673
This commit is contained in:
11
Cargo.toml
11
Cargo.toml
@@ -1,18 +1,23 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ff"
|
name = "ff"
|
||||||
version = "0.4.0"
|
version = "0.5.2"
|
||||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||||
description = "Library for building and interfacing with finite fields"
|
description = "Library for building and interfacing with finite fields"
|
||||||
|
readme = "README.md"
|
||||||
documentation = "https://docs.rs/ff/"
|
documentation = "https://docs.rs/ff/"
|
||||||
homepage = "https://github.com/ebfull/ff"
|
homepage = "https://github.com/ebfull/ff"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
repository = "https://github.com/ebfull/ff"
|
repository = "https://github.com/ebfull/ff"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
rand = "0.4"
|
ff_derive = { version = "^0.4.1", path = "ff_derive", optional = true }
|
||||||
ff_derive = { version = "0.3.0", path = "ff_derive", optional = true }
|
rand_core = "0.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
derive = ["ff_derive"]
|
derive = ["ff_derive"]
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "actively-developed" }
|
||||||
|
17
README.md
17
README.md
@@ -12,14 +12,18 @@ Add the `ff` crate to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ff = "0.4"
|
ff = "0.5"
|
||||||
```
|
```
|
||||||
|
|
||||||
The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits. See the **[documentation](https://docs.rs/ff/0.4.0/ff/)** for more.
|
The `ff` crate contains `Field`, `PrimeField`, `PrimeFieldRepr` and `SqrtField` traits.
|
||||||
|
See the **[documentation](https://docs.rs/ff/)** for more.
|
||||||
|
|
||||||
### #![derive(PrimeField)]
|
### #![derive(PrimeField)]
|
||||||
|
|
||||||
If you need an implementation of a prime field, this library also provides a procedural macro that will expand into an efficient implementation of a prime field when supplied with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is also quadratic nonresidue.
|
If you need an implementation of a prime field, this library also provides a procedural
|
||||||
|
macro that will expand into an efficient implementation of a prime field when supplied
|
||||||
|
with the modulus. `PrimeFieldGenerator` must be an element of Fp of p-1 order, that is
|
||||||
|
also quadratic nonresidue.
|
||||||
|
|
||||||
First, enable the `derive` crate feature:
|
First, enable the `derive` crate feature:
|
||||||
|
|
||||||
@@ -41,13 +45,16 @@ extern crate ff;
|
|||||||
struct Fp(FpRepr);
|
struct Fp(FpRepr);
|
||||||
```
|
```
|
||||||
|
|
||||||
And that's it! `Fp` now implements `Field` and `PrimeField`. `Fp` will also implement `SqrtField` if supported. The library implements `FpRepr` itself and derives `PrimeFieldRepr` for it.
|
And that's it! `Fp` now implements `Field` and `PrimeField`. `Fp` will also implement
|
||||||
|
`SqrtField` if supported. The library implements `FpRepr` itself and derives
|
||||||
|
`PrimeFieldRepr` for it.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Licensed under either of
|
Licensed under either of
|
||||||
|
|
||||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
at your option.
|
at your option.
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ff_derive"
|
name = "ff_derive"
|
||||||
version = "0.3.0"
|
version = "0.4.1"
|
||||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||||
description = "Procedural macro library used to build custom prime field implementations"
|
description = "Procedural macro library used to build custom prime field implementations"
|
||||||
documentation = "https://docs.rs/ff/"
|
documentation = "https://docs.rs/ff/"
|
||||||
homepage = "https://github.com/ebfull/ff"
|
homepage = "https://github.com/ebfull/ff"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
repository = "https://github.com/ebfull/ff"
|
repository = "https://github.com/ebfull/ff"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
@@ -15,6 +16,9 @@ proc-macro = true
|
|||||||
num-bigint = "0.2"
|
num-bigint = "0.2"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-integer = "0.1"
|
num-integer = "0.1"
|
||||||
proc-macro2 = "0.4"
|
proc-macro2 = "1"
|
||||||
quote = "0.6"
|
quote = "1"
|
||||||
syn = "0.14"
|
syn = "1"
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "passively-maintained" }
|
||||||
|
@@ -52,13 +52,8 @@ pub fn prime_field(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
|
|
||||||
let mut gen = proc_macro2::TokenStream::new();
|
let mut gen = proc_macro2::TokenStream::new();
|
||||||
|
|
||||||
let (constants_impl, sqrt_impl) = prime_field_constants_and_sqrt(
|
let (constants_impl, sqrt_impl) =
|
||||||
&ast.ident,
|
prime_field_constants_and_sqrt(&ast.ident, &repr_ident, modulus, limbs, generator);
|
||||||
&repr_ident,
|
|
||||||
modulus,
|
|
||||||
limbs,
|
|
||||||
generator,
|
|
||||||
);
|
|
||||||
|
|
||||||
gen.extend(constants_impl);
|
gen.extend(constants_impl);
|
||||||
gen.extend(prime_field_repr_impl(&repr_ident, limbs));
|
gen.extend(prime_field_repr_impl(&repr_ident, limbs));
|
||||||
@@ -96,10 +91,10 @@ fn fetch_wrapped_ident(body: &syn::Data) -> Option<syn::Ident> {
|
|||||||
/// Fetch an attribute string from the derived struct.
|
/// Fetch an attribute string from the derived struct.
|
||||||
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
|
fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if let Some(meta) = attr.interpret_meta() {
|
if let Ok(meta) = attr.parse_meta() {
|
||||||
match meta {
|
match meta {
|
||||||
syn::Meta::NameValue(nv) => {
|
syn::Meta::NameValue(nv) => {
|
||||||
if nv.ident.to_string() == name {
|
if nv.path.get_ident().map(|i| i.to_string()) == Some(name.to_string()) {
|
||||||
match nv.lit {
|
match nv.lit {
|
||||||
syn::Lit::Str(ref s) => return Some(s.value()),
|
syn::Lit::Str(ref s) => return Some(s.value()),
|
||||||
_ => {
|
_ => {
|
||||||
@@ -127,27 +122,20 @@ fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenS
|
|||||||
impl ::std::fmt::Debug for #repr
|
impl ::std::fmt::Debug 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"));
|
write!(f, "0x")?;
|
||||||
for i in self.0.iter().rev() {
|
for i in self.0.iter().rev() {
|
||||||
try!(write!(f, "{:016x}", *i));
|
write!(f, "{:016x}", *i)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::rand::Rand for #repr {
|
|
||||||
#[inline(always)]
|
|
||||||
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
|
||||||
#repr(rng.gen())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::fmt::Display 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"));
|
write!(f, "0x")?;
|
||||||
for i in self.0.iter().rev() {
|
for i in self.0.iter().rev() {
|
||||||
try!(write!(f, "{:016x}", *i));
|
write!(f, "{:016x}", *i)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -366,7 +354,8 @@ fn biguint_num_bits(mut v: BigUint) -> u32 {
|
|||||||
fn exp(base: BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
fn exp(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()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd()))
|
.flat_map(|x| (0..8).rev().map(move |i| (x >> i).is_odd()))
|
||||||
{
|
{
|
||||||
@@ -387,11 +376,13 @@ fn test_exp() {
|
|||||||
&BigUint::from_str("5489673498567349856734895").unwrap(),
|
&BigUint::from_str("5489673498567349856734895").unwrap(),
|
||||||
&BigUint::from_str(
|
&BigUint::from_str(
|
||||||
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
|
"52435875175126190479447740508185965837690552500527637822603658699938581184513"
|
||||||
).unwrap()
|
)
|
||||||
|
.unwrap()
|
||||||
),
|
),
|
||||||
BigUint::from_str(
|
BigUint::from_str(
|
||||||
"4371221214068404307866768905142520595925044802278091865033317963560480051536"
|
"4371221214068404307866768905142520595925044802278091865033317963560480051536"
|
||||||
).unwrap()
|
)
|
||||||
|
.unwrap()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +421,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
|
|
||||||
let mod_minus_1_over_2 =
|
let mod_minus_1_over_2 =
|
||||||
biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
|
biguint_to_u64_vec((&modulus - BigUint::from_str("1").unwrap()) >> 1, limbs);
|
||||||
let legendre_impl = quote!{
|
let legendre_impl = quote! {
|
||||||
fn legendre(&self) -> ::ff::LegendreSymbol {
|
fn legendre(&self) -> ::ff::LegendreSymbol {
|
||||||
// s = self^((modulus - 1) // 2)
|
// s = self^((modulus - 1) // 2)
|
||||||
let s = self.pow(#mod_minus_1_over_2);
|
let s = self.pow(#mod_minus_1_over_2);
|
||||||
@@ -452,7 +443,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
// 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
|
#legendre_impl
|
||||||
|
|
||||||
@@ -479,7 +470,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
let t_plus_1_over_2 = biguint_to_u64_vec((&t + BigUint::one()) >> 1, limbs);
|
let t_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
|
#legendre_impl
|
||||||
|
|
||||||
@@ -526,7 +517,7 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote!{}
|
quote! {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute R^2 mod m
|
// Compute R^2 mod m
|
||||||
@@ -543,36 +534,39 @@ fn prime_field_constants_and_sqrt(
|
|||||||
}
|
}
|
||||||
inv = inv.wrapping_neg();
|
inv = inv.wrapping_neg();
|
||||||
|
|
||||||
(quote! {
|
(
|
||||||
/// This is the modulus m of the prime field
|
quote! {
|
||||||
const MODULUS: #repr = #repr([#(#modulus,)*]);
|
/// This is the modulus m of the prime field
|
||||||
|
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;
|
||||||
|
|
||||||
/// The number of bits that must be shaved from the beginning of
|
/// The number of bits that must be shaved from the beginning of
|
||||||
/// the representation when randomly sampling.
|
/// the representation when randomly sampling.
|
||||||
const REPR_SHAVE_BITS: u32 = #repr_shave_bits;
|
const REPR_SHAVE_BITS: u32 = #repr_shave_bits;
|
||||||
|
|
||||||
/// 2^{limbs*64} mod m
|
/// 2^{limbs*64} mod m
|
||||||
const R: #repr = #repr(#r);
|
const R: #repr = #repr(#r);
|
||||||
|
|
||||||
/// 2^{limbs*64*2} mod m
|
/// 2^{limbs*64*2} mod m
|
||||||
const R2: #repr = #repr(#r2);
|
const R2: #repr = #repr(#r2);
|
||||||
|
|
||||||
/// -(m^{-1} mod m) mod m
|
/// -(m^{-1} mod m) mod m
|
||||||
const INV: u64 = #inv;
|
const INV: u64 = #inv;
|
||||||
|
|
||||||
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
/// Multiplicative generator of `MODULUS` - 1 order, also quadratic
|
||||||
/// nonresidue.
|
/// nonresidue.
|
||||||
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: u32 = #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.
|
||||||
@@ -592,9 +586,9 @@ fn prime_field_impl(
|
|||||||
mont_paramlist.append_separated(
|
mont_paramlist.append_separated(
|
||||||
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
|
(0..(limbs * 2)).map(|i| (i, get_temp(i))).map(|(i, x)| {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
quote!{mut #x: u64}
|
quote! {mut #x: u64}
|
||||||
} else {
|
} else {
|
||||||
quote!{#x: u64}
|
quote! {#x: u64}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
||||||
@@ -607,7 +601,7 @@ fn prime_field_impl(
|
|||||||
for i in 0..limbs {
|
for i in 0..limbs {
|
||||||
{
|
{
|
||||||
let temp = get_temp(i);
|
let temp = get_temp(i);
|
||||||
gen.extend(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);
|
||||||
@@ -616,7 +610,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.extend(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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -624,17 +618,17 @@ fn prime_field_impl(
|
|||||||
let temp = get_temp(i + limbs);
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
#temp = ::ff::adc(#temp, 0, &mut carry);
|
#temp = ::ff::adc(#temp, 0, &mut carry);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gen.extend(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.extend(quote!{
|
gen.extend(quote! {
|
||||||
let carry2 = carry;
|
let carry2 = carry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -643,7 +637,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.extend(quote!{
|
gen.extend(quote! {
|
||||||
(self.0).0[#i] = #temp;
|
(self.0).0[#i] = #temp;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -655,14 +649,14 @@ fn prime_field_impl(
|
|||||||
let mut gen = proc_macro2::TokenStream::new();
|
let mut gen = proc_macro2::TokenStream::new();
|
||||||
|
|
||||||
for i in 0..(limbs - 1) {
|
for i in 0..(limbs - 1) {
|
||||||
gen.extend(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.extend(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 {
|
||||||
@@ -674,7 +668,7 @@ fn prime_field_impl(
|
|||||||
|
|
||||||
let temp = get_temp(i + limbs);
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp = carry;
|
let #temp = carry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -684,21 +678,21 @@ fn prime_field_impl(
|
|||||||
let temp1 = get_temp(limbs * 2 - i - 1);
|
let temp1 = get_temp(limbs * 2 - i - 1);
|
||||||
|
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp0 = #temp1 >> 63;
|
let #temp0 = #temp1 >> 63;
|
||||||
});
|
});
|
||||||
} else if i == (limbs * 2 - 1) {
|
} else if i == (limbs * 2 - 1) {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp0 = #temp0 << 1;
|
let #temp0 = #temp0 << 1;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp0 = (#temp0 << 1) | (#temp1 >> 63);
|
let #temp0 = (#temp0 << 1) | (#temp1 >> 63);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -706,7 +700,7 @@ 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.extend(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 {
|
||||||
@@ -715,7 +709,7 @@ fn prime_field_impl(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp1 = ::ff::adc(#temp1, 0, &mut carry);
|
let #temp1 = ::ff::adc(#temp1, 0, &mut carry);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -726,7 +720,7 @@ fn prime_field_impl(
|
|||||||
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
||||||
);
|
);
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
self.mont_reduce(#mont_calling);
|
self.mont_reduce(#mont_calling);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -741,7 +735,7 @@ fn prime_field_impl(
|
|||||||
let mut gen = proc_macro2::TokenStream::new();
|
let mut gen = proc_macro2::TokenStream::new();
|
||||||
|
|
||||||
for i in 0..limbs {
|
for i in 0..limbs {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let mut carry = 0;
|
let mut carry = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -749,7 +743,7 @@ fn prime_field_impl(
|
|||||||
let temp = get_temp(i + j);
|
let temp = get_temp(i + j);
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
let #temp = ::ff::mac_with_carry(0, (#a.0).0[#i], (#b.0).0[#j], &mut carry);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -761,7 +755,7 @@ fn prime_field_impl(
|
|||||||
|
|
||||||
let temp = get_temp(i + limbs);
|
let temp = get_temp(i + limbs);
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
let #temp = carry;
|
let #temp = carry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -772,29 +766,29 @@ fn prime_field_impl(
|
|||||||
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
||||||
);
|
);
|
||||||
|
|
||||||
gen.extend(quote!{
|
gen.extend(quote! {
|
||||||
self.mont_reduce(#mont_calling);
|
self.mont_reduce(#mont_calling);
|
||||||
});
|
});
|
||||||
|
|
||||||
gen
|
gen
|
||||||
}
|
}
|
||||||
|
|
||||||
let squaring_impl = sqr_impl(quote!{self}, limbs);
|
let squaring_impl = sqr_impl(quote! {self}, limbs);
|
||||||
let multiply_impl = mul_impl(quote!{self}, quote!{other}, limbs);
|
let multiply_impl = mul_impl(quote! {self}, quote! {other}, limbs);
|
||||||
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 = proc_macro2::TokenStream::new();
|
let mut into_repr_params = proc_macro2::TokenStream::new();
|
||||||
into_repr_params.append_separated(
|
into_repr_params.append_separated(
|
||||||
(0..limbs)
|
(0..limbs)
|
||||||
.map(|i| quote!{ (self.0).0[#i] })
|
.map(|i| quote! { (self.0).0[#i] })
|
||||||
.chain((0..limbs).map(|_| quote!{0})),
|
.chain((0..limbs).map(|_| quote! {0})),
|
||||||
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
proc_macro2::Punct::new(',', proc_macro2::Spacing::Alone),
|
||||||
);
|
);
|
||||||
|
|
||||||
let top_limb_index = limbs - 1;
|
let top_limb_index = limbs - 1;
|
||||||
|
|
||||||
quote!{
|
quote! {
|
||||||
impl ::std::marker::Copy for #name { }
|
impl ::std::marker::Copy for #name { }
|
||||||
|
|
||||||
impl ::std::clone::Clone for #name {
|
impl ::std::clone::Clone for #name {
|
||||||
@@ -839,22 +833,6 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::rand::Rand for #name {
|
|
||||||
/// Computes a uniformly random element using rejection sampling.
|
|
||||||
fn rand<R: ::rand::Rng>(rng: &mut R) -> Self {
|
|
||||||
loop {
|
|
||||||
let mut tmp = #name(#repr::rand(rng));
|
|
||||||
|
|
||||||
// Mask away the unused bits at the beginning.
|
|
||||||
tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
|
|
||||||
|
|
||||||
if tmp.is_valid() {
|
|
||||||
return tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<#name> for #repr {
|
impl From<#name> for #repr {
|
||||||
fn from(e: #name) -> #repr {
|
fn from(e: #name) -> #repr {
|
||||||
e.into_repr()
|
e.into_repr()
|
||||||
@@ -904,6 +882,26 @@ fn prime_field_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ::ff::Field for #name {
|
impl ::ff::Field for #name {
|
||||||
|
/// Computes a uniformly random element using rejection sampling.
|
||||||
|
fn random<R: ::rand_core::RngCore + ?std::marker::Sized>(rng: &mut R) -> Self {
|
||||||
|
loop {
|
||||||
|
let mut tmp = {
|
||||||
|
let mut repr = [0u64; #limbs];
|
||||||
|
for i in 0..#limbs {
|
||||||
|
repr[i] = rng.next_u64();
|
||||||
|
}
|
||||||
|
#name(#repr(repr))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mask away the unused most-significant bits.
|
||||||
|
tmp.0.as_mut()[#top_limb_index] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
|
||||||
|
|
||||||
|
if tmp.is_valid() {
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
#name(#repr::from(0))
|
#name(#repr::from(0))
|
||||||
|
18
src/lib.rs
18
src/lib.rs
@@ -1,7 +1,8 @@
|
|||||||
#![allow(unused_imports)]
|
//! This crate provides traits for working with finite fields.
|
||||||
|
|
||||||
extern crate byteorder;
|
// Catch documentation errors caused by code changes.
|
||||||
extern crate rand;
|
#![deny(intra_doc_link_resolution_failure)]
|
||||||
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
#[cfg(feature = "derive")]
|
#[cfg(feature = "derive")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -10,14 +11,18 @@ extern crate ff_derive;
|
|||||||
#[cfg(feature = "derive")]
|
#[cfg(feature = "derive")]
|
||||||
pub use ff_derive::*;
|
pub use ff_derive::*;
|
||||||
|
|
||||||
|
use rand_core::RngCore;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{self, Read, Write};
|
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:
|
pub trait Field:
|
||||||
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand
|
Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static
|
||||||
{
|
{
|
||||||
|
/// Returns an element chosen uniformly at random using a user-provided RNG.
|
||||||
|
fn random<R: RngCore + ?std::marker::Sized>(rng: &mut R) -> Self;
|
||||||
|
|
||||||
/// 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;
|
||||||
|
|
||||||
@@ -100,7 +105,6 @@ pub trait PrimeFieldRepr:
|
|||||||
+ fmt::Debug
|
+ fmt::Debug
|
||||||
+ fmt::Display
|
+ fmt::Display
|
||||||
+ 'static
|
+ 'static
|
||||||
+ rand::Rand
|
|
||||||
+ AsRef<[u64]>
|
+ AsRef<[u64]>
|
||||||
+ AsMut<[u64]>
|
+ AsMut<[u64]>
|
||||||
+ From<u64>
|
+ From<u64>
|
||||||
@@ -207,7 +211,7 @@ impl Error for PrimeFieldDecodingError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PrimeFieldDecodingError {
|
impl fmt::Display for PrimeFieldDecodingError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
PrimeFieldDecodingError::NotInField(ref repr) => {
|
PrimeFieldDecodingError::NotInField(ref repr) => {
|
||||||
write!(f, "{} is not an element of the field", repr)
|
write!(f, "{} is not an element of the field", repr)
|
||||||
@@ -263,7 +267,7 @@ pub trait PrimeField: Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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, PrimeFieldDecodingError>;
|
fn from_repr(_: Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
|
||||||
|
|
||||||
/// Convert a biginteger representation 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.
|
||||||
|
Reference in New Issue
Block a user