use crate::{Per, Quantity, Unit};
pub use crate::dimension::AngularRate as AngularRateDimension;
pub trait AngularRateUnit: Unit<Dim = crate::AngularRate> {}
impl<T: Unit<Dim = crate::AngularRate>> AngularRateUnit for T {}
pub type AngularRate<N, D> = Quantity<Per<N, D>>;
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
#[cfg(feature = "astro")]
use crate::units::angular::MilliArcsecond;
use crate::units::angular::{Degree, Degrees, Radian};
use crate::units::time::{Day, Days, Year};
use crate::Per;
use approx::{assert_abs_diff_eq, assert_relative_eq};
use proptest::prelude::*;
use std::f64::consts::PI;
#[test]
fn deg_per_day_to_rad_per_day() {
let f: AngularRate<Degree, Day> = AngularRate::new(180.0);
let f_rad: AngularRate<Radian, Day> = f.to();
assert_abs_diff_eq!(f_rad.value(), PI, epsilon = 1e-12);
}
#[test]
fn rad_per_day_to_deg_per_day() {
let f: AngularRate<Radian, Day> = AngularRate::new(PI);
let f_deg: AngularRate<Degree, Day> = f.to();
assert_abs_diff_eq!(f_deg.value(), 180.0, epsilon = 1e-12);
}
#[test]
fn deg_per_day_to_deg_per_year() {
let f: AngularRate<Degree, Day> = AngularRate::new(1.0);
let f_year: AngularRate<Degree, Year> = f.to();
assert_relative_eq!(f_year.value(), 365.2425, max_relative = 1e-6);
}
#[test]
fn deg_per_year_to_deg_per_day() {
let f: AngularRate<Degree, Year> = AngularRate::new(365.2425);
let f_day: AngularRate<Degree, Day> = f.to();
assert_relative_eq!(f_day.value(), 1.0, max_relative = 1e-6);
}
#[test]
#[cfg(feature = "astro")]
fn mas_per_day_to_deg_per_day() {
let f: AngularRate<MilliArcsecond, Day> = AngularRate::new(3_600_000.0);
let f_deg: AngularRate<Degree, Day> = f.to();
assert_abs_diff_eq!(f_deg.value(), 1.0, epsilon = 1e-9);
}
#[test]
fn per_ratio_deg_day() {
let ratio = <Per<Degree, Day>>::RATIO;
assert_abs_diff_eq!(ratio, 1.0 / 86400.0, epsilon = 1e-12);
}
#[test]
fn per_ratio_rad_day() {
let ratio = <Per<Radian, Day>>::RATIO;
assert_relative_eq!(ratio, (180.0 / PI) / 86400.0, max_relative = 1e-12);
}
#[test]
fn angular_rate_times_time() {
let f: AngularRate<Degree, Day> = AngularRate::new(360.0);
let t: Days = Days::new(0.5);
let angle: Degrees = (f * t).to();
assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
}
#[test]
fn time_times_angular_rate() {
let f: AngularRate<Degree, Day> = AngularRate::new(360.0);
let t: Days = Days::new(0.5);
let angle: Degrees = (t * f).to();
assert_abs_diff_eq!(angle.value(), 180.0, epsilon = 1e-9);
}
#[test]
fn angle_div_time() {
let angle: Degrees = Degrees::new(360.0);
let t: Days = Days::new(1.0);
let f: AngularRate<Degree, Day> = angle / t;
assert_abs_diff_eq!(f.value(), 360.0, epsilon = 1e-9);
}
#[test]
fn roundtrip_deg_rad_per_day() {
let original: AngularRate<Degree, Day> = AngularRate::new(90.0);
let converted: AngularRate<Radian, Day> = original.to();
let back: AngularRate<Degree, Day> = converted.to();
assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-9);
}
proptest! {
#[test]
fn prop_roundtrip_deg_rad_per_day(f in 1e-6..1e6f64) {
let original: AngularRate<Degree, Day> = AngularRate::new(f);
let converted: AngularRate<Radian, Day> = original.to();
let back: AngularRate<Degree, Day> = converted.to();
prop_assert!((back.value() - original.value()).abs() < 1e-9 * f.abs().max(1.0));
}
#[test]
fn prop_angular_rate_time_roundtrip(
f_val in 1e-3..1e3f64,
t_val in 1e-3..1e3f64
) {
let f: AngularRate<Degree, Day> = AngularRate::new(f_val);
let t: Days = Days::new(t_val);
let angle: Degrees = (f * t).to();
let f_back: AngularRate<Degree, Day> = angle / t;
prop_assert!((f_back.value() - f.value()).abs() / f.value() < 1e-12);
}
}
}