• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
4 use core::fmt;
5 use core::iter::{Product, Sum};
6 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7 
8 use core::simd::*;
9 
10 /// Creates a 2x2 matrix from two column vectors.
11 #[inline(always)]
12 #[must_use]
mat2(x_axis: Vec2, y_axis: Vec2) -> Mat213 pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
14     Mat2::from_cols(x_axis, y_axis)
15 }
16 
17 /// A 2x2 column major matrix.
18 ///
19 /// SIMD vector types are used for storage on supported platforms.
20 ///
21 /// This type is 16 byte aligned.
22 #[derive(Clone, Copy)]
23 #[repr(transparent)]
24 pub struct Mat2(pub(crate) f32x4);
25 
26 impl Mat2 {
27     /// A 2x2 matrix with all elements set to `0.0`.
28     pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
29 
30     /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
31     pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
32 
33     /// All NAN:s.
34     pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
35 
36     #[allow(clippy::too_many_arguments)]
37     #[inline(always)]
38     #[must_use]
new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self39     const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
40         Self(f32x4::from_array([m00, m01, m10, m11]))
41     }
42 
43     /// Creates a 2x2 matrix from two column vectors.
44     #[inline(always)]
45     #[must_use]
from_cols(x_axis: Vec2, y_axis: Vec2) -> Self46     pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
47         Self(f32x4::from_array([x_axis.x, x_axis.y, y_axis.x, y_axis.y]))
48     }
49 
50     /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
51     /// If your data is stored in row major you will need to `transpose` the returned
52     /// matrix.
53     #[inline]
54     #[must_use]
from_cols_array(m: &[f32; 4]) -> Self55     pub const fn from_cols_array(m: &[f32; 4]) -> Self {
56         Self(f32x4::from_array(*m))
57     }
58 
59     /// Creates a `[f32; 4]` array storing data in column major order.
60     /// If you require data in row major order `transpose` the matrix first.
61     #[inline]
62     #[must_use]
to_cols_array(&self) -> [f32; 4]63     pub const fn to_cols_array(&self) -> [f32; 4] {
64         unsafe { *(self as *const Self as *const [f32; 4]) }
65     }
66 
67     /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
68     /// If your data is in row major order you will need to `transpose` the returned
69     /// matrix.
70     #[inline]
71     #[must_use]
from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self72     pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
73         Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
74     }
75 
76     /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
77     /// If you require data in row major order `transpose` the matrix first.
78     #[inline]
79     #[must_use]
to_cols_array_2d(&self) -> [[f32; 2]; 2]80     pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
81         unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
82     }
83 
84     /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
85     #[doc(alias = "scale")]
86     #[inline]
87     #[must_use]
from_diagonal(diagonal: Vec2) -> Self88     pub const fn from_diagonal(diagonal: Vec2) -> Self {
89         Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
90     }
91 
92     /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
93     /// `angle` (in radians).
94     #[inline]
95     #[must_use]
from_scale_angle(scale: Vec2, angle: f32) -> Self96     pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
97         let (sin, cos) = math::sin_cos(angle);
98         Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
99     }
100 
101     /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
102     #[inline]
103     #[must_use]
from_angle(angle: f32) -> Self104     pub fn from_angle(angle: f32) -> Self {
105         let (sin, cos) = math::sin_cos(angle);
106         Self::new(cos, sin, -sin, cos)
107     }
108 
109     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
110     #[inline]
111     #[must_use]
from_mat3(m: Mat3) -> Self112     pub fn from_mat3(m: Mat3) -> Self {
113         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
114     }
115 
116     /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
117     /// and `j`th row.
118     ///
119     /// # Panics
120     ///
121     /// Panics if `i` or `j` is greater than 2.
122     #[inline]
123     #[must_use]
from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self124     pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
125         match (i, j) {
126             (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
127             (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
128             (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
129             (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
130             (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
131             (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
132             (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
133             (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
134             (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
135             _ => panic!("index out of bounds"),
136         }
137     }
138 
139     /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
140     #[inline]
141     #[must_use]
from_mat3a(m: Mat3A) -> Self142     pub fn from_mat3a(m: Mat3A) -> Self {
143         Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
144     }
145 
146     /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
147     /// and `j`th row.
148     ///
149     /// # Panics
150     ///
151     /// Panics if `i` or `j` is greater than 2.
152     #[inline]
153     #[must_use]
from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self154     pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
155         match (i, j) {
156             (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
157             (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
158             (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
159             (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
160             (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
161             (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
162             (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
163             (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
164             (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
165             _ => panic!("index out of bounds"),
166         }
167     }
168 
169     /// Creates a 2x2 matrix from the first 4 values in `slice`.
170     ///
171     /// # Panics
172     ///
173     /// Panics if `slice` is less than 4 elements long.
174     #[inline]
175     #[must_use]
from_cols_slice(slice: &[f32]) -> Self176     pub const fn from_cols_slice(slice: &[f32]) -> Self {
177         Self::new(slice[0], slice[1], slice[2], slice[3])
178     }
179 
180     /// Writes the columns of `self` to the first 4 elements in `slice`.
181     ///
182     /// # Panics
183     ///
184     /// Panics if `slice` is less than 4 elements long.
185     #[inline]
write_cols_to_slice(self, slice: &mut [f32])186     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
187         slice[0] = self.x_axis.x;
188         slice[1] = self.x_axis.y;
189         slice[2] = self.y_axis.x;
190         slice[3] = self.y_axis.y;
191     }
192 
193     /// Returns the matrix column for the given `index`.
194     ///
195     /// # Panics
196     ///
197     /// Panics if `index` is greater than 1.
198     #[inline]
199     #[must_use]
col(&self, index: usize) -> Vec2200     pub fn col(&self, index: usize) -> Vec2 {
201         match index {
202             0 => self.x_axis,
203             1 => self.y_axis,
204             _ => panic!("index out of bounds"),
205         }
206     }
207 
208     /// Returns a mutable reference to the matrix column for the given `index`.
209     ///
210     /// # Panics
211     ///
212     /// Panics if `index` is greater than 1.
213     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec2214     pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
215         match index {
216             0 => &mut self.x_axis,
217             1 => &mut self.y_axis,
218             _ => panic!("index out of bounds"),
219         }
220     }
221 
222     /// Returns the matrix row for the given `index`.
223     ///
224     /// # Panics
225     ///
226     /// Panics if `index` is greater than 1.
227     #[inline]
228     #[must_use]
row(&self, index: usize) -> Vec2229     pub fn row(&self, index: usize) -> Vec2 {
230         match index {
231             0 => Vec2::new(self.x_axis.x, self.y_axis.x),
232             1 => Vec2::new(self.x_axis.y, self.y_axis.y),
233             _ => panic!("index out of bounds"),
234         }
235     }
236 
237     /// Returns `true` if, and only if, all elements are finite.
238     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
239     #[inline]
240     #[must_use]
is_finite(&self) -> bool241     pub fn is_finite(&self) -> bool {
242         self.x_axis.is_finite() && self.y_axis.is_finite()
243     }
244 
245     /// Returns `true` if any elements are `NaN`.
246     #[inline]
247     #[must_use]
is_nan(&self) -> bool248     pub fn is_nan(&self) -> bool {
249         self.x_axis.is_nan() || self.y_axis.is_nan()
250     }
251 
252     /// Returns the transpose of `self`.
253     #[inline]
254     #[must_use]
transpose(&self) -> Self255     pub fn transpose(&self) -> Self {
256         Self(simd_swizzle!(self.0, [0, 2, 1, 3]))
257     }
258 
259     /// Returns the determinant of `self`.
260     #[inline]
261     #[must_use]
determinant(&self) -> f32262     pub fn determinant(&self) -> f32 {
263         let abcd = self.0;
264         let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
265         let prod = abcd * dcba;
266         let det = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
267         det[0]
268     }
269 
270     /// Returns the inverse of `self`.
271     ///
272     /// If the matrix is not invertible the returned matrix will be invalid.
273     ///
274     /// # Panics
275     ///
276     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
277     #[inline]
278     #[must_use]
inverse(&self) -> Self279     pub fn inverse(&self) -> Self {
280         const SIGN: f32x4 = f32x4::from_array([1.0, -1.0, -1.0, 1.0]);
281         let abcd = self.0;
282         let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]);
283         let prod = abcd * dcba;
284         let sub = prod - simd_swizzle!(prod, [1, 1, 1, 1]);
285         let det = simd_swizzle!(sub, [0, 0, 0, 0]);
286         let tmp = SIGN / det;
287         glam_assert!(Mat2(tmp).is_finite());
288         let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]);
289         Self(dbca.mul(tmp))
290     }
291 
292     /// Transforms a 2D vector.
293     #[inline]
294     #[must_use]
mul_vec2(&self, rhs: Vec2) -> Vec2295     pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
296         let abcd = self.0;
297         let xxyy = f32x4::from_array([rhs.x, rhs.x, rhs.y, rhs.y]);
298         let axbxcydy = abcd.mul(xxyy);
299         let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]);
300         let result = axbxcydy.add(cydyaxbx);
301         unsafe { *(&result as *const f32x4 as *const Vec2) }
302     }
303 
304     /// Multiplies two 2x2 matrices.
305     #[inline]
306     #[must_use]
mul_mat2(&self, rhs: &Self) -> Self307     pub fn mul_mat2(&self, rhs: &Self) -> Self {
308         let abcd = self.0;
309         let xxyy0 = simd_swizzle!(rhs.0, [0, 0, 1, 1]);
310         let xxyy1 = simd_swizzle!(rhs.0, [2, 2, 3, 3]);
311         let axbxcydy0 = abcd * xxyy0;
312         let axbxcydy1 = abcd * xxyy1;
313         let cydyaxbx0 = simd_swizzle!(axbxcydy0, [2, 3, 0, 1]);
314         let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]);
315         let result0 = axbxcydy0 + cydyaxbx0;
316         let result1 = axbxcydy1 + cydyaxbx1;
317         Self(simd_swizzle!(result0, result1, [0, 1, 4, 5]))
318     }
319 
320     /// Adds two 2x2 matrices.
321     #[inline]
322     #[must_use]
add_mat2(&self, rhs: &Self) -> Self323     pub fn add_mat2(&self, rhs: &Self) -> Self {
324         Self(self.0 + rhs.0)
325     }
326 
327     /// Subtracts two 2x2 matrices.
328     #[inline]
329     #[must_use]
sub_mat2(&self, rhs: &Self) -> Self330     pub fn sub_mat2(&self, rhs: &Self) -> Self {
331         Self(self.0 - rhs.0)
332     }
333 
334     /// Multiplies a 2x2 matrix by a scalar.
335     #[inline]
336     #[must_use]
mul_scalar(&self, rhs: f32) -> Self337     pub fn mul_scalar(&self, rhs: f32) -> Self {
338         Self(self.0 * f32x4::splat(rhs))
339     }
340 
341     /// Divides a 2x2 matrix by a scalar.
342     #[inline]
343     #[must_use]
div_scalar(&self, rhs: f32) -> Self344     pub fn div_scalar(&self, rhs: f32) -> Self {
345         Self(self.0 / f32x4::splat(rhs))
346     }
347 
348     /// Returns true if the absolute difference of all elements between `self` and `rhs`
349     /// is less than or equal to `max_abs_diff`.
350     ///
351     /// This can be used to compare if two matrices contain similar elements. It works best
352     /// when comparing with a known value. The `max_abs_diff` that should be used used
353     /// depends on the values being compared against.
354     ///
355     /// For more see
356     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
357     #[inline]
358     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool359     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
360         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
361             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
362     }
363 
364     /// Takes the absolute value of each element in `self`
365     #[inline]
366     #[must_use]
abs(&self) -> Self367     pub fn abs(&self) -> Self {
368         Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
369     }
370 
371     #[inline]
as_dmat2(&self) -> DMat2372     pub fn as_dmat2(&self) -> DMat2 {
373         DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
374     }
375 }
376 
377 impl Default for Mat2 {
378     #[inline]
default() -> Self379     fn default() -> Self {
380         Self::IDENTITY
381     }
382 }
383 
384 impl Add<Mat2> for Mat2 {
385     type Output = Self;
386     #[inline]
add(self, rhs: Self) -> Self::Output387     fn add(self, rhs: Self) -> Self::Output {
388         self.add_mat2(&rhs)
389     }
390 }
391 
392 impl AddAssign<Mat2> for Mat2 {
393     #[inline]
add_assign(&mut self, rhs: Self)394     fn add_assign(&mut self, rhs: Self) {
395         *self = self.add_mat2(&rhs);
396     }
397 }
398 
399 impl Sub<Mat2> for Mat2 {
400     type Output = Self;
401     #[inline]
sub(self, rhs: Self) -> Self::Output402     fn sub(self, rhs: Self) -> Self::Output {
403         self.sub_mat2(&rhs)
404     }
405 }
406 
407 impl SubAssign<Mat2> for Mat2 {
408     #[inline]
sub_assign(&mut self, rhs: Self)409     fn sub_assign(&mut self, rhs: Self) {
410         *self = self.sub_mat2(&rhs);
411     }
412 }
413 
414 impl Neg for Mat2 {
415     type Output = Self;
416     #[inline]
neg(self) -> Self::Output417     fn neg(self) -> Self::Output {
418         Self(-self.0)
419     }
420 }
421 
422 impl Mul<Mat2> for Mat2 {
423     type Output = Self;
424     #[inline]
mul(self, rhs: Self) -> Self::Output425     fn mul(self, rhs: Self) -> Self::Output {
426         self.mul_mat2(&rhs)
427     }
428 }
429 
430 impl MulAssign<Mat2> for Mat2 {
431     #[inline]
mul_assign(&mut self, rhs: Self)432     fn mul_assign(&mut self, rhs: Self) {
433         *self = self.mul_mat2(&rhs);
434     }
435 }
436 
437 impl Mul<Vec2> for Mat2 {
438     type Output = Vec2;
439     #[inline]
mul(self, rhs: Vec2) -> Self::Output440     fn mul(self, rhs: Vec2) -> Self::Output {
441         self.mul_vec2(rhs)
442     }
443 }
444 
445 impl Mul<Mat2> for f32 {
446     type Output = Mat2;
447     #[inline]
mul(self, rhs: Mat2) -> Self::Output448     fn mul(self, rhs: Mat2) -> Self::Output {
449         rhs.mul_scalar(self)
450     }
451 }
452 
453 impl Mul<f32> for Mat2 {
454     type Output = Self;
455     #[inline]
mul(self, rhs: f32) -> Self::Output456     fn mul(self, rhs: f32) -> Self::Output {
457         self.mul_scalar(rhs)
458     }
459 }
460 
461 impl MulAssign<f32> for Mat2 {
462     #[inline]
mul_assign(&mut self, rhs: f32)463     fn mul_assign(&mut self, rhs: f32) {
464         *self = self.mul_scalar(rhs);
465     }
466 }
467 
468 impl Div<Mat2> for f32 {
469     type Output = Mat2;
470     #[inline]
div(self, rhs: Mat2) -> Self::Output471     fn div(self, rhs: Mat2) -> Self::Output {
472         rhs.div_scalar(self)
473     }
474 }
475 
476 impl Div<f32> for Mat2 {
477     type Output = Self;
478     #[inline]
div(self, rhs: f32) -> Self::Output479     fn div(self, rhs: f32) -> Self::Output {
480         self.div_scalar(rhs)
481     }
482 }
483 
484 impl DivAssign<f32> for Mat2 {
485     #[inline]
div_assign(&mut self, rhs: f32)486     fn div_assign(&mut self, rhs: f32) {
487         *self = self.div_scalar(rhs);
488     }
489 }
490 
491 impl Sum<Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,492     fn sum<I>(iter: I) -> Self
493     where
494         I: Iterator<Item = Self>,
495     {
496         iter.fold(Self::ZERO, Self::add)
497     }
498 }
499 
500 impl<'a> Sum<&'a Self> for Mat2 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,501     fn sum<I>(iter: I) -> Self
502     where
503         I: Iterator<Item = &'a Self>,
504     {
505         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
506     }
507 }
508 
509 impl Product for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,510     fn product<I>(iter: I) -> Self
511     where
512         I: Iterator<Item = Self>,
513     {
514         iter.fold(Self::IDENTITY, Self::mul)
515     }
516 }
517 
518 impl<'a> Product<&'a Self> for Mat2 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,519     fn product<I>(iter: I) -> Self
520     where
521         I: Iterator<Item = &'a Self>,
522     {
523         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
524     }
525 }
526 
527 impl PartialEq for Mat2 {
528     #[inline]
eq(&self, rhs: &Self) -> bool529     fn eq(&self, rhs: &Self) -> bool {
530         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
531     }
532 }
533 
534 #[cfg(not(target_arch = "spirv"))]
535 impl AsRef<[f32; 4]> for Mat2 {
536     #[inline]
as_ref(&self) -> &[f32; 4]537     fn as_ref(&self) -> &[f32; 4] {
538         unsafe { &*(self as *const Self as *const [f32; 4]) }
539     }
540 }
541 
542 #[cfg(not(target_arch = "spirv"))]
543 impl AsMut<[f32; 4]> for Mat2 {
544     #[inline]
as_mut(&mut self) -> &mut [f32; 4]545     fn as_mut(&mut self) -> &mut [f32; 4] {
546         unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
547     }
548 }
549 
550 impl core::ops::Deref for Mat2 {
551     type Target = crate::deref::Cols2<Vec2>;
552     #[inline]
deref(&self) -> &Self::Target553     fn deref(&self) -> &Self::Target {
554         unsafe { &*(self as *const Self as *const Self::Target) }
555     }
556 }
557 
558 impl core::ops::DerefMut for Mat2 {
559     #[inline]
deref_mut(&mut self) -> &mut Self::Target560     fn deref_mut(&mut self) -> &mut Self::Target {
561         unsafe { &mut *(self as *mut Self as *mut Self::Target) }
562     }
563 }
564 
565 impl fmt::Debug for Mat2 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result566     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
567         fmt.debug_struct(stringify!(Mat2))
568             .field("x_axis", &self.x_axis)
569             .field("y_axis", &self.y_axis)
570             .finish()
571     }
572 }
573 
574 impl fmt::Display for Mat2 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result575     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
576         if let Some(p) = f.precision() {
577             write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
578         } else {
579             write!(f, "[{}, {}]", self.x_axis, self.y_axis)
580         }
581     }
582 }
583