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 conversion from base prime field to field #440

Merged
merged 4 commits into from
Jul 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- `SWModelParameters` → `SWCurveConfig`
- `TEModelParameters` → `TECurveConfig`
- `MontgomeryModelParameters` → `MontCurveConfig`
- [\#440](https://github.com/arkworks-rs/algebra/pull/440) (`ark-ff`) Add a method to construct a field element from an element of the underlying base prime field.

### Features

Expand Down
10 changes: 10 additions & 0 deletions ff/src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ pub trait Field:
/// If the slice length != Self::extension_degree(), must return None.
fn from_base_prime_field_elems(elems: &[Self::BasePrimeField]) -> Option<Self>;

/// Constructs a field element from a single base prime field elements.
/// ```
/// # use ark_ff::Field;
/// # use ark_test_curves::bls12_381::Fq as F;
/// # use ark_test_curves::bls12_381::Fq2 as F2;
/// # use ark_std::One;
/// assert_eq!(F2::from_base_prime_field(F::one()), F2::one());
/// ```
fn from_base_prime_field(elem: Self::BasePrimeField) -> Self;

/// Returns `self + self`.
#[must_use]
fn double(&self) -> Self;
Expand Down
47 changes: 30 additions & 17 deletions ff/src/fields/models/cubic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,7 @@ impl<P: CubicExtConfig> CubicExtField<P> {

impl<P: CubicExtConfig> Zero for CubicExtField<P> {
fn zero() -> Self {
Self::new(
P::BaseField::zero(),
P::BaseField::zero(),
P::BaseField::zero(),
)
Self::new(P::BaseField::ZERO, P::BaseField::ZERO, P::BaseField::ZERO)
}

fn is_zero(&self) -> bool {
Expand All @@ -148,11 +144,7 @@ impl<P: CubicExtConfig> Zero for CubicExtField<P> {

impl<P: CubicExtConfig> One for CubicExtField<P> {
fn one() -> Self {
Self::new(
P::BaseField::one(),
P::BaseField::zero(),
P::BaseField::zero(),
)
Self::new(P::BaseField::ONE, P::BaseField::ZERO, P::BaseField::ZERO)
}

fn is_one(&self) -> bool {
Expand All @@ -172,6 +164,11 @@ impl<P: CubicExtConfig> Field for CubicExtField<P> {
3 * P::BaseField::extension_degree()
}

fn from_base_prime_field(elem: Self::BasePrimeField) -> Self {
let fe = P::BaseField::from_base_prime_field(elem);
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}

fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter {
self.c0.to_base_prime_field_elements().chain(
self.c1
Expand Down Expand Up @@ -344,7 +341,7 @@ impl<P: CubicExtConfig> Zeroize for CubicExtField<P> {
impl<P: CubicExtConfig> From<u128> for CubicExtField<P> {
fn from(other: u128) -> Self {
let fe: P::BaseField = other.into();
Self::new(fe, P::BaseField::zero(), P::BaseField::zero())
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}
}

Expand All @@ -363,7 +360,7 @@ impl<P: CubicExtConfig> From<i128> for CubicExtField<P> {
impl<P: CubicExtConfig> From<u64> for CubicExtField<P> {
fn from(other: u64) -> Self {
let fe: P::BaseField = other.into();
Self::new(fe, P::BaseField::zero(), P::BaseField::zero())
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}
}

Expand All @@ -382,7 +379,7 @@ impl<P: CubicExtConfig> From<i64> for CubicExtField<P> {
impl<P: CubicExtConfig> From<u32> for CubicExtField<P> {
fn from(other: u32) -> Self {
let fe: P::BaseField = other.into();
Self::new(fe, P::BaseField::zero(), P::BaseField::zero())
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}
}

Expand All @@ -401,7 +398,7 @@ impl<P: CubicExtConfig> From<i32> for CubicExtField<P> {
impl<P: CubicExtConfig> From<u16> for CubicExtField<P> {
fn from(other: u16) -> Self {
let fe: P::BaseField = other.into();
Self::new(fe, P::BaseField::zero(), P::BaseField::zero())
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}
}

Expand All @@ -420,7 +417,7 @@ impl<P: CubicExtConfig> From<i16> for CubicExtField<P> {
impl<P: CubicExtConfig> From<u8> for CubicExtField<P> {
fn from(other: u8) -> Self {
let fe: P::BaseField = other.into();
Self::new(fe, P::BaseField::zero(), P::BaseField::zero())
Self::new(fe, P::BaseField::ZERO, P::BaseField::ZERO)
}
}

Expand All @@ -440,8 +437,8 @@ impl<P: CubicExtConfig> From<bool> for CubicExtField<P> {
fn from(other: bool) -> Self {
Self::new(
u8::from(other).into(),
P::BaseField::zero(),
P::BaseField::zero(),
P::BaseField::ZERO,
P::BaseField::ZERO,
)
}
}
Expand Down Expand Up @@ -699,4 +696,20 @@ mod cube_ext_tests {
assert_eq!(actual, expected);
}
}

#[test]
fn test_from_base_prime_field_element() {
let ext_degree = Fq6::extension_degree() as usize;
let max_num_elems_to_test = 10;
for _ in 0..max_num_elems_to_test {
let mut random_coeffs = vec![Fq::zero(); ext_degree];
let random_coeff = Fq::rand(&mut test_rng());
let res = Fq6::from_base_prime_field(random_coeff);
random_coeffs[0] = random_coeff;
assert_eq!(
res,
Fq6::from_base_prime_field_elems(&random_coeffs).unwrap()
);
}
}
}
4 changes: 4 additions & 0 deletions ff/src/fields/models/fp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ impl<P: FpConfig<N>, const N: usize> Field for Fp<P, N> {
1
}

fn from_base_prime_field(elem: Self::BasePrimeField) -> Self {
elem
}

fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter {
iter::once(*self)
}
Expand Down
37 changes: 29 additions & 8 deletions ff/src/fields/models/quadratic_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ impl<P: QuadExtConfig> Field for QuadExtField<P> {
2 * P::BaseField::extension_degree()
}

fn from_base_prime_field(elem: Self::BasePrimeField) -> Self {
let fe = P::BaseField::from_base_prime_field(elem);
Self::new(fe, P::BaseField::ZERO)
}

fn to_base_prime_field_elements(&self) -> Self::BasePrimeFieldIter {
self.c0
.to_base_prime_field_elements()
Expand Down Expand Up @@ -410,12 +415,12 @@ where
// so either a0 = sqrt(c0) or a1 = sqrt(c0/P::NONRESIDUE)
if self.c0.legendre().is_qr() {
// either c0 is a valid sqrt in the base field
return self.c0.sqrt().map(|c0| Self::new(c0, P::BaseField::zero()));
return self.c0.sqrt().map(|c0| Self::new(c0, P::BaseField::ZERO));
} else {
// or we need to compute sqrt(c0/P::NONRESIDUE)
return (self.c0.div(P::NONRESIDUE))
.sqrt()
.map(|res| Self::new(P::BaseField::zero(), res));
.map(|res| Self::new(P::BaseField::ZERO, res));
}
}
// Try computing the square root
Expand Down Expand Up @@ -497,7 +502,7 @@ impl<P: QuadExtConfig> Zeroize for QuadExtField<P> {

impl<P: QuadExtConfig> From<u128> for QuadExtField<P> {
fn from(other: u128) -> Self {
Self::new(other.into(), P::BaseField::zero())
Self::new(other.into(), P::BaseField::ZERO)
}
}

Expand All @@ -515,7 +520,7 @@ impl<P: QuadExtConfig> From<i128> for QuadExtField<P> {

impl<P: QuadExtConfig> From<u64> for QuadExtField<P> {
fn from(other: u64) -> Self {
Self::new(other.into(), P::BaseField::zero())
Self::new(other.into(), P::BaseField::ZERO)
}
}

Expand All @@ -533,7 +538,7 @@ impl<P: QuadExtConfig> From<i64> for QuadExtField<P> {

impl<P: QuadExtConfig> From<u32> for QuadExtField<P> {
fn from(other: u32) -> Self {
Self::new(other.into(), P::BaseField::zero())
Self::new(other.into(), P::BaseField::ZERO)
}
}

Expand All @@ -551,7 +556,7 @@ impl<P: QuadExtConfig> From<i32> for QuadExtField<P> {

impl<P: QuadExtConfig> From<u16> for QuadExtField<P> {
fn from(other: u16) -> Self {
Self::new(other.into(), P::BaseField::zero())
Self::new(other.into(), P::BaseField::ZERO)
}
}

Expand All @@ -569,7 +574,7 @@ impl<P: QuadExtConfig> From<i16> for QuadExtField<P> {

impl<P: QuadExtConfig> From<u8> for QuadExtField<P> {
fn from(other: u8) -> Self {
Self::new(other.into(), P::BaseField::zero())
Self::new(other.into(), P::BaseField::ZERO)
}
}

Expand All @@ -587,7 +592,7 @@ impl<P: QuadExtConfig> From<i8> for QuadExtField<P> {

impl<P: QuadExtConfig> From<bool> for QuadExtField<P> {
fn from(other: bool) -> Self {
Self::new(u8::from(other).into(), P::BaseField::zero())
Self::new(u8::from(other).into(), P::BaseField::ZERO)
}
}

Expand Down Expand Up @@ -802,4 +807,20 @@ mod quad_ext_tests {
assert_eq!(actual, expected);
}
}

#[test]
fn test_from_base_prime_field_element() {
let ext_degree = Fq2::extension_degree() as usize;
let max_num_elems_to_test = 10;
for _ in 0..max_num_elems_to_test {
let mut random_coeffs = vec![Fq::zero(); ext_degree];
let random_coeff = Fq::rand(&mut test_rng());
let res = Fq2::from_base_prime_field(random_coeff);
random_coeffs[0] = random_coeff;
assert_eq!(
res,
Fq2::from_base_prime_field_elems(&random_coeffs).unwrap()
);
}
}
}