2021-05-11 15:26:20 +02:00
|
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
|
|
|
use std::iter::{Product, Sum};
|
|
|
|
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
|
|
|
|
|
2021-07-22 13:08:14 -07:00
|
|
|
use num::bigint::BigUint;
|
2021-07-15 07:35:12 -07:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-06-10 14:10:35 -07:00
|
|
|
|
2022-06-27 07:18:21 -07:00
|
|
|
use crate::extension::{Extendable, FieldExtension, Frobenius, OEF};
|
2021-12-30 12:11:02 -08:00
|
|
|
use crate::ops::Square;
|
2022-06-27 12:24:09 -07:00
|
|
|
use crate::types::Field;
|
2021-06-10 14:10:35 -07:00
|
|
|
|
2021-07-15 07:35:12 -07:00
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
2021-09-13 11:45:17 -07:00
|
|
|
#[serde(bound = "")]
|
2021-12-28 11:51:13 -08:00
|
|
|
pub struct QuadraticExtension<F: Extendable<2>>(pub [F; 2]);
|
2021-05-11 15:26:20 +02:00
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Default for QuadraticExtension<F> {
|
2021-08-20 08:44:28 -07:00
|
|
|
fn default() -> Self {
|
|
|
|
|
Self::ZERO
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> OEF<2> for QuadraticExtension<F> {
|
|
|
|
|
const W: F = F::W;
|
2021-10-10 20:42:10 +11:00
|
|
|
const DTH_ROOT: F = F::DTH_ROOT;
|
2021-05-24 14:12:08 +02:00
|
|
|
}
|
2021-05-11 15:26:20 +02:00
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Frobenius<2> for QuadraticExtension<F> {}
|
2021-06-11 13:45:51 +02:00
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> FieldExtension<2> for QuadraticExtension<F> {
|
|
|
|
|
type BaseField = F;
|
2021-05-24 14:12:08 +02:00
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
fn to_basefield_array(&self) -> [F; 2] {
|
2021-05-11 15:26:20 +02:00
|
|
|
self.0
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
fn from_basefield_array(arr: [F; 2]) -> Self {
|
2021-05-24 14:12:08 +02:00
|
|
|
Self(arr)
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
fn from_basefield(x: F) -> Self {
|
2021-05-24 14:12:08 +02:00
|
|
|
x.into()
|
2021-05-11 15:26:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> From<F> for QuadraticExtension<F> {
|
|
|
|
|
fn from(x: F) -> Self {
|
|
|
|
|
Self([x, F::ZERO])
|
2021-05-18 15:22:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Field for QuadraticExtension<F> {
|
|
|
|
|
const ZERO: Self = Self([F::ZERO; 2]);
|
|
|
|
|
const ONE: Self = Self([F::ONE, F::ZERO]);
|
|
|
|
|
const TWO: Self = Self([F::TWO, F::ZERO]);
|
|
|
|
|
const NEG_ONE: Self = Self([F::NEG_ONE, F::ZERO]);
|
|
|
|
|
|
|
|
|
|
// `p^2 - 1 = (p - 1)(p + 1)`. The `p - 1` term has a two-adicity of `F::TWO_ADICITY`. As
|
|
|
|
|
// long as `F::TWO_ADICITY >= 2`, `p` can be written as `4n + 1`, so `p + 1` can be written as
|
|
|
|
|
// `2(2n + 1)`, which has a 2-adicity of 1.
|
|
|
|
|
const TWO_ADICITY: usize = F::TWO_ADICITY + 1;
|
2021-12-14 17:12:14 +01:00
|
|
|
const CHARACTERISTIC_TWO_ADICITY: usize = F::CHARACTERISTIC_TWO_ADICITY;
|
2021-09-13 11:45:17 -07:00
|
|
|
|
|
|
|
|
const MULTIPLICATIVE_GROUP_GENERATOR: Self = Self(F::EXT_MULTIPLICATIVE_GROUP_GENERATOR);
|
|
|
|
|
const POWER_OF_TWO_GENERATOR: Self = Self(F::EXT_POWER_OF_TWO_GENERATOR);
|
2021-05-11 15:26:20 +02:00
|
|
|
|
2021-11-10 11:49:30 -08:00
|
|
|
const BITS: usize = F::BITS * 2;
|
|
|
|
|
|
2021-07-21 13:05:32 -07:00
|
|
|
fn order() -> BigUint {
|
2021-09-13 11:45:17 -07:00
|
|
|
F::order() * F::order()
|
2021-07-21 13:05:32 -07:00
|
|
|
}
|
2021-12-14 17:12:14 +01:00
|
|
|
fn characteristic() -> BigUint {
|
|
|
|
|
F::characteristic()
|
|
|
|
|
}
|
2021-07-21 13:05:32 -07:00
|
|
|
|
2021-05-11 15:26:20 +02:00
|
|
|
// Algorithm 11.3.4 in Handbook of Elliptic and Hyperelliptic Curve Cryptography.
|
|
|
|
|
fn try_inverse(&self) -> Option<Self> {
|
|
|
|
|
if self.is_zero() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 13:45:51 +02:00
|
|
|
let a_pow_r_minus_1 = self.frobenius();
|
2021-05-11 15:26:20 +02:00
|
|
|
let a_pow_r = a_pow_r_minus_1 * *self;
|
2021-05-24 14:12:08 +02:00
|
|
|
debug_assert!(FieldExtension::<2>::is_in_basefield(&a_pow_r));
|
2021-05-11 15:26:20 +02:00
|
|
|
|
2021-08-17 10:26:31 +02:00
|
|
|
Some(FieldExtension::<2>::scalar_mul(
|
|
|
|
|
&a_pow_r_minus_1,
|
|
|
|
|
a_pow_r.0[0].inverse(),
|
|
|
|
|
))
|
2021-05-11 15:26:20 +02:00
|
|
|
}
|
|
|
|
|
|
2022-08-19 09:21:10 -07:00
|
|
|
fn from_noncanonical_biguint(n: BigUint) -> Self {
|
|
|
|
|
F::from_noncanonical_biguint(n).into()
|
2021-10-19 13:26:48 -07:00
|
|
|
}
|
|
|
|
|
|
2021-05-11 15:26:20 +02:00
|
|
|
fn from_canonical_u64(n: u64) -> Self {
|
2021-09-13 11:45:17 -07:00
|
|
|
F::from_canonical_u64(n).into()
|
2021-05-11 15:26:20 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-05 10:27:11 -07:00
|
|
|
fn from_noncanonical_u128(n: u128) -> Self {
|
2021-09-13 11:45:17 -07:00
|
|
|
F::from_noncanonical_u128(n).into()
|
2021-09-05 10:27:11 -07:00
|
|
|
}
|
|
|
|
|
|
2022-08-06 11:35:32 -04:00
|
|
|
#[cfg(feature = "rand")]
|
|
|
|
|
fn rand_from_rng<R: rand::Rng>(rng: &mut R) -> Self {
|
2021-09-13 11:45:17 -07:00
|
|
|
Self([F::rand_from_rng(rng), F::rand_from_rng(rng)])
|
2021-05-11 15:26:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Display for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
write!(f, "{} + {}*a", self.0[0], self.0[1])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Debug for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
Display::fmt(self, f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Neg for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn neg(self) -> Self {
|
|
|
|
|
Self([-self.0[0], -self.0[1]])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Add for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn add(self, rhs: Self) -> Self {
|
|
|
|
|
Self([self.0[0] + rhs.0[0], self.0[1] + rhs.0[1]])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> AddAssign for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
|
|
|
*self = *self + rhs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Sum for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
|
|
|
|
iter.fold(Self::ZERO, |acc, x| acc + x)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Sub for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn sub(self, rhs: Self) -> Self {
|
|
|
|
|
Self([self.0[0] - rhs.0[0], self.0[1] - rhs.0[1]])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> SubAssign for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
#[inline]
|
|
|
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
|
|
|
*self = *self - rhs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Mul for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2022-03-04 09:34:31 +11:00
|
|
|
default fn mul(self, rhs: Self) -> Self {
|
2021-05-11 15:26:20 +02:00
|
|
|
let Self([a0, a1]) = self;
|
|
|
|
|
let Self([b0, b1]) = rhs;
|
|
|
|
|
|
2021-05-24 22:04:06 +02:00
|
|
|
let c0 = a0 * b0 + <Self as OEF<2>>::W * a1 * b1;
|
2021-05-11 15:26:20 +02:00
|
|
|
let c1 = a0 * b1 + a1 * b0;
|
|
|
|
|
|
|
|
|
|
Self([c0, c1])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> MulAssign for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
#[inline]
|
|
|
|
|
fn mul_assign(&mut self, rhs: Self) {
|
|
|
|
|
*self = *self * rhs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-30 12:11:02 -08:00
|
|
|
impl<F: Extendable<2>> Square for QuadraticExtension<F> {
|
|
|
|
|
#[inline(always)]
|
|
|
|
|
fn square(&self) -> Self {
|
|
|
|
|
// Specialising mul reduces the computation of c1 from 2 muls
|
|
|
|
|
// and one add to one mul and a shift
|
|
|
|
|
|
|
|
|
|
let Self([a0, a1]) = *self;
|
|
|
|
|
|
|
|
|
|
let c0 = a0.square() + <Self as OEF<2>>::W * a1.square();
|
|
|
|
|
let c1 = a0 * a1.double();
|
|
|
|
|
|
|
|
|
|
Self([c0, c1])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Product for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
|
|
|
|
|
iter.fold(Self::ONE, |acc, x| acc * x)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> Div for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
#[allow(clippy::suspicious_arithmetic_impl)]
|
|
|
|
|
fn div(self, rhs: Self) -> Self::Output {
|
|
|
|
|
self * rhs.inverse()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-13 11:45:17 -07:00
|
|
|
impl<F: Extendable<2>> DivAssign for QuadraticExtension<F> {
|
2021-05-11 15:26:20 +02:00
|
|
|
fn div_assign(&mut self, rhs: Self) {
|
|
|
|
|
*self = *self / rhs;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
2021-09-15 09:36:56 +02:00
|
|
|
mod goldilocks {
|
2021-09-15 09:52:49 +02:00
|
|
|
use crate::{test_field_arithmetic, test_field_extension};
|
2021-09-15 09:36:56 +02:00
|
|
|
|
2021-12-28 11:51:13 -08:00
|
|
|
test_field_extension!(crate::goldilocks_field::GoldilocksField, 2);
|
2021-09-15 09:36:56 +02:00
|
|
|
test_field_arithmetic!(
|
2022-06-27 07:18:21 -07:00
|
|
|
crate::extension::quadratic::QuadraticExtension<
|
2021-12-28 11:51:13 -08:00
|
|
|
crate::goldilocks_field::GoldilocksField,
|
2021-09-15 09:36:56 +02:00
|
|
|
>
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-05-11 15:26:20 +02:00
|
|
|
}
|