use crate::dimension::{Dimension, Rational16};
use crate::unit::base::BaseUnit;
const C_M_S: f64 = 299_792_458.0; const AU_M: f64 = 1.495_978_707e11; const PC_M: f64 = 3.085_677_581_491_367e16; const LY_M: f64 = 9.460_730_472_580_8e15;
const MSUN_KG: f64 = 1.988_409_870_698_051e30; const RSUN_M: f64 = 6.957e8; const LSUN_W: f64 = 3.828e26;
const MJUP_KG: f64 = 1.898_13e27; const RJUP_M: f64 = 6.991_1e7; const MEARTH_KG: f64 = 5.972_17e24; const REARTH_M: f64 = 6.378_1e6;
const DIM_ENERGY: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH.pow(Rational16::new(2, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
const DIM_FORCE: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH)
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
const DIM_POWER: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH.pow(Rational16::new(2, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-3, 1)));
const DIM_MAGNETIC_FIELD: Dimension = Dimension::MASS
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)))
.mul(&Dimension::CURRENT.pow(Rational16::new(-1, 1)));
const DIM_AREA: Dimension = Dimension::LENGTH.pow(Rational16::new(2, 1));
const DIM_SPECTRAL_FLUX: Dimension =
Dimension::MASS.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
pub const AU: BaseUnit = BaseUnit::new("astronomical_unit", "AU", &["au"], Dimension::LENGTH, AU_M);
pub const PARSEC: BaseUnit = BaseUnit::new("parsec", "pc", &[], Dimension::LENGTH, PC_M);
pub const KPC: BaseUnit = BaseUnit::new("kiloparsec", "kpc", &[], Dimension::LENGTH, PC_M * 1e3);
pub const MPC: BaseUnit = BaseUnit::new("megaparsec", "Mpc", &[], Dimension::LENGTH, PC_M * 1e6);
pub const GPC: BaseUnit = BaseUnit::new("gigaparsec", "Gpc", &[], Dimension::LENGTH, PC_M * 1e9);
pub const LIGHT_YEAR: BaseUnit = BaseUnit::new(
"light_year",
"lyr",
&["ly", "lightyear"],
Dimension::LENGTH,
LY_M,
);
pub const LIGHT_SECOND: BaseUnit =
BaseUnit::new("light_second", "ls", &[], Dimension::LENGTH, C_M_S);
pub const SOLAR_MASS: BaseUnit = BaseUnit::new(
"solar_mass",
"M_sun",
&["Msun", "solMass", "M_sol"],
Dimension::MASS,
MSUN_KG,
);
pub const SOLAR_RADIUS: BaseUnit = BaseUnit::new(
"solar_radius",
"R_sun",
&["Rsun", "solRad", "R_sol"],
Dimension::LENGTH,
RSUN_M,
);
pub const SOLAR_LUMINOSITY: BaseUnit = BaseUnit::new(
"solar_luminosity",
"L_sun",
&["Lsun", "solLum", "L_sol"],
DIM_POWER,
LSUN_W,
);
pub const JUPITER_MASS: BaseUnit = BaseUnit::new(
"jupiter_mass",
"M_jup",
&["Mjup", "jupiterMass"],
Dimension::MASS,
MJUP_KG,
);
pub const JUPITER_RADIUS: BaseUnit = BaseUnit::new(
"jupiter_radius",
"R_jup",
&["Rjup", "jupiterRad"],
Dimension::LENGTH,
RJUP_M,
);
pub const EARTH_MASS: BaseUnit = BaseUnit::new(
"earth_mass",
"M_earth",
&["Mearth", "earthMass"],
Dimension::MASS,
MEARTH_KG,
);
pub const EARTH_RADIUS: BaseUnit = BaseUnit::new(
"earth_radius",
"R_earth",
&["Rearth", "earthRad"],
Dimension::LENGTH,
REARTH_M,
);
pub const ANGSTROM: BaseUnit = BaseUnit::new(
"angstrom",
"Angstrom",
&["AA", "angstrom"],
Dimension::LENGTH,
1e-10,
);
pub const JANSKY: BaseUnit = BaseUnit::new("jansky", "Jy", &[], DIM_SPECTRAL_FLUX, 1e-26);
pub const MJY: BaseUnit = BaseUnit::new("millijansky", "mJy", &[], DIM_SPECTRAL_FLUX, 1e-29);
pub const UJY: BaseUnit = BaseUnit::new("microjansky", "uJy", &[], DIM_SPECTRAL_FLUX, 1e-32);
pub const RAYLEIGH: BaseUnit = BaseUnit::new(
"rayleigh",
"R",
&[],
Dimension::PHOTON
.mul(&Dimension::LENGTH.pow(Rational16::new(-2, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-1, 1)))
.mul(&Dimension::SOLID_ANGLE.pow(Rational16::new(-1, 1))),
1e10,
);
pub const BARN: BaseUnit = BaseUnit::new("barn", "barn", &["b"], DIM_AREA, 1e-28);
pub const MBARN: BaseUnit = BaseUnit::new("millibarn", "mbarn", &["mb"], DIM_AREA, 1e-31);
pub const UBARN: BaseUnit = BaseUnit::new("microbarn", "ubarn", &["ub"], DIM_AREA, 1e-34);
pub const ERG: BaseUnit = BaseUnit::new("erg", "erg", &[], DIM_ENERGY, 1e-7);
pub const DYN: BaseUnit = BaseUnit::new("dyne", "dyn", &[], DIM_FORCE, 1e-5);
pub const GAUSS: BaseUnit = BaseUnit::new("gauss", "G", &["Gauss"], DIM_MAGNETIC_FIELD, 1e-4);
pub const FLAM_NU: BaseUnit = BaseUnit::new(
"erg_per_s_cm2_Hz",
"erg/(s cm^2 Hz)",
&["erg/s/cm2/Hz", "cgs_fnu"],
DIM_SPECTRAL_FLUX,
1e-3,
);
pub const FLAM: BaseUnit = BaseUnit::new(
"erg_per_s_cm2_angstrom",
"erg/(s cm^2 Angstrom)",
&["erg/s/cm2/A", "FLAM", "flam"],
Dimension::MASS
.mul(&Dimension::LENGTH.pow(Rational16::new(-1, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-3, 1))),
1e7,
);
pub const PHOTLAM: BaseUnit = BaseUnit::new(
"photon_per_s_cm2_angstrom",
"photon/(s cm^2 Angstrom)",
&["PHOTLAM", "photlam"],
Dimension::PHOTON
.mul(&Dimension::LENGTH.pow(Rational16::new(-3, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-1, 1))),
1e14,
);
pub const PHOTNU: BaseUnit = BaseUnit::new(
"photon_per_s_cm2_Hz",
"photon/(s cm^2 Hz)",
&["PHOTNU", "photnu"],
Dimension::PHOTON
.mul(&Dimension::LENGTH.pow(Rational16::new(-2, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1))),
1e4,
);
pub const PHOTON: BaseUnit = BaseUnit::new("photon", "ph", &["photon"], Dimension::PHOTON, 1.0);
pub const COUNT: BaseUnit = BaseUnit::new("count", "ct", &["count", "cts"], Dimension::PHOTON, 1.0);
pub const ELECTRON: BaseUnit =
BaseUnit::new("electron", "e-", &["electron"], Dimension::PHOTON, 1.0);
pub const SIDEREAL_DAY: BaseUnit =
BaseUnit::new("sidereal_day", "sday", &[], Dimension::TIME, 86_164.090_5);
pub const TROPICAL_YEAR: BaseUnit = BaseUnit::new(
"tropical_year",
"tyr",
&[],
Dimension::TIME,
365.24219 * 86400.0,
);
pub const SIDEREAL_YEAR: BaseUnit = BaseUnit::new(
"sidereal_year",
"syr",
&[],
Dimension::TIME,
365.25636 * 86400.0,
);
pub const HUBBLE_TIME: BaseUnit = BaseUnit::new("hubble_time", "t_H", &[], Dimension::TIME, 4.4e17);
pub const HUBBLE_DISTANCE: BaseUnit =
BaseUnit::new("hubble_distance", "d_H", &[], Dimension::LENGTH, 1.32e26);
#[cfg(test)]
mod tests {
use super::*;
use crate::systems::si::{J, KG, M, W};
#[test]
fn test_parsec_to_meters() {
let q = 1.0 * PARSEC;
let q_m = q.to(M).unwrap();
assert!((q_m.value() - 3.0856775814913673e16).abs() / 3.0856775814913673e16 < 1e-9);
}
#[test]
fn test_light_year_to_meters() {
let q = 1.0 * LIGHT_YEAR;
let q_m = q.to(M).unwrap();
assert!((q_m.value() - 9.4607304725808e15).abs() / 9.4607304725808e15 < 1e-9);
}
#[test]
fn test_au_to_meters() {
let q = 1.0 * AU;
let q_m = q.to(M).unwrap();
assert!((q_m.value() - 1.495978707e11).abs() < 1.0);
}
#[test]
fn test_solar_mass_to_kg() {
let q = 1.0 * SOLAR_MASS;
let q_kg = q.to(KG).unwrap();
assert!((q_kg.value() - 1.98840987e30).abs() / 1.98840987e30 < 1e-6);
}
#[test]
fn test_solar_luminosity_to_watts() {
let q = 1.0 * SOLAR_LUMINOSITY;
let q_w = q.to(W).unwrap();
assert!((q_w.value() - 3.828e26).abs() / 3.828e26 < 1e-6);
}
#[test]
fn test_angstrom_to_nm() {
let q = 10.0 * ANGSTROM;
let q_m = q.to(M).unwrap();
assert!((q_m.value() - 1e-9).abs() < 1e-20);
}
#[test]
fn test_erg_to_joule() {
let q = 1e7 * ERG;
let q_j = q.to(J).unwrap();
assert!((q_j.value() - 1.0).abs() < 1e-10);
}
}