geomath/
vector.rs

1//!
2//! A vector is represented as a struct containing a `f64` field for each cartesian component.
3//!
4
5use std::fmt::{Debug, Error, Formatter};
6use std::ops::*;
7use crate::prelude::*;
8use crate::prelude::coordinates::*;
9use crate::matrix::{Matrix2, Matrix3, Matrix4};
10use crate::point::Point2;
11use crate::{impl_vector, impl_debug_vector};
12
13/// constant vectors
14pub mod consts {
15    use super::*;
16
17    /// 2D positive unit x vector (1, 0)
18    pub const EX_2: Vector2 = Vector2 { x: 1., y: 0. };
19    /// 2D negative unit x vector (-1, 0)
20    pub const N_EX_2: Vector2 = Vector2 { x: -1., y: 0. };
21    /// 2D positive unit y vector (0, 1)
22    pub const EY_2: Vector2 = Vector2 { x: 0., y: 1. };
23    /// 2D negative unit y vector (0, -1)
24    pub const N_EY_2: Vector2 = Vector2 { x: 0., y: -1. };
25    /// 2D zero vector (0, 0)
26    pub const ZEROS_2: Vector2 = Vector2 { x: 0., y: 0. };
27    /// 2D one vector (1, 1)
28    pub const ONES_2: Vector2 = Vector2 { x: 1., y: 1. };
29
30
31    /// 3D positive unit x vector (1, 0, 0)
32    pub const EX_3: Vector3 = Vector3 { x: 1., y: 0., z: 0. };
33    /// 3D negative unit x vector (-1, 0, 0)
34    pub const N_EX_3: Vector3 = Vector3 { x: -1., y: 0., z: 0. };
35    /// 3D positive unit y vector (0, 1, 0)
36    pub const EY_3: Vector3 = Vector3 { x: 0., y: 1., z: 0. };
37    /// 3D negative unit y vector (0, -1, 0)
38    pub const N_EY_3: Vector3 = Vector3 { x: 0., y: -1., z: 0. };
39    /// 3D positive unit z vector (0, 0, 1)
40    pub const EZ_3: Vector3 = Vector3 { x: 0., y: 0., z: 1. };
41    /// 3D negative unit z vector (0, 0, -1)
42    pub const N_EZ_3: Vector3 = Vector3 { x: 0., y: 0., z: -1. };
43    /// 3D zero vector (0, 0, 0)
44    pub const ZEROS_3: Vector3 = Vector3 { x: 0., y: 0., z: 0. };
45    /// 3D one vector (1, 1, 1)
46    pub const ONES_3: Vector3 = Vector3 { x: 1., y: 1., z: 1. };
47
48
49    /// 3D positive unit x vector (1, 0, 0, 0)
50    pub const EX_4: Vector4 = Vector4 { x: 1., y: 0., z: 0., w: 0. };
51    /// 4D negative unit x vector (-1, 0, 0, 0)
52    pub const N_EX_4: Vector4 = Vector4 { x: -1., y: 0., z: 0., w: 0. };
53    /// 4D positive unit y vector (0, 1, 0, 0)
54    pub const EY_4: Vector4 = Vector4 { x: 0., y: 1., z: 0., w: 0. };
55    /// 4D negative unit y vector (0, -1, 0, 0)
56    pub const N_EY_4: Vector4 = Vector4 { x: 0., y: -1., z: 0., w: 0. };
57    /// 4D positive unit z vector (0, 0, 1, 0)
58    pub const EZ_4: Vector4 = Vector4 { x: 0., y: 0., z: 1., w: 0. };
59    /// 4D negative unit z vector (0, 0, -1, 0)
60    pub const N_EZ_4: Vector4 = Vector4 { x: 0., y: 0., z: -1., w: 0. };
61    /// 4D positive unit w vector (0, 0, 0, 1)
62    pub const EW_4: Vector4 = Vector4 { x: 0., y: 0., z: 0., w: 1. };
63    /// 4D negative unit w vector (0, 0, 0, -1)
64    pub const N_EW_4: Vector4 = Vector4 { x: 0., y: 0., z: 0., w: -1. };
65    /// 4D zero vector (0, 0, 0, 0)
66    pub const ZEROS_4: Vector4 = Vector4 { x: 0., y: 0., z: 0., w: 0. };
67    /// 4D one vector (1, 1, 1, 1)
68    pub const ONES_4: Vector4 = Vector4 { x: 1., y: 1., z: 1., w: 1. };
69}
70
71/// 2D vectors (x, y)
72#[derive(Copy, Clone)]
73pub struct Vector2 {
74    pub x: f64,
75    pub y: f64,
76}
77
78/// 3D vectors (x, y, z)
79#[derive(Copy, Clone)]
80pub struct Vector3 {
81    pub x: f64,
82    pub y: f64,
83    pub z: f64,
84}
85
86/// 4D vectors (x, y, z, w)
87#[derive(Copy, Clone)]
88pub struct Vector4 {
89    pub x: f64,
90    pub y: f64,
91    pub z: f64,
92    pub w: f64,
93}
94
95/// 6D vectors (x, y, z, u, v, w)
96#[derive(Copy, Clone)]
97pub struct Vector6 {
98    pub x: f64,
99    pub y: f64,
100    pub z: f64,
101    pub u: f64,
102    pub v: f64,
103    pub w: f64,
104}
105
106impl From<[f64; 2]> for Vector2 {
107    fn from(array: [f64; 2]) -> Self {
108        vec2(array[0], array[1])
109    }
110}
111
112impl From<[f64; 3]> for Vector3 {
113    fn from(array: [f64; 3]) -> Self {
114        vec3(array[0], array[1], array[2])
115    }
116}
117
118impl From<[f64; 4]> for Vector4 {
119    fn from(array: [f64; 4]) -> Self {
120        vec4(array[0], array[1], array[2], array[3])
121    }
122}
123
124impl From<[f64; 6]> for Vector6 {
125    fn from(array: [f64; 6]) -> Self {
126        vec6(array[0], array[1], array[2], array[3], array[4], array[5])
127    }
128}
129
130impl From<Point2> for Vector4 {
131    fn from(point: Point2) -> Self {
132        vec4(point.position.x, point.position.y, point.speed.x, point.speed.y)
133    }
134}
135
136impl_vector!(Vector2 {x, y}, 2, vec2);
137impl_vector!(Vector3 {x, y, z}, 3, vec3);
138impl_vector!(Vector4 {x, y, z, w}, 4, vec4);
139impl_vector!(Vector6 {x, y, z, u, v, w}, 6, vec6);
140
141impl_debug_vector!(Vector2 {x, y});
142impl_debug_vector!(Vector3 {x, y, z});
143impl_debug_vector!(Vector4 {x, y, z, w});
144impl_debug_vector!(Vector6 {x, y, z, u, v, w});
145
146impl MulAssign<Matrix2> for Vector2 {
147    fn mul_assign(&mut self, rhs: Matrix2) {
148        let x = self.x;
149        let y = self.y;
150        self.x = rhs.xx * x + rhs.xy * y;
151        self.y = rhs.yx * x + rhs.yy * y;
152    }
153}
154
155impl MulAssign<Matrix3> for Vector3 {
156    fn mul_assign(&mut self, rhs: Matrix3) {
157        let x = self.x;
158        let y = self.y;
159        let z = self.z;
160        self.x = rhs.xx * x + rhs.xy * y + rhs.xz * z;
161        self.y = rhs.yx * x + rhs.yy * y + rhs.yz * z;
162        self.z = rhs.zx * x + rhs.zy * y + rhs.zz * z;
163    }
164}
165
166impl MulAssign<Matrix3> for Vector2 {
167    fn mul_assign(&mut self, rhs: Matrix3) {
168        let x = self.x;
169        let y = self.y;
170        self.x = rhs.xx * x + rhs.xy * y + rhs.xz;
171        self.y = rhs.yx * x + rhs.yy * y + rhs.yz;
172    }
173}
174
175impl MulAssign<Matrix4> for Vector4 {
176    fn mul_assign(&mut self, rhs: Matrix4) {
177        let x = self.x;
178        let y = self.y;
179        let z = self.z;
180        let w = self.w;
181        self.x = rhs.xx * x + rhs.xy * y + rhs.xz * z + rhs.xw * w;
182        self.y = rhs.yx * x + rhs.yy * y + rhs.yz * z + rhs.yw * w;
183        self.z = rhs.zx * x + rhs.zy * y + rhs.zz * z + rhs.zw * w;
184        self.w = rhs.wx * x + rhs.wy * y + rhs.wz * z + rhs.ww * w;
185    }
186}
187
188impl MulAssign<Matrix4> for Vector3 {
189    fn mul_assign(&mut self, rhs: Matrix4) {
190        let x = self.x;
191        let y = self.y;
192        let z = self.z;
193        self.x = rhs.xx * x + rhs.xy * y + rhs.xz * z + rhs.xw;
194        self.y = rhs.yx * x + rhs.yy * y + rhs.yz * z + rhs.yw;
195        self.z = rhs.zx * x + rhs.zy * y + rhs.zz * z + rhs.zw;
196    }
197}
198
199impl Angle for Vector2 {
200    fn area(&self, rhs: &Self) -> f64 {
201        self.x * rhs.y - self.y * rhs.x
202    }
203}
204
205impl Angle for Vector3 {
206    fn area(&self, rhs: &Self) -> f64 {
207        self.cross(rhs).magnitude()
208    }
209}
210
211impl Cross for Vector3 {
212    fn set_cross(&mut self, rhs: &Self) -> &mut Self {
213        let x = self.x;
214        let y = self.y;
215        let z = self.z;
216        self.x = y * rhs.z - z * rhs.y;
217        self.y = z * rhs.x - x * rhs.z;
218        self.z = x * rhs.y - y * rhs.x;
219        self
220    }
221}
222
223impl coordinates::Polar for Vector2 {
224    #[inline]
225    fn from_polar(rho: f64, phi: f64) -> Self {
226        Vector2 { x: rho * phi.cos(), y: rho * phi.sin() }
227    }
228
229    #[inline]
230    fn set_polar(&mut self, rho: f64, phi: f64) -> &mut Self {
231        self.x = rho * phi.cos();
232        self.y = rho * phi.sin();
233        self
234    }
235
236    #[inline]
237    fn unit_rho(ang: f64) -> Self {
238        Vector2 { x: ang.cos(), y: ang.sin() }
239    }
240
241    #[inline]
242    fn unit_phi(ang: f64) -> Self {
243        Vector2 { x: -ang.sin(), y: ang.cos() }
244    }
245
246    #[inline]
247    fn rho(&self) -> f64 {
248        self.magnitude()
249    }
250
251    #[inline]
252    fn phi(&self) -> f64 {
253        (self.y).atan2(self.x)
254    }
255
256    #[inline]
257    fn set_rho(&mut self, rho: f64) -> &mut Self {
258        self.set_polar(rho, self.phi())
259    }
260
261    #[inline]
262    fn set_phi(&mut self, phi: f64) -> &mut Self {
263        self.set_polar(self.rho(), phi)
264    }
265}
266
267impl coordinates::Polar for Vector3 {
268    #[inline]
269    fn from_polar(rho: f64, phi: f64) -> Self {
270        Vector3 { x: rho * phi.cos(), y: rho * phi.sin(), z: 0. }
271    }
272
273    #[inline]
274    fn set_polar(&mut self, rho: f64, phi: f64) -> &mut Self {
275        self.x = rho * phi.cos();
276        self.y = rho * phi.sin();
277        self
278    }
279
280    #[inline]
281    fn unit_rho(phi: f64) -> Self {
282        Vector3 { x: phi.cos(), y: phi.sin(), z: 0. }
283    }
284
285    #[inline]
286    fn unit_phi(phi: f64) -> Self {
287        Vector3 { x: -phi.sin(), y: phi.cos(), z: 0. }
288    }
289
290    #[inline]
291    fn rho(&self) -> f64 {
292        (self.x * self.x + self.y * self.y).sqrt()
293    }
294
295    #[inline]
296    fn phi(&self) -> f64 {
297        (self.y).atan2(self.x)
298    }
299
300    #[inline]
301    fn set_rho(&mut self, rho: f64) -> &mut Self {
302        self.set_polar(rho, self.phi())
303    }
304
305    #[inline]
306    fn set_phi(&mut self, phi: f64) -> &mut Self {
307        self.set_polar(self.rho(), phi)
308    }
309}
310
311impl coordinates::Cylindrical for Vector3 {
312    #[inline]
313    fn from_cylindrical(rho: f64, phi: f64, z: f64) -> Self {
314        Vector3 { x: rho * phi.cos(), y: rho * phi.sin(), z }
315    }
316
317    #[inline]
318    fn set_cylindrical(&mut self, rho: f64, phi: f64, z: f64) -> &mut Self {
319        self.x = rho * phi.cos();
320        self.y = rho * phi.sin();
321        self.z = z;
322        self
323    }
324}
325
326impl coordinates::Spherical for Vector3 {
327    #[inline]
328    fn from_spherical(radius: f64, phi: f64, theta: f64) -> Self {
329        let s = theta.sin();
330        Vector3 {
331            x: radius * s * phi.cos(),
332            y: radius * s * phi.sin(),
333            z: radius * theta.cos(),
334        }
335    }
336
337    #[inline]
338    fn set_spherical(&mut self, radius: f64, phi: f64, theta: f64) -> &mut Self {
339        let s = theta.sin();
340        self.x = radius * s * phi.cos();
341        self.y = radius * s * phi.sin();
342        self.z = radius * theta.cos();
343        self
344    }
345
346    #[inline]
347    fn unit_radius(phi: f64, theta: f64) -> Self {
348        let s = theta.sin();
349        Vector3 {
350            x: s * phi.cos(),
351            y: s * phi.sin(),
352            z: theta.cos(),
353        }
354    }
355
356    #[inline]
357    fn unit_theta(phi: f64, theta: f64) -> Self {
358        let c = theta.cos();
359        Vector3 {
360            x: c * phi.cos(),
361            y: c * phi.sin(),
362            z: -theta.sin(),
363        }
364    }
365
366    #[inline]
367    fn theta(&self) -> f64 {
368        (self.x * self.x + self.y * self.y).atan2(self.z)
369    }
370
371    #[inline]
372    fn set_theta(&mut self, theta: f64) -> &mut Self {
373        self.set_spherical(self.magnitude(), self.phi(), theta)
374    }
375}
376
377impl coordinates::Homogeneous<Vector3> for Vector2 {
378    fn from_homogeneous(vector: &Vector3) -> Self {
379        vec2(vector.x / vector.z, vector.y / vector.z)
380    }
381
382    fn to_homogeneous(&self) -> Vector3 {
383        vec3(self.x, self.y, 1.)
384    }
385}
386
387impl coordinates::Homogeneous<Vector4> for Vector3 {
388    fn from_homogeneous(vector: &Vector4) -> Self {
389        vec3(vector.x / vector.w, vector.y / vector.w, vector.z / vector.w)
390    }
391
392    fn to_homogeneous(&self) -> Vector4 {
393        vec4(self.x, self.y, self.z, 1.)
394    }
395}
396
397impl transforms::Rotation3 for Vector3 {
398    fn set_rotation(&mut self, angle: f64, axis: &Vector3) -> &mut Self {
399        let c = angle.cos();
400        let s = angle.sin();
401        let k = 1. - c;
402        let x = self.x;
403        let y = self.y;
404        let z = self.z;
405        let ux = axis.x;
406        let uy = axis.y;
407        let uz = axis.z;
408
409        let k_uxy = k * ux * uy;
410        let k_uxz = k * ux * uz;
411        let k_uyz = k * uy * uz;
412
413        self.x = (k * ux * ux + c) * x + (k_uxy - uz * s) * y + (k_uxz + uy * s) * z;
414        self.y = (k_uxy + uz * s) * x + (k * uy * uy + c) * y + (k_uyz - ux * s) * z;
415        self.z = (k_uxz - uy * s) * x + (k_uyz + ux * s) * y + (k * uz * uz + c) * z;
416        self
417    }
418
419    fn set_rotation_x(&mut self, angle: f64) -> &mut Self {
420        let c = angle.cos();
421        let s = angle.sin();
422        let y = self.y;
423        let z = self.z;
424
425        self.y = y * c - z * s;
426        self.z = y * s + z * c;
427        self
428    }
429
430    fn set_rotation_y(&mut self, angle: f64) -> &mut Self {
431        let c = angle.cos();
432        let s = angle.sin();
433        let x = self.x;
434        let z = self.z;
435
436        self.x = x * c + z * s;
437        self.z = z * c - x * s;
438        self
439    }
440
441    fn set_rotation_z(&mut self, angle: f64) -> &mut Self {
442        let c = angle.cos();
443        let s = angle.sin();
444        let x = self.x;
445        let y = self.y;
446
447        self.x = x * c - y * s;
448        self.y = x * s + y * c;
449        self
450    }
451}
452
453impl Array<[f64; 2]> for Vector2 {
454    #[inline]
455    fn to_array(&self) -> [f64; 2] {
456        [self.x, self.y]
457    }
458
459    #[inline]
460    fn set_array(&mut self, array: &[f64; 2]) -> &mut Self {
461        self.x = array[0];
462        self.y = array[1];
463        self
464    }
465}
466
467impl Array<[f64; 3]> for Vector3 {
468    #[inline]
469    fn to_array(&self) -> [f64; 3] {
470        [self.x, self.y, self.z]
471    }
472
473    #[inline]
474    fn set_array(&mut self, array: &[f64; 3]) -> &mut Self {
475        self.x = array[0];
476        self.y = array[1];
477        self.z = array[2];
478        self
479    }
480}
481
482impl Array<[f64; 4]> for Vector4 {
483    #[inline]
484    fn to_array(&self) -> [f64; 4] {
485        [self.x, self.y, self.z, self.w]
486    }
487
488    #[inline]
489    fn set_array(&mut self, array: &[f64; 4]) -> &mut Self {
490        self.x = array[0];
491        self.y = array[1];
492        self.z = array[2];
493        self.w = array[3];
494        self
495    }
496}
497
498impl Array<[f64; 6]> for Vector6 {
499    #[inline]
500    fn to_array(&self) -> [f64; 6] {
501        [self.x, self.y, self.z, self.u, self.v, self.w]
502    }
503
504    #[inline]
505    fn set_array(&mut self, array: &[f64; 6]) -> &mut Self {
506        self.x = array[0];
507        self.y = array[1];
508        self.z = array[2];
509        self.u = array[3];
510        self.v = array[4];
511        self.w = array[5];
512        self
513    }
514}
515
516impl Split<Vector2> for Vector4 {
517    fn split(&self) -> [Vector2; 2] {
518        [self.upper(), self.lower()]
519    }
520
521    fn concat(lhs: &Vector2, rhs: &Vector2) -> Self {
522        vec4(lhs.x, lhs.y, rhs.x, rhs.y)
523    }
524
525    #[inline]
526    fn upper(&self) -> Vector2 {
527        vec2(self.x, self.y)
528    }
529
530    #[inline]
531    fn lower(&self) -> Vector2 {
532        vec2(self.z, self.w)
533    }
534
535    #[inline]
536    fn set_upper(&mut self, vector: &Vector2) -> &mut Self {
537        self.x = vector.x;
538        self.y = vector.y;
539        self
540    }
541
542    #[inline]
543    fn set_lower(&mut self, vector: &Vector2) -> &mut Self {
544        self.z = vector.x;
545        self.w = vector.y;
546        self
547    }
548}
549
550impl Split<Vector3> for Vector6 {
551    fn split(&self) -> [Vector3; 2] {
552        [self.upper(), self.lower()]
553    }
554
555    fn concat(lhs: &Vector3, rhs: &Vector3) -> Self {
556        vec6(lhs.x, lhs.y, lhs.z, rhs.x, rhs.y, rhs.z)
557    }
558
559    #[inline]
560    fn upper(&self) -> Vector3 {
561        vec3(self.x, self.y, self.z)
562    }
563
564    #[inline]
565    fn lower(&self) -> Vector3 {
566        vec3(self.u, self.v, self.w)
567    }
568
569    #[inline]
570    fn set_upper(&mut self, vector: &Vector3) -> &mut Self {
571        self.x = vector.x;
572        self.y = vector.y;
573        self.z = vector.z;
574        self
575    }
576
577    #[inline]
578    fn set_lower(&mut self, vector: &Vector3) -> &mut Self {
579        self.u = vector.x;
580        self.v = vector.y;
581        self.w = vector.z;
582        self
583    }
584}
585
586#[cfg(test)]
587mod tests {
588    mod vector3 {
589        use crate::assert_near;
590        use crate::prelude::*;
591        use crate::prelude::transforms::Rotation3;
592        use crate::vector;
593        use crate::prelude::coordinates::*;
594        use crate::vector::vec3;
595
596        #[test]
597        fn new() {
598            let u = vec3(1., 2., 3.);
599            assert_eq!(u.x, 1.);
600            assert_eq!(u.y, 2.);
601            assert_eq!(u.z, 3.);
602        }
603
604        #[test]
605        fn magnitude() {
606            let sqrt_2 = std::f64::consts::SQRT_2;
607            let zero = vector::consts::ZEROS_3;
608            let u = vec3(1., 1., 0.);
609            assert_eq!(u.magnitude2(), 2.);
610            assert_eq!(u.magnitude(), sqrt_2);
611            assert_eq!(u.distance2(&zero), 2.);
612            assert_eq!(u.distance(&zero), sqrt_2);
613        }
614
615        #[test]
616        fn partial_eq() {
617            let u = vec3(-4., 0., 1.);
618            let v = vec3(-2., 0., 1.);
619            assert_eq!(u, u);
620            assert_ne!(u, v);
621        }
622
623        #[test]
624        fn polar_coordinates() {
625            let u = vector::consts::ONES_3;
626            assert_eq!(u.rho(), std::f64::consts::SQRT_2);
627            assert_eq!(u.phi(), std::f64::consts::FRAC_PI_4);
628        }
629
630        #[test]
631        fn normalized() {
632            let mut u = vec3(1., 1., 0.);
633            let tol = 10. * std::f64::EPSILON;
634            let inv_sqrt2 = std::f64::consts::FRAC_1_SQRT_2;
635            u.set_normalized();
636            assert_near!(u.magnitude2(), 1f64, tol);
637            assert_near!(u.x, inv_sqrt2,  tol);
638            assert_near!(u.y, inv_sqrt2,  tol);
639            assert_near!(u.z, 0.,  tol);
640        }
641
642        #[test]
643        fn fmt() {
644            let u = vec3(1., 2., 3.);
645            let formatted = format!("{:?}", u);
646            assert_eq!(formatted.as_str(), "( 1.000  2.000  3.000 )");
647        }
648
649        #[test]
650        fn distance() {
651            let u = vec3(1., 1., 0.);
652            let v = vector::consts::ZEROS_3;
653            assert_eq!(u.distance2(&v), 2f64);
654        }
655
656        #[test]
657        fn arithmetic() {
658            let mut u = vec3(-4., 1., 1.);
659            let v = vec3(3., 2., -1.);
660
661            assert_eq!(u + v, vec3(-1., 3., 0.));
662            assert_eq!(u - v, vec3(-7., -1., 2.));
663            assert_eq!(u * 2., vec3(-8., 2., 2.));
664            assert_eq!(u / 4., vec3(-1., 0.25, 0.25));
665
666            u += v;
667            assert_eq!(u, vec3(-1., 3., 0.));
668        }
669
670        #[test]
671        fn angles() {
672            let angle = std::f64::consts::FRAC_PI_4;
673            let u = vector::consts::EX_3;
674            let mut v = u;
675
676            assert_eq!(u.angle(&v), 0.);
677            v.set_rotation_z(angle);
678            assert_near!(u.angle(&v), angle, std::f64::EPSILON);
679            assert_near!(v.angle(&u), angle, std::f64::EPSILON);
680            v.set_rotation_z(angle);
681            assert_near!(u.angle(&v), 2. * angle, 10. * std::f64::EPSILON);
682            v.set_rotation_z(angle);
683            assert_near!(u.angle(&v), 3. * angle, 10. * std::f64::EPSILON);
684            v.set_rotation_z(angle);
685            assert_eq!(u.angle(&v), 4. * angle);
686        }
687
688        #[test]
689        fn rotations_xyz() {
690            let angle = std::f64::consts::FRAC_PI_2;
691            let mut u = vector::consts::EX_3;
692            let mut v = vector::consts::EY_3;
693            let mut w = vector::consts::EZ_3;
694
695            u.set_rotation_z(angle);
696            assert_near!(u.distance2(&vector::consts::EY_3), 0., std::f64::EPSILON);
697
698            v.set_rotation_x(angle);
699            assert_near!(v.distance2(&vector::consts::EZ_3), 0., std::f64::EPSILON);
700
701            w.set_rotation_y(angle);
702            assert_near!(w.distance2(&vector::consts::EX_3), 0., std::f64::EPSILON);
703        }
704
705        #[test]
706        fn rotations() {
707            let angle = std::f64::consts::FRAC_PI_2;
708            let mut u = vector::consts::EX_3;
709            let mut v = vector::consts::EY_3;
710            let mut w = vector::consts::EZ_3;
711
712            let mut axis = vector::consts::EZ_3;
713            u.set_rotation(angle, &axis);
714            assert_near!(u.distance2(&vector::consts::EY_3), 0., std::f64::EPSILON);
715
716            axis = vector::consts::EX_3;
717            v.set_rotation(angle, &axis);
718            assert_near!(v.distance2(&vector::consts::EZ_3), 0., std::f64::EPSILON);
719
720            axis = vector::consts::EY_3;
721            w.set_rotation(angle, &axis);
722            assert_near!(w.distance2(&vector::consts::EX_3), 0., std::f64::EPSILON);
723        }
724    }
725}