1use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
4use core::fmt;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8#[cfg(target_arch = "x86")]
9use core::arch::x86::*;
10#[cfg(target_arch = "x86_64")]
11use core::arch::x86_64::*;
12
13#[repr(C)]
14union UnionCast {
15 a: [f32; 4],
16 v: Mat2,
17}
18
19#[inline(always)]
21#[must_use]
22pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
23 Mat2::from_cols(x_axis, y_axis)
24}
25
26#[derive(Clone, Copy)]
32#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
33#[repr(transparent)]
34pub struct Mat2(pub(crate) __m128);
35
36impl Mat2 {
37 pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
39
40 pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
42
43 pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
45
46 #[allow(clippy::too_many_arguments)]
47 #[inline(always)]
48 #[must_use]
49 const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
50 unsafe {
51 UnionCast {
52 a: [m00, m01, m10, m11],
53 }
54 .v
55 }
56 }
57
58 #[inline(always)]
60 #[must_use]
61 pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
62 unsafe {
63 UnionCast {
64 a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
65 }
66 .v
67 }
68 }
69
70 #[inline]
74 #[must_use]
75 pub const fn from_cols_array(m: &[f32; 4]) -> Self {
76 Self::new(m[0], m[1], m[2], m[3])
77 }
78
79 #[inline]
82 #[must_use]
83 pub const fn to_cols_array(&self) -> [f32; 4] {
84 unsafe { *(self as *const Self as *const [f32; 4]) }
85 }
86
87 #[inline]
91 #[must_use]
92 pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
93 Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
94 }
95
96 #[inline]
99 #[must_use]
100 pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
101 unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
102 }
103
104 #[doc(alias = "scale")]
106 #[inline]
107 #[must_use]
108 pub const fn from_diagonal(diagonal: Vec2) -> Self {
109 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
110 }
111
112 #[inline]
115 #[must_use]
116 pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
117 let (sin, cos) = math::sin_cos(angle);
118 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
119 }
120
121 #[inline]
123 #[must_use]
124 pub fn from_angle(angle: f32) -> Self {
125 let (sin, cos) = math::sin_cos(angle);
126 Self::new(cos, sin, -sin, cos)
127 }
128
129 #[inline]
131 #[must_use]
132 pub fn from_mat3(m: Mat3) -> Self {
133 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
134 }
135
136 #[inline]
143 #[must_use]
144 pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
145 match (i, j) {
146 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
147 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
148 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
149 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
150 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
151 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
152 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
153 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
154 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
155 _ => panic!("index out of bounds"),
156 }
157 }
158
159 #[inline]
161 #[must_use]
162 pub fn from_mat3a(m: Mat3A) -> Self {
163 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
164 }
165
166 #[inline]
173 #[must_use]
174 pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
175 match (i, j) {
176 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
177 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
178 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
179 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
180 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
181 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
182 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
183 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
184 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
185 _ => panic!("index out of bounds"),
186 }
187 }
188
189 #[inline]
195 #[must_use]
196 pub const fn from_cols_slice(slice: &[f32]) -> Self {
197 Self::new(slice[0], slice[1], slice[2], slice[3])
198 }
199
200 #[inline]
206 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
207 slice[0] = self.x_axis.x;
208 slice[1] = self.x_axis.y;
209 slice[2] = self.y_axis.x;
210 slice[3] = self.y_axis.y;
211 }
212
213 #[inline]
219 #[must_use]
220 pub fn col(&self, index: usize) -> Vec2 {
221 match index {
222 0 => self.x_axis,
223 1 => self.y_axis,
224 _ => panic!("index out of bounds"),
225 }
226 }
227
228 #[inline]
234 pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
235 match index {
236 0 => &mut self.x_axis,
237 1 => &mut self.y_axis,
238 _ => panic!("index out of bounds"),
239 }
240 }
241
242 #[inline]
248 #[must_use]
249 pub fn row(&self, index: usize) -> Vec2 {
250 match index {
251 0 => Vec2::new(self.x_axis.x, self.y_axis.x),
252 1 => Vec2::new(self.x_axis.y, self.y_axis.y),
253 _ => panic!("index out of bounds"),
254 }
255 }
256
257 #[inline]
260 #[must_use]
261 pub fn is_finite(&self) -> bool {
262 self.x_axis.is_finite() && self.y_axis.is_finite()
263 }
264
265 #[inline]
267 #[must_use]
268 pub fn is_nan(&self) -> bool {
269 self.x_axis.is_nan() || self.y_axis.is_nan()
270 }
271
272 #[inline]
274 #[must_use]
275 pub fn transpose(&self) -> Self {
276 Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
277 }
278
279 #[inline]
281 #[must_use]
282 pub fn determinant(&self) -> f32 {
283 unsafe {
284 let abcd = self.0;
285 let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
286 let prod = _mm_mul_ps(abcd, dcba);
287 let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
288 _mm_cvtss_f32(det)
289 }
290 }
291
292 #[inline]
300 #[must_use]
301 pub fn inverse(&self) -> Self {
302 unsafe {
303 const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
304 let abcd = self.0;
305 let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
306 let prod = _mm_mul_ps(abcd, dcba);
307 let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
308 let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
309 let tmp = _mm_div_ps(SIGN, det);
310 glam_assert!(Mat2(tmp).is_finite());
311 let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
312 Self(_mm_mul_ps(dbca, tmp))
313 }
314 }
315
316 #[inline]
318 #[must_use]
319 pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
320 unsafe {
321 use crate::Align16;
322 use core::mem::MaybeUninit;
323 let abcd = self.0;
324 let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
325 let axbxcydy = _mm_mul_ps(abcd, xxyy);
326 let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
327 let result = _mm_add_ps(axbxcydy, cydyaxbx);
328 let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
329 _mm_store_ps(out.as_mut_ptr().cast(), result);
330 out.assume_init().0
331 }
332 }
333
334 #[inline]
336 #[must_use]
337 pub fn mul_mat2(&self, rhs: &Self) -> Self {
338 self.mul(rhs)
339 }
340
341 #[inline]
343 #[must_use]
344 pub fn add_mat2(&self, rhs: &Self) -> Self {
345 self.add(rhs)
346 }
347
348 #[inline]
350 #[must_use]
351 pub fn sub_mat2(&self, rhs: &Self) -> Self {
352 self.sub(rhs)
353 }
354
355 #[inline]
357 #[must_use]
358 pub fn mul_scalar(&self, rhs: f32) -> Self {
359 Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
360 }
361
362 #[inline]
364 #[must_use]
365 pub fn div_scalar(&self, rhs: f32) -> Self {
366 Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
367 }
368
369 #[inline]
379 #[must_use]
380 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
381 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
382 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
383 }
384
385 #[inline]
387 #[must_use]
388 pub fn abs(&self) -> Self {
389 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
390 }
391
392 #[inline]
393 pub fn as_dmat2(&self) -> DMat2 {
394 DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
395 }
396}
397
398impl Default for Mat2 {
399 #[inline]
400 fn default() -> Self {
401 Self::IDENTITY
402 }
403}
404
405impl Add for Mat2 {
406 type Output = Self;
407 #[inline]
408 fn add(self, rhs: Self) -> Self {
409 Self(unsafe { _mm_add_ps(self.0, rhs.0) })
410 }
411}
412
413impl Add<&Self> for Mat2 {
414 type Output = Self;
415 #[inline]
416 fn add(self, rhs: &Self) -> Self {
417 self.add(*rhs)
418 }
419}
420
421impl Add<&Mat2> for &Mat2 {
422 type Output = Mat2;
423 #[inline]
424 fn add(self, rhs: &Mat2) -> Mat2 {
425 (*self).add(*rhs)
426 }
427}
428
429impl Add<Mat2> for &Mat2 {
430 type Output = Mat2;
431 #[inline]
432 fn add(self, rhs: Mat2) -> Mat2 {
433 (*self).add(rhs)
434 }
435}
436
437impl AddAssign for Mat2 {
438 #[inline]
439 fn add_assign(&mut self, rhs: Self) {
440 *self = self.add(rhs);
441 }
442}
443
444impl AddAssign<&Self> for Mat2 {
445 #[inline]
446 fn add_assign(&mut self, rhs: &Self) {
447 self.add_assign(*rhs);
448 }
449}
450
451impl Sub for Mat2 {
452 type Output = Self;
453 #[inline]
454 fn sub(self, rhs: Self) -> Self {
455 Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
456 }
457}
458
459impl Sub<&Self> for Mat2 {
460 type Output = Self;
461 #[inline]
462 fn sub(self, rhs: &Self) -> Self {
463 self.sub(*rhs)
464 }
465}
466
467impl Sub<&Mat2> for &Mat2 {
468 type Output = Mat2;
469 #[inline]
470 fn sub(self, rhs: &Mat2) -> Mat2 {
471 (*self).sub(*rhs)
472 }
473}
474
475impl Sub<Mat2> for &Mat2 {
476 type Output = Mat2;
477 #[inline]
478 fn sub(self, rhs: Mat2) -> Mat2 {
479 (*self).sub(rhs)
480 }
481}
482
483impl SubAssign for Mat2 {
484 #[inline]
485 fn sub_assign(&mut self, rhs: Self) {
486 *self = self.sub(rhs);
487 }
488}
489
490impl SubAssign<&Self> for Mat2 {
491 #[inline]
492 fn sub_assign(&mut self, rhs: &Self) {
493 self.sub_assign(*rhs);
494 }
495}
496
497impl Neg for Mat2 {
498 type Output = Self;
499 #[inline]
500 fn neg(self) -> Self::Output {
501 Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
502 }
503}
504
505impl Neg for &Mat2 {
506 type Output = Mat2;
507 #[inline]
508 fn neg(self) -> Mat2 {
509 (*self).neg()
510 }
511}
512
513impl Mul for Mat2 {
514 type Output = Self;
515 #[inline]
516 fn mul(self, rhs: Self) -> Self {
517 unsafe {
518 let abcd = self.0;
519 let rhs = rhs.0;
520 let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
521 let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
522 let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
523 let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
524 let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
525 let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
526 let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
527 let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
528 Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
529 }
530 }
531}
532
533impl Mul<&Self> for Mat2 {
534 type Output = Self;
535 #[inline]
536 fn mul(self, rhs: &Self) -> Self {
537 self.mul(*rhs)
538 }
539}
540
541impl Mul<&Mat2> for &Mat2 {
542 type Output = Mat2;
543 #[inline]
544 fn mul(self, rhs: &Mat2) -> Mat2 {
545 (*self).mul(*rhs)
546 }
547}
548
549impl Mul<Mat2> for &Mat2 {
550 type Output = Mat2;
551 #[inline]
552 fn mul(self, rhs: Mat2) -> Mat2 {
553 (*self).mul(rhs)
554 }
555}
556
557impl MulAssign for Mat2 {
558 #[inline]
559 fn mul_assign(&mut self, rhs: Self) {
560 *self = self.mul(rhs);
561 }
562}
563
564impl MulAssign<&Self> for Mat2 {
565 #[inline]
566 fn mul_assign(&mut self, rhs: &Self) {
567 self.mul_assign(*rhs);
568 }
569}
570
571impl Mul<Vec2> for Mat2 {
572 type Output = Vec2;
573 #[inline]
574 fn mul(self, rhs: Vec2) -> Self::Output {
575 self.mul_vec2(rhs)
576 }
577}
578
579impl Mul<&Vec2> for Mat2 {
580 type Output = Vec2;
581 #[inline]
582 fn mul(self, rhs: &Vec2) -> Vec2 {
583 self.mul(*rhs)
584 }
585}
586
587impl Mul<&Vec2> for &Mat2 {
588 type Output = Vec2;
589 #[inline]
590 fn mul(self, rhs: &Vec2) -> Vec2 {
591 (*self).mul(*rhs)
592 }
593}
594
595impl Mul<Vec2> for &Mat2 {
596 type Output = Vec2;
597 #[inline]
598 fn mul(self, rhs: Vec2) -> Vec2 {
599 (*self).mul(rhs)
600 }
601}
602
603impl Mul<Mat2> for f32 {
604 type Output = Mat2;
605 #[inline]
606 fn mul(self, rhs: Mat2) -> Self::Output {
607 rhs.mul_scalar(self)
608 }
609}
610
611impl Mul<&Mat2> for f32 {
612 type Output = Mat2;
613 #[inline]
614 fn mul(self, rhs: &Mat2) -> Mat2 {
615 self.mul(*rhs)
616 }
617}
618
619impl Mul<&Mat2> for &f32 {
620 type Output = Mat2;
621 #[inline]
622 fn mul(self, rhs: &Mat2) -> Mat2 {
623 (*self).mul(*rhs)
624 }
625}
626
627impl Mul<Mat2> for &f32 {
628 type Output = Mat2;
629 #[inline]
630 fn mul(self, rhs: Mat2) -> Mat2 {
631 (*self).mul(rhs)
632 }
633}
634
635impl Mul<f32> for Mat2 {
636 type Output = Self;
637 #[inline]
638 fn mul(self, rhs: f32) -> Self {
639 self.mul_scalar(rhs)
640 }
641}
642
643impl Mul<&f32> for Mat2 {
644 type Output = Self;
645 #[inline]
646 fn mul(self, rhs: &f32) -> Self {
647 self.mul(*rhs)
648 }
649}
650
651impl Mul<&f32> for &Mat2 {
652 type Output = Mat2;
653 #[inline]
654 fn mul(self, rhs: &f32) -> Mat2 {
655 (*self).mul(*rhs)
656 }
657}
658
659impl Mul<f32> for &Mat2 {
660 type Output = Mat2;
661 #[inline]
662 fn mul(self, rhs: f32) -> Mat2 {
663 (*self).mul(rhs)
664 }
665}
666
667impl MulAssign<f32> for Mat2 {
668 #[inline]
669 fn mul_assign(&mut self, rhs: f32) {
670 *self = self.mul(rhs);
671 }
672}
673
674impl MulAssign<&f32> for Mat2 {
675 #[inline]
676 fn mul_assign(&mut self, rhs: &f32) {
677 self.mul_assign(*rhs);
678 }
679}
680
681impl Div<Mat2> for f32 {
682 type Output = Mat2;
683 #[inline]
684 fn div(self, rhs: Mat2) -> Self::Output {
685 rhs.div_scalar(self)
686 }
687}
688
689impl Div<&Mat2> for f32 {
690 type Output = Mat2;
691 #[inline]
692 fn div(self, rhs: &Mat2) -> Mat2 {
693 self.div(*rhs)
694 }
695}
696
697impl Div<&Mat2> for &f32 {
698 type Output = Mat2;
699 #[inline]
700 fn div(self, rhs: &Mat2) -> Mat2 {
701 (*self).div(*rhs)
702 }
703}
704
705impl Div<Mat2> for &f32 {
706 type Output = Mat2;
707 #[inline]
708 fn div(self, rhs: Mat2) -> Mat2 {
709 (*self).div(rhs)
710 }
711}
712
713impl Div<f32> for Mat2 {
714 type Output = Self;
715 #[inline]
716 fn div(self, rhs: f32) -> Self {
717 self.div_scalar(rhs)
718 }
719}
720
721impl Div<&f32> for Mat2 {
722 type Output = Self;
723 #[inline]
724 fn div(self, rhs: &f32) -> Self {
725 self.div(*rhs)
726 }
727}
728
729impl Div<&f32> for &Mat2 {
730 type Output = Mat2;
731 #[inline]
732 fn div(self, rhs: &f32) -> Mat2 {
733 (*self).div(*rhs)
734 }
735}
736
737impl Div<f32> for &Mat2 {
738 type Output = Mat2;
739 #[inline]
740 fn div(self, rhs: f32) -> Mat2 {
741 (*self).div(rhs)
742 }
743}
744
745impl DivAssign<f32> for Mat2 {
746 #[inline]
747 fn div_assign(&mut self, rhs: f32) {
748 *self = self.div(rhs);
749 }
750}
751
752impl DivAssign<&f32> for Mat2 {
753 #[inline]
754 fn div_assign(&mut self, rhs: &f32) {
755 self.div_assign(*rhs);
756 }
757}
758
759impl Sum<Self> for Mat2 {
760 fn sum<I>(iter: I) -> Self
761 where
762 I: Iterator<Item = Self>,
763 {
764 iter.fold(Self::ZERO, Self::add)
765 }
766}
767
768impl<'a> Sum<&'a Self> for Mat2 {
769 fn sum<I>(iter: I) -> Self
770 where
771 I: Iterator<Item = &'a Self>,
772 {
773 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
774 }
775}
776
777impl Product for Mat2 {
778 fn product<I>(iter: I) -> Self
779 where
780 I: Iterator<Item = Self>,
781 {
782 iter.fold(Self::IDENTITY, Self::mul)
783 }
784}
785
786impl<'a> Product<&'a Self> for Mat2 {
787 fn product<I>(iter: I) -> Self
788 where
789 I: Iterator<Item = &'a Self>,
790 {
791 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
792 }
793}
794
795impl PartialEq for Mat2 {
796 #[inline]
797 fn eq(&self, rhs: &Self) -> bool {
798 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
799 }
800}
801
802impl AsRef<[f32; 4]> for Mat2 {
803 #[inline]
804 fn as_ref(&self) -> &[f32; 4] {
805 unsafe { &*(self as *const Self as *const [f32; 4]) }
806 }
807}
808
809impl AsMut<[f32; 4]> for Mat2 {
810 #[inline]
811 fn as_mut(&mut self) -> &mut [f32; 4] {
812 unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
813 }
814}
815
816impl core::ops::Deref for Mat2 {
817 type Target = crate::deref::Cols2<Vec2>;
818 #[inline]
819 fn deref(&self) -> &Self::Target {
820 unsafe { &*(self as *const Self as *const Self::Target) }
821 }
822}
823
824impl core::ops::DerefMut for Mat2 {
825 #[inline]
826 fn deref_mut(&mut self) -> &mut Self::Target {
827 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
828 }
829}
830
831impl fmt::Debug for Mat2 {
832 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
833 fmt.debug_struct(stringify!(Mat2))
834 .field("x_axis", &self.x_axis)
835 .field("y_axis", &self.y_axis)
836 .finish()
837 }
838}
839
840impl fmt::Display for Mat2 {
841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
842 if let Some(p) = f.precision() {
843 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
844 } else {
845 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
846 }
847 }
848}