Rename PrimeField -> Field64 (#454)

* Rename `PrimeField` -> `Field64`

And add TODOs for moving around various methods which aren't well-defined in their current traits, or would be well-defined in a supertrait.

* fix test

* TODOs as per PR feedback
This commit is contained in:
Daniel Lubarov 2022-02-01 22:40:19 -08:00 committed by GitHub
parent 8e07058ad2
commit 43800ba23d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 61 additions and 45 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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]

View File

@ -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<F: PrimeField>(x: &F) -> Option<F> {
pub(crate) fn try_inverse_u64<F: Field64>(x: &F) -> Option<F> {
let mut f = x.to_noncanonical_u64();
let mut g = F::ORDER;
// NB: These two are very rarely such that their absolute

View File

@ -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<u64> {
/// word_bits)` and panic if the two resulting vectors differ.
pub fn run_unaryop_test_cases<F, UnaryOp, ExpectedOp>(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<F, BinaryOp, ExpectedOp>(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]

View File

@ -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;

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Represents a base arithmetic operation in the circuit. Used to memoize results.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct BaseArithmeticOperation<F: PrimeField> {
pub(crate) struct BaseArithmeticOperation<F: Field64> {
const_0: F,
const_1: F,
multiplicand_0: Target,

View File

@ -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<F: RichField + Extendable<D>, const D: usize> CircuitBuilder<F, D> {
/// Represents an extension arithmetic operation in the circuit. Used to memoize results.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub(crate) struct ExtensionArithmeticOperation<F: PrimeField + Extendable<D>, const D: usize> {
pub(crate) struct ExtensionArithmeticOperation<F: Field64 + Extendable<D>, const D: usize> {
const_0: F,
const_1: F,
multiplicand_0: ExtensionTarget<D>,

View File

@ -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<F: PrimeField + Extendable<D>, const D: usize> {
pub struct AssertLessThanGate<F: Field64 + Extendable<D>, const D: usize> {
pub(crate) num_bits: usize,
pub(crate) num_chunks: usize,
_phantom: PhantomData<F>,
@ -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;

View File

@ -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<const B: usize> BaseSumGate<B> {
Self { num_limbs }
}
pub fn new_from_config<F: PrimeField>(config: &CircuitConfig) -> Self {
pub fn new_from_config<F: Field64>(config: &CircuitConfig) -> Self {
let num_limbs = F::BITS.min(config.num_routed_wires - Self::START_LIMBS);
Self::new(num_limbs)
}

View File

@ -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<F: PrimeField + Extendable<D>, const D: usize> {
pub struct ComparisonGate<F: Field64 + Extendable<D>, const D: usize> {
pub(crate) num_bits: usize,
pub(crate) num_chunks: usize,
_phantom: PhantomData<F>,
@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {}

View File

@ -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<F: PrimeField>((n_lo, n_hi): (u128, u32)) -> F {
fn reduce_u160<F: Field64>((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;

View File

@ -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};

View File

@ -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<F: PrimeField>(&mut self, x: F) -> Result<()> {
fn write_field<F: Field64>(&mut self, x: F) -> Result<()> {
self.0.write_all(&x.to_canonical_u64().to_le_bytes())
}
fn read_field<F: PrimeField>(&mut self) -> Result<F> {
fn read_field<F: Field64>(&mut self) -> Result<F> {
let mut buf = [0; std::mem::size_of::<u64>()];
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<F: PrimeField>(&mut self, v: &[F]) -> Result<()> {
pub fn write_field_vec<F: Field64>(&mut self, v: &[F]) -> Result<()> {
for &a in v {
self.write_field(a)?;
}
Ok(())
}
pub fn read_field_vec<F: PrimeField>(&mut self, length: usize) -> Result<Vec<F>> {
pub fn read_field_vec<F: Field64>(&mut self, length: usize) -> Result<Vec<F>> {
(0..length)
.map(|_| self.read_field())
.collect::<Result<Vec<_>>>()

View File

@ -183,7 +183,7 @@ impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
#[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};