angular_units/
lib.rs

1//! Library for representing and manipulating angular quantities.
2//! Provides type-safe wrapper types for each unit as well as helper
3//! traits for abstracting over the concrete types.
4//! Conversions between types is easy and safe, allowing highly flexible manipulation.
5//!
6//! ## Details
7//!
8//! ### Arithmetic
9//!
10//! Each angle type defines basic arithmetic operators. Multiplication and
11//! division are between an angle and a scalar. Addition and subtraction
12//! are between two angles and the two angles do not have to be represented using
13//! the same units for example, the following is valid:
14//!
15//! ```
16//! # use angular_units::*;
17//! let angle = Turns(0.25) + Deg(30.0) - ArcMinutes(15.0);
18//! ```
19//!
20//! When combining units like this, the left-hand side type will be the result.
21//!
22//! ### Normalization
23//!
24//! For performance, most operations do not normalize the results or inputs automatically.
25//! This is mathematically sound, but it is often more convenient to have a single
26//! value to represent each angle. Thus, for methods that expect an angle within
27//! the standard domain, `normalize()` should be used to create an equivalent
28//! angle that is less than one period.
29
30
31extern crate num_traits as num;
32#[macro_use]
33#[cfg(feature = "approx")]
34extern crate approx;
35#[cfg(feature = "serde")]
36#[macro_use]
37extern crate serde;
38
39use std::ops::*;
40use std::f64::consts;
41use std::fmt;
42use std::convert::From;
43use num::{Float, NumCast};
44
45/// An angular quantity measured in degrees.
46///
47/// Degrees are uniquely defined from 0..360.
48#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
49#[repr(transparent)]
50#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
51pub struct Deg<T>(pub T);
52/// An angular quantity measured in gons.
53///
54/// Gons, or gradians, are uniquely defined from 0..400.
55#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
56#[repr(transparent)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58pub struct Gon<T>(pub T);
59/// An angular quantity measured in degrees.
60///
61/// Radians are uniquely defined from 0..2π.
62#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
63#[repr(transparent)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65pub struct Rad<T>(pub T);
66/// An angular quantity measured in "turns", or full rotations.
67///
68/// Turns are uniquely defined from 0..1.
69#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
70#[repr(transparent)]
71#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
72pub struct Turns<T>(pub T);
73/// An angular quantity measured in arc minutes, which are
74/// 1/60th of a degree.
75#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
76#[repr(transparent)]
77#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
78pub struct ArcMinutes<T>(pub T);
79/// An angular quantity measured in arc seconds, which are
80/// 1/60th of an arc minute.
81#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Hash)]
82#[repr(transparent)]
83#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
84pub struct ArcSeconds<T>(pub T);
85
86/// Construct `Self` from an angle.
87///
88/// Analogous to the traits in the standard library,
89/// FromAngle and IntoAngle provide a way to convert between angle
90/// types and to mix various angle types in a single operation.
91pub trait FromAngle<T>
92    where T: Angle
93{
94    /// Construct `Self` by converting a `T`.
95    fn from_angle(from: T) -> Self;
96}
97
98/// Construct an angle by converting from another type.
99///
100/// IntoAngle is provided automatically based on FromAngle.
101pub trait IntoAngle<To>
102    where To: Angle<Scalar = Self::OutputScalar>
103{
104    type OutputScalar: Float;
105    /// Construct an angle from `self`.
106    fn into_angle(self) -> To;
107}
108
109/// Base functionality for all angle types.
110pub trait Angle: Clone + FromAngle<Self> + PartialEq + PartialOrd + num::Zero {
111    /// Internal type storing the angle value.
112    type Scalar: Float;
113
114    /// Construct a new angle.
115    ///
116    /// Equivalent to constructing the tuple struct directly, eg. `Deg(value)`,
117    /// but usable in a generic context.
118    fn new(value: Self::Scalar) -> Self;
119
120    /// The length of a full rotation.
121    fn period() -> Self::Scalar;
122    /// Return the scalar (unitless) value.
123    ///
124    /// Equivalent to `self.0` or to doing `let Deg(val) = self`
125    fn scalar(&self) -> Self::Scalar;
126    /// Set the internal scalar value of the angle.
127    fn set_scalar(&mut self, value: Self::Scalar);
128    /// Normalize the angle, wrapping it back into the standard domain.
129    ///
130    /// After normalization, an angle will be in the range `[0, self.period())`.
131    ///
132    /// For performance reasons, normalization does not happen automatically
133    /// during most operations. Thus, when passing an angle to a method that
134    /// expects it to be within the standard domain, first normalize the angle.
135    fn normalize(self) -> Self;
136    /// Whether the angle is in the standard domain.
137    fn is_normalized(&self) -> bool;
138
139    /// Compute the sine of an angle.
140    fn sin(self) -> Self::Scalar;
141    /// Compute the cosine of an angle.
142    fn cos(self) -> Self::Scalar;
143    /// Compute the tangent of an angle.
144    fn tan(self) -> Self::Scalar;
145    /// Simultaneously compute sine and cosine.
146    fn sin_cos(self) -> (Self::Scalar, Self::Scalar);
147
148    /// Compute the arcsine of a value, returning an angle.
149    fn asin(value: Self::Scalar) -> Self;
150    /// Compute the arccosine of a value, returning an angle.
151    fn acos(value: Self::Scalar) -> Self;
152    /// Compute the arctangent of a value, returning an angle.
153    fn atan(value: Self::Scalar) -> Self;
154    /// Compute the arctangent of a value, using information from
155    /// the numerator and denominator in order to increase the domain.
156    fn atan2(x: Self::Scalar, y: Self::Scalar) -> Self;
157
158    /// Return one full rotation in some unit.
159    ///
160    /// Equivalent to `Self(Self::period())`.
161    fn full_turn() -> Self;
162    /// Return one half of a full rotation in some unit.
163    fn half_turn() -> Self;
164    /// Return one quarter of a full rotation in some unit.
165    fn quarter_turn() -> Self;
166
167    /// Return the inverse of an angle.
168    ///
169    /// The inverse is equivalent to adding half a rotation
170    /// or inverting the unit vector pointing from the origin along the
171    /// angle.
172    fn invert(self) -> Self;
173    /// Return the reflection of an angle over the x axis.
174    ///
175    /// Equivalent to `full_turn() - self`.
176    fn reflect_x(self) -> Self;
177}
178
179/// A trait for linear interpolation between angles.
180pub trait Interpolate: Angle {
181    /// Perform a linear interpolation between two angles.
182    ///
183    /// This method will always follow the shortest past between
184    /// the two angles. This means it will go backward if the
185    /// angles are more than a half turn apart. To force the interpolation
186    /// to go forward, use `interpolate_forward`.
187    /// The output is not normalized, and may exceed a
188    /// full turn if it interpolates backward,
189    /// even if both inputs are normalized.
190    /// The angles may be represented in different units.
191    fn interpolate<U>(&self, right: &U, pos: Self::Scalar) -> Self
192        where U: Clone + IntoAngle<Self, OutputScalar = Self::Scalar>;
193
194    /// Perform a linear interpolation between two angles,
195    /// going forward from `self` to `right`.
196    ///
197    /// Unlike `interpolate` this will always go forward from `self` to `right`,
198    /// even if going backward would take a shorter path. The output is not
199    /// normalized, but should remain normalized if both `self` and `right` are.
200    /// The angles may be represented in different units.
201    fn interpolate_forward<U>(&self, right: &U, pos: Self::Scalar) -> Self
202        where U: Clone + IntoAngle<Self, OutputScalar = Self::Scalar>;
203}
204
205macro_rules! impl_angle {
206    ($Struct: ident, $period: expr) => {
207        impl<T: Float> Angle for $Struct<T>
208        {
209            type Scalar = T;
210
211            fn new(value: T) -> $Struct<T> {
212                $Struct(value)
213            }
214
215            fn period() -> T {
216                cast($period).unwrap()
217            }
218
219            fn scalar(&self) -> T {
220                self.0
221            }
222            fn set_scalar(&mut self, value: T) {
223                self.0 = value;
224            }
225            fn is_normalized(&self) -> bool {
226                self.0 >= T::zero() && self.0 < Self::period()
227            }
228
229            fn normalize(self) -> $Struct<T> {
230                if !self.is_normalized() {
231                    let shifted = self.0 % Self::period();
232                    if shifted < T::zero() {
233                        $Struct(shifted + Self::period())
234                    } else {
235                        $Struct(shifted)
236                    }
237                } else {
238                    self
239                }
240            }
241
242            fn sin(self) -> T {
243                Rad::from_angle(self).0.sin()
244            }
245            fn cos(self) -> T {
246                Rad::from_angle(self).0.cos()
247            }
248            fn tan(self) -> T {
249                Rad::from_angle(self).0.tan()
250            }
251            fn sin_cos(self) -> (T, T) {
252                Rad::from_angle(self).0.sin_cos()
253            }
254            fn asin(value: T) -> $Struct<T> {
255                $Struct::from_angle(Rad(value.asin()))
256            }
257            fn acos(value: T) -> $Struct<T> {
258                $Struct::from_angle(Rad(value.acos()))
259            }
260            fn atan(value: T) -> $Struct<T> {
261                $Struct::from_angle(Rad(value.atan()))
262            }
263            fn atan2(y: T, x: T) -> $Struct<T> {
264                $Struct::from_angle(Rad(y.atan2(x)))
265            }
266
267            fn full_turn() -> Self {
268                $Struct(Self::period())
269            }
270            fn half_turn() -> Self {
271                $Struct(cast::<_, Self::Scalar>(0.5).unwrap() * Self::period())
272            }
273            fn quarter_turn() -> Self {
274                $Struct(cast::<_, Self::Scalar>(0.25).unwrap() * Self::period())
275            }
276            fn invert(self) -> Self {
277                self + Self::half_turn()
278            }
279            fn reflect_x(self) -> Self {
280                Self::full_turn() - self
281            }
282        }
283
284        impl<T: Float> Interpolate for $Struct<T> {
285            fn interpolate<U>(&self, right: &U, pos: Self::Scalar) -> Self
286                where U: Clone + IntoAngle<Self, OutputScalar=Self::Scalar>
287            {
288                let end = right.clone().into_angle();
289                let forward_distance = (end.0 - self.0).abs();
290                let inv_pos = cast::<_, Self::Scalar>(1.0).unwrap() - pos;
291                
292                if forward_distance > Self::half_turn().0 {
293                    if *self > end {
294                        $Struct(self.0 * inv_pos + (end.0 + Self::period()) * pos)
295                    } else {
296                        $Struct((self.0 + Self::period()) * inv_pos + end.0 * pos)
297                    }
298                } else {
299                    $Struct(self.0 * inv_pos + end.0 * pos)
300                }
301            }
302
303            fn interpolate_forward<U>(&self, right: &U, pos: Self::Scalar) -> Self
304                where U: Clone + IntoAngle<Self, OutputScalar = Self::Scalar>
305            {
306                let inv_pos = cast::<_, Self::Scalar>(1.0).unwrap() - pos;
307                $Struct(self.0 * inv_pos + right.clone().into_angle().0 * pos)
308            }
309        }
310
311        #[cfg(feature = "approx")]
312        impl<T: Float + approx::AbsDiffEq> approx::AbsDiffEq for $Struct<T>
313            where T::Epsilon: Clone,
314        {
315            type Epsilon = T::Epsilon;
316
317            fn default_epsilon() -> Self::Epsilon {
318                T::default_epsilon()
319            }
320
321            fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool
322            {
323                let inv_self = self.clone().reflect_x();
324
325                self.0.abs_diff_eq(&other.0, epsilon.clone())
326                || self.0.abs_diff_eq(&other.clone().reflect_x().0,
327                      epsilon.clone())
328                || inv_self.0.abs_diff_eq(&other.0, epsilon)
329            }
330        }
331
332        #[cfg(feature = "approx")]
333        impl<T: Float + approx::RelativeEq> approx::RelativeEq for $Struct<T>
334            where T::Epsilon: Clone,
335        {
336            fn default_max_relative() -> Self::Epsilon {
337                T::default_max_relative()
338            }
339
340            fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, 
341                           max_relative: Self::Epsilon) -> bool {
342                let inv_self = self.clone().reflect_x();
343
344                self.0.relative_eq(&other.0, epsilon.clone(), max_relative.clone())
345                || self.0.relative_eq(&other.clone().reflect_x().0, 
346                      epsilon.clone(), max_relative.clone())
347                || inv_self.0.relative_eq(&other.0, epsilon, max_relative)
348            }
349        }
350
351        #[cfg(feature = "approx")]
352        impl<T: Float + approx::UlpsEq> approx::UlpsEq for $Struct<T>
353        where T::Epsilon: Clone,
354        {
355            fn default_max_ulps() -> u32 {
356                T::default_max_ulps()
357            }
358            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
359                let inv_self = self.clone().reflect_x();
360
361                self.0.ulps_eq(&other.0, epsilon.clone(), max_ulps)
362                || self.0.ulps_eq(&other.clone().reflect_x().0, epsilon.clone(), max_ulps)
363                || inv_self.0.ulps_eq(&other.0, epsilon, max_ulps)
364            }
365        }
366
367        impl<T: Rem<T, Output=T>> Rem for $Struct<T> {
368            type Output=$Struct<T>;
369            fn rem(self, rhs: $Struct<T>) -> $Struct<T> {
370                $Struct(self.0 % rhs.0)
371            }
372        }
373
374        impl<T: RemAssign> RemAssign for $Struct<T> {
375            fn rem_assign(&mut self, rhs: $Struct<T>) {
376                self.0 %= rhs.0;
377            }
378        }
379
380        impl<U, T> Add<U> for $Struct<T> 
381            where T: Float + Add<T, Output=T>,
382                  U: IntoAngle<$Struct<T>, OutputScalar=T>
383        {
384            type Output=$Struct<T>;
385            fn add(self, rhs: U) -> $Struct<T> {
386                $Struct(self.0 + rhs.into_angle().0)
387            }
388        }
389
390        impl<U, T> AddAssign<U> for $Struct<T> 
391            where T: Float + AddAssign<T>,
392                  U: IntoAngle<$Struct<T>, OutputScalar=T>
393        {
394            fn add_assign(&mut self, rhs: U) {
395                self.0 += rhs.into_angle().0;
396            }
397        }
398
399        impl<U, T> Sub<U> for $Struct<T> 
400            where T: Float + Sub<T, Output=T>,
401                  U: IntoAngle<$Struct<T>, OutputScalar=T>
402        {
403            type Output=$Struct<T>;
404            fn sub(self, rhs: U) -> $Struct<T> {
405                $Struct(self.0 - rhs.into_angle().0)
406            }
407        }
408
409        impl<U, T> SubAssign<U> for $Struct<T> 
410            where T: Float + SubAssign<T>,
411                  U: IntoAngle<$Struct<T>, OutputScalar=T>
412        {
413            fn sub_assign(&mut self, rhs: U) {
414                self.0 -= rhs.into_angle().0;
415            }
416        }
417        
418        impl<T: Mul<T, Output=T>> Mul<T> for $Struct<T> {
419            type Output=$Struct<T>;
420            fn mul(self, rhs: T) -> $Struct<T> {
421                $Struct(self.0 * rhs)
422            }
423        }
424
425        impl<T: MulAssign<T>> MulAssign<T> for $Struct<T> {
426            fn mul_assign(&mut self, rhs: T) {
427                self.0 *= rhs;
428            }
429        }
430
431        impl<T: Div<T, Output=T>> Div<T> for $Struct<T> {
432            type Output=$Struct<T>;
433            fn div(self, rhs: T) -> $Struct<T> {
434                $Struct(self.0 / rhs)
435            }
436        }
437
438        impl<T: DivAssign<T>> DivAssign<T> for $Struct<T> {
439            fn div_assign(&mut self, rhs: T) {
440                self.0 /= rhs;
441            }
442        }
443
444        impl<T: Neg<Output=T>> Neg for $Struct<T> {
445            type Output=$Struct<T>;
446            fn neg(self) -> $Struct<T> {
447                $Struct(-self.0)
448            }
449        }
450
451        impl<T: Float> num::Zero for $Struct<T> {
452            fn zero() -> $Struct<T> {
453                $Struct(T::zero())
454            }
455            fn is_zero(&self) -> bool {
456                self.0 == T::zero()
457            }
458        }
459
460        impl<T: num::Zero> Default for $Struct<T> {
461            fn default() -> $Struct<T> {
462                $Struct(T::zero())
463            }
464        }
465
466        impl<T, U> FromAngle<U> for $Struct<T>
467            where U: Angle<Scalar=T>,
468                  T: Float,
469        {
470            fn from_angle(from: U) -> $Struct<T> {
471                $Struct(from.scalar() * $Struct::period() / U::period())
472            }
473        }
474    }
475}
476
477macro_rules! impl_from_for_angle {
478    ($from: ty, $to: ty) => {
479        impl<T: Float> From<$from> for $to {
480            fn from(from: $from) -> $to {Self::from_angle(from)}
481        }
482    }
483}
484
485impl_angle!(Deg, 360.0);
486impl_angle!(Gon, 400.0);
487impl_angle!(Rad, consts::PI * 2.0);
488impl_angle!(Turns, 1.0);
489impl_angle!(ArcMinutes, 360.0 * 60.0);
490impl_angle!(ArcSeconds, 360.0 * 3600.0);
491
492impl_from_for_angle!(Deg<T>, Rad<T>);
493impl_from_for_angle!(Deg<T>, Turns<T>);
494impl_from_for_angle!(Deg<T>, Gon<T>);
495
496impl_from_for_angle!(Gon<T>, Deg<T>);
497impl_from_for_angle!(Gon<T>, Rad<T>);
498impl_from_for_angle!(Gon<T>, Turns<T>);
499
500impl_from_for_angle!(Rad<T>, Deg<T>);
501impl_from_for_angle!(Rad<T>, Gon<T>);
502impl_from_for_angle!(Rad<T>, Turns<T>);
503
504impl_from_for_angle!(Turns<T>, Deg<T>);
505impl_from_for_angle!(Turns<T>, Gon<T>);
506impl_from_for_angle!(Turns<T>, Rad<T>);
507
508impl_from_for_angle!(ArcMinutes<T>, Deg<T>);
509impl_from_for_angle!(ArcSeconds<T>, Deg<T>);
510impl_from_for_angle!(ArcSeconds<T>, ArcMinutes<T>);
511
512impl<T: Float> Deg<T> {
513    /// Construct a `Deg` instance from base degrees, minutes and seconds.
514    ///
515    /// The opposite of decompose. Equivalent to adding the components together:
516    ///
517    /// ```
518    /// #   use angular_units::*;
519    ///     let angle = Deg(50.0) + ArcMinutes(30.0) + ArcSeconds(10.0);
520    ///     assert_eq!(angle, Deg::from_components(Deg(50.0),
521    ///         ArcMinutes(30.0), ArcSeconds(10.0)));
522    /// ```
523    pub fn from_components(degs: Deg<T>, mins: ArcMinutes<T>, secs: ArcSeconds<T>) -> Self {
524        degs + mins + secs
525    }
526
527    /// Split an angle in degrees into base degrees, minutes and seconds.
528    ///
529    /// If the decomposition would not be perfect, seconds will be
530    /// a fractional value.
531    pub fn decompose(self) -> (Deg<T>, ArcMinutes<T>, ArcSeconds<T>) {
532        let sixty: T = cast(60.0).unwrap();
533        let degs = self.0.floor();
534        let rem = self.0 - degs;
535        let mins = (rem * sixty).floor();
536        let rem_s = rem * sixty - mins;
537        let seconds = rem_s * sixty;
538
539        (Deg(degs), ArcMinutes(mins), ArcSeconds(seconds))
540    }
541}
542
543impl<T: Float> Rad<T> {
544    pub fn pi() -> Rad<T> {
545        Rad(cast(consts::PI).unwrap())
546    }
547    pub fn pi_over_2() -> Rad<T> {
548        Rad(cast(consts::PI / 2.0).unwrap())
549    }
550    pub fn pi_over_3() -> Rad<T> {
551        Rad(cast(consts::PI / 3.0).unwrap())
552    }
553    pub fn pi_over_4() -> Rad<T> {
554        Rad(cast(consts::PI / 4.0).unwrap())
555    }
556}
557
558impl<T, U> IntoAngle<U> for T
559    where U: Angle<Scalar = T::Scalar> + FromAngle<T>,
560          T: Angle
561{
562    type OutputScalar = T::Scalar;
563    fn into_angle(self) -> U {
564        U::from_angle(self)
565    }
566}
567impl<T: fmt::Display> fmt::Display for Deg<T> {
568    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569        write!(f, "{}°", self.0)
570    }
571}
572impl<T: fmt::Display> fmt::Display for Gon<T> {
573    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
574        write!(f, "{}gon", self.0)
575    }
576}
577impl<T: fmt::Display> fmt::Display for Rad<T> {
578    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579        write!(f, "{}r", self.0)
580    }
581}
582impl<T: fmt::Display> fmt::Display for Turns<T> {
583    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
584        write!(f, "{}", self.0)
585    }
586}
587impl<T: fmt::Display> fmt::Display for ArcMinutes<T> {
588    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
589        write!(f, "{}'", self.0)
590    }
591}
592impl<T: fmt::Display> fmt::Display for ArcSeconds<T> {
593    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594        write!(f, "{}\"", self.0)
595    }
596}
597
598/// Compute the mean of a collection of angles.
599///
600/// Note that because angles are circular, a standard summation and dividing by `len()`
601/// is _not_ valid, even if all angles are normalized.
602pub fn mean<T, Scalar, Out>(iter: T) -> Out
603    where T: IntoIterator,
604          T::Item: IntoAngle<Rad<Scalar>, OutputScalar=Scalar>,
605          Scalar: Float + AddAssign,
606          Out: Angle<Scalar=Scalar> + FromAngle<Rad<Scalar>>,
607{
608    let mut sum_of_sines: Scalar = cast(0.0).unwrap();
609    let mut sum_of_cosines: Scalar = cast(0.0).unwrap();
610
611    for angle in iter.into_iter() {
612        let intermediate_angle: Rad<Scalar> = angle.into_angle();
613        let (sin, cos) = intermediate_angle.sin_cos();
614        sum_of_sines += sin;
615        sum_of_cosines += cos;
616    }
617
618    Out::atan2(sum_of_sines, sum_of_cosines).normalize()
619}
620
621fn cast<T: NumCast, U: NumCast>(from: T) -> Option<U> {
622    U::from(from)
623}
624
625#[cfg(test)]
626mod test {
627    #[cfg(feature = "serde")]
628    extern crate serde_test;
629
630    use std::f64::consts;
631    use std::f64;
632    use super::*;
633
634    #[test]
635    fn test_construct() {
636        assert_relative_eq!(Deg(50.0), Deg::new(50.0));
637        let mut a1 = Deg(100.0);
638        let scalar = a1.scalar();
639        a1.set_scalar(scalar + 150.0);
640        assert_relative_eq!(a1, Deg(250.0));
641    }
642
643    #[test]
644    fn test_convert() {
645        assert_relative_eq!(ArcMinutes(120.0).into_angle(), Deg(2.0), epsilon=1e-6);
646        assert_relative_eq!(ArcMinutes(120.0).into_angle(), Gon(2.222222), epsilon=1e-6);
647        assert_relative_eq!(ArcSeconds(30.0).into_angle(), ArcMinutes(0.5), epsilon=1e-6);
648        assert_relative_eq!(Deg(30.0) + ArcMinutes(30.0) + ArcSeconds(30.0), 
649            Deg(30.50833333333), epsilon=1e-6);
650        assert_relative_eq!(Rad(consts::PI).into_angle(), Deg(180.0), epsilon=1e-6);
651        assert_relative_eq!(Turns(0.25).into_angle(), Deg(90.0), epsilon=1e-6);
652        assert_relative_eq!(Turns(0.25).into_angle(), Rad(consts::PI / 2.0), epsilon=1e-6);
653        assert_relative_eq!(ArcMinutes(600.0).into_angle(), Deg(10.0), epsilon=1e-6);
654        assert_relative_eq!(ArcMinutes(5400.0).into_angle(), Rad(consts::PI / 2.0), epsilon=1e-6);
655        assert_relative_eq!(Gon(100.0).into_angle(), Deg(90.0), epsilon=1e-6);
656        assert_relative_eq!(Gon(50.0).into_angle(), Rad(consts::PI / 4.0), epsilon=1e-6);
657    }
658
659    #[test]
660    fn test_arithmetic() {
661        {
662            let a1 = Rad(2.0);
663            let a2 = Deg(100.0);
664
665            let a3 = a2 + a1;
666            assert_relative_eq!(a3.0, 214.59, epsilon=1e-2);
667
668            let a4 = Deg(50.0);
669            let a5 = a2 + a4;
670            assert_ulps_eq!(a5.0, 150.0);
671
672            let mut a6 = Deg(123.0);
673            a6 += Deg(10.0);
674            a6 += Rad::pi();
675            assert_ulps_eq!(a6.0, 313.0);
676
677            let a7 = Deg(50.0);
678            assert_ulps_eq!(a7 * 2.0, Deg(100.0));
679        }
680        {
681            let a1 = Rad(2.0);
682            let a2 = a1 % Rad(1.5);
683            assert_ulps_eq!(a2, Rad(0.5));
684            assert_ulps_eq!(Rad(1.0) * 2.0, Rad(2.0));
685            assert_ulps_eq!(Rad(consts::PI * 2.0) / 2.0, Rad(consts::PI));
686        }
687        {
688            let a10 = Gon(15.0);
689            let a11 = Deg(43.0);
690            let a12 = a11 + a10;
691            assert_relative_eq!(a12.0, 56.5, epsilon=1e-2);
692            let a13 = a10 + a11;
693            assert_relative_eq!(a13.0, 62.7778, epsilon=1e-2);
694        }
695    }
696
697    #[test]
698    fn test_trig() {
699        assert_ulps_eq!(Deg(0.0).sin(), 0.0);
700        assert_ulps_eq!(Gon(0.0).sin(), 0.0);
701        assert_ulps_eq!(Rad(consts::PI / 2.0).sin(), 1.0);
702        assert_ulps_eq!(Deg(90.0).sin(), 1.0);
703        assert_ulps_eq!(Deg(45.0).tan(), 1.0);
704        assert_relative_eq!(Deg(405.0).tan(), 1.0, epsilon=1e-6);
705        assert_relative_eq!(Gon(450.0).tan(), 1.0, epsilon=1e-6);
706        let a1 = Rad(consts::PI * 1.25);
707        assert_relative_eq!(a1.cos(), -f64::sqrt(2.0) / 2.0, epsilon=1e-6);
708        assert_relative_eq!(a1.cos(), Deg(135.0).cos(), epsilon=1e-6);
709        assert_relative_eq!(a1.cos(), Gon(150.0).cos(), epsilon=1e-6);
710
711        assert_relative_eq!(Deg::acos(1.0), Deg(0.0));
712        assert_relative_eq!(Deg::acos(0.0), Deg(90.0));
713        assert_relative_eq!(Deg::acos(0.0), Deg::from(Gon(100.0)));
714        assert_relative_eq!(Rad::acos(0.0), Rad::pi_over_2());
715    }
716
717    #[test]
718    fn test_equality() {
719        let a1 = Rad(2.0);
720        assert_ulps_eq!(a1, Rad(2.0));
721        assert_ulps_eq!(Deg(200.0), Deg(200.0));
722        assert!(!(Deg(200.0) == Deg(100.0)));
723
724        assert!(Deg(200.0) < Deg(300.0));
725        assert!(Deg(250.0) > Deg(100.0));
726
727        assert_relative_eq!(Deg(359.999999), Deg(0.0), epsilon=1e-4);
728        assert_ulps_eq!(Deg(359.999999), Deg(0.0), epsilon=1e-4);
729        assert_ulps_eq!(Deg(359.99999), Deg(0.0), epsilon=1e-4);
730    }
731
732    #[test]
733    fn test_normalize() {
734        let mut a1 = Deg(200.0);
735        a1 += Deg(300.0);
736        assert_ulps_eq!(a1, Deg(500.0));
737        a1 = a1.normalize();
738        assert_ulps_eq!(a1, Deg(140.0));
739        assert_ulps_eq!(a1.normalize(), a1);
740
741        let a2 = Deg(50.0);
742        assert_ulps_eq!(a2 - Deg(150.0), Deg(-100.0));
743        let a3 = a2 - Deg(100.0);
744        assert!(!a3.is_normalized());
745        assert_ulps_eq!(a3.normalize(), Deg(310.0));
746        assert_ulps_eq!(a3.normalize().normalize(), a3.normalize());
747        assert!(a3.normalize().is_normalized());
748
749        let a4 = Rad(consts::PI);
750        let a5 = a4 + Rad(consts::PI * 2.0);
751        assert_ulps_eq!(a5, Rad(consts::PI * 3.0));
752        assert!(!a3.is_normalized());
753        assert_ulps_eq!(a5.normalize(), Rad(consts::PI));
754        let a6 = a4 - Rad(consts::PI * 2.0);
755        assert_ulps_eq!(a6, Rad(consts::PI * -1.0));
756        assert!(!a6.is_normalized());
757        assert_ulps_eq!(a6.normalize(), a5.normalize());
758
759        assert_ulps_eq!(Deg(360.0).normalize(), Deg(0.0));
760        assert_ulps_eq!(Deg(-1.0).normalize(), Deg(359.0));
761        assert_ulps_eq!(Deg(-360.0).normalize(), Deg(0.0));
762        assert_relative_eq!(Deg(-359.9).normalize(), Deg(0.1), epsilon=1e-6);
763
764        assert_relative_eq!(Gon(725.0).normalize().into_angle(), Deg(292.5), epsilon=1e-6);
765        assert_relative_eq!(Gon(-275.0).normalize(), Gon(125.0), epsilon=1e-6);
766    }
767
768    #[test]
769    fn decompose() {
770        {
771            let (deg, min, sec) = Deg(50.25).decompose();
772
773            assert_ulps_eq!(deg, Deg(50.0));
774            assert_ulps_eq!(min, ArcMinutes(15.0));
775            assert_ulps_eq!(sec, ArcSeconds(0.0));
776        }
777        {
778            let (deg, min, sec) = Deg(90.3131).decompose();
779
780            assert_ulps_eq!(deg, Deg(90.0));
781            assert_ulps_eq!(min, ArcMinutes(18.0));
782            assert_relative_eq!(sec, ArcSeconds(47.16), epsilon=1e-6);
783        }
784    }
785
786    #[test]
787    fn test_interpolate() {
788        assert_relative_eq!(Deg(60.0).interpolate(&Deg(120.0), 0.5), Deg(90.0));
789        assert_relative_eq!(Deg(50.0).interpolate(&Rad(consts::PI), 0.75), 
790                            Deg(147.5), epsilon=1e-6);
791        assert_relative_eq!(Turns(0.50).interpolate(&Deg(30.0), 0.25), 
792                            Turns(0.39583333333), epsilon=1e-6);
793
794        assert_relative_eq!(Deg(100.0).interpolate(&Deg(310.0), 0.5).normalize(), Deg(25.0));
795        assert_relative_eq!(Deg(100.0).interpolate_forward(&Deg(310.0), 0.5).normalize(), 
796                            Deg(205.0));
797        assert_relative_eq!(Gon(66.6666667).interpolate(&Deg(120.0), 0.5), Gon(100.0), epsilon=1e-6);
798        assert_relative_eq!(Rad::pi_over_2().interpolate(&Rad(0.0), 0.5), Rad::pi_over_4());
799    }
800
801    #[test]
802    fn test_constants() {
803        assert_ulps_eq!(Deg::half_turn(), Deg(180.0));
804        assert_ulps_eq!(Deg::quarter_turn(), Deg(90.0));
805        assert_ulps_eq!(Rad::half_turn(), Rad(consts::PI));
806        assert_ulps_eq!(Rad::<f32>::full_turn(), Rad(Rad::period()));
807        assert_ulps_eq!(Gon::half_turn(), Gon(200.0));
808        assert_ulps_eq!(Gon::quarter_turn(), Gon(100.0));
809    }
810
811    #[test]
812    fn test_invert() {
813        assert_ulps_eq!(Deg(0.0).invert(), Deg(180.0));
814        assert_ulps_eq!(Deg(180.0).invert().normalize(), Deg(0.0));
815        assert_ulps_eq!(Gon(200.0).invert().normalize(), Gon(0.0));
816        assert_ulps_eq!(Deg(80.0).invert(), Deg(260.0));
817        assert_ulps_eq!(Gon(80.0).invert(), Gon(280.0));
818    }
819
820    #[test]
821    fn test_reflect_x() {
822        assert_relative_eq!(Deg(359.9999999999).reflect_x(), 
823            Deg(0.0000000000001), epsilon=1e-5);
824        assert_relative_eq!(Deg(180.0).reflect_x(), Deg(180.0));
825        assert_relative_eq!(Deg(90.0).reflect_x(), Deg(90.0));
826        assert_relative_eq!(Deg(0.0).reflect_x(), Deg(0.0));
827        assert_relative_eq!(Deg(45.0).reflect_x(), Deg(315.0));
828        assert_relative_eq!(Deg(215.0).reflect_x(), Deg(145.0));
829        assert_relative_eq!(Gon(50.0).reflect_x(), Gon(350.0));
830        assert_relative_eq!(Gon(215.0).reflect_x(), Gon(185.0));
831    }
832
833    #[test]
834    fn test_mean() {
835        assert_relative_eq!(mean(vec![Deg(280.0), Deg(10.0)].into_iter()), Deg(325.0));
836        assert_relative_eq!(mean(vec![Turns(0.5), Turns(0.0)].into_iter()), Deg(90.0));
837        assert_relative_eq!(mean([Rad(0.0), Rad(0.0)].into_iter().cloned()), Rad(0.0));
838    }
839
840    #[cfg(feature = "serde")]
841    #[test]
842    fn test_serialize() {
843        use self::serde_test::{Token, assert_tokens};
844
845        assert_tokens(&Deg(90.0), &[Token::NewtypeStruct {name: "Deg"}, Token::F64(90.0)]);
846        assert_tokens(&Rad(0.5f32), &[Token::NewtypeStruct {name: "Rad"}, Token::F32(0.5f32)]);
847        assert_tokens(&Gon(300.0), &[Token::NewtypeStruct {name: "Gon"}, Token::F64(300.0)]);
848        assert_tokens(&Turns(0.666), &[Token::NewtypeStruct {name: "Turns"}, Token::F64(0.666)]);
849    }
850
851    #[cfg(feature = "serde")]
852    #[test]
853    fn test_deserialize() {
854        use self::serde_test::{Token, assert_de_tokens};
855
856        assert_de_tokens(&Deg(90.0), &[Token::NewtypeStruct {name: "Deg"}, Token::F64(90.0)]);
857        assert_de_tokens(&Rad(0.5f32), &[Token::NewtypeStruct {name: "Rad"}, Token::F32(0.5f32)]);
858        assert_de_tokens(&Gon(300.0), &[Token::NewtypeStruct {name: "Gon"}, Token::F64(300.0)]);
859        assert_de_tokens(&Turns(0.666), &[Token::NewtypeStruct {name: "Turns"}, Token::F64(0.666)]);
860    }
861}