reefer 0.3.0

Optimizing proc-macro for geometric algebra
Documentation
//! used for basis math and multivector representation.

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;

/// Wrapper around `f64` used for symbolic scalar coefficients during macro expansion.
#[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
    }
}

/// Domain modelling the scalar field used by the symbolic Clifford algebra runtime.
#[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 {}