diff --git a/field/src/arch/x86_64/avx2_goldilocks_field.rs b/field/src/arch/x86_64/avx2_goldilocks_field.rs index b9336cee..e185cb4c 100644 --- a/field/src/arch/x86_64/avx2_goldilocks_field.rs +++ b/field/src/arch/x86_64/avx2_goldilocks_field.rs @@ -5,7 +5,7 @@ use std::iter::{Product, Sum}; use std::mem::transmute; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::field_types::{Field, PrimeField}; +use crate::field_types::{Field, Field64}; use crate::goldilocks_field::GoldilocksField; use crate::ops::Square; use crate::packed_field::PackedField; @@ -510,7 +510,7 @@ unsafe fn interleave2(x: __m256i, y: __m256i) -> (__m256i, __m256i) { #[cfg(test)] mod tests { use crate::arch::x86_64::avx2_goldilocks_field::Avx2GoldilocksField; - use crate::field_types::PrimeField; + use crate::field_types::Field64; use crate::goldilocks_field::GoldilocksField; use crate::ops::Square; use crate::packed_field::PackedField; diff --git a/field/src/arch/x86_64/avx512_goldilocks_field.rs b/field/src/arch/x86_64/avx512_goldilocks_field.rs index ede87626..aaa05e93 100644 --- a/field/src/arch/x86_64/avx512_goldilocks_field.rs +++ b/field/src/arch/x86_64/avx512_goldilocks_field.rs @@ -5,7 +5,7 @@ use std::iter::{Product, Sum}; use std::mem::transmute; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; -use crate::field_types::{Field, PrimeField}; +use crate::field_types::{Field, Field64}; use crate::goldilocks_field::GoldilocksField; use crate::ops::Square; use crate::packed_field::PackedField; @@ -407,7 +407,7 @@ unsafe fn interleave4(x: __m512i, y: __m512i) -> (__m512i, __m512i) { #[cfg(test)] mod tests { use crate::arch::x86_64::avx512_goldilocks_field::Avx512GoldilocksField; - use crate::field_types::PrimeField; + use crate::field_types::Field64; use crate::goldilocks_field::GoldilocksField; use crate::ops::Square; use crate::packed_field::PackedField; diff --git a/field/src/field_types.rs b/field/src/field_types.rs index 0d7b314f..65d5bf21 100644 --- a/field/src/field_types.rs +++ b/field/src/field_types.rs @@ -264,17 +264,25 @@ pub trait Field: subgroup.into_iter().map(|x| x * shift).collect() } - // TODO: move these to a new `PrimeField` trait (for all prime fields, not just 64-bit ones) + // TODO: The current behavior for composite fields doesn't seem natural or useful. + // Rename to `from_noncanonical_biguint` and have it return `n % Self::characteristic()`. fn from_biguint(n: BigUint) -> Self; + // TODO: Move to a new `PrimeField` trait. fn to_biguint(&self) -> BigUint; + /// Returns `n`. Assumes that `n` is already in canonical form, i.e. `n < Self::order()`. + // TODO: Should probably be unsafe. fn from_canonical_u64(n: u64) -> Self; + /// Returns `n`. Assumes that `n` is already in canonical form, i.e. `n < Self::order()`. + // TODO: Should probably be unsafe. fn from_canonical_u32(n: u32) -> Self { Self::from_canonical_u64(n as u64) } + /// Returns `n`. Assumes that `n` is already in canonical form, i.e. `n < Self::order()`. + // TODO: Should probably be unsafe. fn from_canonical_usize(n: usize) -> Self { Self::from_canonical_u64(n as u64) } @@ -283,11 +291,11 @@ pub trait Field: Self::from_canonical_u64(b as u64) } - /// Returns `n % Self::CHARACTERISTIC`. + /// Returns `n % Self::characteristic()`. fn from_noncanonical_u128(n: u128) -> Self; - /// Returns `n % Self::CHARACTERISTIC`. May be cheaper than from_noncanonical_u128 when we know - /// that n < 2 ** 96. + /// Returns `n % Self::characteristic()`. May be cheaper than from_noncanonical_u128 when we know + /// that `n < 2 ** 96`. #[inline] fn from_noncanonical_u96((n_lo, n_hi): (u64, u32)) -> Self { // Default implementation. @@ -399,22 +407,28 @@ pub trait Field: } } -/// A finite field of prime order less than 2^64. -pub trait PrimeField: Field { +/// A finite field of order less than 2^64. +pub trait Field64: Field { const ORDER: u64; + // TODO: Only well-defined for prime 64-bit fields. Move to a new PrimeField64 trait? fn to_canonical_u64(&self) -> u64; + // TODO: Only well-defined for prime 64-bit fields. Move to a new PrimeField64 trait? fn to_noncanonical_u64(&self) -> u64; + /// Returns `x % Self::CHARACTERISTIC`. + // TODO: Move to `Field`. fn from_noncanonical_u64(n: u64) -> Self; #[inline] + // TODO: Move to `Field`. fn add_one(&self) -> Self { unsafe { self.add_canonical_u64(1) } } #[inline] + // TODO: Move to `Field`. fn sub_one(&self) -> Self { unsafe { self.sub_canonical_u64(1) } } @@ -423,6 +437,7 @@ pub trait PrimeField: Field { /// Equivalent to *self + Self::from_canonical_u64(rhs), but may be cheaper. The caller must /// ensure that 0 <= rhs < Self::ORDER. The function may return incorrect results if this /// precondition is not met. It is marked unsafe for this reason. + // TODO: Move to `Field`. #[inline] unsafe fn add_canonical_u64(&self, rhs: u64) -> Self { // Default implementation. @@ -433,6 +448,7 @@ pub trait PrimeField: Field { /// Equivalent to *self - Self::from_canonical_u64(rhs), but may be cheaper. The caller must /// ensure that 0 <= rhs < Self::ORDER. The function may return incorrect results if this /// precondition is not met. It is marked unsafe for this reason. + // TODO: Move to `Field`. #[inline] unsafe fn sub_canonical_u64(&self, rhs: u64) -> Self { // Default implementation. diff --git a/field/src/goldilocks_field.rs b/field/src/goldilocks_field.rs index 54866b1f..a121b4d2 100644 --- a/field/src/goldilocks_field.rs +++ b/field/src/goldilocks_field.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use crate::extension_field::quadratic::QuadraticExtension; use crate::extension_field::quartic::QuarticExtension; use crate::extension_field::{Extendable, Frobenius}; -use crate::field_types::{Field, PrimeField}; +use crate::field_types::{Field, Field64}; use crate::inversion::try_inverse_u64; const EPSILON: u64 = (1 << 32) - 1; @@ -123,7 +123,7 @@ impl Field for GoldilocksField { } } -impl PrimeField for GoldilocksField { +impl Field64 for GoldilocksField { const ORDER: u64 = 0xFFFFFFFF00000001; #[inline] diff --git a/field/src/inversion.rs b/field/src/inversion.rs index bbfb8e0d..10c02879 100644 --- a/field/src/inversion.rs +++ b/field/src/inversion.rs @@ -1,4 +1,4 @@ -use crate::field_types::PrimeField; +use crate::field_types::Field64; /// This is a 'safe' iteration for the modular inversion algorithm. It /// is safe in the sense that it will produce the right answer even @@ -63,7 +63,7 @@ unsafe fn unsafe_iteration(f: &mut u64, g: &mut u64, c: &mut i128, d: &mut i128, /// Elliptic and Hyperelliptic Cryptography, Algorithms 11.6 /// and 11.12. #[allow(clippy::many_single_char_names)] -pub(crate) fn try_inverse_u64(x: &F) -> Option { +pub(crate) fn try_inverse_u64(x: &F) -> Option { let mut f = x.to_noncanonical_u64(); let mut g = F::ORDER; // NB: These two are very rarely such that their absolute diff --git a/field/src/prime_field_testing.rs b/field/src/prime_field_testing.rs index 4aec6712..772336e9 100644 --- a/field/src/prime_field_testing.rs +++ b/field/src/prime_field_testing.rs @@ -1,4 +1,4 @@ -use crate::field_types::PrimeField; +use crate::field_types::Field64; /// Generates a series of non-negative integers less than `modulus` which cover a range of /// interesting test values. @@ -19,7 +19,7 @@ pub fn test_inputs(modulus: u64) -> Vec { /// word_bits)` and panic if the two resulting vectors differ. pub fn run_unaryop_test_cases(op: UnaryOp, expected_op: ExpectedOp) where - F: PrimeField, + F: Field64, UnaryOp: Fn(F) -> F, ExpectedOp: Fn(u64) -> u64, { @@ -43,7 +43,7 @@ where /// Apply the binary functions `op` and `expected_op` to each pair of inputs. pub fn run_binaryop_test_cases(op: BinaryOp, expected_op: ExpectedOp) where - F: PrimeField, + F: Field64, BinaryOp: Fn(F, F) -> F, ExpectedOp: Fn(u64, u64) -> u64, { @@ -70,7 +70,7 @@ macro_rules! test_prime_field_arithmetic { mod prime_field_arithmetic { use std::ops::{Add, Mul, Neg, Sub}; - use crate::field_types::{Field, PrimeField}; + use crate::field_types::{Field, Field64}; use crate::ops::Square; #[test] diff --git a/plonky2/src/bin/generate_constants.rs b/plonky2/src/bin/generate_constants.rs index d9757aff..d2744991 100644 --- a/plonky2/src/bin/generate_constants.rs +++ b/plonky2/src/bin/generate_constants.rs @@ -2,7 +2,7 @@ #![allow(clippy::needless_range_loop)] -use plonky2_field::field_types::PrimeField; +use plonky2_field::field_types::Field64; use plonky2_field::goldilocks_field::GoldilocksField; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; diff --git a/plonky2/src/gadgets/arithmetic.rs b/plonky2/src/gadgets/arithmetic.rs index 90f3b090..5bc8be07 100644 --- a/plonky2/src/gadgets/arithmetic.rs +++ b/plonky2/src/gadgets/arithmetic.rs @@ -1,7 +1,7 @@ use std::borrow::Borrow; use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::PrimeField; +use plonky2_field::field_types::Field64; use crate::gates::arithmetic_base::ArithmeticGate; use crate::gates::exponentiation::ExponentiationGate; @@ -325,7 +325,7 @@ impl, const D: usize> CircuitBuilder { /// Represents a base arithmetic operation in the circuit. Used to memoize results. #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub(crate) struct BaseArithmeticOperation { +pub(crate) struct BaseArithmeticOperation { const_0: F, const_1: F, multiplicand_0: Target, diff --git a/plonky2/src/gadgets/arithmetic_extension.rs b/plonky2/src/gadgets/arithmetic_extension.rs index 125fb49a..ae343aff 100644 --- a/plonky2/src/gadgets/arithmetic_extension.rs +++ b/plonky2/src/gadgets/arithmetic_extension.rs @@ -1,6 +1,6 @@ use plonky2_field::extension_field::FieldExtension; use plonky2_field::extension_field::{Extendable, OEF}; -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use plonky2_util::bits_u64; use crate::gates::arithmetic_extension::ArithmeticExtensionGate; @@ -544,7 +544,7 @@ impl, const D: usize> CircuitBuilder { /// Represents an extension arithmetic operation in the circuit. Used to memoize results. #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub(crate) struct ExtensionArithmeticOperation, const D: usize> { +pub(crate) struct ExtensionArithmeticOperation, const D: usize> { const_0: F, const_1: F, multiplicand_0: ExtensionTarget, diff --git a/plonky2/src/gates/assert_le.rs b/plonky2/src/gates/assert_le.rs index c385bb31..c087a963 100644 --- a/plonky2/src/gates/assert_le.rs +++ b/plonky2/src/gates/assert_le.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; @@ -25,7 +25,7 @@ use crate::plonk::vars::{ /// A gate for checking that one value is less than or equal to another. #[derive(Clone, Debug)] -pub struct AssertLessThanGate, const D: usize> { +pub struct AssertLessThanGate, const D: usize> { pub(crate) num_bits: usize, pub(crate) num_chunks: usize, _phantom: PhantomData, @@ -455,7 +455,7 @@ mod tests { use anyhow::Result; use plonky2_field::extension_field::quartic::QuarticExtension; - use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::field_types::{Field, Field64}; use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; diff --git a/plonky2/src/gates/base_sum.rs b/plonky2/src/gates/base_sum.rs index a5391abf..e03a2c5b 100644 --- a/plonky2/src/gates/base_sum.rs +++ b/plonky2/src/gates/base_sum.rs @@ -1,7 +1,7 @@ use std::ops::Range; use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; use crate::gates::gate::Gate; @@ -31,7 +31,7 @@ impl BaseSumGate { Self { num_limbs } } - pub fn new_from_config(config: &CircuitConfig) -> Self { + pub fn new_from_config(config: &CircuitConfig) -> Self { let num_limbs = F::BITS.min(config.num_routed_wires - Self::START_LIMBS); Self::new(num_limbs) } diff --git a/plonky2/src/gates/comparison.rs b/plonky2/src/gates/comparison.rs index 424ecb5b..bc3e69b9 100644 --- a/plonky2/src/gates/comparison.rs +++ b/plonky2/src/gates/comparison.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use plonky2_field::extension_field::Extendable; -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use plonky2_field::packed_field::PackedField; use plonky2_util::{bits_u64, ceil_div_usize}; @@ -23,7 +23,7 @@ use crate::plonk::vars::{ /// A gate for checking that one value is less than or equal to another. #[derive(Clone, Debug)] -pub struct ComparisonGate, const D: usize> { +pub struct ComparisonGate, const D: usize> { pub(crate) num_bits: usize, pub(crate) num_chunks: usize, _phantom: PhantomData, @@ -520,7 +520,7 @@ mod tests { use std::marker::PhantomData; use anyhow::Result; - use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::field_types::{Field, Field64}; use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; diff --git a/plonky2/src/gates/subtraction_u32.rs b/plonky2/src/gates/subtraction_u32.rs index f083db5a..80bc03ed 100644 --- a/plonky2/src/gates/subtraction_u32.rs +++ b/plonky2/src/gates/subtraction_u32.rs @@ -338,7 +338,7 @@ mod tests { use anyhow::Result; use plonky2_field::extension_field::quartic::QuarticExtension; - use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::field_types::{Field, Field64}; use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; diff --git a/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs b/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs index f903cd96..f2276506 100644 --- a/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs +++ b/plonky2/src/hash/arch/aarch64/poseidon_goldilocks_neon.rs @@ -3,7 +3,7 @@ use std::arch::aarch64::*; use std::arch::asm; -use plonky2_field::field_types::PrimeField; +use plonky2_field::field_types::Field64; use plonky2_field::goldilocks_field::GoldilocksField; use plonky2_util::branch_hint; use static_assertions::const_assert; diff --git a/plonky2/src/hash/hash_types.rs b/plonky2/src/hash/hash_types.rs index 51a93fdc..ed6fca43 100644 --- a/plonky2/src/hash/hash_types.rs +++ b/plonky2/src/hash/hash_types.rs @@ -1,4 +1,4 @@ -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use plonky2_field::goldilocks_field::GoldilocksField; use rand::Rng; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -8,7 +8,7 @@ use crate::iop::target::Target; use crate::plonk::config::GenericHashOut; /// A prime order field with the features we need to use it as a base field in our argument system. -pub trait RichField: PrimeField + Poseidon {} +pub trait RichField: Field64 + Poseidon {} impl RichField for GoldilocksField {} diff --git a/plonky2/src/hash/poseidon.rs b/plonky2/src/hash/poseidon.rs index 9dc5f394..d2b47932 100644 --- a/plonky2/src/hash/poseidon.rs +++ b/plonky2/src/hash/poseidon.rs @@ -2,7 +2,7 @@ //! https://eprint.iacr.org/2019/458.pdf use plonky2_field::extension_field::{Extendable, FieldExtension}; -use plonky2_field::field_types::{Field, PrimeField}; +use plonky2_field::field_types::{Field, Field64}; use unroll::unroll_for_loops; use crate::gates::gate::Gate; @@ -35,7 +35,7 @@ fn add_u160_u128((x_lo, x_hi): (u128, u32), y: u128) -> (u128, u32) { } #[inline(always)] -fn reduce_u160((n_lo, n_hi): (u128, u32)) -> F { +fn reduce_u160((n_lo, n_hi): (u128, u32)) -> F { let n_lo_hi = (n_lo >> 64) as u64; let n_lo_lo = n_lo as u64; let reduced_hi: u64 = F::from_noncanonical_u96((n_lo_hi, n_hi)).to_noncanonical_u64(); @@ -148,7 +148,7 @@ pub const ALL_ROUND_CONSTANTS: [u64; MAX_WIDTH * N_ROUNDS] = [ ]; const WIDTH: usize = SPONGE_WIDTH; -pub trait Poseidon: PrimeField { +pub trait Poseidon: Field64 { // Total number of round constants required: width of the input // times number of rounds. const N_ROUND_CONSTANTS: usize = WIDTH * N_ROUNDS; diff --git a/plonky2/src/hash/poseidon_goldilocks.rs b/plonky2/src/hash/poseidon_goldilocks.rs index b8f63ab4..ab886847 100644 --- a/plonky2/src/hash/poseidon_goldilocks.rs +++ b/plonky2/src/hash/poseidon_goldilocks.rs @@ -270,7 +270,7 @@ impl Poseidon for GoldilocksField { #[cfg(test)] mod tests { - use plonky2_field::field_types::{Field, PrimeField}; + use plonky2_field::field_types::{Field, Field64}; use plonky2_field::goldilocks_field::GoldilocksField as F; use crate::hash::poseidon::test_helpers::{check_consistency, check_test_vectors}; diff --git a/plonky2/src/util/serialization.rs b/plonky2/src/util/serialization.rs index 45a463a8..adc8baee 100644 --- a/plonky2/src/util/serialization.rs +++ b/plonky2/src/util/serialization.rs @@ -3,7 +3,7 @@ use std::io::Cursor; use std::io::{Read, Result, Write}; use plonky2_field::extension_field::{Extendable, FieldExtension}; -use plonky2_field::field_types::PrimeField; +use plonky2_field::field_types::Field64; use plonky2_field::polynomial::PolynomialCoeffs; use crate::fri::proof::{ @@ -53,10 +53,10 @@ impl Buffer { Ok(u32::from_le_bytes(buf)) } - fn write_field(&mut self, x: F) -> Result<()> { + fn write_field(&mut self, x: F) -> Result<()> { self.0.write_all(&x.to_canonical_u64().to_le_bytes()) } - fn read_field(&mut self) -> Result { + fn read_field(&mut self) -> Result { let mut buf = [0; std::mem::size_of::()]; self.0.read_exact(&mut buf)?; Ok(F::from_canonical_u64(u64::from_le_bytes( @@ -116,13 +116,13 @@ impl Buffer { )) } - pub fn write_field_vec(&mut self, v: &[F]) -> Result<()> { + pub fn write_field_vec(&mut self, v: &[F]) -> Result<()> { for &a in v { self.write_field(a)?; } Ok(()) } - pub fn read_field_vec(&mut self, length: usize) -> Result> { + pub fn read_field_vec(&mut self, length: usize) -> Result> { (0..length) .map(|_| self.read_field()) .collect::>>() diff --git a/waksman/src/sorting.rs b/waksman/src/sorting.rs index b3e616d5..b154436e 100644 --- a/waksman/src/sorting.rs +++ b/waksman/src/sorting.rs @@ -183,7 +183,7 @@ impl, const D: usize> SimpleGenerator #[cfg(test)] mod tests { use anyhow::Result; - use plonky2::field::field_types::{Field, PrimeField}; + use plonky2::field::field_types::{Field, Field64}; use plonky2::iop::witness::PartialWitness; use plonky2::plonk::circuit_data::CircuitConfig; use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};