1use 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#[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
23pub 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}