algebra/
wrapper.rs

1//! Wrappers that attach an algebraic structure with a value type.
2
3use std::ops::{Add, Neg, Sub, Mul, Div};
4use std::fmt::{Display, Formatter, Error};
5
6use ops::{Op, Inverse, Recip, Additive, Multiplicative};
7use cmp::ApproxEq;
8use ident::Identity;
9
10use structure::MagmaApprox;
11use structure::QuasigroupApprox;
12
13/// Wrapper that allows to use operators on algebraic types.
14#[derive(Clone, Copy, PartialOrd, PartialEq, Debug)]
15pub struct Wrapper<M>(pub M);
16
17impl<M: Display> Display for Wrapper<M> {
18    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
19        self.0.fmt(fmt)
20    }
21}
22
23/// Creates wrapper with identity value for a specific operator.
24pub fn id<O: Op, M>(_: O) -> Wrapper<M>
25where M: Identity<O>
26{
27    Wrapper(Identity::<O>::id())
28}
29
30impl<M> ApproxEq for Wrapper<M>
31where M: ApproxEq
32{
33    type Eps = M::Eps;
34    fn default_epsilon() -> Self::Eps {
35        M::default_epsilon()
36    }
37
38    fn approx_eq_eps(&self, b: &Self, epsilon: &Self::Eps) -> bool {
39        M::approx_eq_eps(&self.0, &b.0, epsilon)
40    }
41}
42
43impl<M> Add<Wrapper<M>> for Wrapper<M>
44where M: MagmaApprox<Additive>
45{
46    type Output = Self;
47    fn add(self, lhs: Self) -> Self {
48        Wrapper(self.0.approx(lhs.0))
49    }
50}
51
52impl<M> Neg for Wrapper<M>
53where M: QuasigroupApprox<Additive>
54{
55    type Output = Self;
56    fn neg(mut self) -> Self {
57        self.0 = self.0.inv();
58        self
59    }
60}
61
62impl<M> Sub<Wrapper<M>> for Wrapper<M>
63where M: QuasigroupApprox<Additive>
64{
65    type Output = Self;
66    fn sub(self, lhs: Self) -> Self {
67        self + -lhs
68    }
69}
70
71impl<M> Mul<Wrapper<M>> for Wrapper<M>
72where M: MagmaApprox<Multiplicative>
73{
74    type Output = Self;
75    fn mul(self, lhs: Self) -> Self {
76        Wrapper(self.0.approx(lhs.0))
77    }
78}
79
80impl<M> Recip for Wrapper<M>
81where M: QuasigroupApprox<Multiplicative>
82{
83    type Result = Self;
84    fn recip(self) -> Self {
85        Wrapper(self.0.inv())
86    }
87}
88
89impl<M> Div<Wrapper<M>> for Wrapper<M>
90where M: QuasigroupApprox<Multiplicative>
91{
92    type Output = Self;
93    fn div(self, lhs: Self) -> Self {
94        self * lhs.inv()
95    }
96}