extern crate alloc;
use crate::circle::point::CirclePoint;
use crate::field::fields::mersenne31::field::Mersenne31Field;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[derive(Debug, Clone)]
pub struct Coset {
pub log_2_size: u32, pub shift: CirclePoint<Mersenne31Field>,
}
impl Coset {
pub fn new(log_2_size: u32, shift: CirclePoint<Mersenne31Field>) -> Self {
Coset { log_2_size, shift }
}
pub fn new_standard(log_2_size: u32) -> Self {
let shift = CirclePoint::get_generator_of_subgroup(log_2_size + 1);
Coset { log_2_size, shift }
}
pub fn get_generator(&self) -> CirclePoint<Mersenne31Field> {
CirclePoint::GENERATOR.repeated_double(31 - self.log_2_size)
}
pub fn half_coset(coset: Self) -> Self {
Coset {
log_2_size: coset.log_2_size - 1,
shift: coset.shift,
}
}
pub fn conjugate(coset: Self) -> Self {
Coset {
log_2_size: coset.log_2_size,
shift: coset.shift.conjugate(),
}
}
#[cfg(feature = "alloc")]
pub fn get_coset_points(coset: &Self) -> Vec<CirclePoint<Mersenne31Field>> {
let generator_n = CirclePoint::get_generator_of_subgroup(coset.log_2_size);
let size: usize = 1 << coset.log_2_size;
core::iter::successors(Some(coset.shift.clone()), move |prev| {
Some(prev + &generator_n)
})
.take(size)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn coset_points_vector_has_right_size() {
let coset = Coset::new_standard(3);
let points = Coset::get_coset_points(&coset);
assert_eq!(1 << coset.log_2_size, points.len())
}
#[test]
fn antipode_of_coset_point_is_in_coset() {
let coset = Coset::new_standard(3);
let points = Coset::get_coset_points(&coset);
let point = points[2].clone();
let anitpode_point = points[6].clone();
assert_eq!(anitpode_point, point.antipode())
}
#[test]
fn coset_generator_has_right_order() {
let coset = Coset::new(2, CirclePoint::GENERATOR * 3);
let generator_n = coset.get_generator();
assert_eq!(generator_n.repeated_double(2), CirclePoint::zero());
}
}