1use nalgebra::{convert, try_convert, RealField};
2use serde_derive::{Deserialize, Serialize};
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5#[derive(Copy, Clone, Eq, PartialEq, Debug, Default, Serialize, Deserialize)]
11pub struct Angle {
12 clockwise: bool,
13 units: Option<u64>,
14}
15
16use quickcheck::{Arbitrary, Gen};
17use rand::Rng;
18
19impl Arbitrary for Angle {
20 fn arbitrary<G: Gen>(g: &mut G) -> Self {
21 let clockwise = g.gen();
22 let units = g.gen();
23 Angle {
24 clockwise: clockwise,
25 units: if g.gen() { None } else { Some(units) },
26 }
27 }
28}
29
30impl Angle {
31 pub fn is_zero(&self) -> bool {
40 self.units == Some(0)
41 }
42
43 pub fn pi_over(n: i64) -> Angle {
51 Angle::pi() / n
52 }
53
54 pub fn set_clockwise(&self, clockwise: bool) -> Angle {
63 if clockwise && !self.clockwise {
64 *self - Angle::two_pi()
65 } else if !clockwise && self.clockwise {
66 *self + Angle::two_pi()
67 } else {
68 *self
69 }
70 }
71
72 pub fn add_or_subtract(&self, add: bool, other: Angle) -> Angle {
81 if add {
82 *self + other
83 } else {
84 *self - other
85 }
86 }
87
88 pub fn zero() -> Angle {
96 Angle {
97 clockwise: false,
98 units: Some(0),
99 }
100 }
101
102 pub fn wrapping_eq(&self, other: Angle) -> bool {
111 self.to_i64() == other.to_i64()
112 }
113
114 pub fn wrapping_approx_eq(&self, other: Angle, error: Angle) -> bool {
115 let error = error.to_i64().abs();
116 (self.to_i64() - other.to_i64()) < error
117 }
118
119 pub fn length<T: RealField>(&self, radius: T) -> T {
130 if let Some(x) = self.units {
131 radius * convert::<f64, T>(x as f64) / convert::<f64, T>((1u64 << 63) as f64) * T::pi()
132 } else {
133 radius * T::two_pi()
134 }
135 }
136
137 pub fn pi_2() -> Angle {
146 Angle {
147 clockwise: false,
148 units: Some(1u64 << 62),
149 }
150 }
151
152 pub fn pi() -> Angle {
160 Angle {
161 clockwise: false,
162 units: Some(1u64 << 63),
163 }
164 }
165
166 pub fn two_pi() -> Angle {
174 Angle {
175 clockwise: false,
176 units: None,
177 }
178 }
179
180 pub fn units(&self) -> Option<u64> {
191 self.units
192 }
193
194 pub fn clockwise(&self) -> bool {
203 self.clockwise
204 }
205
206 fn cos_partial<T: RealField>(x: i64) -> T {
210 assert!(x >= -(1 << 62) && x <= (1 << 62));
211
212 let pi = 1i128 << 63;
213
214 let a = 1152921504606846976;
216 let b = -5689439577989151082;
217 let c = 4679376491554475694;
218 let d = -1539453160513334483;
219 let e = 271317744433296946;
220 let f = -29753320046888181;
221 let g = 2224647666372392;
222 let h = -120639134191123;
223 let i = 4959362087252;
224 let j = -155841981042;
225
226 let coeffs = vec![i, h, g, f, e, d, c, b, a];
227
228 let mut sum: i128 = j;
229 let x = x as i128;
230
231 for i in 0..coeffs.len() {
232 sum *= x; sum /= pi; sum *= x; sum /= pi;
236 sum += coeffs[i];
237 }
238
239 T::from_i64(sum as i64).unwrap() / T::from_i64(1i64 << 60).unwrap()
241 }
242
243 pub fn to_i64(&self) -> i64 {
255 (self.units.unwrap_or(0) as i64).wrapping_mul(if self.clockwise { -1 } else { 1 })
256 }
257
258 pub fn cos<T: RealField>(&self) -> T {
270 let x = self.to_i64();
271 if x < -(1 << 62) {
272 -Angle::cos_partial::<T>(x.wrapping_add(i64::min_value()))
274 } else if x > (1 << 62) {
275 -Angle::cos_partial::<T>(x.wrapping_add(i64::min_value()))
276 } else {
277 Angle::cos_partial(x)
278 }
279 }
280
281 pub fn sin<T: RealField>(&self) -> T {
293 (*self - Angle::pi_2()).cos() }
295
296 pub fn tan<T: RealField>(&self) -> T {
304 self.sin::<T>() / self.cos::<T>() }
306
307 pub fn acos<T: RealField>(x: T) -> Angle {
315 let mut min = 0;
316 let mut max = 1 << 63;
317
318 let mut error = max - min;
319 while error > 1 {
320 let middle = (max + min) / 2;
321 let cos: T = (Angle {
322 units: Some(middle),
323 clockwise: false,
324 })
325 .cos();
326 if cos == x {
327 return Angle {
328 units: Some(middle),
329 clockwise: false,
330 };
331 } else if cos < x {
332 max = middle;
333 } else {
334 min = middle;
335 }
336 error = max - min;
337 }
338
339 Angle {
340 units: Some((max + min) / 2),
341 clockwise: false,
342 }
343 }
344
345 pub fn asin<T: RealField>(x: T) -> Angle {
353 let mut min: i64 = -(1 << 62);
354 let mut max: i64 = 1 << 62;
355
356 while min + 1 < max {
357 let middle = (max + min) / 2;
358 let sin: T = (Angle {
359 units: Some(middle as u64),
360 clockwise: false,
361 })
362 .sin();
363 if sin == x {
364 break;
365 } else if sin < x {
366 min = middle;
367 } else {
368 max = middle;
369 }
370 }
371
372 let x = ((max + min) / 2) as u64;
373 if x > (1 << 63) {
374 Angle {
375 units: Some(u64::max_value() - x + 1),
376 clockwise: true,
377 }
378 } else {
379 Angle {
380 units: Some(x),
381 clockwise: false,
382 }
383 }
384 }
385
386 pub fn atan<T: RealField>(x: T) -> Angle {
394 let mut min: i64 = -(1 << 62);
395 let mut max: i64 = 1 << 62;
396
397 while min + 1 < max {
398 let middle = (max + min) / 2;
399 let tan: T = (Angle {
400 units: Some(middle as u64),
401 clockwise: false,
402 })
403 .tan();
404 if tan == x {
405 break;
406 } else if tan < x {
407 min = middle;
408 } else {
409 max = middle;
410 }
411 }
412
413 let x = ((max + min) / 2) as u64;
414 if x > (1 << 63) {
415 Angle {
416 units: Some(u64::max_value() - x + 1),
417 clockwise: true,
418 }
419 } else {
420 Angle {
421 units: Some(x),
422 clockwise: false,
423 }
424 }
425 }
426
427 pub fn atan2<T: RealField>(y: T, x: T) -> Option<Angle> {
438 if x == T::zero() && y == T::zero() {
439 None } else {
442 let r = if x == T::zero() {
443 y.abs()
444 } else if y == T::zero() {
445 x.abs()
446 } else {
447 x.hypot(y)
448 };
449
450 if (r + x).abs() >= y.abs() {
451 Some(Angle::atan(y / (r + x)) * 2)
453 } else if y.abs() > T::zero() {
454 Some(Angle::atan((r - x) / y) * 2)
456 } else if x < T::zero() {
457 Some(Angle::pi())
459 } else {
460 Some(Angle::pi() * -1)
462 }
463 }
464 }
465
466 pub fn radians<T: RealField>(self) -> T {
475 match (self.units, self.clockwise) {
476 (None, true) => -T::two_pi(),
477 (None, false) => T::two_pi(),
478 (Some(0), _) => T::zero(),
479 (Some(x), clockwise) => {
480 let x: T = convert::<f64, T>(x as f64) / convert::<f64, T>((1u64 << 63) as f64);
481 let x = x * T::pi();
482
483 if !clockwise {
484 x
485 } else {
486 -x
487 }
488 }
489 }
490 }
491
492 pub fn degrees<T: RealField>(self) -> T {
493 match (self.units, self.clockwise) {
494 (None, true) => -T::two_pi(),
495 (None, false) => T::two_pi(),
496 (Some(0), _) => T::zero(),
497 (Some(x), clockwise) => {
498 let x: T = convert::<f64, T>(x as f64) / convert::<f64, T>((1u64 << 63) as f64);
499 let x = x * convert::<f64, T>(180.0f64);
500
501 if !clockwise {
502 x
503 } else {
504 -x
505 }
506 }
507 }
508 }
509}
510
511impl<T: RealField> From<T> for Angle {
512 fn from(real: T) -> Angle {
521 let mut real = real;
523 if real < T::zero() {
524 real = -convert::<f64, T>(f64::rem_euclid(-try_convert(real).unwrap(), f64::two_pi()));
525 } else if real > T::zero() {
526 real = convert::<f64, T>(f64::rem_euclid(try_convert(real).unwrap(), f64::two_pi()));
527 }
528
529 if real == T::zero() {
530 Angle {
531 clockwise: false,
532 units: Some(0),
533 }
534 } else if real == T::two_pi() {
535 Angle {
537 clockwise: false,
538 units: None,
539 }
540 } else if real == -T::two_pi() {
541 Angle {
542 clockwise: true,
543 units: None,
544 }
545 } else if real > T::zero() {
546 let i =
547 try_convert((real * T::from_u64(Angle::pi().units.unwrap()).unwrap()) / T::pi())
548 .unwrap();
549 Angle {
550 clockwise: false,
551 units: Some(i as u64),
552 }
553 } else if real < T::zero() {
554 let i =
555 try_convert(((-real) * T::from_u64(Angle::pi().units.unwrap()).unwrap()) / T::pi())
556 .unwrap();
557 Angle {
558 clockwise: true,
559 units: Some(i as u64),
560 }
561 } else {
562 panic!("NaN or Infinity passed into From<T: RealField> to Angle");
563 }
564 }
565}
566
567#[test]
568fn negative_is_positive() {
569 assert_eq!(Angle::from(-2.0f64).units, Angle::from(2.0f64).units);
570}
571
572impl Mul<i64> for Angle {
573 type Output = Angle;
574
575 fn mul(self, rhs: i64) -> Self {
576 let flip_clockwise = rhs < 0;
577
578 let rhs: u64 = if rhs > 0 {
579 rhs as u64
580 } else if rhs == i64::min_value() {
581 1 << 63
582 } else {
583 rhs.abs() as u64
584 };
585
586 match self.units {
587 None => Angle {
588 units: None,
589 clockwise: self.clockwise ^ flip_clockwise,
590 },
591 Some(x) => {
592 let units = x.wrapping_mul(rhs);
593 if units == 0 && x != 0 && rhs != 0 {
594 Angle {
596 units: None,
597 clockwise: self.clockwise ^ flip_clockwise,
598 }
599 } else {
600 Angle {
601 units: Some(units),
602 clockwise: self.clockwise ^ flip_clockwise,
603 }
604 }
605 }
606 }
607 }
608}
609
610impl Mul<Angle> for i64 {
611 type Output = Angle;
612
613 fn mul(self, rhs: Angle) -> Angle {
614 rhs * self
615 }
616}
617
618impl MulAssign<i64> for Angle {
619 fn mul_assign(&mut self, rhs: i64) {
620 *self = *self * rhs;
621 }
622}
623
624impl Div<i64> for Angle {
625 type Output = Angle;
626
627 fn div(self, rhs: i64) -> Angle {
628 let invert_clockwise = rhs < 0;
629 let rhs = if rhs > 0 {
630 rhs as u64
631 } else if rhs == i64::min_value() {
632 1u64 << 63
633 } else {
634 (-rhs) as u64
635 };
636
637 match self.units {
638 None => {
639 if rhs == 1 {
640 Angle {
641 units: self.units,
642 clockwise: self.clockwise ^ invert_clockwise,
643 }
644 } else {
645 Angle {
646 units: Some(((1i128 << 64) / (rhs as i128)) as u64),
647 clockwise: self.clockwise ^ invert_clockwise,
648 }
649 }
650 }
651 Some(x) => Angle {
652 units: Some(x / rhs),
653 clockwise: self.clockwise ^ invert_clockwise,
654 },
655 }
656 }
657}
658
659impl DivAssign<i64> for Angle {
660 fn div_assign(&mut self, rhs: i64) {
661 *self = *self / rhs;
662 }
663}
664
665fn add(units1: Option<u64>, units2: Option<u64>) -> Option<u64> {
666 match (units1, units2) {
667 (None, None) => None,
668 (None, Some(x)) => Some(x),
669 (Some(x), None) => Some(x),
670 (Some(x), Some(y)) => {
671 if x == 0 && y == 0 {
672 Some(0)
673 } else if x.wrapping_add(y) == 0 {
674 None
675 } else {
676 Some(x.wrapping_add(y))
677 }
678 }
679 }
680}
681
682fn sub(units1: Option<u64>, units2: Option<u64>) -> Option<u64> {
683 match (units1, units2) {
684 (None, None) => Some(0),
685 (None, Some(x)) => {
686 if x == 0 {
687 None
688 } else {
689 Some(u64::max_value().wrapping_sub(x - 1))
690 }
691 }
692 (Some(x), None) => {
693 if x == 0 {
694 None
695 } else {
696 Some(u64::max_value().wrapping_sub(x - 1))
697 }
698 }
699 (Some(x), Some(y)) => {
700 if x > y {
701 Some(x - y)
702 } else {
703 Some(y - x)
704 }
705 }
706 }
707}
708
709impl Add for Angle {
710 type Output = Self;
711
712 fn add(self, other: Self) -> Self {
713 if self.clockwise == other.clockwise {
714 Angle {
715 units: add(self.units, other.units),
716 clockwise: self.clockwise,
717 }
718 } else {
719 let result = sub(self.units, other.units);
721 let flip_sign = if self.units.is_none() {
722 false
723 } else if other.units.is_none() {
724 true
725 } else {
726 self.units.unwrap() < other.units.unwrap()
727 };
728
729 Angle {
730 units: result,
731 clockwise: self.clockwise ^ flip_sign,
732 }
733 }
734 }
735}
736
737use std::cmp::Ordering;
738
739impl Ord for Angle {
740 fn cmp(&self, other: &Self) -> Ordering {
741 if self == other {
742 Ordering::Equal
743 } else if !self.clockwise && other.clockwise {
744 Ordering::Greater
745 } else if self.clockwise && !other.clockwise {
746 Ordering::Less
747 } else if self.clockwise && other.clockwise {
748 if self.units.is_none() {
749 Ordering::Less
750 } else if other.units.is_none() {
751 Ordering::Greater
752 } else if self.units.unwrap() < other.units.unwrap() {
753 Ordering::Greater
754 } else {
755 Ordering::Less
756 }
757 } else {
758 if self.units.is_none() {
759 Ordering::Greater
760 } else if other.units.is_none() {
761 Ordering::Less
762 } else if self.units.unwrap() < other.units.unwrap() {
763 Ordering::Less
764 } else {
765 Ordering::Greater
766 }
767 }
768 }
769}
770
771impl PartialOrd for Angle {
772 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
773 Some(self.cmp(other))
774 }
775}
776
777impl AddAssign<Angle> for Angle {
778 fn add_assign(&mut self, other: Self) {
779 *self = *self + other;
780 }
781}
782
783impl Sub for Angle {
784 type Output = Self;
785
786 fn sub(self, other: Self) -> Self {
787 let to_add = Angle {
788 units: other.units,
789 clockwise: !other.clockwise,
790 };
791
792 self + to_add
793 }
794}
795
796impl SubAssign<Angle> for Angle {
797 fn sub_assign(&mut self, other: Self) {
798 *self = *self - other;
799 }
800}
801
802impl Neg for Angle {
803 type Output = Angle;
804
805 fn neg(self) -> Self::Output {
806 Angle {
807 units: self.units,
808 clockwise: !self.clockwise,
809 }
810 }
811}