use core::ops::{Add, Mul, Neg, Sub};
pub trait Ring:
Clone
+ PartialEq
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Neg<Output = Self>
{
fn zero(&self) -> Self;
fn one(&self) -> Self;
fn is_zero(&self) -> bool;
}
#[cfg(feature = "int")]
impl Ring for crate::int::Int {
#[inline]
fn zero(&self) -> Self {
crate::int::Int::ZERO
}
#[inline]
fn one(&self) -> Self {
crate::int::Int::ONE
}
#[inline]
fn is_zero(&self) -> bool {
crate::int::Int::is_zero(self)
}
}
#[cfg(feature = "rational")]
impl Ring for crate::rational::Rational {
#[inline]
fn zero(&self) -> Self {
crate::rational::Rational::ZERO
}
#[inline]
fn one(&self) -> Self {
crate::rational::Rational::ONE
}
#[inline]
fn is_zero(&self) -> bool {
crate::rational::Rational::is_zero(self)
}
}
#[cfg(feature = "float")]
impl Ring for crate::float::Float {
#[inline]
fn zero(&self) -> Self {
crate::float::Float::zero(self.precision())
}
#[inline]
fn one(&self) -> Self {
crate::float::Float::from_int(
&crate::int::Int::ONE,
self.precision(),
crate::float::RoundingMode::Nearest,
)
}
#[inline]
fn is_zero(&self) -> bool {
crate::float::Float::is_zero(self)
}
}
#[cfg(feature = "dyadic")]
impl Ring for crate::dyadic::Dyadic {
#[inline]
fn zero(&self) -> Self {
crate::dyadic::Dyadic::zero()
}
#[inline]
fn one(&self) -> Self {
crate::dyadic::Dyadic::one()
}
#[inline]
fn is_zero(&self) -> bool {
crate::dyadic::Dyadic::is_zero(self)
}
}
#[cfg(feature = "decimal")]
impl Ring for crate::decimal::Decimal {
#[inline]
fn zero(&self) -> Self {
crate::decimal::Decimal::zero()
}
#[inline]
fn one(&self) -> Self {
crate::decimal::Decimal::one()
}
#[inline]
fn is_zero(&self) -> bool {
crate::decimal::Decimal::is_zero(self)
}
}
#[cfg(feature = "int")]
impl Ring for crate::mod_int::ModInt {
#[inline]
fn zero(&self) -> Self {
self.of(crate::int::Int::ZERO)
}
#[inline]
fn one(&self) -> Self {
self.of(crate::int::Int::ONE)
}
#[inline]
fn is_zero(&self) -> bool {
crate::mod_int::ModInt::is_zero(self)
}
}
#[cfg(feature = "galois")]
impl Ring for crate::galois::GfElement {
#[inline]
fn zero(&self) -> Self {
self.field().zero()
}
#[inline]
fn one(&self) -> Self {
self.field().one()
}
#[inline]
fn is_zero(&self) -> bool {
crate::galois::GfElement::is_zero(self)
}
}
#[cfg(feature = "complex")]
impl<T: Ring> Ring for crate::complex::Complex<T> {
#[inline]
fn zero(&self) -> Self {
crate::complex::Complex::new(self.re.zero(), self.im.zero())
}
#[inline]
fn one(&self) -> Self {
crate::complex::Complex::new(self.re.one(), self.im.zero())
}
#[inline]
fn is_zero(&self) -> bool {
self.re.is_zero() && self.im.is_zero()
}
}
pub trait Field: Ring + core::ops::Div<Output = Self> {
fn inv(&self) -> Option<Self> {
if self.is_zero() {
None
} else {
Some(self.one() / self.clone())
}
}
}
#[cfg(feature = "rational")]
impl Field for crate::rational::Rational {}
#[cfg(feature = "float")]
impl Field for crate::float::Float {}
#[cfg(feature = "int")]
impl Field for crate::mod_int::ModInt {
#[inline]
fn inv(&self) -> Option<Self> {
crate::mod_int::ModInt::inv(self)
}
}
#[cfg(feature = "galois")]
impl Field for crate::galois::GfElement {
#[inline]
fn inv(&self) -> Option<Self> {
crate::galois::GfElement::inv(self)
}
}
#[cfg(feature = "complex")]
impl<F: Field> Field for crate::complex::Complex<F> {}
#[cfg(feature = "int")]
pub trait FiniteField: Field {
fn order(&self) -> crate::int::Int;
fn characteristic(&self) -> crate::int::Int;
#[allow(clippy::wrong_self_convention)]
fn from_index(&self, index: &crate::int::Int) -> Self;
}
#[cfg(feature = "int")]
impl FiniteField for crate::mod_int::ModInt {
#[inline]
fn order(&self) -> crate::int::Int {
self.modulus()
}
#[inline]
fn characteristic(&self) -> crate::int::Int {
self.modulus()
}
#[inline]
fn from_index(&self, index: &crate::int::Int) -> Self {
self.of(index.clone())
}
}
#[cfg(feature = "galois")]
impl FiniteField for crate::galois::GfElement {
#[inline]
fn order(&self) -> crate::int::Int {
self.field().order()
}
#[inline]
fn characteristic(&self) -> crate::int::Int {
self.field().characteristic()
}
fn from_index(&self, index: &crate::int::Int) -> Self {
let field = self.field();
let p = field.characteristic();
let mut n = index.rem_euclid(&field.order());
let mut digits = alloc::vec::Vec::with_capacity(field.degree());
for _ in 0..field.degree() {
digits.push(n.rem_euclid(&p));
n = n.div_floor(&p);
}
field.element(&digits)
}
}