Auto merge of #26 - ebfull:even-more-adjustments, r=ebfull
Even more adjustments Closes #22 Closes #24 Closes #25
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pairing"
|
name = "pairing"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ repository = "https://github.com/ebfull/pairing"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
byteorder = "1.1.0"
|
byteorder = "1.1.0"
|
||||||
clippy = { version = "0.0.145", optional = true }
|
clippy = { version = "0.0.148", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
unstable-wnaf = []
|
unstable-wnaf = []
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ macro_rules! curve_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CurveAffine for $affine {
|
impl CurveAffine for $affine {
|
||||||
|
type Engine = Bls12;
|
||||||
type Scalar = $scalarfield;
|
type Scalar = $scalarfield;
|
||||||
type Base = $basefield;
|
type Base = $basefield;
|
||||||
type Prepared = $prepared;
|
type Prepared = $prepared;
|
||||||
@@ -174,6 +175,7 @@ macro_rules! curve_impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CurveProjective for $projective {
|
impl CurveProjective for $projective {
|
||||||
|
type Engine = Bls12;
|
||||||
type Scalar = $scalarfield;
|
type Scalar = $scalarfield;
|
||||||
type Base = $basefield;
|
type Base = $basefield;
|
||||||
type Affine = $affine;
|
type Affine = $affine;
|
||||||
@@ -582,7 +584,7 @@ macro_rules! curve_impl {
|
|||||||
pub mod g1 {
|
pub mod g1 {
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
use super::g2::G2Affine;
|
use super::g2::G2Affine;
|
||||||
use super::super::{Fq, Fr, FrRepr, FqRepr, Fq12};
|
use super::super::{Bls12, Fq, Fr, FrRepr, FqRepr, Fq12};
|
||||||
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
|
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
|
||||||
|
|
||||||
curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed, G2Affine);
|
curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed, G2Affine);
|
||||||
@@ -1134,7 +1136,7 @@ pub mod g1 {
|
|||||||
|
|
||||||
pub mod g2 {
|
pub mod g2 {
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr, Fq12};
|
use super::super::{Bls12, Fq2, Fr, Fq, FrRepr, FqRepr, Fq12};
|
||||||
use super::g1::G1Affine;
|
use super::g1::G1Affine;
|
||||||
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
|
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const MODULUS_BITS: u32 = 381;
|
|||||||
|
|
||||||
// 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: usize = 3;
|
const REPR_SHAVE_BITS: u32 = 3;
|
||||||
|
|
||||||
// R = 2**384 % q
|
// R = 2**384 % q
|
||||||
const R: FqRepr = FqRepr([0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493]);
|
const R: FqRepr = FqRepr([0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493]);
|
||||||
@@ -25,7 +25,7 @@ const INV: u64 = 0x89f3fffcfffcfffd;
|
|||||||
const GENERATOR: FqRepr = FqRepr([0x321300000006554f, 0xb93c0018d6c40005, 0x57605e0db0ddbb51, 0x8b256521ed1f9bcb, 0x6cf28d7901622c03, 0x11ebab9dbb81e28c]);
|
const GENERATOR: FqRepr = FqRepr([0x321300000006554f, 0xb93c0018d6c40005, 0x57605e0db0ddbb51, 0x8b256521ed1f9bcb, 0x6cf28d7901622c03, 0x11ebab9dbb81e28c]);
|
||||||
|
|
||||||
// 2^s * t = MODULUS - 1 with t odd
|
// 2^s * t = MODULUS - 1 with t odd
|
||||||
const S: usize = 1;
|
const S: u32 = 1;
|
||||||
|
|
||||||
// 2^s root of unity computed by GENERATOR^t
|
// 2^s root of unity computed by GENERATOR^t
|
||||||
const ROOT_OF_UNITY: FqRepr = FqRepr([0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x7e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x40ab3263eff0206]);
|
const ROOT_OF_UNITY: FqRepr = FqRepr([0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x7e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x40ab3263eff0206]);
|
||||||
@@ -278,7 +278,7 @@ impl PrimeFieldRepr for FqRepr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn divn(&mut self, mut n: usize) {
|
fn divn(&mut self, mut n: u32) {
|
||||||
if n >= 64 * 6 {
|
if n >= 64 * 6 {
|
||||||
*self = Self::from(0);
|
*self = Self::from(0);
|
||||||
return;
|
return;
|
||||||
@@ -325,6 +325,32 @@ impl PrimeFieldRepr for FqRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn muln(&mut self, mut n: u32) {
|
||||||
|
if n >= 64 * 6 {
|
||||||
|
*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 = (6 as u32) * 64;
|
let mut ret = (6 as u32) * 64;
|
||||||
@@ -444,7 +470,7 @@ impl PrimeField for Fq {
|
|||||||
Fq(GENERATOR)
|
Fq(GENERATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn s() -> usize {
|
fn s() -> u32 {
|
||||||
S
|
S
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1740,6 +1766,7 @@ fn fq_field_tests() {
|
|||||||
::tests::field::random_field_tests::<Fq>();
|
::tests::field::random_field_tests::<Fq>();
|
||||||
::tests::field::random_sqrt_tests::<Fq>();
|
::tests::field::random_sqrt_tests::<Fq>();
|
||||||
::tests::field::random_frobenius_tests::<Fq, _>(Fq::char(), 13);
|
::tests::field::random_frobenius_tests::<Fq, _>(Fq::char(), 13);
|
||||||
|
::tests::field::from_str_tests::<Fq>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const MODULUS_BITS: u32 = 255;
|
|||||||
|
|
||||||
// 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: usize = 1;
|
const REPR_SHAVE_BITS: u32 = 1;
|
||||||
|
|
||||||
// R = 2**256 % r
|
// R = 2**256 % r
|
||||||
const R: FrRepr = FrRepr([0x1fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f]);
|
const R: FrRepr = FrRepr([0x1fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f]);
|
||||||
@@ -23,7 +23,7 @@ const INV: u64 = 0xfffffffeffffffff;
|
|||||||
const GENERATOR: FrRepr = FrRepr([0xefffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4]);
|
const GENERATOR: FrRepr = FrRepr([0xefffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4]);
|
||||||
|
|
||||||
// 2^s * t = MODULUS - 1 with t odd
|
// 2^s * t = MODULUS - 1 with t odd
|
||||||
const S: usize = 32;
|
const S: u32 = 32;
|
||||||
|
|
||||||
// 2^s root of unity computed by GENERATOR^t
|
// 2^s root of unity computed by GENERATOR^t
|
||||||
const ROOT_OF_UNITY: FrRepr = FrRepr([0xb9b58d8c5f0e466a, 0x5b1b4c801819d7ec, 0xaf53ae352a31e64, 0x5bf3adda19e9b27b]);
|
const ROOT_OF_UNITY: FrRepr = FrRepr([0xb9b58d8c5f0e466a, 0x5b1b4c801819d7ec, 0xaf53ae352a31e64, 0x5bf3adda19e9b27b]);
|
||||||
@@ -114,7 +114,7 @@ impl PrimeFieldRepr for FrRepr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn divn(&mut self, mut n: usize) {
|
fn divn(&mut self, mut n: u32) {
|
||||||
if n >= 64 * 4 {
|
if n >= 64 * 4 {
|
||||||
*self = Self::from(0);
|
*self = Self::from(0);
|
||||||
return;
|
return;
|
||||||
@@ -161,6 +161,32 @@ impl PrimeFieldRepr for FrRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn muln(&mut self, mut n: u32) {
|
||||||
|
if n >= 64 * 4 {
|
||||||
|
*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 = (4 as u32) * 64;
|
let mut ret = (4 as u32) * 64;
|
||||||
@@ -264,7 +290,7 @@ impl PrimeField for Fr {
|
|||||||
Fr(GENERATOR)
|
Fr(GENERATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn s() -> usize {
|
fn s() -> u32 {
|
||||||
S
|
S
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1452,6 +1478,7 @@ fn fr_field_tests() {
|
|||||||
::tests::field::random_field_tests::<Fr>();
|
::tests::field::random_field_tests::<Fr>();
|
||||||
::tests::field::random_sqrt_tests::<Fr>();
|
::tests::field::random_sqrt_tests::<Fr>();
|
||||||
::tests::field::random_frobenius_tests::<Fr, _>(Fr::char(), 13);
|
::tests::field::random_frobenius_tests::<Fr, _>(Fr::char(), 13);
|
||||||
|
::tests::field::from_str_tests::<Fr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ mod tests;
|
|||||||
pub use self::fr::{Fr, FrRepr};
|
pub use self::fr::{Fr, FrRepr};
|
||||||
pub use self::fq::{Fq, FqRepr};
|
pub use self::fq::{Fq, FqRepr};
|
||||||
pub use self::fq2::Fq2;
|
pub use self::fq2::Fq2;
|
||||||
|
pub use self::fq6::Fq6;
|
||||||
pub use self::fq12::Fq12;
|
pub use self::fq12::Fq12;
|
||||||
pub use self::ec::{G1, G2, G1Affine, G2Affine, G1Prepared, G2Prepared, G1Uncompressed, G2Uncompressed, G1Compressed, G2Compressed};
|
pub use self::ec::{G1, G2, G1Affine, G2Affine, G1Prepared, G2Prepared, G1Uncompressed, G2Uncompressed, G1Compressed, G2Compressed};
|
||||||
|
|
||||||
|
|||||||
63
src/lib.rs
63
src/lib.rs
@@ -9,6 +9,7 @@
|
|||||||
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
||||||
#![cfg_attr(feature = "clippy", allow(inline_always))]
|
#![cfg_attr(feature = "clippy", allow(inline_always))]
|
||||||
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
|
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
|
||||||
|
#![cfg_attr(feature = "clippy", allow(unreadable_literal))]
|
||||||
|
|
||||||
// The compiler provides `test` (on nightly) for benchmarking tools, but
|
// The compiler provides `test` (on nightly) for benchmarking tools, but
|
||||||
// it's hidden behind a feature flag. Enable it if we're testing.
|
// it's hidden behind a feature flag. Enable it if we're testing.
|
||||||
@@ -34,21 +35,21 @@ use std::io::{self, Read, Write};
|
|||||||
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
|
||||||
/// with well-defined relationships. In particular, the G1/G2 curve groups are
|
/// with well-defined relationships. In particular, the G1/G2 curve groups are
|
||||||
/// of prime order `r`, and are equipped with a bilinear pairing function.
|
/// of prime order `r`, and are equipped with a bilinear pairing function.
|
||||||
pub trait Engine {
|
pub trait Engine: Sized {
|
||||||
/// This is the scalar field of the G1/G2 groups.
|
/// This is the scalar field of the G1/G2 groups.
|
||||||
type Fr: PrimeField;
|
type Fr: PrimeField;
|
||||||
|
|
||||||
/// The projective representation of an element in G1.
|
/// The projective representation of an element in G1.
|
||||||
type G1: CurveProjective<Base=Self::Fq, Scalar=Self::Fr, Affine=Self::G1Affine> + From<Self::G1Affine>;
|
type G1: CurveProjective<Engine=Self, Base=Self::Fq, Scalar=Self::Fr, Affine=Self::G1Affine> + From<Self::G1Affine>;
|
||||||
|
|
||||||
/// The affine representation of an element in G1.
|
/// The affine representation of an element in G1.
|
||||||
type G1Affine: CurveAffine<Base=Self::Fq, Scalar=Self::Fr, Projective=Self::G1, Pair=Self::G2Affine, PairingResult=Self::Fqk> + From<Self::G1>;
|
type G1Affine: CurveAffine<Engine=Self, Base=Self::Fq, Scalar=Self::Fr, Projective=Self::G1, Pair=Self::G2Affine, PairingResult=Self::Fqk> + From<Self::G1>;
|
||||||
|
|
||||||
/// The projective representation of an element in G2.
|
/// The projective representation of an element in G2.
|
||||||
type G2: CurveProjective<Base=Self::Fqe, Scalar=Self::Fr, Affine=Self::G2Affine> + From<Self::G2Affine>;
|
type G2: CurveProjective<Engine=Self, Base=Self::Fqe, Scalar=Self::Fr, Affine=Self::G2Affine> + From<Self::G2Affine>;
|
||||||
|
|
||||||
/// The affine representation of an element in G2.
|
/// The affine representation of an element in G2.
|
||||||
type G2Affine: CurveAffine<Base=Self::Fqe, Scalar=Self::Fr, Projective=Self::G2, Pair=Self::G1Affine, PairingResult=Self::Fqk> + From<Self::G2>;
|
type G2Affine: CurveAffine<Engine=Self, Base=Self::Fqe, Scalar=Self::Fr, Projective=Self::G2, Pair=Self::G1Affine, PairingResult=Self::Fqk> + From<Self::G2>;
|
||||||
|
|
||||||
/// The base field that hosts G1.
|
/// The base field that hosts G1.
|
||||||
type Fq: PrimeField + SqrtField;
|
type Fq: PrimeField + SqrtField;
|
||||||
@@ -97,6 +98,7 @@ pub trait CurveProjective: PartialEq +
|
|||||||
rand::Rand +
|
rand::Rand +
|
||||||
'static
|
'static
|
||||||
{
|
{
|
||||||
|
type Engine: Engine;
|
||||||
type Scalar: PrimeField;
|
type Scalar: PrimeField;
|
||||||
type Base: SqrtField;
|
type Base: SqrtField;
|
||||||
type Affine: CurveAffine<Projective=Self, Scalar=Self::Scalar>;
|
type Affine: CurveAffine<Projective=Self, Scalar=Self::Scalar>;
|
||||||
@@ -166,6 +168,7 @@ pub trait CurveAffine: Copy +
|
|||||||
Eq +
|
Eq +
|
||||||
'static
|
'static
|
||||||
{
|
{
|
||||||
|
type Engine: Engine;
|
||||||
type Scalar: PrimeField;
|
type Scalar: PrimeField;
|
||||||
type Base: SqrtField;
|
type Base: SqrtField;
|
||||||
type Projective: CurveProjective<Affine=Self, Scalar=Self::Scalar>;
|
type Projective: CurveProjective<Affine=Self, Scalar=Self::Scalar>;
|
||||||
@@ -352,7 +355,8 @@ pub trait PrimeFieldRepr: Sized +
|
|||||||
/// Add another representation to this one, returning the carry bit.
|
/// Add another representation to this one, returning the carry bit.
|
||||||
fn add_nocarry(&mut self, other: &Self) -> bool;
|
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. 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.
|
||||||
@@ -369,12 +373,15 @@ pub trait PrimeFieldRepr: Sized +
|
|||||||
fn div2(&mut self);
|
fn div2(&mut self);
|
||||||
|
|
||||||
/// Performs a rightwise bitshift of this number by some amount.
|
/// Performs a rightwise bitshift of this number by some amount.
|
||||||
fn divn(&mut self, amt: usize);
|
fn divn(&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 muln(&mut self, amt: u32);
|
||||||
|
|
||||||
/// Writes this `PrimeFieldRepr` as a big endian integer. Always writes
|
/// Writes this `PrimeFieldRepr` as a big endian integer. Always writes
|
||||||
/// `(num_bits` / 8) bytes.
|
/// `(num_bits` / 8) bytes.
|
||||||
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
@@ -473,6 +480,46 @@ pub trait PrimeField: Field
|
|||||||
/// representation.
|
/// representation.
|
||||||
type Repr: PrimeFieldRepr + From<Self>;
|
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(c as u64)).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, PrimeFieldDecodingError>;
|
fn from_repr(Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
|
||||||
|
|
||||||
@@ -496,7 +543,7 @@ pub trait PrimeField: Field
|
|||||||
fn multiplicative_generator() -> Self;
|
fn multiplicative_generator() -> Self;
|
||||||
|
|
||||||
/// Returns s such that 2^s * t = `char()` - 1 with t odd.
|
/// Returns s such that 2^s * t = `char()` - 1 with t odd.
|
||||||
fn s() -> usize;
|
fn 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.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use rand::{Rng, SeedableRng, XorShiftRng};
|
use rand::{Rng, SeedableRng, XorShiftRng};
|
||||||
use ::{SqrtField, Field};
|
use ::{SqrtField, Field, PrimeField};
|
||||||
|
|
||||||
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
|
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
|
||||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
@@ -87,6 +87,40 @@ pub fn random_field_tests<F: Field>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_str_tests<F: PrimeField>() {
|
||||||
|
{
|
||||||
|
let a = "84395729384759238745923745892374598234705297301958723458712394587103249587213984572934750213947582345792304758273458972349582734958273495872304598234";
|
||||||
|
let b = "38495729084572938457298347502349857029384609283450692834058293405982304598230458230495820394850293845098234059823049582309485203948502938452093482039";
|
||||||
|
let c = "3248875134290623212325429203829831876024364170316860259933542844758450336418538569901990710701240661702808867062612075657861768196242274635305077449545396068598317421057721935408562373834079015873933065667961469731886739181625866970316226171512545167081793907058686908697431878454091011239990119126";
|
||||||
|
|
||||||
|
let mut a = F::from_str(a).unwrap();
|
||||||
|
let b = F::from_str(b).unwrap();
|
||||||
|
let c = F::from_str(c).unwrap();
|
||||||
|
|
||||||
|
a.mul_assign(&b);
|
||||||
|
|
||||||
|
assert_eq!(a, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
for _ in 0..1000 {
|
||||||
|
let n: u64 = rng.gen();
|
||||||
|
|
||||||
|
let a = F::from_str(&format!("{}", n)).unwrap();
|
||||||
|
let b = F::from_repr(n.into()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(F::from_str("").is_none());
|
||||||
|
assert!(F::from_str("0").unwrap().is_zero());
|
||||||
|
assert!(F::from_str("00").is_none());
|
||||||
|
assert!(F::from_str("00000000000").is_none());
|
||||||
|
}
|
||||||
|
|
||||||
fn random_multiplication_tests<F: Field, R: Rng>(rng: &mut R) {
|
fn random_multiplication_tests<F: Field, R: Rng>(rng: &mut R) {
|
||||||
for _ in 0..10000 {
|
for _ in 0..10000 {
|
||||||
let a = F::rand(rng);
|
let a = F::rand(rng);
|
||||||
|
|||||||
@@ -2,20 +2,64 @@ use rand::{SeedableRng, XorShiftRng};
|
|||||||
use ::{PrimeFieldRepr};
|
use ::{PrimeFieldRepr};
|
||||||
|
|
||||||
pub fn random_repr_tests<R: PrimeFieldRepr>() {
|
pub fn random_repr_tests<R: PrimeFieldRepr>() {
|
||||||
random_encoding_tests::<R>();
|
random_encoding_tests::<R>();
|
||||||
|
random_muln_tests::<R>();
|
||||||
|
random_divn_tests::<R>();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_encoding_tests<R: PrimeFieldRepr>() {
|
fn random_encoding_tests<R: PrimeFieldRepr>() {
|
||||||
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
let r = R::rand(&mut rng);
|
let r = R::rand(&mut rng);
|
||||||
let mut rdecoded = R::default();
|
let mut rdecoded = R::default();
|
||||||
|
|
||||||
let mut v: Vec<u8> = vec![];
|
let mut v: Vec<u8> = vec![];
|
||||||
r.write_be(&mut v).unwrap();
|
r.write_be(&mut v).unwrap();
|
||||||
rdecoded.read_be(&v[0..]).unwrap();
|
rdecoded.read_be(&v[0..]).unwrap();
|
||||||
|
|
||||||
assert_eq!(r, rdecoded);
|
assert_eq!(r, rdecoded);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_muln_tests<R: PrimeFieldRepr>() {
|
||||||
|
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
for _ in 0..100 {
|
||||||
|
let r = R::rand(&mut rng);
|
||||||
|
|
||||||
|
for shift in 0..(r.num_bits()+1) {
|
||||||
|
let mut r1 = r;
|
||||||
|
let mut r2 = r;
|
||||||
|
|
||||||
|
for _ in 0..shift {
|
||||||
|
r1.mul2();
|
||||||
|
}
|
||||||
|
|
||||||
|
r2.muln(shift);
|
||||||
|
|
||||||
|
assert_eq!(r1, r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn random_divn_tests<R: PrimeFieldRepr>() {
|
||||||
|
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
for _ in 0..100 {
|
||||||
|
let r = R::rand(&mut rng);
|
||||||
|
|
||||||
|
for shift in 0..(r.num_bits()+1) {
|
||||||
|
let mut r1 = r;
|
||||||
|
let mut r2 = r;
|
||||||
|
|
||||||
|
for _ in 0..shift {
|
||||||
|
r1.div2();
|
||||||
|
}
|
||||||
|
|
||||||
|
r2.divn(shift);
|
||||||
|
|
||||||
|
assert_eq!(r1, r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user