use core::ops::{Add, Sub};
use cryptix_bigint::{
ops::BigIntOps,
property::IsBigInt
};
use crate::{Modular, Element};
use super::*;
impl<I, M> AbelianGroup for Element<I, M>
where
M: Modular<I>,
Self: Group + CommunicativeAdd
{ }
impl<I, M> Group for Element<I, M>
where
M: Modular<I>,
I: BigIntOps
{ }
impl<I, M> Add for Element<I, M>
where
M: Modular<I>,
I: BigIntOps
{
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
let (res, _) = self.0 + rhs.0;
Self::new_unchecked(if res >= M::P { (res - M::P).0 } else { res })
}
}
impl<I, M> Sub for Element<I, M>
where
M: Modular<I>,
I: BigIntOps
{
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
let (res, _) = self.0 - rhs.0;
Self::new_unchecked(if res >= M::P { (res + M::P).0 } else { res })
}
}
impl<I, M> AddIdentity for Element<I, M>
where
M: Modular<I>,
I: BigIntOps + IsBigInt
{
const ADD_IDENTITY: Self = Self(I::ZERO, core::marker::PhantomData);
}
impl<I, M> Neg for Element<I, M>
where
M: Modular<I>,
Self: Sub<Output = Self> + AddIdentity
{
type Output = Self;
fn neg(self) -> Self::Output {
Self::ADD_IDENTITY - self
}
}
impl<I, M> AssociativeAdd for Element<I, M>
where
M: Modular<I>,
Self: Add<Output = Self>
{ }
impl<I, M> CommunicativeAdd for Element<I, M>
where
M: Modular<I>,
Self: Add<Output = Self>
{ }