use std::fmt::Display;
use abstalg::{
AbelianGroup, ApproxFloats, CommuntativeMonoid, DistributiveLattice, Domain, F64, Field,
Lattice, Monoid, PartialOrder, SemiRing, Semigroup, UnitaryRing,
};
type Float = f64;
const F: ApproxFloats<Float> = F64;
#[derive(Clone, Copy, Debug)]
pub struct Scalar(Float);
impl Display for Scalar {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl Scalar {
pub fn new(value: Float) -> Self {
Scalar(value)
}
pub fn value(&self) -> Float {
self.0
}
}
#[derive(Clone, Debug)]
pub struct ScalarSpace;
impl PartialEq for Scalar {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl PartialOrd for Scalar {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.0.partial_cmp(&other.0)
}
}
impl Ord for Scalar {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap()
}
}
impl Eq for Scalar {}
impl Domain for ScalarSpace {
type Elem = Scalar;
fn contains(&self, elem: &Self::Elem) -> bool {
F.contains(&elem.0)
}
fn equals(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
F.equals(&elem1.0, &elem2.0)
}
}
impl Semigroup for ScalarSpace {
fn mul(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.mul(&elem1.0, &elem2.0))
}
}
impl Monoid for ScalarSpace {
fn one(&self) -> Self::Elem {
Scalar(F.one())
}
fn try_inv(&self, elem: &Self::Elem) -> Option<Self::Elem> {
F.try_inv(&elem.0).map(Scalar)
}
}
impl CommuntativeMonoid for ScalarSpace {
fn zero(&self) -> Self::Elem {
Scalar(F.zero())
}
fn is_zero(&self, elem: &Self::Elem) -> bool {
F.is_zero(&elem.0)
}
fn add(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.add(&elem1.0, &elem2.0))
}
}
impl AbelianGroup for ScalarSpace {
fn neg(&self, elem: &Self::Elem) -> Self::Elem {
Scalar(F.neg(&elem.0))
}
fn sub(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.sub(&elem1.0, &elem2.0))
}
fn times(&self, num: isize, elem: &Self::Elem) -> Self::Elem {
Scalar(AbelianGroup::times(&F, num, &elem.0))
}
}
impl SemiRing for ScalarSpace {}
impl UnitaryRing for ScalarSpace {}
impl Field for ScalarSpace {
fn inv(&self, elem: &Self::Elem) -> Self::Elem {
Scalar(F.inv(&elem.0))
}
fn div(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.div(&elem1.0, &elem2.0))
}
}
impl PartialOrder for ScalarSpace {
fn leq(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> bool {
F.leq(&elem1.0, &elem2.0)
}
}
impl Lattice for ScalarSpace {
fn meet(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.meet(&elem1.0, &elem2.0))
}
fn join(&self, elem1: &Self::Elem, elem2: &Self::Elem) -> Self::Elem {
Scalar(F.join(&elem1.0, &elem2.0))
}
}
impl DistributiveLattice for ScalarSpace {}