1#[macro_use]
75extern crate nearly_eq;
76
77use std::cmp;
78use std::error;
79use std::f64::consts::PI;
80use std::fmt;
81use std::ops;
82
83use float_cmp::ApproxEq;
84
85#[derive(Copy, Clone, Debug, PartialEq)]
86pub enum Vec3DError {
87 RadiusLessThanZero,
88 ThetaNotWithinRange,
89}
90
91impl fmt::Display for Vec3DError {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 match *self {
94 Vec3DError::RadiusLessThanZero => write!(f, "Vec3D error: given value for the radius is less than 0.0."),
95 Vec3DError::ThetaNotWithinRange => write!(f, "Vec3D error: given value for theta not within the range [0, PI]"),
96 }
97 }
98}
99
100impl error::Error for Vec3DError {}
101
102#[derive(Copy, Clone, Debug)]
103pub struct Vec3D {
104 pub x: f64,
105 pub y: f64,
106 pub z: f64,
107}
108
109impl Vec3D {
110 pub fn new(x: f64, y: f64, z: f64) -> Vec3D {
111 Vec3D { x, y, z }
112 }
113
114 pub fn new_from_spherical_coordinates(r: f64, theta: f64, phi: f64) -> Result<Vec3D, Vec3DError> {
127 if r < 0.0 {
128 return Err(Vec3DError::RadiusLessThanZero);
129 };
130
131 if theta < 0.0 || theta > PI {
132 return Err(Vec3DError::ThetaNotWithinRange);
133 };
134
135 let (sin_theta, cos_theta) = theta.sin_cos();
136 let (sin_phi, cos_phi) = phi.sin_cos();
137 let rho = r * sin_theta;
138
139 Ok(Vec3D {
140 x: rho * cos_phi,
141 y: rho * sin_phi,
142 z: r * cos_theta,
143 })
144 }
145
146 pub fn new_from_cylindrical_coordinates(r: f64, phi: f64, z: f64) -> Result<Vec3D, Vec3DError> {
157 if r < 0.0 {
158 return Err(Vec3DError::RadiusLessThanZero);
159 };
160
161 let (sin_phi, cos_phi) = phi.sin_cos();
162
163 Ok(Vec3D {
164 x: r * cos_phi,
165 y: r * sin_phi,
166 z,
167 })
168 }
169
170 #[inline]
172 pub fn zeros() -> Vec3D {
173 Vec3D::new(0.0, 0.0, 0.0)
174 }
175
176 #[inline]
178 pub fn ones() -> Vec3D {
179 Vec3D::new(1.0, 1.0, 1.0)
180 }
181
182 #[inline]
184 pub fn x_proj(&self) -> Vec3D {
185 Vec3D::new(self.x, 0.0, 0.0)
186 }
187
188 #[inline]
190 pub fn y_proj(&self) -> Vec3D {
191 Vec3D::new(0.0, self.y, 0.0)
192 }
193
194 #[inline]
196 pub fn z_proj(&self) -> Vec3D {
197 Vec3D::new(0.0, 0.0, self.z)
198 }
199
200 #[inline]
202 pub fn theta(&self) -> f64 {
203 if self.x == 0.0 && self.y == 0.0 && self.z == 0.0 {
204 0.0
205 } else {
206 (self.x * self.x + self.y * self.y).sqrt().atan2(self.z)
207 }
208 }
209
210 #[inline]
212 pub fn phi(&self) -> f64 {
213 if self.x == 0.0 && self.y == 0.0 {
214 0.0
215 } else {
216 self.y.atan2(self.x)
217 }
218 }
219
220 #[inline]
222 pub fn mag(&self) -> f64 {
223 self.mag2().sqrt()
224 }
225
226 #[inline]
228 pub fn mag2(&self) -> f64 {
229 self.x * self.x + self.y * self.y + self.z * self.z
230 }
231
232 #[inline]
234 pub fn norm(&self) -> Vec3D {
235 let mag2 = self.mag2();
236
237 if mag2 == 0.0 {
238 Vec3D::new(0.0, 0.0, 0.0)
239 } else {
240 *self * 1.0 / mag2.sqrt()
241 }
242 }
243
244 #[inline]
246 pub fn unit(&self) -> Vec3D {
247 self.norm()
248 }
249
250 #[inline]
252 pub fn inner_product(&self, other: Vec3D) -> f64 {
253 self.x * other.x + self.y * other.y + self.z * other.z
254 }
255
256 #[inline]
258 pub fn dot(&self, other: Vec3D) -> f64 {
259 self.x * other.x + self.y * other.y + self.z * other.z
260 }
261
262 #[inline]
264 pub fn distance_to(&self, other: Vec3D) -> f64 {
265 (*self - other).mag()
266 }
267
268 #[inline]
270 pub fn distance_to2(&self, other: Vec3D) -> f64 {
271 (*self - other).mag2()
272 }
273
274 #[inline]
276 pub fn cross(&self, other: Vec3D) -> Vec3D {
277 Vec3D::new(
278 self.y * other.z - other.y * self.z,
279 self.z * other.x - other.z * self.x,
280 self.x * other.y - other.x * self.y,
281 )
282 }
283
284 pub fn pseudo_rapidity(&self) -> f64 {
288 let m = self.mag();
289
290 if m.approx_eq(&0.0, 2.0 * ::std::f64::EPSILON, 2) {
291 0.0
292 } else if m.approx_eq(&self.z, 2.0 * ::std::f64::EPSILON, 2) {
293 std::f64::INFINITY
294 } else if m.approx_eq(&(-self.z), 2.0 * ::std::f64::EPSILON, 2) {
295 std::f64::NEG_INFINITY
296 } else {
297 0.5 * ((m + self.z) / (m - self.z)).ln()
298 }
299 }
300
301 pub fn rotate_x(&mut self, angle: f64) {
303 let (sinphi, cosphi) = angle.sin_cos();
304
305 let ty = self.y * cosphi - self.z * sinphi;
306 self.z = self.z * cosphi + self.y * sinphi;
307 self.y = ty;
308 }
309
310 pub fn rotated_x(&self, angle: f64) -> Vec3D {
312 let (sinphi, cosphi) = angle.sin_cos();
313
314 Vec3D::new(self.x, self.y * cosphi - self.z * sinphi, self.z * cosphi + self.y * sinphi)
315 }
316
317 pub fn rotate_y(&mut self, angle: f64) {
319 let (sinphi, cosphi) = angle.sin_cos();
320
321 let tz = self.z * cosphi - self.x * sinphi;
322 self.x = self.x * cosphi + self.z * sinphi;
323 self.z = tz;
324 }
325
326 pub fn rotated_y(&self, angle: f64) -> Vec3D {
328 let (sinphi, cosphi) = angle.sin_cos();
329
330 Vec3D::new(self.x * cosphi + self.z * sinphi, self.y, self.z * cosphi - self.x * sinphi)
331 }
332
333 pub fn rotate_z(&mut self, angle: f64) {
335 let (sinphi, cosphi) = angle.sin_cos();
336
337 let tx = self.x * cosphi - self.y * sinphi;
338 self.y = self.y * cosphi + self.x * sinphi;
339 self.x = tx;
340 }
341
342 pub fn rotated_z(&self, angle: f64) -> Vec3D {
344 let (sinphi, cosphi) = angle.sin_cos();
345
346 Vec3D::new(self.x * cosphi - self.y * sinphi, self.y * cosphi + self.x * sinphi, self.z)
347 }
348
349 pub fn approx_eq(self, other: Vec3D) -> bool {
351 self.x.approx_eq(&other.x, 2.0 * ::std::f64::EPSILON, 2)
352 && self.y.approx_eq(&other.y, 2.0 * ::std::f64::EPSILON, 2)
353 && self.z.approx_eq(&other.z, 2.0 * ::std::f64::EPSILON, 2)
354 }
355}
356
357impl fmt::Display for Vec3D {
358 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359 write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z)
360 }
361}
362
363impl cmp::PartialEq for Vec3D {
364 #[inline]
365 fn eq(&self, other: &Vec3D) -> bool {
366 self.x == other.x && self.y == other.y && self.z == other.z
367 }
368}
369impl Eq for Vec3D {}
370
371impl ops::Add<Vec3D> for Vec3D {
372 type Output = Vec3D;
373
374 #[inline]
375 fn add(self, other: Vec3D) -> Vec3D {
376 Vec3D::new(self.x + other.x, self.y + other.y, self.z + other.z)
377 }
378}
379
380impl ops::AddAssign<Vec3D> for Vec3D {
381 #[inline]
382 fn add_assign(&mut self, other: Vec3D) {
383 self.x += other.x;
384 self.y += other.y;
385 self.z += other.z;
386 }
387}
388
389impl ops::Sub<Vec3D> for Vec3D {
390 type Output = Vec3D;
391
392 #[inline]
393 fn sub(self, other: Vec3D) -> Vec3D {
394 Vec3D::new(self.x - other.x, self.y - other.y, self.z - other.z)
395 }
396}
397
398impl ops::SubAssign<Vec3D> for Vec3D {
399 #[inline]
400 fn sub_assign(&mut self, other: Vec3D) {
401 self.x -= other.x;
402 self.y -= other.y;
403 self.z -= other.z;
404 }
405}
406
407impl ops::Neg for Vec3D {
408 type Output = Vec3D;
409
410 #[inline]
411 fn neg(self) -> Vec3D {
412 Vec3D::new(-self.x, -self.y, -self.z)
413 }
414}
415
416impl ops::Mul<f64> for Vec3D {
417 type Output = Vec3D;
418
419 #[inline]
420 fn mul(self, other: f64) -> Vec3D {
421 Vec3D::new(self.x * other, self.y * other, self.z * other)
422 }
423}
424
425impl ops::MulAssign<f64> for Vec3D {
426 #[inline]
427 fn mul_assign(&mut self, other: f64) {
428 self.x *= other;
429 self.y *= other;
430 self.z *= other;
431 }
432}
433
434impl ops::Div<f64> for Vec3D {
435 type Output = Vec3D;
436
437 #[inline]
438 fn div(self, other: f64) -> Vec3D {
439 Vec3D::new(self.x / other, self.y / other, self.z / other)
440 }
441}
442
443impl ops::DivAssign<f64> for Vec3D {
444 #[inline]
445 fn div_assign(&mut self, other: f64) {
446 self.x /= other;
447 self.y /= other;
448 self.z /= other;
449 }
450}
451
452#[cfg(test)]
453mod tests {
454 use super::{Vec3D, Vec3DError};
455
456 const PI: f64 = std::f64::consts::PI;
457
458 #[test]
459 fn create_vector() {
460 let vec = Vec3D::new(1.0, 2.0, 3.0);
462 assert_eq!(vec.x, 1.0);
463 assert_eq!(vec.y, 2.0);
464 assert_eq!(vec.z, 3.0);
465 }
466
467 #[test]
468 fn new_from_spherical_coordinates() {
469 let vec = Vec3D::new_from_spherical_coordinates(10.0, PI / 4.0, PI / 4.0).unwrap();
471 assert_nearly_eq!(vec.x, 5.0);
472 assert_nearly_eq!(vec.y, 5.0);
473 assert_nearly_eq!(vec.z, 7.0710678118654752);
474
475 let vec = Vec3D::new_from_spherical_coordinates(-1.0, PI / 2.0, PI / 2.0);
477 assert!(vec.is_err());
478 assert_eq!(vec.err().unwrap(), Vec3DError::RadiusLessThanZero);
479
480 let vec = Vec3D::new_from_spherical_coordinates(1.0, PI * 2.0, PI / 2.0);
482 assert!(vec.is_err());
483 assert_eq!(vec.err().unwrap(), Vec3DError::ThetaNotWithinRange);
484 }
485
486 #[test]
487 fn new_from_cylindrical_coordinates() {
488 let vec = Vec3D::new_from_cylindrical_coordinates(10.0, PI / 4.0, 20.0).unwrap();
490 assert_nearly_eq!(vec.x, 7.0710678118654752);
491 assert_nearly_eq!(vec.y, 7.0710678118654752);
492 assert_nearly_eq!(vec.z, 20.0);
493
494 let vec = Vec3D::new_from_cylindrical_coordinates(-1.0, PI / 2.0, 10.0);
496 assert!(vec.is_err());
497 assert_eq!(vec.err().unwrap(), Vec3DError::RadiusLessThanZero);
498 }
499
500 #[test]
501 fn x_proj() {
502 let vec = Vec3D::new(10.0, 10.0, 10.0);
504 assert_eq!(vec.x_proj(), Vec3D::new(10.0, 0.0, 0.0));
505 }
506
507 #[test]
508 fn y_proj() {
509 let vec = Vec3D::new(10.0, 10.0, 10.0);
511 assert_eq!(vec.y_proj(), Vec3D::new(0.0, 10.0, 0.0));
512 }
513
514 #[test]
515 fn z_proj() {
516 let vec = Vec3D::new(10.0, 10.0, 10.0);
518 assert_eq!(vec.z_proj(), Vec3D::new(0.0, 0.0, 10.0));
519 }
520
521 #[test]
522 fn theta() {
523 let vec = Vec3D::new(1.0, 0.0, 0.0);
525 assert_eq!(vec.theta(), PI / 2.0);
526
527 let vec = Vec3D::new(0.0, 1.0, 1.0);
528 assert_eq!(vec.theta(), PI / 4.0);
529
530 let vec = Vec3D::new(0.0, 0.0, 1.0);
531 assert_eq!(vec.theta(), 0.0);
532
533 for i in 1..8 {
534 let theta = PI / i as f64;
535
536 let vec = Vec3D::new_from_spherical_coordinates(1.0, theta, 0.0).unwrap();
537 assert_nearly_eq!(vec.theta(), theta);
538 }
539 }
540
541 #[test]
542 fn phi() {
543 let vec = Vec3D::new(1.0, 0.0, 0.0);
545 assert_eq!(vec.phi(), 0.0);
546
547 let vec = Vec3D::new(0.0, 1.0, 1.0);
548 assert_eq!(vec.phi(), PI / 2.0);
549
550 let vec = Vec3D::new(0.0, 0.0, 1.0);
551 assert_eq!(vec.phi(), 0.0);
552
553 for i in 2..8 {
554 let phi = (2.0 * PI) / i as f64;
555 let vec = Vec3D::new_from_spherical_coordinates(1.0, PI / 2.0, phi).unwrap();
556 assert_nearly_eq!(vec.phi(), phi);
557 }
558 }
559
560 #[test]
561 fn mag() {
562 let vec = Vec3D::new(10.0, 10.0, 10.0);
564 assert_nearly_eq!(vec.mag(), 17.320508075688772);
565 }
566
567 #[test]
568 fn mag2() {
569 let vec = Vec3D::new(10.0, 10.0, 10.0);
571 assert_eq!(vec.mag2(), 300.0);
572 }
573
574 #[test]
575 fn unit() {
576 let vec = Vec3D::new(10.0, 20.0, 30.0).unit();
578 assert_nearly_eq!(vec.x, 0.2672612419124243);
579 assert_nearly_eq!(vec.y, 0.5345224838248487);
580 assert_nearly_eq!(vec.z, 0.8017837257372731);
581 }
582
583 #[test]
584 fn inner_product() {
585 let vec1 = Vec3D::new(10.0, 20.0, 30.0);
587 let vec2 = Vec3D::new(40.0, 50.0, 60.0);
588 assert_eq!(vec1.inner_product(vec2), 3200.0);
589 assert_eq!(vec2.inner_product(vec1), 3200.0);
590 }
591
592 #[test]
593 fn dot() {
594 let vec1 = Vec3D::new(10.0, 20.0, 30.0);
596 let vec2 = Vec3D::new(40.0, 50.0, 60.0);
597 assert_eq!(vec1.dot(vec2), 3200.0);
598 assert_eq!(vec2.dot(vec1), 3200.0);
599 }
600
601 #[test]
602 fn distance_to() {
603 let vec1 = Vec3D::new(10.0, 20.0, 30.0);
605 let vec2 = Vec3D::new(40.0, 50.0, 60.0);
606
607 assert_nearly_eq!(vec1.distance_to(vec1), 0.0);
608 assert_nearly_eq!(vec1.distance_to(vec2), 51.96152422706632);
609 }
610
611 #[test]
612 fn distance_to2() {
613 let vec1 = Vec3D::new(10.0, 20.0, 30.0);
615 let vec2 = Vec3D::new(40.0, 50.0, 60.0);
616
617 assert_nearly_eq!(vec1.distance_to2(vec1), 0.0);
618 assert_nearly_eq!(vec1.distance_to2(vec2), 2700.0);
619 }
620
621 #[test]
622 fn cross() {
623 let vec1 = Vec3D::new(10.0, 20.0, 30.0);
625 let vec2 = Vec3D::new(40.0, 50.0, 60.0);
626 assert_eq!(vec1.cross(vec2), Vec3D::new(-300.0, 600.0, -300.0));
627 assert_eq!(vec2.cross(vec1), Vec3D::new(300.0, -600.0, 300.0));
628 }
629
630 #[test]
631 fn pseudo_rapidity() {
632 let vec1 = Vec3D::new(1.0, 1.0, 0.0);
634 assert_eq!(vec1.pseudo_rapidity(), 0.0);
635
636 let vec2 = Vec3D::new(0.0, 0.0, 1.0);
638 assert_eq!(vec2.pseudo_rapidity(), std::f64::INFINITY);
639
640 let vec3 = Vec3D::new(1.0, 0.0, 1.0);
642 assert_nearly_eq!(vec3.pseudo_rapidity(), 0.881373587019543025232609);
643 }
644
645 #[test]
646 fn rotate_x() {
647 let vec = Vec3D::new(0.0, 0.0, 0.0);
649 let mut vec2 = vec;
650 vec2.rotate_x(0.0);
651 assert_eq!(vec, vec2);
652
653 let vec = Vec3D::new(0.0, 0.0, 0.0);
655 let mut vec2 = vec;
656 vec2.rotate_x(PI);
657 assert_eq!(vec, vec2);
658
659 let mut vec = Vec3D::new(0.0, 1.0, 0.0);
661 vec.rotate_x(PI);
662 assert_nearly_eq!(vec.x, 0.0);
663 assert_nearly_eq!(vec.y, -1.0);
664 assert_nearly_eq!(vec.z, 0.0);
665
666 let mut vec = Vec3D::new(0.0, 1.0, 0.0);
668 vec.rotate_x(PI / 2.0);
669 assert_nearly_eq!(vec.x, 0.0);
670 assert_nearly_eq!(vec.y, 0.0);
671 assert_nearly_eq!(vec.z, 1.0);
672
673 let mut vec = Vec3D::new(0.0, 0.0, 1.0);
675 vec.rotate_x(PI);
676 assert_nearly_eq!(vec.x, 0.0);
677 assert_nearly_eq!(vec.y, 0.0);
678 assert_nearly_eq!(vec.z, -1.0);
679
680 let mut vec = Vec3D::new(0.0, 0.0, 1.0);
682 vec.rotate_x(PI / 2.0);
683 assert_nearly_eq!(vec.x, 0.0);
684 assert_nearly_eq!(vec.y, -1.0);
685 assert_nearly_eq!(vec.z, 0.0);
686 }
687
688 #[test]
689 fn rotated_x() {
690 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
692 let vec2 = vec1.rotated_x(0.0);
693 assert_eq!(vec1, vec2);
694
695 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
697 let vec2 = vec1.rotated_x(PI);
698 assert_eq!(vec1, vec2);
699
700 let vec1 = Vec3D::new(0.0, 1.0, 0.0);
702 let vec2 = vec1.rotated_x(PI);
703 assert_nearly_eq!(vec2.x, 0.0);
704 assert_nearly_eq!(vec2.y, -1.0);
705 assert_nearly_eq!(vec2.z, 0.0);
706
707 let vec1 = Vec3D::new(0.0, 1.0, 0.0);
709 let vec2 = vec1.rotated_x(PI / 2.0);
710 assert_nearly_eq!(vec2.x, 0.0);
711 assert_nearly_eq!(vec2.y, 0.0);
712 assert_nearly_eq!(vec2.z, 1.0);
713
714 let vec1 = Vec3D::new(0.0, 0.0, 1.0);
716 let vec2 = vec1.rotated_x(PI);
717 assert_nearly_eq!(vec2.x, 0.0);
718 assert_nearly_eq!(vec2.y, 0.0);
719 assert_nearly_eq!(vec2.z, -1.0);
720
721 let vec1 = Vec3D::new(0.0, 0.0, 1.0);
723 let vec2 = vec1.rotated_x(PI / 2.0);
724 assert_nearly_eq!(vec2.x, 0.0);
725 assert_nearly_eq!(vec2.y, -1.0);
726 assert_nearly_eq!(vec2.z, 0.0);
727 }
728
729 #[test]
730 fn rotate_y() {
731 let vec = Vec3D::new(0.0, 0.0, 0.0);
733 let mut vec2 = vec;
734 vec2.rotate_y(0.0);
735 assert_eq!(vec, vec2);
736
737 let vec = Vec3D::new(0.0, 0.0, 0.0);
739 let mut vec2 = vec;
740 vec2.rotate_y(PI);
741 assert_eq!(vec, vec2);
742
743 let mut vec = Vec3D::new(1.0, 0.0, 0.0);
745 vec.rotate_y(PI);
746 assert_nearly_eq!(vec.x, -1.0);
747 assert_nearly_eq!(vec.y, 0.0);
748 assert_nearly_eq!(vec.z, 0.0);
749
750 let mut vec = Vec3D::new(1.0, 0.0, 0.0);
752 vec.rotate_y(PI / 2.0);
753 assert_nearly_eq!(vec.x, 0.0);
754 assert_nearly_eq!(vec.y, 0.0);
755 assert_nearly_eq!(vec.z, -1.0);
756
757 let mut vec = Vec3D::new(0.0, 0.0, 1.0);
759 vec.rotate_y(PI);
760 assert_nearly_eq!(vec.x, 0.0);
761 assert_nearly_eq!(vec.y, 0.0);
762 assert_nearly_eq!(vec.z, -1.0);
763
764 let mut vec = Vec3D::new(0.0, 0.0, 1.0);
766 vec.rotate_y(PI / 2.0);
767 assert_nearly_eq!(vec.x, 1.0);
768 assert_nearly_eq!(vec.y, 0.0);
769 assert_nearly_eq!(vec.z, 0.0);
770 }
771
772 #[test]
773 fn rotated_y() {
774 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
776 let vec2 = vec1.rotated_y(0.0);
777 assert_eq!(vec1, vec2);
778
779 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
781 let vec2 = vec1.rotated_y(PI);
782 assert_eq!(vec1, vec2);
783
784 let vec1 = Vec3D::new(1.0, 0.0, 0.0);
786 let vec2 = vec1.rotated_y(PI);
787 assert_nearly_eq!(vec2.x, -1.0);
788 assert_nearly_eq!(vec2.y, 0.0);
789 assert_nearly_eq!(vec2.z, 0.0);
790
791 let vec1 = Vec3D::new(1.0, 0.0, 0.0);
793 let vec2 = vec1.rotated_y(PI / 2.0);
794 assert_nearly_eq!(vec2.x, 0.0);
795 assert_nearly_eq!(vec2.y, 0.0);
796 assert_nearly_eq!(vec2.z, -1.0);
797
798 let vec1 = Vec3D::new(0.0, 0.0, 1.0);
800 let vec2 = vec1.rotated_y(PI);
801 assert_nearly_eq!(vec2.x, 0.0);
802 assert_nearly_eq!(vec2.y, 0.0);
803 assert_nearly_eq!(vec2.z, -1.0);
804
805 let vec1 = Vec3D::new(0.0, 0.0, 1.0);
807 let vec2 = vec1.rotated_y(PI / 2.0);
808 assert_nearly_eq!(vec2.x, 1.0);
809 assert_nearly_eq!(vec2.y, 0.0);
810 assert_nearly_eq!(vec2.z, 0.0);
811 }
812
813 #[test]
814 fn rotate_z() {
815 let vec = Vec3D::new(0.0, 0.0, 0.0);
817 let mut vec2 = vec;
818 vec2.rotate_z(0.0);
819 assert_eq!(vec, vec2);
820
821 let vec = Vec3D::new(0.0, 0.0, 0.0);
823 let mut vec2 = vec;
824 vec2.rotate_z(PI);
825 assert_eq!(vec, vec2);
826
827 let mut vec = Vec3D::new(1.0, 0.0, 0.0);
829 vec.rotate_z(PI);
830 assert_nearly_eq!(vec.x, -1.0);
831 assert_nearly_eq!(vec.y, 0.0);
832 assert_nearly_eq!(vec.z, 0.0);
833
834 let mut vec = Vec3D::new(1.0, 0.0, 0.0);
836 vec.rotate_z(PI / 2.0);
837 assert_nearly_eq!(vec.x, 0.0);
838 assert_nearly_eq!(vec.y, 1.0);
839 assert_nearly_eq!(vec.z, 0.0);
840
841 let mut vec = Vec3D::new(0.0, 1.0, 0.0);
843 vec.rotate_z(PI);
844 assert_nearly_eq!(vec.x, 0.0);
845 assert_nearly_eq!(vec.y, -1.0);
846 assert_nearly_eq!(vec.z, 0.0);
847
848 let mut vec = Vec3D::new(0.0, 1.0, 0.0);
850 vec.rotate_z(PI / 2.0);
851 assert_nearly_eq!(vec.x, -1.0);
852 assert_nearly_eq!(vec.y, 0.0);
853 assert_nearly_eq!(vec.z, 0.0);
854 }
855
856 #[test]
857 fn rotated_z() {
858 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
860 let vec2 = vec1.rotated_z(0.0);
861 assert_eq!(vec1, vec2);
862
863 let vec1 = Vec3D::new(0.0, 0.0, 0.0);
865 let vec2 = vec1.rotated_z(PI);
866 assert_eq!(vec1, vec2);
867
868 let vec1 = Vec3D::new(1.0, 0.0, 0.0);
870 let vec2 = vec1.rotated_z(PI);
871 assert_nearly_eq!(vec2.x, -1.0);
872 assert_nearly_eq!(vec2.y, 0.0);
873 assert_nearly_eq!(vec2.z, 0.0);
874
875 let vec1 = Vec3D::new(1.0, 0.0, 0.0);
877 let vec2 = vec1.rotated_z(PI / 2.0);
878 assert_nearly_eq!(vec2.x, 0.0);
879 assert_nearly_eq!(vec2.y, 1.0);
880 assert_nearly_eq!(vec2.z, 0.0);
881
882 let vec1 = Vec3D::new(0.0, 1.0, 0.0);
884 let vec2 = vec1.rotated_z(PI);
885 assert_nearly_eq!(vec2.x, 0.0);
886 assert_nearly_eq!(vec2.y, -1.0);
887 assert_nearly_eq!(vec2.z, 0.0);
888
889 let vec1 = Vec3D::new(0.0, 1.0, 0.0);
891 let vec2 = vec1.rotated_z(PI / 2.0);
892 assert_nearly_eq!(vec2.x, -1.0);
893 assert_nearly_eq!(vec2.y, 0.0);
894 assert_nearly_eq!(vec2.z, 0.0);
895 }
896
897 #[test]
898 fn partial_eq() {
899 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
900 let vec2 = Vec3D::new(10.0, 10.0, 10.0);
901 let vec3 = Vec3D::new(20.0, 20.0, 20.0);
902 assert_eq!(vec1, vec2);
903 assert_ne!(vec2, vec3);
904 }
905
906 #[test]
907 fn add() {
908 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
909 let vec2 = Vec3D::new(20.0, 20.0, 20.0);
910 let vec3 = Vec3D::new(30.0, 30.0, 30.0);
911 assert_eq!(vec1 + vec2, vec3);
912 }
913
914 #[test]
915 fn add_assign() {
916 let mut vec1 = Vec3D::new(10.0, 10.0, 10.0);
917 let vec2 = Vec3D::new(20.0, 20.0, 20.0);
918 let vec3 = Vec3D::new(30.0, 30.0, 30.0);
919
920 vec1 += vec2;
921 assert_eq!(vec1, vec3);
922 }
923
924 #[test]
925 fn sub() {
926 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
927 let vec2 = Vec3D::new(20.0, 20.0, 20.0);
928 let vec3 = Vec3D::new(30.0, 30.0, 30.0);
929 assert_eq!(vec3 - vec2, vec1);
930 }
931
932 #[test]
933 fn sub_assign() {
934 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
935 let vec2 = Vec3D::new(20.0, 20.0, 20.0);
936 let mut vec3 = Vec3D::new(30.0, 30.0, 30.0);
937
938 vec3 -= vec2;
939 assert_eq!(vec1, vec3);
940 }
941
942 #[test]
943 fn neg() {
944 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
945 let vec2 = Vec3D::new(-10.0, -10.0, -10.0);
946 assert_eq!(-vec1, vec2);
947 assert_eq!(vec1, -vec2);
948 }
949
950 #[test]
951 fn mul() {
952 let vec1 = Vec3D::new(10.0, 10.0, 10.0);
953 let vec2 = Vec3D::new(30.0, 30.0, 30.0);
954 assert_eq!(vec1 * 3.0, vec2);
955 }
956
957 #[test]
958 fn mul_assign() {
959 let mut vec1 = Vec3D::new(10.0, 10.0, 10.0);
960 let vec2 = Vec3D::new(30.0, 30.0, 30.0);
961
962 vec1 *= 3.0;
963 assert_eq!(vec1, vec2);
964 }
965
966 #[test]
967 fn div() {
968 let vec1 = Vec3D::new(30.0, 30.0, 30.0);
969 let vec2 = Vec3D::new(10.0, 10.0, 10.0);
970 assert_eq!(vec1 / 3.0, vec2);
971 }
972
973 #[test]
974 fn div_assign() {
975 let mut vec1 = Vec3D::new(30.0, 30.0, 30.0);
976 let vec2 = Vec3D::new(10.0, 10.0, 10.0);
977
978 vec1 /= 3.0;
979 assert_eq!(vec1, vec2);
980 }
981}