Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Babybear field #549

Merged
merged 14 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions math/src/field/fields/fft_friendly/babybear.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use crate::{
field::{
element::FieldElement,
fields::montgomery_backed_prime_fields::{IsModulus, MontgomeryBackendPrimeField},
traits::IsFFTField,
},
unsigned_integer::element::{UnsignedInteger, U64},
};

pub type U64MontgomeryBackendPrimeField<T> = MontgomeryBackendPrimeField<T, 1>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MontgomeryConfigBabybear31PrimeField;
impl IsModulus<U64> for MontgomeryConfigBabybear31PrimeField {
//Babybear Prime p = 2^31 - 2^27 + 1 = 0x78000001
const MODULUS: U64 = U64::from_u64(2013265921);
}

pub type Babybear31PrimeField =
U64MontgomeryBackendPrimeField<MontgomeryConfigBabybear31PrimeField>;

// 21^(2^24)=1 mod 2013265921
// 2^27(2^4-1)+1 where n=27 (two-adicity) and k=2^4+1
impl IsFFTField for Babybear31PrimeField {
const TWO_ADICITY: u64 = 27;

const TWO_ADIC_PRIMITVE_ROOT_OF_UNITY: Self::BaseType = UnsignedInteger { limbs: [21] };

fn field_name() -> &'static str {
"babybear31"
}
}

impl FieldElement<Babybear31PrimeField> {
pub fn to_bytes_le(&self) -> [u8; 8] {
let limbs = self.representative().limbs;
limbs[0].to_le_bytes()
}

pub fn to_bytes_be(&self) -> [u8; 8] {
let limbs = self.representative().limbs;
limbs[0].to_be_bytes()
}
}

impl PartialOrd for FieldElement<Babybear31PrimeField> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.representative().partial_cmp(&other.representative())
}
}

impl Ord for FieldElement<Babybear31PrimeField> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.representative().cmp(&other.representative())
}
}
Comment on lines +33 to +43
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed, but it's ok, we can document this later and remove if needed. Doesn't hurt either


#[cfg(test)]
mod test_babybear_31_bytes_ops {
use super::Babybear31PrimeField;
use crate::{field::element::FieldElement, traits::ByteConversion};

#[test]
#[cfg(feature = "std")]
fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_le() {
let element = FieldElement::<Babybear31PrimeField>::from_hex_unchecked(
"\
0123456701234567\
",
);
let bytes = element.to_bytes_le();
let expected_bytes: [u8; 8] = ByteConversion::to_bytes_le(&element).try_into().unwrap();
assert_eq!(bytes, expected_bytes);
}

#[test]
#[cfg(feature = "std")]
fn byte_serialization_for_a_number_matches_with_byte_conversion_implementation_be() {
let element = FieldElement::<Babybear31PrimeField>::from_hex_unchecked(
"\
0123456701234567\
",
);
let bytes = element.to_bytes_be();
let expected_bytes: [u8; 8] = ByteConversion::to_bytes_be(&element).try_into().unwrap();
assert_eq!(bytes, expected_bytes);
}

#[test]

fn byte_serialization_and_deserialization_works_le() {
let element = FieldElement::<Babybear31PrimeField>::from_hex_unchecked(
"\
7654321076543210\
",
);
let bytes = element.to_bytes_le();
let from_bytes = FieldElement::<Babybear31PrimeField>::from_bytes_le(&bytes).unwrap();
assert_eq!(element, from_bytes);
}

#[test]

fn byte_serialization_and_deserialization_works_be() {
let element = FieldElement::<Babybear31PrimeField>::from_hex_unchecked(
"\
7654321076543210\
",
);
let bytes = element.to_bytes_be();
let from_bytes = FieldElement::<Babybear31PrimeField>::from_bytes_be(&bytes).unwrap();
assert_eq!(element, from_bytes);
}
}
2 changes: 2 additions & 0 deletions math/src/field/fields/fft_friendly/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/// Implemenation of the Babybear Prime field p = 2^31 - 2^27 + 1
pub mod babybear;
/// Implementation of two-adic prime field over 256 bit unsigned integers.
pub mod stark_252_prime_field;
1 change: 1 addition & 0 deletions math/src/unsigned_integer/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use core::fmt::{self, Debug, Display};
pub type U384 = UnsignedInteger<6>;
pub type U256 = UnsignedInteger<4>;
pub type U128 = UnsignedInteger<2>;
pub type U64 = UnsignedInteger<1>;

/// A big unsigned integer in base 2^{64} represented
/// as fixed-size array `limbs` of `u64` components.
Expand Down