use crate::dimension::Dimension;
use crate::equivalencies::{Converter, Equivalency};
use crate::systems::logarithmic::{
amplitude_ratio_to_db, db_to_amplitude_ratio, db_to_power_ratio, dex_to_ratio,
flux_ratio_to_mag, mag_to_flux_ratio, power_ratio_to_db, ratio_to_dex,
};
pub fn magnitude_flux() -> Equivalency {
Equivalency::new("magnitude_flux", |from, to| {
let from_dim = from.dimension();
let to_dim = to.dimension();
if from_dim == Dimension::MAGNITUDE && to_dim.is_dimensionless() {
return Some(Converter::new(
move |mag| {
Ok(mag_to_flux_ratio(mag))
},
move |flux| flux_ratio_to_mag(flux).map_err(|e| e.to_string()),
));
}
if from_dim.is_dimensionless() && to_dim == Dimension::MAGNITUDE {
return Some(Converter::new(
move |flux| flux_ratio_to_mag(flux).map_err(|e| e.to_string()),
move |mag| Ok(mag_to_flux_ratio(mag)),
));
}
None
})
}
pub fn db_power() -> Equivalency {
Equivalency::new("db_power", |from, to| {
let from_dim = from.dimension();
let to_dim = to.dimension();
if from_dim == Dimension::MAGNITUDE && to_dim.is_dimensionless() {
return Some(Converter::new(
move |db| Ok(db_to_power_ratio(db)),
move |power| power_ratio_to_db(power).map_err(|e| e.to_string()),
));
}
if from_dim.is_dimensionless() && to_dim == Dimension::MAGNITUDE {
return Some(Converter::new(
move |power| power_ratio_to_db(power).map_err(|e| e.to_string()),
move |db| Ok(db_to_power_ratio(db)),
));
}
None
})
}
pub fn db_amplitude() -> Equivalency {
Equivalency::new("db_amplitude", |from, to| {
let from_dim = from.dimension();
let to_dim = to.dimension();
if from_dim == Dimension::MAGNITUDE && to_dim.is_dimensionless() {
return Some(Converter::new(
move |db| Ok(db_to_amplitude_ratio(db)),
move |amplitude| amplitude_ratio_to_db(amplitude).map_err(|e| e.to_string()),
));
}
if from_dim.is_dimensionless() && to_dim == Dimension::MAGNITUDE {
return Some(Converter::new(
move |amplitude| amplitude_ratio_to_db(amplitude).map_err(|e| e.to_string()),
move |db| Ok(db_to_amplitude_ratio(db)),
));
}
None
})
}
pub fn dex_ratio() -> Equivalency {
Equivalency::new("dex_ratio", |from, to| {
let from_dim = from.dimension();
let to_dim = to.dimension();
if from_dim == Dimension::MAGNITUDE && to_dim.is_dimensionless() {
return Some(Converter::new(
move |dex| Ok(dex_to_ratio(dex)),
move |ratio| ratio_to_dex(ratio).map_err(|e| e.to_string()),
));
}
if from_dim.is_dimensionless() && to_dim == Dimension::MAGNITUDE {
return Some(Converter::new(
move |ratio| ratio_to_dex(ratio).map_err(|e| e.to_string()),
move |dex| Ok(dex_to_ratio(dex)),
));
}
None
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::systems::logarithmic::{DB, DEX, MAG, MILLIMAG};
use crate::unit::Unit;
#[test]
fn test_magnitude_to_flux() {
let mag5 = 5.0 * MAG.clone();
let flux = mag5
.to_equiv(&Unit::dimensionless(), magnitude_flux())
.unwrap();
assert!((flux.value() - 0.01).abs() < 1e-10);
}
#[test]
fn test_flux_to_magnitude() {
let flux = 0.01 * Unit::dimensionless();
let mag = flux.to_equiv(&MAG, magnitude_flux()).unwrap();
assert!((mag.value() - 5.0).abs() < 1e-10);
}
#[test]
fn test_zero_magnitude() {
let mag0 = 0.0 * MAG.clone();
let flux = mag0
.to_equiv(&Unit::dimensionless(), magnitude_flux())
.unwrap();
assert!((flux.value() - 1.0).abs() < 1e-10);
}
#[test]
fn test_negative_magnitude() {
let mag_neg5 = -5.0 * MAG.clone();
let flux = mag_neg5
.to_equiv(&Unit::dimensionless(), magnitude_flux())
.unwrap();
assert!((flux.value() - 100.0).abs() < 1e-10);
}
#[test]
fn test_millimag_conversion() {
let mmag = 5000.0 * MILLIMAG.clone();
let flux = mmag
.to_equiv(&Unit::dimensionless(), magnitude_flux())
.unwrap();
assert!((flux.value() - 0.01).abs() < 1e-10);
}
#[test]
fn test_db_power_conversion() {
let db10 = 10.0 * DB.clone();
let power = db10.to_equiv(&Unit::dimensionless(), db_power()).unwrap();
assert!((power.value() - 10.0).abs() < 1e-10);
}
#[test]
fn test_db_3db_is_2x() {
let db3 = 3.0 * DB.clone();
let power = db3.to_equiv(&Unit::dimensionless(), db_power()).unwrap();
assert!((power.value() - 2.0).abs() < 0.01);
}
#[test]
fn test_power_to_db() {
let power = 100.0 * Unit::dimensionless();
let db = power.to_equiv(&DB, db_power()).unwrap();
assert!((db.value() - 20.0).abs() < 1e-10);
}
#[test]
fn test_db_amplitude_6db() {
let db6 = 6.0 * DB.clone();
let amp = db6
.to_equiv(&Unit::dimensionless(), db_amplitude())
.unwrap();
assert!((amp.value() - 2.0).abs() < 0.01);
}
#[test]
fn test_dex_conversion() {
let dex2 = 2.0 * DEX.clone();
let ratio = dex2.to_equiv(&Unit::dimensionless(), dex_ratio()).unwrap();
assert!((ratio.value() - 100.0).abs() < 1e-10);
}
#[test]
fn test_ratio_to_dex() {
let ratio = 1000.0 * Unit::dimensionless();
let dex = ratio.to_equiv(&DEX, dex_ratio()).unwrap();
assert!((dex.value() - 3.0).abs() < 1e-10);
}
#[test]
fn test_invalid_flux_conversion() {
let flux = -1.0 * Unit::dimensionless();
let result = flux.to_equiv(&MAG, magnitude_flux());
assert!(result.is_err());
}
}