mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
exp_biguint test
This commit is contained in:
parent
b6e74b8244
commit
ffc90e902b
@ -23,7 +23,6 @@ unroll = "0.1.5"
|
|||||||
anyhow = "1.0.40"
|
anyhow = "1.0.40"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_cbor = "0.11.1"
|
serde_cbor = "0.11.1"
|
||||||
num-bigint = "0.2.3"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
|
|||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num::Integer;
|
use num::Integer;
|
||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -252,15 +252,7 @@ impl Field for CrandallField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_canonical_biguint(n: BigUint) -> Self {
|
fn from_canonical_biguint(n: BigUint) -> Self {
|
||||||
let smallest_two: Vec<_> = n
|
Self(n.iter_u64_digits().next().unwrap_or(0))
|
||||||
.to_u32_digits()
|
|
||||||
.iter()
|
|
||||||
.take(2)
|
|
||||||
.pad_using(2, |_| &0u32)
|
|
||||||
.map(|x| *x as u64)
|
|
||||||
.collect();
|
|
||||||
let n_u64 = smallest_two[0] + (1u64 << 32) * smallest_two[1];
|
|
||||||
Self(n_u64)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cube_root(&self) -> Self {
|
fn cube_root(&self) -> Self {
|
||||||
@ -480,7 +472,8 @@ impl Frobenius<1> for CrandallField {}
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::test_prime_field_arithmetic;
|
use crate::{test_field_arithmetic, test_prime_field_arithmetic};
|
||||||
|
|
||||||
test_prime_field_arithmetic!(crate::field::crandall_field::CrandallField);
|
test_prime_field_arithmetic!(crate::field::crandall_field::CrandallField);
|
||||||
|
test_field_arithmetic!(crate::field::crandall_field::CrandallField);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use std::iter::{Product, Sum};
|
|||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi
|
|||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use num::traits::Pow;
|
use num::traits::Pow;
|
||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -141,13 +141,13 @@ impl Field for QuarticCrandallField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_canonical_biguint(n: BigUint) -> Self {
|
fn from_canonical_biguint(n: BigUint) -> Self {
|
||||||
let first = n.clone() % Self::CHARACTERISTIC;
|
let first = &n % Self::CHARACTERISTIC;
|
||||||
let mut remaining = n.clone() / Self::CHARACTERISTIC;
|
let mut remaining = &n / Self::CHARACTERISTIC;
|
||||||
let second = remaining.clone() % Self::CHARACTERISTIC;
|
let second = &remaining % Self::CHARACTERISTIC;
|
||||||
remaining = remaining / Self::CHARACTERISTIC;
|
remaining = remaining / Self::CHARACTERISTIC;
|
||||||
let third = remaining.clone() % Self::CHARACTERISTIC;
|
let third = &remaining % Self::CHARACTERISTIC;
|
||||||
remaining = remaining / Self::CHARACTERISTIC;
|
remaining = remaining / Self::CHARACTERISTIC;
|
||||||
let fourth = remaining.clone() % Self::CHARACTERISTIC;
|
let fourth = &remaining % Self::CHARACTERISTIC;
|
||||||
|
|
||||||
Self([
|
Self([
|
||||||
<Self as FieldExtension<4>>::BaseField::from_canonical_biguint(first),
|
<Self as FieldExtension<4>>::BaseField::from_canonical_biguint(first),
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use std::iter::{Product, Sum};
|
|||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||||
|
|
||||||
use num::{Integer, Zero};
|
use num::{Integer, Zero};
|
||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::util::{bits_u64, ceil_div_usize};
|
use crate::util::ceil_div_usize;
|
||||||
|
|
||||||
/// Generates a series of non-negative integers less than
|
/// Generates a series of non-negative integers less than
|
||||||
/// `modulus` which cover a range of values and which will
|
/// `modulus` which cover a range of values and which will
|
||||||
@ -9,7 +9,7 @@ use crate::util::{bits_u64, ceil_div_usize};
|
|||||||
/// boundaries.
|
/// boundaries.
|
||||||
pub fn test_inputs(modulus: BigUint, word_bits: usize) -> Vec<BigUint> {
|
pub fn test_inputs(modulus: BigUint, word_bits: usize) -> Vec<BigUint> {
|
||||||
//assert!(word_bits == 32 || word_bits == 64);
|
//assert!(word_bits == 32 || word_bits == 64);
|
||||||
let modwords = ceil_div_usize(modulus.bits(), word_bits);
|
let modwords = ceil_div_usize(modulus.bits() as usize, word_bits);
|
||||||
// Start with basic set close to zero: 0 .. 10
|
// Start with basic set close to zero: 0 .. 10
|
||||||
const BIGGEST_SMALL: u32 = 10;
|
const BIGGEST_SMALL: u32 = 10;
|
||||||
let smalls: Vec<_> = (0..BIGGEST_SMALL).map(BigUint::from).collect();
|
let smalls: Vec<_> = (0..BIGGEST_SMALL).map(BigUint::from).collect();
|
||||||
@ -148,13 +148,128 @@ pub fn run_binaryop_test_cases<F, BinaryOp, ExpectedOp>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! test_field_arithmetic {
|
||||||
|
($field:ty) => {
|
||||||
|
mod field_arithmetic {
|
||||||
|
use num::bigint::BigUint;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
|
use crate::field::field::Field;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn batch_inversion() {
|
||||||
|
let xs = (1..=3)
|
||||||
|
.map(|i| <$field>::from_canonical_u64(i))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let invs = <$field>::batch_multiplicative_inverse(&xs);
|
||||||
|
for (x, inv) in xs.into_iter().zip(invs) {
|
||||||
|
assert_eq!(x * inv, <$field>::ONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn primitive_root_order() {
|
||||||
|
for n_power in 0..8 {
|
||||||
|
let root = <$field>::primitive_root_of_unity(n_power);
|
||||||
|
let order = <$field>::generator_order(root);
|
||||||
|
assert_eq!(order, 1 << n_power, "2^{}'th primitive root", n_power);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negation() {
|
||||||
|
let zero = <$field>::ZERO;
|
||||||
|
let order = <$field>::order();
|
||||||
|
|
||||||
|
for i in [
|
||||||
|
BigUint::from(0u32),
|
||||||
|
BigUint::from(1u32),
|
||||||
|
BigUint::from(2u32),
|
||||||
|
order.clone() - 2u32,
|
||||||
|
order.clone() - 1u32,
|
||||||
|
] {
|
||||||
|
let i_f = <$field>::from_canonical_biguint(i);
|
||||||
|
assert_eq!(i_f + -i_f, zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bits() {
|
||||||
|
assert_eq!(<$field>::ZERO.bits(), 0);
|
||||||
|
assert_eq!(<$field>::ONE.bits(), 1);
|
||||||
|
assert_eq!(<$field>::TWO.bits(), 2);
|
||||||
|
assert_eq!(<$field>::from_canonical_u64(3).bits(), 2);
|
||||||
|
assert_eq!(<$field>::from_canonical_u64(4).bits(), 3);
|
||||||
|
assert_eq!(<$field>::from_canonical_u64(5).bits(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exponentiation() {
|
||||||
|
type F = $field;
|
||||||
|
|
||||||
|
assert_eq!(F::ZERO.exp_u32(0), <F>::ONE);
|
||||||
|
assert_eq!(F::ONE.exp_u32(0), <F>::ONE);
|
||||||
|
assert_eq!(F::TWO.exp_u32(0), <F>::ONE);
|
||||||
|
|
||||||
|
assert_eq!(F::ZERO.exp_u32(1), <F>::ZERO);
|
||||||
|
assert_eq!(F::ONE.exp_u32(1), <F>::ONE);
|
||||||
|
assert_eq!(F::TWO.exp_u32(1), <F>::TWO);
|
||||||
|
|
||||||
|
assert_eq!(F::ZERO.kth_root_u32(1), <F>::ZERO);
|
||||||
|
assert_eq!(F::ONE.kth_root_u32(1), <F>::ONE);
|
||||||
|
assert_eq!(F::TWO.kth_root_u32(1), <F>::TWO);
|
||||||
|
|
||||||
|
for power in 1..10 {
|
||||||
|
if F::is_monomial_permutation(power) {
|
||||||
|
let x = F::rand();
|
||||||
|
assert_eq!(x.exp(power).kth_root(power), x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exponentiation_large() {
|
||||||
|
type F = $field;
|
||||||
|
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let base = F::rand();
|
||||||
|
let pow = BigUint::from(rng.gen::<u64>());
|
||||||
|
let cycles = rng.gen::<u32>();
|
||||||
|
let mul_group_order = F::order() - 1u32;
|
||||||
|
let big_pow = &pow + &mul_group_order * cycles;
|
||||||
|
let big_pow_wrong = &pow + &mul_group_order * cycles + 1u32;
|
||||||
|
|
||||||
|
assert_eq!(base.exp_biguint(pow.clone()), base.exp_biguint(big_pow));
|
||||||
|
assert_ne!(base.exp_biguint(pow), base.exp_biguint(big_pow_wrong));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inverse_2exp() {
|
||||||
|
// Just check consistency with try_inverse()
|
||||||
|
type F = $field;
|
||||||
|
|
||||||
|
let v = <F as Field>::PrimeField::TWO_ADICITY;
|
||||||
|
|
||||||
|
for e in [0, 1, 2, 3, 4, v - 2, v - 1, v, v + 1, v + 2, 123 * v] {
|
||||||
|
let x = F::TWO.exp(e as u64).inverse();
|
||||||
|
let y = F::inverse_2exp(e);
|
||||||
|
assert_eq!(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! test_prime_field_arithmetic {
|
macro_rules! test_prime_field_arithmetic {
|
||||||
($field:ty) => {
|
($field:ty) => {
|
||||||
mod prime_field_arithmetic {
|
mod prime_field_arithmetic {
|
||||||
use std::ops::{Add, Mul, Neg, Sub};
|
use std::ops::{Add, Mul, Neg, Sub};
|
||||||
|
|
||||||
use num_bigint::BigUint;
|
use num::bigint::BigUint;
|
||||||
|
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
|
|
||||||
@ -266,99 +381,3 @@ macro_rules! test_prime_field_arithmetic {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! test_field_arithmetic {
|
|
||||||
($field:ty) => {
|
|
||||||
mod field_arithmetic {
|
|
||||||
use num_bigint::BigUint;
|
|
||||||
|
|
||||||
use crate::field::field::Field;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn batch_inversion() {
|
|
||||||
let xs = (1..=3)
|
|
||||||
.map(|i| <$field>::from_canonical_u64(i))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let invs = <$field>::batch_multiplicative_inverse(&xs);
|
|
||||||
for (x, inv) in xs.into_iter().zip(invs) {
|
|
||||||
assert_eq!(x * inv, <$field>::ONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn primitive_root_order() {
|
|
||||||
for n_power in 0..8 {
|
|
||||||
let root = <$field>::primitive_root_of_unity(n_power);
|
|
||||||
let order = <$field>::generator_order(root);
|
|
||||||
assert_eq!(order, 1 << n_power, "2^{}'th primitive root", n_power);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn negation() {
|
|
||||||
let zero = <$field>::ZERO;
|
|
||||||
let order = <$field>::order();
|
|
||||||
|
|
||||||
for i in [
|
|
||||||
BigUint::from(0u32),
|
|
||||||
BigUint::from(1u32),
|
|
||||||
BigUint::from(2u32),
|
|
||||||
order.clone() - 2u32,
|
|
||||||
order.clone() - 1u32,
|
|
||||||
] {
|
|
||||||
let i_f = <$field>::from_canonical_biguint(i);
|
|
||||||
assert_eq!(i_f + -i_f, zero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bits() {
|
|
||||||
assert_eq!(<$field>::ZERO.bits(), 0);
|
|
||||||
assert_eq!(<$field>::ONE.bits(), 1);
|
|
||||||
assert_eq!(<$field>::TWO.bits(), 2);
|
|
||||||
assert_eq!(<$field>::from_canonical_u64(3).bits(), 2);
|
|
||||||
assert_eq!(<$field>::from_canonical_u64(4).bits(), 3);
|
|
||||||
assert_eq!(<$field>::from_canonical_u64(5).bits(), 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn exponentiation() {
|
|
||||||
type F = $field;
|
|
||||||
|
|
||||||
assert_eq!(F::ZERO.exp_u32(0), <F>::ONE);
|
|
||||||
assert_eq!(F::ONE.exp_u32(0), <F>::ONE);
|
|
||||||
assert_eq!(F::TWO.exp_u32(0), <F>::ONE);
|
|
||||||
|
|
||||||
assert_eq!(F::ZERO.exp_u32(1), <F>::ZERO);
|
|
||||||
assert_eq!(F::ONE.exp_u32(1), <F>::ONE);
|
|
||||||
assert_eq!(F::TWO.exp_u32(1), <F>::TWO);
|
|
||||||
|
|
||||||
assert_eq!(F::ZERO.kth_root_u32(1), <F>::ZERO);
|
|
||||||
assert_eq!(F::ONE.kth_root_u32(1), <F>::ONE);
|
|
||||||
assert_eq!(F::TWO.kth_root_u32(1), <F>::TWO);
|
|
||||||
|
|
||||||
for power in 1..10 {
|
|
||||||
if F::is_monomial_permutation(power) {
|
|
||||||
let x = F::rand();
|
|
||||||
assert_eq!(x.exp(power).kth_root(power), x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn inverse_2exp() {
|
|
||||||
// Just check consistency with try_inverse()
|
|
||||||
type F = $field;
|
|
||||||
|
|
||||||
let v = <F as Field>::PrimeField::TWO_ADICITY;
|
|
||||||
|
|
||||||
for e in [0, 1, 2, 3, 4, v - 2, v - 1, v, v + 1, v + 2, 123 * v] {
|
|
||||||
let x = F::TWO.exp(e as u64).inverse();
|
|
||||||
let y = F::inverse_2exp(e);
|
|
||||||
assert_eq!(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user