iridium_units/equivalencies/
mod.rs1#[cfg(feature = "astrophysics")]
26pub mod brightness_temperature;
27pub mod dimensionless_angles;
28#[cfg(feature = "astrophysics")]
29pub mod doppler;
30#[cfg(feature = "logarithmic")]
31pub mod logarithmic;
32pub mod mass_energy;
33#[cfg(feature = "astrophysics")]
34pub mod parallax;
35#[cfg(feature = "astrophysics")]
36pub mod spectral;
37#[cfg(feature = "astrophysics")]
38pub mod spectral_density;
39pub mod temperature;
40
41use crate::error::{UnitError, UnitResult};
42use crate::quantity::Quantity;
43use crate::unit::Unit;
44use std::sync::Arc;
45
46pub type ConverterFn = Arc<dyn Fn(&Unit, &Unit) -> Option<Converter> + Send + Sync>;
48
49#[derive(Clone)]
51pub struct Equivalency {
52 name: &'static str,
53 converter_fn: ConverterFn,
54}
55
56impl Equivalency {
57 pub fn new<F>(name: &'static str, converter_fn: F) -> Self
59 where
60 F: Fn(&Unit, &Unit) -> Option<Converter> + Send + Sync + 'static,
61 {
62 Equivalency {
63 name,
64 converter_fn: Arc::new(converter_fn),
65 }
66 }
67
68 pub fn name(&self) -> &str {
70 self.name
71 }
72
73 pub fn get_converter(&self, from: &Unit, to: &Unit) -> Option<Converter> {
75 (self.converter_fn)(from, to)
76 }
77}
78
79impl std::fmt::Debug for Equivalency {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 write!(f, "Equivalency({})", self.name())
82 }
83}
84
85pub struct Converter {
90 forward: Box<dyn Fn(f64) -> Result<f64, String> + Send + Sync>,
91 backward: Box<dyn Fn(f64) -> Result<f64, String> + Send + Sync>,
92}
93
94impl Converter {
95 pub fn new<F, B>(forward: F, backward: B) -> Self
97 where
98 F: Fn(f64) -> Result<f64, String> + Send + Sync + 'static,
99 B: Fn(f64) -> Result<f64, String> + Send + Sync + 'static,
100 {
101 Converter {
102 forward: Box::new(forward),
103 backward: Box::new(backward),
104 }
105 }
106
107 pub fn new_infallible<F, B>(forward: F, backward: B) -> Self
109 where
110 F: Fn(f64) -> f64 + Send + Sync + 'static,
111 B: Fn(f64) -> f64 + Send + Sync + 'static,
112 {
113 Converter {
114 forward: Box::new(move |x| Ok(forward(x))),
115 backward: Box::new(move |x| Ok(backward(x))),
116 }
117 }
118
119 pub fn convert(&self, value: f64) -> Result<f64, String> {
121 (self.forward)(value)
122 }
123
124 pub fn convert_back(&self, value: f64) -> Result<f64, String> {
126 (self.backward)(value)
127 }
128}
129
130impl Quantity {
131 pub fn to_equiv(&self, target: impl Into<Unit>, equiv: Equivalency) -> UnitResult<Quantity> {
136 self.to_equiv_list(target, &[equiv])
137 }
138
139 pub fn to_equiv_list(
141 &self,
142 target: impl Into<Unit>,
143 equivs: &[Equivalency],
144 ) -> UnitResult<Quantity> {
145 let target = target.into();
146 if self.unit().dimension() == target.dimension() {
148 let si_value = self.unit().to_si(self.value());
149 return Ok(Quantity::new(target.from_si(si_value), target));
150 }
151
152 for equiv in equivs {
154 if let Some(converter) = equiv.get_converter(self.unit(), &target) {
155 let si_value = self.unit().to_si(self.value());
157 let converted_si =
159 converter
160 .convert(si_value)
161 .map_err(|msg| UnitError::NoEquivalency {
162 from: format!("{} ({})", self.unit(), msg),
163 to: target.to_string(),
164 })?;
165 let target_value = target.from_si(converted_si);
167 return Ok(Quantity::new(target_value, target));
168 }
169 }
170
171 Err(UnitError::NoEquivalency {
172 from: self.unit().to_string(),
173 to: target.to_string(),
174 })
175 }
176}
177
178#[cfg(feature = "astrophysics")]
180pub use brightness_temperature::{
181 brightness_temperature, brightness_temperature_intensity, brightness_temperature_planck,
182};
183pub use dimensionless_angles::dimensionless_angles;
184#[cfg(feature = "astrophysics")]
185pub use doppler::{doppler_optical, doppler_radio, doppler_relativistic};
186#[cfg(feature = "logarithmic")]
187pub use logarithmic::{db_amplitude, db_power, dex_ratio, magnitude_flux};
188pub use mass_energy::mass_energy;
189#[cfg(feature = "astrophysics")]
190pub use parallax::parallax;
191#[cfg(feature = "astrophysics")]
192pub use spectral::spectral;
193#[cfg(feature = "astrophysics")]
194pub use spectral_density::{ab_magnitude, ab_magnitude_lambda, spectral_density};
195pub use temperature::{temperature, temperature_energy};