Skip to content

Commit

Permalink
add test
Browse files Browse the repository at this point in the history
  • Loading branch information
lonerapier committed May 7, 2024
1 parent 37b8f66 commit 50651e1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 17 deletions.
98 changes: 91 additions & 7 deletions src/field/gf_101_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,41 @@ use std::ops::{Div, DivAssign, MulAssign, Rem};

use serde::{Deserialize, Serialize};

use super::ExtensionField;
use crate::field::FiniteField;

/// Pluto curve with modulus 101 supports two degree extension field. This can be verified
/// by finding out embedding degree of the curve, i.e. smallest k: r|q^k-1
const EXT_DEGREE: usize = 2;
const QUADRATIC_EXTENSION_FIELD_ORDER: u32 = 10201;
const QUADRATIC_EXTENSION_FIELD_ORDER: u32 = 101 * 101;

#[derive(Clone, Default, Copy, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]

/// Quadratic Extension field element represented as polynomial of degree 1 in form:
/// a_0 + a_1*t where {a_0, a_1} \in \mathhbb{F}. Uses irreducible poly of the form:
/// (X^2-K).
pub struct QuadraticExtensionField<F: FiniteField> {
pub(crate) value: [F; 2],
}

impl<F: FiniteField> QuadraticExtensionField<F> {
const D: usize = 2;

fn residue() -> F { F::from_canonical_u32(2) }
/// irreducible polynomial used to reduce field polynomials to second degree:
/// F[X]/(X^2-K)
fn irreducible() -> F { F::from_canonical_u32(2) }
}

impl<F: FiniteField> ExtensionField<F> for QuadraticExtensionField<F> {
const D: usize = EXT_DEGREE;

fn irreducible() -> F { Self::irreducible() }

fn from_base(b: F) -> Self { Self { value: [b, F::zero()] } }
}

impl<F: FiniteField> From<F> for QuadraticExtensionField<F> {
fn from(value: F) -> Self { Self::from_base(value) }
}

impl<F: FiniteField> FiniteField for QuadraticExtensionField<F> {
Expand All @@ -30,11 +50,11 @@ impl<F: FiniteField> FiniteField for QuadraticExtensionField<F> {

fn zero() -> Self { Self { value: [F::zero(); EXT_DEGREE] } }

fn one() -> Self { Self { value: [F::one(); EXT_DEGREE] } }
fn one() -> Self { Self { value: [F::one(), F::zero()] } }

fn two() -> Self { Self { value: [F::two(); EXT_DEGREE] } }
fn two() -> Self { Self { value: [F::two(), F::zero()] } }

fn neg_one() -> Self { Self { value: [F::neg_one(); EXT_DEGREE] } }
fn neg_one() -> Self { Self { value: [F::neg_one(), F::zero()] } }

fn generator() -> Self { Self { value: [F::from_canonical_u32(15), F::from_canonical_u32(20)] } }

Expand All @@ -45,7 +65,7 @@ impl<F: FiniteField> FiniteField for QuadraticExtensionField<F> {

let mut res = Self::default();
let scalar =
(self.value[0].square() - Self::residue() * self.value[1].square()).inverse().unwrap();
(self.value[0].square() - Self::irreducible() * self.value[1].square()).inverse().unwrap();
res.value[0] = self.value[0] * scalar;
res.value[1] = -self.value[1] * scalar;
Some(res)
Expand Down Expand Up @@ -125,7 +145,7 @@ impl<F: FiniteField> Mul for QuadraticExtensionField<F> {
let a = self.value;
let b = rhs.value;
let mut res = Self::default();
res.value[0] = a[0].clone() * b[0].clone() + a[1].clone() * a[1].clone() * Self::residue();
res.value[0] = a[0].clone() * b[0].clone() + a[1].clone() * a[1].clone() * Self::irreducible();
res.value[1] = a[0].clone() * b[1].clone() + a[1].clone() * b[0].clone();
res
}
Expand Down Expand Up @@ -157,3 +177,67 @@ impl<F: FiniteField> Rem for QuadraticExtensionField<F> {

fn rem(self, rhs: Self) -> Self::Output { self - (self / rhs) * rhs }
}

#[cfg(test)]
mod tests {

use super::*;
use crate::field::gf_101::GF101;
type F = GF101;
type F2 = QuadraticExtensionField<GF101>;
use rand::{thread_rng, Rng};

#[test]
fn test_field() {
let order = F2::ORDER;
assert_eq!(order, 101 * 101);

let degree = F2::D;
assert_eq!(2, degree);
}

#[test]
fn test_from_base() {
let x = F::new(10);
let x_2 = F2::from_base(x);

assert_eq!(x_2.value[0], F::new(10));
assert_eq!(x_2.value[1], F::new(0));
}

#[test]
fn test_add_sub_neg_mul() {
let mut rng = rand::thread_rng();
let x = F2::from_base(rng.gen::<F>());
let y = F2::from_base(rng.gen::<F>());
let z = F2::from_base(rng.gen::<F>());
assert_eq!(x + (-x), F2::zero());
assert_eq!(-x, F2::zero() - x);
assert_eq!(x + x, x * F2::two());
assert_eq!(x * (-x), -(x * x));
assert_eq!(x + y, y + x);
assert_eq!(x * y, y * x);
assert_eq!(x * (y * z), (x * y) * z);
assert_eq!(x - (y + z), (x - y) - z);
assert_eq!((x + y) - z, x + (y - z));
assert_eq!(x * (y + z), x * y + x * z);
assert_eq!(x + y + z + x + y + z, [x, x, y, y, z, z].iter().cloned().sum());
}

#[test]
fn test_inv_div() {
let mut rng = rand::thread_rng();
let x = F2::from_base(rng.gen::<F>());
let y = F2::from_base(rng.gen::<F>());
let z = F2::from_base(rng.gen::<F>());
assert_eq!(x * x.inverse().unwrap(), F2::one());
assert_eq!(x.inverse().unwrap_or(F2::one()) * x, F2::one());
assert_eq!(
x.square().inverse().unwrap_or(F2::one()),
x.inverse().unwrap_or(F2::one()).square()
);
assert_eq!((x / y) * y, x);
assert_eq!(x / (y * z), (x / y) / z);
assert_eq!((x * y) / z, x * (y / z));
}
}
13 changes: 3 additions & 10 deletions src/field/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,9 @@ pub trait FiniteField:
}
}

pub trait ExtensionField<Base: FiniteField>:
FiniteField
+ From<Base>
+ Add<Base, Output = Self>
+ AddAssign<Base>
+ Sub<Base, Output = Self>
+ SubAssign<Base>
+ Mul<Base, Output = Self>
+ MulAssign<Base> {
/// A Finite field extension trait
pub trait ExtensionField<Base: FiniteField>: FiniteField + From<Base> {
const D: usize;
fn irreducible() -> Self;
fn irreducible() -> Base;
fn from_base(b: Base) -> Self;
}

0 comments on commit 50651e1

Please sign in to comment.