1use core::ops::{Add, Div, Mul, Neg, Rem, Sub};
3use num_traits::{Num, Zero};
4
5use super::Vector2;
7
8#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Default)]
19pub struct Matrix2<T> {
21 pub x_: Vector2<T>,
23 pub y_: Vector2<T>,
25}
26
27impl<T> Matrix2<T> {
28 #[inline]
52 pub const fn new(x_: Vector2<T>, y_: Vector2<T>) -> Self {
53 Matrix2 { x_, y_ }
54 }
55}
56
57impl<T: Clone + Num> Matrix2<T> {
58 #[inline]
78 pub fn det(&self) -> T {
79 self.x_.cross(&self.y_)
80 }
81
82 #[inline]
108 pub fn mdot(&self, v: &Vector2<T>) -> Vector2<T> {
109 Vector2::<T>::new(self.x_.dot(v), self.y_.dot(v))
110 }
111
112 #[inline]
134 pub fn scale(&self, alpha: T) -> Self {
135 Self::new(self.x_.clone() * alpha.clone(), self.y_.clone() * alpha)
136 }
137
138 #[inline]
162 pub fn unscale(&self, alpha: T) -> Self {
163 Self::new(self.x_.clone() / alpha.clone(), self.y_.clone() / alpha)
164 }
165}
166
167macro_rules! forward_xf_xf_binop {
168 (impl $imp:ident, $method:ident) => {
169 impl<'a, 'b, T: Clone + Num> $imp<&'b Matrix2<T>> for &'a Matrix2<T> {
170 type Output = Matrix2<T>;
171
172 #[inline]
173 fn $method(self, other: &Matrix2<T>) -> Self::Output {
174 self.clone().$method(other.clone())
175 }
176 }
177 };
178}
179
180macro_rules! forward_xf_val_binop {
181 (impl $imp:ident, $method:ident) => {
182 impl<'a, T: Clone + Num> $imp<Matrix2<T>> for &'a Matrix2<T> {
183 type Output = Matrix2<T>;
184
185 #[inline]
186 fn $method(self, other: Matrix2<T>) -> Self::Output {
187 self.clone().$method(other)
188 }
189 }
190 };
191}
192
193macro_rules! forward_val_xf_binop {
194 (impl $imp:ident, $method:ident) => {
195 impl<'a, T: Clone + Num> $imp<&'a Matrix2<T>> for Matrix2<T> {
196 type Output = Matrix2<T>;
197
198 #[inline]
199 fn $method(self, other: &Matrix2<T>) -> Self::Output {
200 self.$method(other.clone())
201 }
202 }
203 };
204}
205
206macro_rules! forward_all_binop {
207 (impl $imp:ident, $method:ident) => {
208 forward_xf_xf_binop!(impl $imp, $method);
209 forward_xf_val_binop!(impl $imp, $method);
210 forward_val_xf_binop!(impl $imp, $method);
211 };
212}
213
214forward_all_binop!(impl Add, add);
216
217impl<T: Clone + Num> Add<Matrix2<T>> for Matrix2<T> {
219 type Output = Self;
220
221 #[inline]
222 fn add(self, other: Self) -> Self::Output {
223 Self::Output::new(self.x_ + other.x_, self.y_ + other.y_)
224 }
225}
226
227forward_all_binop!(impl Sub, sub);
228
229impl<T: Clone + Num> Sub<Matrix2<T>> for Matrix2<T> {
231 type Output = Self;
232
233 #[inline]
234 fn sub(self, other: Self) -> Self::Output {
235 Self::Output::new(self.x_ - other.x_, self.y_ - other.y_)
236 }
237}
238
239mod opassign {
242 use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
243
244 use num_traits::NumAssign;
245
246 use crate::Matrix2;
247
248 impl<T: Clone + NumAssign> AddAssign for Matrix2<T> {
249 fn add_assign(&mut self, other: Self) {
250 self.x_ += other.x_;
251 self.y_ += other.y_;
252 }
253 }
254
255 impl<T: Clone + NumAssign> SubAssign for Matrix2<T> {
256 fn sub_assign(&mut self, other: Self) {
257 self.x_ -= other.x_;
258 self.y_ -= other.y_;
259 }
260 }
261
262 impl<T: Clone + NumAssign> MulAssign<T> for Matrix2<T> {
263 fn mul_assign(&mut self, other: T) {
264 self.x_ *= other.clone();
265 self.y_ *= other;
266 }
267 }
268
269 impl<T: Clone + NumAssign> DivAssign<T> for Matrix2<T> {
270 fn div_assign(&mut self, other: T) {
271 self.x_ /= other.clone();
272 self.y_ /= other;
273 }
274 }
275
276 macro_rules! forward_op_assign1 {
277 (impl $imp:ident, $method:ident) => {
278 impl<'a, T: Clone + NumAssign> $imp<&'a Matrix2<T>> for Matrix2<T> {
279 #[inline]
280 fn $method(&mut self, other: &Self) {
281 self.$method(other.clone())
282 }
283 }
284 };
285 }
286
287 macro_rules! forward_op_assign2 {
288 (impl $imp:ident, $method:ident) => {
289 impl<'a, T: Clone + NumAssign> $imp<&'a T> for Matrix2<T> {
290 #[inline]
291 fn $method(&mut self, other: &T) {
292 self.$method(other.clone())
293 }
294 }
295 };
296 }
297
298 forward_op_assign1!(impl AddAssign, add_assign);
299 forward_op_assign1!(impl SubAssign, sub_assign);
300 forward_op_assign2!(impl MulAssign, mul_assign);
301 forward_op_assign2!(impl DivAssign, div_assign);
302}
303
304impl<T: Clone + Num + Neg<Output = T>> Neg for Matrix2<T> {
305 type Output = Self;
306
307 #[inline]
308 fn neg(self) -> Self::Output {
309 Self::Output::new(-self.x_, -self.y_)
310 }
311}
312
313impl<'a, T: Clone + Num + Neg<Output = T>> Neg for &'a Matrix2<T> {
314 type Output = Matrix2<T>;
315
316 #[inline]
317 fn neg(self) -> Self::Output {
318 -self.clone()
319 }
320}
321
322macro_rules! scalar_arithmetic {
323 (@forward $imp:ident::$method:ident for $($scalar:ident),*) => (
324 impl<'a, T: Clone + Num> $imp<&'a T> for Matrix2<T> {
325 type Output = Matrix2<T>;
326
327 #[inline]
328 fn $method(self, other: &T) -> Self::Output {
329 self.$method(other.clone())
330 }
331 }
332 impl<'a, T: Clone + Num> $imp<T> for &'a Matrix2<T> {
333 type Output = Matrix2<T>;
334
335 #[inline]
336 fn $method(self, other: T) -> Self::Output {
337 self.clone().$method(other)
338 }
339 }
340 impl<'a, 'b, T: Clone + Num> $imp<&'a T> for &'b Matrix2<T> {
341 type Output = Matrix2<T>;
342
343 #[inline]
344 fn $method(self, other: &T) -> Self::Output {
345 self.clone().$method(other.clone())
346 }
347 }
348 $(
349 impl<'a> $imp<&'a Matrix2<$scalar>> for $scalar {
350 type Output = Matrix2<$scalar>;
351
352 #[inline]
353 fn $method(self, other: &Matrix2<$scalar>) -> Matrix2<$scalar> {
354 self.$method(other.clone())
355 }
356 }
357 impl<'a> $imp<Matrix2<$scalar>> for &'a $scalar {
358 type Output = Matrix2<$scalar>;
359
360 #[inline]
361 fn $method(self, other: Matrix2<$scalar>) -> Matrix2<$scalar> {
362 self.clone().$method(other)
363 }
364 }
365 impl<'a, 'b> $imp<&'a Matrix2<$scalar>> for &'b $scalar {
366 type Output = Matrix2<$scalar>;
367
368 #[inline]
369 fn $method(self, other: &Matrix2<$scalar>) -> Matrix2<$scalar> {
370 self.clone().$method(other.clone())
371 }
372 }
373 )*
374 );
375 ($($scalar:ident),*) => (
376 scalar_arithmetic!(@forward Mul::mul for $($scalar),*);
377 $(
381 impl Mul<Matrix2<$scalar>> for $scalar {
382 type Output = Matrix2<$scalar>;
383
384 #[inline]
385 fn mul(self, other: Matrix2<$scalar>) -> Self::Output {
386 Self::Output::new(self * other.x_, self * other.y_)
387 }
388 }
389
390 )*
391 );
392}
393
394impl<T: Clone + Num> Mul<T> for Matrix2<T> {
395 type Output = Matrix2<T>;
396
397 #[inline]
398 fn mul(self, other: T) -> Self::Output {
399 Self::Output::new(self.x_ * other.clone(), self.y_ * other)
400 }
401}
402
403impl<T: Clone + Num> Div<T> for Matrix2<T> {
404 type Output = Self;
405
406 #[inline]
407 fn div(self, other: T) -> Self::Output {
408 Self::Output::new(self.x_ / other.clone(), self.y_ / other)
409 }
410}
411
412impl<T: Clone + Num> Rem<T> for Matrix2<T> {
413 type Output = Matrix2<T>;
414
415 #[inline]
416 fn rem(self, other: T) -> Self::Output {
417 Self::Output::new(self.x_ % other.clone(), self.y_ % other)
418 }
419}
420
421scalar_arithmetic!(usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64);
422
423impl<T: Clone + Num> Zero for Matrix2<T> {
425 #[inline]
426 fn zero() -> Self {
427 Self::new(Zero::zero(), Zero::zero())
428 }
429
430 #[inline]
431 fn is_zero(&self) -> bool {
432 self.x_.is_zero() && self.y_.is_zero()
433 }
434
435 #[inline]
436 fn set_zero(&mut self) {
437 self.x_.set_zero();
438 self.y_.set_zero();
439 }
440}
441
442#[cfg(test)]
452mod test {
453 #![allow(non_upper_case_globals)]
454
455 use super::{Matrix2, Vector2};
457 use core::f64;
458 use num_traits::Zero;
459
460 pub const _0_0v: Vector2<f64> = Vector2 { x_: 0.0, y_: 0.0 };
461 pub const _1_0v: Vector2<f64> = Vector2 { x_: 1.0, y_: 0.0 };
462 pub const _1_1v: Vector2<f64> = Vector2 { x_: 1.0, y_: 1.0 };
463 pub const _0_1v: Vector2<f64> = Vector2 { x_: 0.0, y_: 1.0 };
464 pub const _neg1_1v: Vector2<f64> = Vector2 { x_: -1.0, y_: 1.0 };
465 pub const _05_05v: Vector2<f64> = Vector2 { x_: 0.5, y_: 0.5 };
466 pub const _4_2v: Vector2<f64> = Vector2 { x_: 4.0, y_: 2.0 };
468
469 pub const _0_0m: Matrix2<f64> = Matrix2 {
470 x_: _0_0v,
471 y_: _0_0v,
472 };
473 pub const _1_0m: Matrix2<f64> = Matrix2 {
474 x_: _1_0v,
475 y_: _0_0v,
476 };
477 pub const _1_1m: Matrix2<f64> = Matrix2 {
478 x_: _1_1v,
479 y_: _1_1v,
480 };
481 pub const _0_1m: Matrix2<f64> = Matrix2 {
482 x_: _0_0v,
483 y_: _1_0v,
484 };
485 pub const _neg1_1m: Matrix2<f64> = Matrix2 {
486 x_: _neg1_1v,
487 y_: _1_0v,
488 };
489 pub const _05_05m: Matrix2<f64> = Matrix2 {
490 x_: _05_05v,
491 y_: _05_05v,
492 };
493 pub const all_consts: [Matrix2<f64>; 5] = [_0_0m, _1_0m, _1_1m, _neg1_1m, _05_05m];
494 pub const _4_2m: Matrix2<f64> = Matrix2 {
495 x_: _4_2v,
496 y_: _4_2v,
497 };
498
499 #[test]
500 fn test_consts() {
501 assert_eq!(_0_0m, Zero::zero());
512 }
513
514 #[test]
515 fn test_scale_unscale() {
516 assert_eq!(_05_05m.scale(2.0), _1_1m);
517 assert_eq!(_1_1m.unscale(2.0), _05_05m);
518 for &c in all_consts.iter() {
519 assert_eq!(c.scale(2.0).unscale(2.0), c);
520 }
521 }
522
523 }