diff --git a/math/src/circle/errors.rs b/math/src/circle/errors.rs new file mode 100644 index 000000000..51dcb720b --- /dev/null +++ b/math/src/circle/errors.rs @@ -0,0 +1,4 @@ +#[derive(Debug)] +pub enum CircleError { + PointDoesntSatisfyCircleEquation, +} diff --git a/math/src/circle/mod.rs b/math/src/circle/mod.rs index f5a65721f..ac576194f 100644 --- a/math/src/circle/mod.rs +++ b/math/src/circle/mod.rs @@ -1,5 +1,6 @@ pub mod cfft; pub mod cosets; +pub mod errors; pub mod point; pub mod polynomial; pub mod twiddles; diff --git a/math/src/circle/point.rs b/math/src/circle/point.rs index 9c6e0662c..24759a043 100644 --- a/math/src/circle/point.rs +++ b/math/src/circle/point.rs @@ -1,3 +1,4 @@ +use super::errors::CircleError; use crate::field::traits::IsField; use crate::field::{ element::FieldElement, @@ -9,16 +10,73 @@ use core::ops::{Add, Mul}; /// x in F, y in F and x^2 + y^2 = 1, i.e. the Circle. The operation of the group will have /// additive notation and is as follows: /// (a, b) + (c, d) = (a * c - b * d, a * d + b * c) - #[derive(Debug, Clone)] pub struct CirclePoint { pub x: FieldElement, pub y: FieldElement, } -#[derive(Debug)] -pub enum CircleError { - PointDoesntSatisfyCircleEquation, +impl> CirclePoint { + pub fn new(x: FieldElement, y: FieldElement) -> Result { + if x.square() + y.square() == FieldElement::one() { + Ok(Self { x, y }) + } else { + Err(CircleError::PointDoesntSatisfyCircleEquation) + } + } + + /// Neutral element of the Circle group (with additive notation). + pub fn zero() -> Self { + Self::new(FieldElement::one(), FieldElement::zero()).unwrap() + } + + /// Computes 2(x, y) = (2x^2 - 1, 2xy). + pub fn double(self) -> Self { + Self::new( + self.x.square().double() - FieldElement::one(), + self.x.double() * self.y, + ) + .unwrap() + } + + /// Computes 2^n * (x, y). + pub fn repeated_double(self, n: u32) -> Self { + let mut res = self; + for _ in 0..n { + res = res.double(); + } + res + } + + /// Computes the inverse of the point. + /// We are using -(x, y) = (x, -y), i.e. the inverse of the group opertion is conjugation + /// because the norm of every point in the circle is one. + pub fn conjugate(self) -> Self { + Self { + x: self.x, + y: -self.y, + } + } + + pub fn antipode(self) -> Self { + Self { + x: -self.x, + y: -self.y, + } + } + + pub const GENERATOR: Self = Self { + x: F::CIRCLE_GENERATOR_X, + y: F::CIRCLE_GENERATOR_Y, + }; + + /// Returns the generator of the subgroup of order n = 2^log_2_size. + /// We are using that 2^k * g is a generator of the subgroup of order 2^{31 - k}. + pub fn get_generator_of_subgroup(log_2_size: u32) -> Self { + Self::GENERATOR.repeated_double(31 - log_2_size) + } + + pub const ORDER: u128 = F::ORDER; } /// Parameters of the base field that we'll need to define its Circle. @@ -119,69 +177,6 @@ impl> Mul for CirclePoint { } } -impl> CirclePoint { - pub fn new(x: FieldElement, y: FieldElement) -> Result { - if x.square() + y.square() == FieldElement::one() { - Ok(Self { x, y }) - } else { - Err(CircleError::PointDoesntSatisfyCircleEquation) - } - } - - /// Neutral element of the Circle group (with additive notation). - pub fn zero() -> Self { - Self::new(FieldElement::one(), FieldElement::zero()).unwrap() - } - - /// Computes 2(x, y) = (2x^2 - 1, 2xy). - pub fn double(self) -> Self { - Self::new( - self.x.square().double() - FieldElement::one(), - self.x.double() * self.y, - ) - .unwrap() - } - - /// Computes 2^n * (x, y). - pub fn repeated_double(self, n: u32) -> Self { - let mut res = self; - for _ in 0..n { - res = res.double(); - } - res - } - - /// Computes the inverse of the point. - /// We are using -(x, y) = (x, -y), i.e. the inverse of the group opertion is conjugation - /// because the norm of every point in the circle is one. - pub fn conjugate(self) -> Self { - Self { - x: self.x, - y: -self.y, - } - } - - pub fn antipode(self) -> Self { - Self { - x: -self.x, - y: -self.y, - } - } - - pub const GENERATOR: Self = Self { - x: F::CIRCLE_GENERATOR_X, - y: F::CIRCLE_GENERATOR_Y, - }; - - /// Returns the generator of the subgroup of order n = 2^log_2_size. - /// We are using that 2^k * g is a generator of the subgroup of order 2^{31 - k}. - pub fn get_generator_of_subgroup(log_2_size: u32) -> Self { - Self::GENERATOR.repeated_double(31 - log_2_size) - } - - pub const ORDER: u128 = F::ORDER; -} - #[cfg(test)] mod tests { use super::*;