use crate::field::{
element::FieldElement,
errors::FieldError,
extensions::{
cubic::{CubicExtensionField, HasCubicNonResidue},
quadratic::{HasQuadraticNonResidue, QuadraticExtensionField},
},
traits::IsField,
};
use super::field::Mersenne31Field;
#[derive(Clone, Debug)]
pub struct Mersenne31Complex;
impl IsField for Mersenne31Complex {
type BaseType = [FieldElement<Mersenne31Field>; 2];
fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
[a[0] + b[0], a[1] + b[1]]
}
fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
let a0b0 = a[0] * b[0];
let a1b1 = a[1] * b[1];
let z = (a[0] + a[1]) * (b[0] + b[1]);
[a0b0 - a1b1, z - a0b0 - a1b1]
}
fn square(a: &Self::BaseType) -> Self::BaseType {
let [a0, a1] = a;
let v0 = a0 * a1;
let c0 = (a0 + a1) * (a0 - a1);
let c1 = v0 + v0;
[c0, c1]
}
fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
[a[0] - b[0], a[1] - b[1]]
}
fn neg(a: &Self::BaseType) -> Self::BaseType {
[-a[0], -a[1]]
}
fn inv(a: &Self::BaseType) -> Result<Self::BaseType, FieldError> {
let inv_norm = (a[0].pow(2_u64) + a[1].pow(2_u64)).inv()?;
Ok([a[0] * inv_norm, -a[1] * inv_norm])
}
fn div(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType {
Self::mul(a, &Self::inv(b).unwrap())
}
fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool {
a[0] == b[0] && a[1] == b[1]
}
fn zero() -> Self::BaseType {
[FieldElement::zero(), FieldElement::zero()]
}
fn one() -> Self::BaseType {
[FieldElement::one(), FieldElement::zero()]
}
fn from_u64(x: u64) -> Self::BaseType {
[FieldElement::from(x), FieldElement::zero()]
}
fn from_base_type(x: Self::BaseType) -> Self::BaseType {
x
}
}
pub type Mersenne31ComplexQuadraticExtensionField =
QuadraticExtensionField<Mersenne31Field, Mersenne31Complex>;
impl HasQuadraticNonResidue<Mersenne31Complex> for Mersenne31Complex {
fn residue() -> FieldElement<Mersenne31Complex> {
FieldElement::from(&Mersenne31Complex::from_base_type([
FieldElement::<Mersenne31Field>::from(2),
FieldElement::<Mersenne31Field>::one(),
]))
}
}
pub type Mersenne31ComplexCubicExtensionField =
CubicExtensionField<Mersenne31Field, Mersenne31Complex>;
impl HasCubicNonResidue<Mersenne31Complex> for Mersenne31Complex {
fn residue() -> FieldElement<Mersenne31Complex> {
FieldElement::from(&Mersenne31Complex::from_base_type([
FieldElement::<Mersenne31Field>::zero(),
FieldElement::<Mersenne31Field>::from(5),
]))
}
}
#[cfg(test)]
mod tests {
use crate::field::fields::mersenne31::field::MERSENNE_31_PRIME_FIELD_ORDER;
use super::*;
type Fi = Mersenne31Complex;
type F = FieldElement<Mersenne31Field>;
#[test]
fn add_real_one_plus_one_is_two() {
assert_eq!(Fi::add(&Fi::one(), &Fi::one()), Fi::from_u64(2))
}
#[test]
fn add_real_neg_one_plus_one_is_zero() {
assert_eq!(Fi::add(&Fi::neg(&Fi::one()), &Fi::one()), Fi::zero())
}
#[test]
fn add_real_neg_one_plus_two_is_one() {
assert_eq!(Fi::add(&Fi::neg(&Fi::one()), &Fi::from_u64(2)), Fi::one())
}
#[test]
fn add_real_neg_one_plus_neg_one_is_order_sub_two() {
assert_eq!(
Fi::add(&Fi::neg(&Fi::one()), &Fi::neg(&Fi::one())),
Fi::from_u64((MERSENNE_31_PRIME_FIELD_ORDER - 2).into())
)
}
#[test]
fn add_complex_one_plus_one_two() {
let one = Fi::from_base_type([F::zero(), F::one()]);
let two = Fi::from_base_type([F::zero(), F::from(2)]);
assert_eq!(Fi::add(&one, &one), two)
}
#[test]
fn add_complex_neg_one_plus_one_is_zero() {
let neg_one = Fi::from_base_type([F::zero(), -F::one()]);
let one = Fi::from_base_type([F::zero(), F::one()]);
assert_eq!(Fi::add(&neg_one, &one), Fi::zero())
}
#[test]
fn add_complex_neg_one_plus_two_is_one() {
let neg_one = Fi::from_base_type([F::zero(), -F::one()]);
let two = Fi::from_base_type([F::zero(), F::from(2)]);
let one = Fi::from_base_type([F::zero(), F::one()]);
assert_eq!(Fi::add(&neg_one, &two), one)
}
#[test]
fn add_complex_neg_one_plus_neg_one_imag_is_order_sub_two() {
let neg_one = Fi::from_base_type([F::zero(), -F::one()]);
assert_eq!(
Fi::add(&neg_one, &neg_one)[1],
F::new(MERSENNE_31_PRIME_FIELD_ORDER - 2)
)
}
#[test]
fn add_order() {
let a = Fi::from_base_type([-F::one(), F::one()]);
let b = Fi::from_base_type([F::from(2), F::new(MERSENNE_31_PRIME_FIELD_ORDER - 2)]);
let c = Fi::from_base_type([F::one(), -F::one()]);
assert_eq!(Fi::add(&a, &b), c)
}
#[test]
fn add_equal_zero() {
let a = Fi::from_base_type([-F::one(), -F::one()]);
let b = Fi::from_base_type([F::one(), F::one()]);
assert_eq!(Fi::add(&a, &b), Fi::zero())
}
#[test]
fn add_plus_one() {
let a = Fi::from_base_type([F::one(), F::from(2)]);
let b = Fi::from_base_type([F::one(), F::one()]);
let c = Fi::from_base_type([F::from(2), F::from(3)]);
assert_eq!(Fi::add(&a, &b), c)
}
#[test]
fn sub_real_one_sub_one_is_zero() {
assert_eq!(Fi::sub(&Fi::one(), &Fi::one()), Fi::zero())
}
#[test]
fn sub_real_two_sub_two_is_zero() {
assert_eq!(
Fi::sub(&Fi::from_u64(2u64), &Fi::from_u64(2u64)),
Fi::zero()
)
}
#[test]
fn sub_real_neg_one_sub_neg_one_is_zero() {
assert_eq!(
Fi::sub(&Fi::neg(&Fi::one()), &Fi::neg(&Fi::one())),
Fi::zero()
)
}
#[test]
fn sub_real_two_sub_one_is_one() {
assert_eq!(Fi::sub(&Fi::from_u64(2), &Fi::one()), Fi::one())
}
#[test]
fn sub_real_neg_one_sub_zero_is_neg_one() {
assert_eq!(
Fi::sub(&Fi::neg(&Fi::one()), &Fi::zero()),
Fi::neg(&Fi::one())
)
}
#[test]
fn sub_complex_one_sub_one_is_zero() {
let one = Fi::from_base_type([F::zero(), F::one()]);
assert_eq!(Fi::sub(&one, &one), Fi::zero())
}
#[test]
fn sub_complex_two_sub_two_is_zero() {
let two = Fi::from_base_type([F::zero(), F::from(2)]);
assert_eq!(Fi::sub(&two, &two), Fi::zero())
}
#[test]
fn sub_complex_neg_one_sub_neg_one_is_zero() {
let neg_one = Fi::from_base_type([F::zero(), -F::one()]);
assert_eq!(Fi::sub(&neg_one, &neg_one), Fi::zero())
}
#[test]
fn sub_complex_two_sub_one_is_one() {
let two = Fi::from_base_type([F::zero(), F::from(2)]);
let one = Fi::from_base_type([F::zero(), F::one()]);
assert_eq!(Fi::sub(&two, &one), one)
}
#[test]
fn sub_complex_neg_one_sub_zero_is_neg_one() {
let neg_one = Fi::from_base_type([F::zero(), -F::one()]);
assert_eq!(Fi::sub(&neg_one, &Fi::zero()), neg_one)
}
#[test]
fn mul() {
let a = Fi::from_base_type([F::from(2), F::from(2)]);
let b = Fi::from_base_type([F::from(4), F::from(5)]);
let c = Fi::from_base_type([-F::from(2), F::from(18)]);
assert_eq!(Fi::mul(&a, &b), c)
}
}