qtty_core/units/
angular_rate.rs1use crate::{Per, Quantity, Unit};
24
25pub use crate::dimension::AngularRate as AngularRateDimension;
27
28pub trait AngularRateUnit: Unit<Dim = crate::AngularRate> {}
30impl<T: Unit<Dim = crate::AngularRate>> AngularRateUnit for T {}
31
32pub type AngularRate<N, D> = Quantity<Per<N, D>>;
45
46#[cfg(all(test, feature = "std"))]
47mod tests {
48 use super::*;
49 #[cfg(feature = "astro")]
50 use crate::units::angular::MilliArcsecond;
51 use crate::units::angular::{Degree, Degrees, Radian};
52 use crate::units::time::{Day, Days, Year};
53 use crate::Per;
54 use approx::{assert_abs_diff_eq, assert_relative_eq};
55 use proptest::prelude::*;
56 use std::f64::consts::PI;
57
58 #[test]
63 fn deg_per_day_to_rad_per_day() {
64 let f: AngularRate<Degree, Day> = AngularRate::new(180.0);
65 let f_rad: AngularRate<Radian, Day> = f.to();
66 assert_abs_diff_eq!(f_rad.value(), PI, epsilon = 1e-12);
68 }
69
70 #[test]
71 fn rad_per_day_to_deg_per_day() {
72 let f: AngularRate<Radian, Day> = AngularRate::new(PI);
73 let f_deg: AngularRate<Degree, Day> = f.to();
74 assert_abs_diff_eq!(f_deg.value(), 180.0, epsilon = 1e-12);
75 }
76
77 #[test]
78 fn deg_per_day_to_deg_per_year() {
79 let f: AngularRate<Degree, Day> = AngularRate::new(1.0);
80 let f_year: AngularRate<Degree, Year> = f.to();
81 assert_relative_eq!(f_year.value(), 365.2425, max_relative = 1e-6);
83 }
84
85 #[test]
86 fn deg_per_year_to_deg_per_day() {
87 let f: AngularRate<Degree, Year> = AngularRate::new(365.2425);
88 let f_day: AngularRate<Degree, Day> = f.to();
89 assert_relative_eq!(f_day.value(), 1.0, max_relative = 1e-6);
90 }
91
92 #[test]
93 #[cfg(feature = "astro")]
94 fn mas_per_day_to_deg_per_day() {
95 let f: AngularRate<MilliArcsecond, Day> = AngularRate::new(3_600_000.0);
96 let f_deg: AngularRate<Degree, Day> = f.to();
97 assert_abs_diff_eq!(f_deg.value(), 1.0, epsilon = 1e-9);
99 }
100
101 #[test]
106 fn per_ratio_deg_day() {
107 let ratio = <Per<Degree, Day>>::RATIO;
110 assert_abs_diff_eq!(ratio, 1.0 / 86400.0, epsilon = 1e-12);
111 }
112
113 #[test]
114 fn per_ratio_rad_day() {
115 let ratio = <Per<Radian, Day>>::RATIO;
117 assert_relative_eq!(ratio, (180.0 / PI) / 86400.0, max_relative = 1e-12);
118 }
119
120 #[test]
125 fn angular_rate_times_time() {
126 let f: AngularRate<Degree, Day> = AngularRate::new(360.0);
127 let t: Days = Days::new(0.5);
128 let angle: Degrees = (f * t).to();
129 assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
130 }
131
132 #[test]
133 fn time_times_angular_rate() {
134 let f: AngularRate<Degree, Day> = AngularRate::new(360.0);
135 let t: Days = Days::new(0.5);
136 let angle: Degrees = (t * f).to();
137 assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
138 }
139
140 #[test]
145 fn angle_div_time() {
146 let angle: Degrees = Degrees::new(360.0);
147 let t: Days = Days::new(1.0);
148 let f: AngularRate<Degree, Day> = angle / t;
149 assert_abs_diff_eq!(f.value(), 360.0, epsilon = 1e-9);
150 }
151
152 #[test]
157 fn roundtrip_deg_rad_per_day() {
158 let original: AngularRate<Degree, Day> = AngularRate::new(90.0);
159 let converted: AngularRate<Radian, Day> = original.to();
160 let back: AngularRate<Degree, Day> = converted.to();
161 assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-9);
162 }
163
164 proptest! {
169 #[test]
170 fn prop_roundtrip_deg_rad_per_day(f in 1e-6..1e6f64) {
171 let original: AngularRate<Degree, Day> = AngularRate::new(f);
172 let converted: AngularRate<Radian, Day> = original.to();
173 let back: AngularRate<Degree, Day> = converted.to();
174 prop_assert!((back.value() - original.value()).abs() < 1e-9 * f.abs().max(1.0));
175 }
176
177 #[test]
178 fn prop_angular_rate_time_roundtrip(
179 f_val in 1e-3..1e3f64,
180 t_val in 1e-3..1e3f64
181 ) {
182 let f: AngularRate<Degree, Day> = AngularRate::new(f_val);
183 let t: Days = Days::new(t_val);
184 let angle: Degrees = (f * t).to();
185 let f_back: AngularRate<Degree, Day> = angle / t;
187 prop_assert!((f_back.value() - f.value()).abs() / f.value() < 1e-12);
188 }
189 }
190}