rsdiff_core/ops/kinds/binary/
arithmetic.rs1use super::{BinOp, BinaryAssignOp};
6use num::traits::{NumAssignOps, NumOps, Pow};
7
8macro_rules! impl_binary_op {
9 ($($operand:ident($($p:ident)::*.$op:ident)),*) => {
10 $(
11 impl_binary_op!(@loop $operand, $($p)::*.$op);
12 )*
13 };
14 (std $(($op:ident, $bound:ident, $operator:tt)),*) => {
15 $(
16 impl_binary_op!(@loop $op, core::ops::$bound, $operator);
17 )*
18 };
19 (@loop $operand:ident, $($p:ident)::*.$op:ident) => {
20 impl<A, B, C> BinOp<A, B> for $operand
21 where
22 A: $($p)::*<B, Output = C>,
23 {
24 type Output = C;
25
26 fn eval(&self, lhs: A, rhs: B) -> Self::Output {
27 $($p)::*::$op(lhs, rhs)
28 }
29 }
30 };
31 (@loop $(($op:ident, $($p:ident)::*, $operator:tt)),*) => {
32 $(
33 impl_binary_op!($op, $($p)::*, $operator);
34 )*
35
36 };
37 (@loop $operand:ident, $($p:ident)::*, $op:tt) => {
38 operator!($operand, Binary);
39
40 impl<A, B, C> BinOp<A, B> for $operand
41 where
42 A: $($p)::*<B, Output = C>,
43 {
44 type Output = C;
45
46 fn eval(&self, lhs: A, rhs: B) -> Self::Output {
47 lhs $op rhs
48 }
49 }
50 };
51}
52
53macro_rules! impl_binary_assign {
54 ($($operand:ident($($p:ident)::*.$op:ident)),*) => {
55 $(
56 impl_binary_assign!(@impl $operand($($p)::*.$op));
57 )*
58 };
59 (@impl $operand:ident($($p:ident)::*.$op:ident)) => {
60
61 impl<A, B> BinOp<A, B> for $operand
62 where
63 A: $($p)::*<B>,
64 {
65 type Output = A;
66
67 fn eval(&self, lhs: A, rhs: B) -> Self::Output {
68 let mut lhs = lhs;
69 $($p)::*::$op(&mut lhs, rhs);
70 lhs
71 }
72 }
73
74 impl<A, B> BinaryAssignOp<A, B> for $operand
75 where
76 A: $($p)::*<B>,
77 {
78 fn eval(&self, lhs: &mut A, rhs: B) {
79 $($p)::*::$op(lhs, rhs);
80 }
81 }
82 };
83}
84
85operations!(Arithmetic<Binary> {
86 Add(Addition): add,
87 Div(Division): div,
88 Mul(Multiplication): mul,
89 Pow(Power): pow,
90 Rem(Remainder): rem,
91 Sub(Subtraction): sub
92});
93
94operations!(ArithmeticAssign<Binary> {
95 AddAssign(AddAssign): add_assign,
96 DivAssign(DivAssign): div_assign,
97 MulAssign(MulAssign): mul_assign,
98 RemAssign(RemAssign): rem_assign,
99 SubAssign(SubAssign): sub_assign
100});
101
102impl_binary_op!(
103 Addition(core::ops::Add.add),
104 Division(core::ops::Div.div),
105 Multiplication(core::ops::Mul.mul),
106 Remainder(core::ops::Rem.rem),
107 Subtraction(core::ops::Sub.sub),
108 Power(num::traits::Pow.pow)
109);
110
111impl_binary_assign!(
112 AddAssign(core::ops::AddAssign.add_assign),
113 DivAssign(core::ops::DivAssign.div_assign),
114 MulAssign(core::ops::MulAssign.mul_assign),
115 RemAssign(core::ops::RemAssign.rem_assign),
116 SubAssign(core::ops::SubAssign.sub_assign)
117);
118
119impl Arithmetic {
120 pub fn new(op: Arithmetic) -> Self {
121 op
122 }
123
124 pub fn is_commutative(&self) -> bool {
125 match self {
126 Arithmetic::Add(_) | Arithmetic::Mul(_) => true,
127 _ => false,
128 }
129 }
130
131 pub fn binop<A, B, C>(&self) -> Box<dyn BinOp<A, B, Output = C>>
132 where
133 A: NumOps<B, C> + Pow<B, Output = C>,
134 {
135 match *self {
136 Arithmetic::Add(op) => Box::new(op),
137 Arithmetic::Div(op) => Box::new(op),
138 Arithmetic::Mul(op) => Box::new(op),
139 Arithmetic::Pow(op) => Box::new(op),
140 Arithmetic::Rem(op) => Box::new(op),
141 Arithmetic::Sub(op) => Box::new(op),
142 }
143 }
144}
145
146impl ArithmeticAssign {
147 pub fn new(op: ArithmeticAssign) -> Self {
148 op
149 }
150
151 pub fn assign_op<A, B>(&self) -> Box<dyn BinaryAssignOp<A, B>>
152 where
153 A: NumAssignOps<B>,
154 {
155 match *self {
156 ArithmeticAssign::AddAssign(op) => Box::new(op),
157 ArithmeticAssign::DivAssign(op) => Box::new(op),
158 ArithmeticAssign::MulAssign(op) => Box::new(op),
159 ArithmeticAssign::RemAssign(op) => Box::new(op),
160 ArithmeticAssign::SubAssign(op) => Box::new(op),
161 }
162 }
163
164 pub fn bin_op<A, B>(&self) -> Box<dyn BinOp<A, B, Output = A>>
165 where
166 A: NumAssignOps<B>,
167 {
168 match *self {
169 ArithmeticAssign::AddAssign(op) => Box::new(op),
170 ArithmeticAssign::DivAssign(op) => Box::new(op),
171 ArithmeticAssign::MulAssign(op) => Box::new(op),
172 ArithmeticAssign::RemAssign(op) => Box::new(op),
173 ArithmeticAssign::SubAssign(op) => Box::new(op),
174 }
175 }
176}
177
178impl Default for Arithmetic {
179 fn default() -> Self {
180 Arithmetic::add()
181 }
182}
183
184impl Default for ArithmeticAssign {
185 fn default() -> Self {
186 ArithmeticAssign::add_assign()
187 }
188}
189
190impl<A, B> BinOp<A, B> for Arithmetic
191where
192 A: NumOps<B> + Pow<B, Output = A>,
193{
194 type Output = A;
195
196 fn eval(&self, lhs: A, rhs: B) -> Self::Output {
197 self.binop().eval(lhs, rhs)
198 }
199}
200
201impl<A, B> BinOp<A, B> for ArithmeticAssign
202where
203 A: NumAssignOps<B>,
204{
205 type Output = A;
206
207 fn eval(&self, lhs: A, rhs: B) -> Self::Output {
208 self.bin_op().eval(lhs, rhs)
209 }
210}
211
212impl<A, B> BinaryAssignOp<A, B> for ArithmeticAssign
213where
214 A: NumAssignOps<B>,
215{
216 fn eval(&self, lhs: &mut A, rhs: B) {
217 self.assign_op().eval(lhs, rhs)
218 }
219}