Skip to main content

pictorus_block_data/
block_ops.rs

1//! This file contains all the basic mathematic operations (Add/Multiply/Divide/etc) we need
2//! specific BlockData implementations for.
3//!
4//! Eventually these might all become macro-generated.
5
6use approx::{AbsDiffEq, RelativeEq};
7use core::ops::{
8    Add, AddAssign, BitAnd, BitOr, BitXor, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Shl,
9    Shr, Sub, SubAssign,
10};
11
12use nalgebra::DMatrix;
13
14use crate::BlockData;
15use crate::BlockTypeRelationship;
16
17impl Sub for &BlockData {
18    type Output = BlockData;
19    fn sub(self, rhs: Self) -> Self::Output {
20        match self.compare(rhs) {
21            BlockTypeRelationship::SameSizes => {
22                BlockData::from_data(self.get_data() - rhs.get_data(), self.get_type())
23            }
24            BlockTypeRelationship::FirstIsScalar => BlockData::from_data(
25                BlockData::scalar_sizeof(self.scalar(), rhs).get_data() - rhs.get_data(),
26                rhs.get_type(),
27            ),
28            BlockTypeRelationship::SecondIsScalar => BlockData::from_data(
29                self.get_data() - BlockData::scalar_sizeof(rhs.scalar(), self).get_data(),
30                self.get_type(),
31            ),
32            _ => panic!("Cannot add unless sizes match or one is scalar."),
33        }
34    }
35}
36
37impl Sub<&BlockData> for BlockData {
38    type Output = Self;
39    fn sub(self, rhs: &BlockData) -> Self::Output {
40        &self - rhs
41    }
42}
43
44impl Sub<BlockData> for &BlockData {
45    type Output = BlockData;
46    fn sub(self, rhs: BlockData) -> Self::Output {
47        self - &rhs
48    }
49}
50
51impl SubAssign<&BlockData> for BlockData {
52    fn sub_assign(&mut self, rhs: &BlockData) {
53        match self.compare(rhs) {
54            BlockTypeRelationship::SameSizes => self.set_data(self.get_data() - rhs.get_data()),
55            BlockTypeRelationship::FirstIsScalar => {
56                self.set_data(
57                    BlockData::scalar_sizeof(self.scalar(), rhs).get_data() - rhs.get_data(),
58                );
59                self.set_type(rhs.get_type());
60            }
61            BlockTypeRelationship::SecondIsScalar => self.set_data(
62                self.get_data() - BlockData::scalar_sizeof(rhs.scalar(), self).get_data(),
63            ),
64            _ => panic!("Cannot add unless sizes match or one is scalar."),
65        }
66    }
67}
68
69impl Add for &BlockData {
70    type Output = BlockData;
71    fn add(self, rhs: &BlockData) -> Self::Output {
72        match self.compare(rhs) {
73            BlockTypeRelationship::SameSizes => {
74                BlockData::from_data(self.get_data() + rhs.get_data(), self.get_type())
75            }
76            BlockTypeRelationship::FirstIsScalar => BlockData::from_data(
77                BlockData::scalar_sizeof(self.scalar(), rhs).get_data() + rhs.get_data(),
78                rhs.get_type(),
79            ),
80            BlockTypeRelationship::SecondIsScalar => BlockData::from_data(
81                BlockData::scalar_sizeof(rhs.scalar(), self).get_data() + self.get_data(),
82                self.get_type(),
83            ),
84            _ => panic!("Cannot add unless sizes match or one is scalar."),
85        }
86    }
87}
88
89impl Add<&BlockData> for BlockData {
90    type Output = BlockData;
91    fn add(self, rhs: &BlockData) -> Self::Output {
92        &self + rhs
93    }
94}
95
96impl AddAssign<&BlockData> for BlockData {
97    fn add_assign(&mut self, rhs: &BlockData) {
98        match self.compare(rhs) {
99            BlockTypeRelationship::SameSizes => self.set_data(self.get_data() + rhs.get_data()),
100            BlockTypeRelationship::FirstIsScalar => {
101                self.set_data(
102                    BlockData::scalar_sizeof(self.scalar(), rhs).get_data() + rhs.get_data(),
103                );
104                self.set_type(rhs.get_type());
105            }
106            BlockTypeRelationship::SecondIsScalar => self.set_data(
107                self.get_data() + BlockData::scalar_sizeof(rhs.scalar(), self).get_data(),
108            ),
109            _ => panic!("Cannot add unless sizes match or one is scalar."),
110        }
111    }
112}
113
114impl Mul for &BlockData {
115    type Output = BlockData;
116    fn mul(self, rhs: &BlockData) -> Self::Output {
117        BlockData::from_data(self.get_data() * rhs.get_data(), self.get_type())
118    }
119}
120
121impl Mul<f64> for &BlockData {
122    type Output = BlockData;
123    fn mul(self, rhs: f64) -> Self::Output {
124        BlockData::from_data(self.get_data() * rhs, self.get_type())
125    }
126}
127
128impl Mul<f64> for BlockData {
129    type Output = Self;
130    fn mul(self, rhs: f64) -> Self::Output {
131        &self * rhs
132    }
133}
134
135impl Mul<&BlockData> for f64 {
136    type Output = BlockData;
137    fn mul(self, rhs: &BlockData) -> Self::Output {
138        rhs * self
139    }
140}
141
142impl Mul<BlockData> for f64 {
143    type Output = BlockData;
144    fn mul(self, rhs: BlockData) -> Self::Output {
145        &rhs * self
146    }
147}
148
149impl MulAssign<&BlockData> for BlockData {
150    fn mul_assign(&mut self, rhs: &BlockData) {
151        self.set_data(self.get_data() * rhs.get_data());
152    }
153}
154
155impl Index<usize> for BlockData {
156    type Output = f64;
157    fn index(&self, index: usize) -> &Self::Output {
158        self.ref_at(index)
159    }
160}
161
162impl IndexMut<usize> for BlockData {
163    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
164        self.ref_at_mut(index)
165    }
166}
167
168impl Div<f64> for BlockData {
169    type Output = Self;
170    fn div(self, rhs: f64) -> Self::Output {
171        Self::from_data(self.get_data() / rhs, self.get_type())
172    }
173}
174
175impl Div<f64> for &BlockData {
176    type Output = BlockData;
177    fn div(self, rhs: f64) -> Self::Output {
178        BlockData::from_data(self.get_data() / rhs, self.get_type())
179    }
180}
181
182impl DivAssign<f64> for BlockData {
183    fn div_assign(&mut self, rhs: f64) {
184        self.set_data(self.get_data() / rhs);
185    }
186}
187
188impl Div for &BlockData {
189    type Output = BlockData;
190    fn div(self, rhs: &BlockData) -> Self::Output {
191        match self.compare(rhs) {
192            BlockTypeRelationship::SameSizes => BlockData::from_data(
193                self.get_data().component_div(rhs.get_data()),
194                self.get_type(),
195            ),
196            BlockTypeRelationship::FirstIsScalar => BlockData::from_data(
197                BlockData::scalar_sizeof(self.scalar(), rhs)
198                    .get_data()
199                    .component_div(rhs.get_data()),
200                rhs.get_type(),
201            ),
202            BlockTypeRelationship::SecondIsScalar => BlockData::from_data(
203                self.get_data()
204                    .component_div(BlockData::scalar_sizeof(rhs.scalar(), self).get_data()),
205                self.get_type(),
206            ),
207            _ => panic!("Cannot add unless sizes match or one is scalar."),
208        }
209    }
210}
211impl Div for BlockData {
212    type Output = BlockData;
213    fn div(self, rhs: BlockData) -> Self::Output {
214        &self / &rhs
215    }
216}
217
218impl DivAssign<&BlockData> for BlockData {
219    fn div_assign(&mut self, rhs: &BlockData) {
220        match self.compare(rhs) {
221            BlockTypeRelationship::SameSizes => {
222                self.set_data(self.get_data().component_div(rhs.get_data()))
223            }
224            BlockTypeRelationship::FirstIsScalar => self.set_data(
225                BlockData::scalar_sizeof(self.scalar(), rhs)
226                    .get_data()
227                    .component_div(rhs.get_data()),
228            ),
229            BlockTypeRelationship::SecondIsScalar => self.set_data(
230                self.get_data()
231                    .component_div(BlockData::scalar_sizeof(rhs.scalar(), self).get_data()),
232            ),
233            _ => panic!("Cannot add unless sizes match or one is scalar."),
234        }
235    }
236}
237
238impl BitAnd for &BlockData {
239    type Output = BlockData;
240    fn bitand(self, rhs: &BlockData) -> Self::Output {
241        match self.compare(rhs) {
242            BlockTypeRelationship::SameSizes => self.component_bitand(rhs),
243            BlockTypeRelationship::FirstIsScalar => {
244                BlockData::scalar_sizeof(self.scalar(), rhs).component_bitand(rhs)
245            }
246            BlockTypeRelationship::SecondIsScalar => {
247                self.component_bitand(&BlockData::scalar_sizeof(rhs.scalar(), self))
248            }
249            _ => panic!("Cannot AND unless sizes match or one is scalar."),
250        }
251    }
252}
253
254impl BitAnd for BlockData {
255    type Output = BlockData;
256    fn bitand(self, rhs: BlockData) -> Self::Output {
257        &self & &rhs
258    }
259}
260
261impl BitOr for &BlockData {
262    type Output = BlockData;
263    fn bitor(self, rhs: &BlockData) -> Self::Output {
264        match self.compare(rhs) {
265            BlockTypeRelationship::SameSizes => self.component_bitor(rhs),
266            BlockTypeRelationship::FirstIsScalar => {
267                BlockData::scalar_sizeof(self.scalar(), rhs).component_bitor(rhs)
268            }
269            BlockTypeRelationship::SecondIsScalar => {
270                self.component_bitor(&BlockData::scalar_sizeof(rhs.scalar(), self))
271            }
272            _ => panic!("Cannot OR unless sizes match or one is scalar."),
273        }
274    }
275}
276
277impl BitOr for BlockData {
278    type Output = BlockData;
279    fn bitor(self, rhs: BlockData) -> Self::Output {
280        &self | &rhs
281    }
282}
283
284impl BitXor for &BlockData {
285    type Output = BlockData;
286    fn bitxor(self, rhs: &BlockData) -> Self::Output {
287        match self.compare(rhs) {
288            BlockTypeRelationship::SameSizes => self.component_bitxor(rhs),
289            BlockTypeRelationship::FirstIsScalar => {
290                BlockData::scalar_sizeof(self.scalar(), rhs).component_bitxor(rhs)
291            }
292            BlockTypeRelationship::SecondIsScalar => {
293                self.component_bitxor(&BlockData::scalar_sizeof(rhs.scalar(), self))
294            }
295            _ => panic!("Cannot XOR unless sizes match or one is scalar."),
296        }
297    }
298}
299
300impl BitXor for BlockData {
301    type Output = BlockData;
302    fn bitxor(self, rhs: BlockData) -> Self::Output {
303        &self ^ &rhs
304    }
305}
306
307impl Shl<i32> for &BlockData {
308    type Output = BlockData;
309    fn shl(self, rhs: i32) -> Self::Output {
310        self.component_lshift(rhs)
311    }
312}
313
314impl Shl<i32> for BlockData {
315    type Output = BlockData;
316    fn shl(self, rhs: i32) -> Self::Output {
317        &self << rhs
318    }
319}
320
321impl Shr<i32> for &BlockData {
322    type Output = BlockData;
323    fn shr(self, rhs: i32) -> Self::Output {
324        self.component_rshift(rhs)
325    }
326}
327
328impl Shr<i32> for BlockData {
329    type Output = BlockData;
330    fn shr(self, rhs: i32) -> Self::Output {
331        &self >> rhs
332    }
333}
334
335impl AbsDiffEq for BlockData {
336    type Epsilon = f64;
337
338    fn default_epsilon() -> Self::Epsilon {
339        DMatrix::<f64>::default_epsilon()
340    }
341
342    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
343        self.get_data().abs_diff_eq(other.get_data(), epsilon)
344    }
345
346    fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
347        self.get_data().abs_diff_ne(other.get_data(), epsilon)
348    }
349}
350
351impl RelativeEq for BlockData {
352    fn default_max_relative() -> Self::Epsilon {
353        DMatrix::<f64>::default_max_relative()
354    }
355
356    fn relative_eq(
357        &self,
358        other: &Self,
359        epsilon: Self::Epsilon,
360        max_relative: Self::Epsilon,
361    ) -> bool {
362        self.get_data()
363            .relative_eq(other.get_data(), epsilon, max_relative)
364    }
365
366    fn relative_ne(
367        &self,
368        other: &Self,
369        epsilon: Self::Epsilon,
370        max_relative: Self::Epsilon,
371    ) -> bool {
372        self.get_data()
373            .relative_ne(other.get_data(), epsilon, max_relative)
374    }
375}