trait api to expose u64

This commit is contained in:
zhenfei
2024-02-25 20:51:45 -05:00
parent bffec3f0a7
commit 27a362fe11
2 changed files with 52 additions and 11 deletions

View File

@@ -11,6 +11,9 @@ use serde::Serialize;
use crate::{fp2::GoldilocksExt2, Goldilocks, GoldilocksExt3};
pub trait SmallField: Serialize + SerdeObject + FromUniformBytes<64> + Hash {
/// MODULUS as u64
const MODULUS_U64: u64 = 0xFFFFFFFF00000001;
/// Base field
type BaseField: SmallField + FromUniformBytes<64>;
@@ -23,9 +26,24 @@ pub trait SmallField: Serialize + SerdeObject + FromUniformBytes<64> + Hash {
/// Convert a byte string into a list of field elements
fn bytes_to_field_elements(bytes: &[u8]) -> Vec<Self>;
/// Convert a field elements to a u64.
fn to_canonical_u64(&self) -> u64 {
// not supported
unimplemented!()
}
/// Convert a field elements to a u64. Do not normalize it.
fn to_noncanonical_u64(&self) -> u64 {
// not supported
unimplemented!()
}
/// Convert a field elements to a u64 vector
fn to_canonical_u64_vec(&self) -> Vec<u64>;
/// Convert a field elements to a u64 vector. Do not normalize it.
fn to_noncanonical_u64_vec(&self) -> Vec<u64>;
/// Convert self to limbs of Goldilocks elements
fn to_limbs(&self) -> Vec<Self::BaseField>;
@@ -62,10 +80,27 @@ impl SmallField for Goldilocks {
.collect::<Vec<_>>()
}
fn to_canonical_u64(&self) -> u64 {
let mut c = self.0;
// We only need one condition subtraction, since 2 * ORDER would not fit in a u64.
if c >= Self::MODULUS_U64 {
c -= Self::MODULUS_U64;
}
c
}
fn to_noncanonical_u64(&self) -> u64 {
self.0
}
fn to_canonical_u64_vec(&self) -> Vec<u64> {
vec![self.to_canonical_u64()]
}
fn to_noncanonical_u64_vec(&self) -> Vec<u64> {
vec![self.to_noncanonical_u64()]
}
fn to_limbs(&self) -> Vec<Goldilocks> {
vec![*self]
}
@@ -104,8 +139,13 @@ impl SmallField for GoldilocksExt2 {
.iter()
.map(|a| a.to_canonical_u64())
.collect::<Vec<u64>>()
.try_into()
.unwrap()
}
fn to_noncanonical_u64_vec(&self) -> Vec<u64> {
self.0
.iter()
.map(|a| a.to_noncanonical_u64())
.collect::<Vec<u64>>()
}
fn to_limbs(&self) -> Vec<Goldilocks> {
@@ -148,8 +188,13 @@ impl SmallField for GoldilocksExt3 {
.iter()
.map(|a| a.to_canonical_u64())
.collect::<Vec<u64>>()
.try_into()
.unwrap()
}
fn to_noncanonical_u64_vec(&self) -> Vec<u64> {
self.0
.iter()
.map(|a| a.to_noncanonical_u64())
.collect::<Vec<u64>>()
}
fn to_limbs(&self) -> Vec<Goldilocks> {

View File

@@ -10,6 +10,7 @@ use rand_core::RngCore;
use serde::{Deserialize, Serialize};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use crate::field::SmallField;
use crate::util::{add_no_canonicalize_trashing_input, branch_hint, split, sqrt_tonelli_shanks};
use crate::util::{assume, try_inverse_u64};
@@ -525,13 +526,8 @@ fn reduce128(x: u128) -> Goldilocks {
impl Goldilocks {
#[inline]
pub fn to_canonical_u64(&self) -> u64 {
let mut c = self.0;
// We only need one condition subtraction, since 2 * ORDER would not fit in a u64.
if c >= MODULUS {
c -= MODULUS;
}
c
pub fn to_noncanonical_u64(&self) -> u64 {
self.0
}
pub const fn size() -> usize {