use super::*;
use qtty_derive::Unit;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "′", dimension = Angular, ratio = 1.0 / 60.0)]
pub struct Arcminute;
pub type MOA = Arcminute;
pub type Arcm = Arcminute;
pub type Arcminutes = Quantity<Arcm>;
pub const ARCM: Arcminutes = Arcminutes::new(1.0);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "″", dimension = Angular, ratio = 1.0 / 3600.0)]
pub struct Arcsecond;
pub type Arcs = Arcsecond;
pub type Arcseconds = Quantity<Arcs>;
pub const ARCS: Arcseconds = Arcseconds::new(1.0);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mas", dimension = Angular, ratio = 1.0 / 3_600_000.0)]
pub struct MilliArcsecond;
pub type Mas = MilliArcsecond;
pub type MilliArcseconds = Quantity<Mas>;
pub const MAS: MilliArcseconds = MilliArcseconds::new(1.0);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "μas", dimension = Angular, ratio = 1.0 / 3_600_000_000.0)]
pub struct MicroArcsecond;
pub type Uas = MicroArcsecond;
pub type MicroArcseconds = Quantity<Uas>;
pub const UAS: MicroArcseconds = MicroArcseconds::new(1.0);
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "h", dimension = Angular, ratio = 15.0)]
pub struct HourAngle;
pub type Hms = HourAngle;
pub type HourAngles = Quantity<Hms>;
pub const HOUR_ANGLE: HourAngles = HourAngles::new(1.0);
impl HourAngles {
pub const fn from_hms(hours: i32, minutes: u32, seconds: f64) -> Self {
let sign = if hours < 0 { -1.0 } else { 1.0 };
let h_abs = if hours < 0 {
-(hours as f64)
} else {
hours as f64
};
let m = minutes as f64 / 60.0;
let s = seconds / 3600.0;
let total_hours = sign * (h_abs + m + s);
Self::new(total_hours)
}
}
crate::impl_unit_from_conversions_between!(
Degree, Radian, Milliradian, Turn;
Arcminute, Arcsecond, MilliArcsecond, MicroArcsecond, HourAngle
);
#[cfg(feature = "cross-unit-ops")]
crate::impl_unit_cross_unit_ops_between!(
Degree, Radian, Milliradian, Turn;
Arcminute, Arcsecond, MilliArcsecond, MicroArcsecond, HourAngle
);
#[macro_export]
#[doc(hidden)]
macro_rules! angular_astro_units {
($cb:path) => {
$cb!(
Arcminute,
Arcsecond,
MilliArcsecond,
MicroArcsecond,
HourAngle,
);
};
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
use proptest::prelude::*;
#[test]
fn arcminute_to_degrees() {
let arcm = Arcminutes::new(60.0);
let degrees: Degrees = arcm.to();
assert_abs_diff_eq!(degrees.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn hour_angle_to_degrees() {
let hour = HourAngles::new(1.0);
let degrees: Degrees = hour.to();
assert_abs_diff_eq!(degrees.value(), 15.0, epsilon = 1e-12);
}
proptest! {
#[test]
fn arcsecond_degree_roundtrip(v in -1.0e9_f64..1.0e9_f64) {
let arcseconds = Arcseconds::new(v);
let roundtrip: Arcseconds = arcseconds.to::<Degree>().to();
prop_assert!((roundtrip.value() - v).abs() <= v.abs().max(1.0) * 1e-12);
}
}
}