use crate::dimension::{Dimension, Rational16};
use crate::unit::base::BaseUnit;
pub const METER: BaseUnit = BaseUnit::new("meter", "m", &["metre"], Dimension::LENGTH, 1.0);
pub const SECOND: BaseUnit = BaseUnit::new("second", "s", &["sec"], Dimension::TIME, 1.0);
pub const KILOGRAM: BaseUnit = BaseUnit::new("kilogram", "kg", &[], Dimension::MASS, 1.0);
pub const AMPERE: BaseUnit = BaseUnit::new("ampere", "A", &["amp"], Dimension::CURRENT, 1.0);
pub const KELVIN: BaseUnit = BaseUnit::new("kelvin", "K", &[], Dimension::TEMPERATURE, 1.0);
pub const MOLE: BaseUnit = BaseUnit::new("mole", "mol", &[], Dimension::AMOUNT, 1.0);
pub const CANDELA: BaseUnit =
BaseUnit::new("candela", "cd", &[], Dimension::LUMINOUS_INTENSITY, 1.0);
pub const RADIAN: BaseUnit = BaseUnit::new("radian", "rad", &[], Dimension::ANGLE, 1.0);
pub const STERADIAN: BaseUnit = BaseUnit::new("steradian", "sr", &[], Dimension::SOLID_ANGLE, 1.0);
pub const M: BaseUnit = METER;
pub const S: BaseUnit = SECOND;
pub const KG: BaseUnit = KILOGRAM;
pub const A: BaseUnit = AMPERE;
pub const K: BaseUnit = KELVIN;
pub const MOL: BaseUnit = MOLE;
pub const CD: BaseUnit = CANDELA;
pub const RAD: BaseUnit = RADIAN;
pub const SR: BaseUnit = STERADIAN;
pub const DEG_C: BaseUnit = BaseUnit::with_offset(
"celsius",
"°C",
&["degC", "Celsius"],
Dimension::TEMPERATURE,
1.0, 273.15, );
pub const DEG_F: BaseUnit = BaseUnit::with_offset(
"fahrenheit",
"°F",
&["degF", "Fahrenheit"],
Dimension::TEMPERATURE,
5.0 / 9.0, 459.67, );
pub const KM: BaseUnit = BaseUnit::new("kilometer", "km", &[], Dimension::LENGTH, 1e3);
pub const CM: BaseUnit = BaseUnit::new("centimeter", "cm", &[], Dimension::LENGTH, 1e-2);
pub const MM: BaseUnit = BaseUnit::new("millimeter", "mm", &[], Dimension::LENGTH, 1e-3);
pub const UM: BaseUnit = BaseUnit::new("micrometer", "um", &["micron"], Dimension::LENGTH, 1e-6);
pub const NM: BaseUnit = BaseUnit::new("nanometer", "nm", &[], Dimension::LENGTH, 1e-9);
pub const PM: BaseUnit = BaseUnit::new("picometer", "pm", &[], Dimension::LENGTH, 1e-12);
pub const FM: BaseUnit = BaseUnit::new("femtometer", "fm", &[], Dimension::LENGTH, 1e-15);
pub const MS: BaseUnit = BaseUnit::new("millisecond", "ms", &[], Dimension::TIME, 1e-3);
pub const US: BaseUnit = BaseUnit::new("microsecond", "us", &[], Dimension::TIME, 1e-6);
pub const NS: BaseUnit = BaseUnit::new("nanosecond", "ns", &[], Dimension::TIME, 1e-9);
pub const PS: BaseUnit = BaseUnit::new("picosecond", "ps", &[], Dimension::TIME, 1e-12);
pub const MIN: BaseUnit = BaseUnit::new("minute", "min", &[], Dimension::TIME, 60.0);
pub const H: BaseUnit = BaseUnit::new("hour", "h", &["hr"], Dimension::TIME, 3600.0);
pub const DAY: BaseUnit = BaseUnit::new("day", "d", &["day"], Dimension::TIME, 86400.0);
pub const YR: BaseUnit = BaseUnit::new(
"year",
"yr",
&["a", "year"],
Dimension::TIME,
365.25 * 86400.0,
);
pub const G: BaseUnit = BaseUnit::new("gram", "g", &[], Dimension::MASS, 1e-3);
pub const MG: BaseUnit = BaseUnit::new("milligram", "mg", &[], Dimension::MASS, 1e-6);
pub const UG: BaseUnit = BaseUnit::new("microgram", "ug", &[], Dimension::MASS, 1e-9);
pub const TONNE: BaseUnit = BaseUnit::new("tonne", "t", &["metric_ton"], Dimension::MASS, 1e3);
const DIM_FREQUENCY: Dimension = Dimension::TIME.inv();
const DIM_FORCE: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH)
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
const DIM_ENERGY: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH.pow(Rational16::new(2, 1)))
.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_PRESSURE: Dimension = Dimension::MASS
.mul(&Dimension::LENGTH.pow(Rational16::new(-1, 1)))
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
const DIM_VOLTAGE: Dimension = DIM_POWER.mul(&Dimension::CURRENT.pow(Rational16::new(-1, 1)));
const DIM_CAPACITANCE: Dimension = Dimension::CURRENT
.pow(Rational16::new(2, 1))
.mul(&Dimension::TIME.pow(Rational16::new(4, 1)))
.mul(&Dimension::MASS.pow(Rational16::new(-1, 1)))
.mul(&Dimension::LENGTH.pow(Rational16::new(-2, 1)));
const DIM_RESISTANCE: Dimension = DIM_POWER.mul(&Dimension::CURRENT.pow(Rational16::new(-2, 1)));
const DIM_CONDUCTANCE: Dimension = Dimension::CURRENT
.pow(Rational16::new(2, 1))
.mul(&Dimension::TIME.pow(Rational16::new(3, 1)))
.mul(&Dimension::MASS.pow(Rational16::new(-1, 1)))
.mul(&Dimension::LENGTH.pow(Rational16::new(-2, 1)));
const DIM_MAGNETIC_FLUX: Dimension =
DIM_ENERGY.mul(&Dimension::CURRENT.pow(Rational16::new(-1, 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_INDUCTANCE: Dimension = DIM_ENERGY.mul(&Dimension::CURRENT.pow(Rational16::new(-2, 1)));
const DIM_LUMINOUS_FLUX: Dimension = Dimension::LUMINOUS_INTENSITY.mul(&Dimension::SOLID_ANGLE);
const DIM_ILLUMINANCE: Dimension =
DIM_LUMINOUS_FLUX.mul(&Dimension::LENGTH.pow(Rational16::new(-2, 1)));
const DIM_DOSE: Dimension = Dimension::LENGTH
.pow(Rational16::new(2, 1))
.mul(&Dimension::TIME.pow(Rational16::new(-2, 1)));
const DIM_CHARGE: Dimension = Dimension::CURRENT.mul(&Dimension::TIME);
pub const HZ: BaseUnit = BaseUnit::new("hertz", "Hz", &[], DIM_FREQUENCY, 1.0);
pub const KHZ: BaseUnit = BaseUnit::new("kilohertz", "kHz", &[], DIM_FREQUENCY, 1e3);
pub const MHZ: BaseUnit = BaseUnit::new("megahertz", "MHz", &[], DIM_FREQUENCY, 1e6);
pub const GHZ: BaseUnit = BaseUnit::new("gigahertz", "GHz", &[], DIM_FREQUENCY, 1e9);
pub const THZ: BaseUnit = BaseUnit::new("terahertz", "THz", &[], DIM_FREQUENCY, 1e12);
pub const N: BaseUnit = BaseUnit::new("newton", "N", &[], DIM_FORCE, 1.0);
pub const J: BaseUnit = BaseUnit::new("joule", "J", &[], DIM_ENERGY, 1.0);
pub const EV: BaseUnit = BaseUnit::new("electronvolt", "eV", &[], DIM_ENERGY, 1.602_176_634e-19);
pub const KEV: BaseUnit = BaseUnit::new(
"kiloelectronvolt",
"keV",
&[],
DIM_ENERGY,
1.602_176_634e-16,
);
pub const MEV: BaseUnit = BaseUnit::new(
"megaelectronvolt",
"MeV",
&[],
DIM_ENERGY,
1.602_176_634e-13,
);
pub const GEV: BaseUnit = BaseUnit::new(
"gigaelectronvolt",
"GeV",
&[],
DIM_ENERGY,
1.602_176_634e-10,
);
pub const W: BaseUnit = BaseUnit::new("watt", "W", &[], DIM_POWER, 1.0);
pub const KW: BaseUnit = BaseUnit::new("kilowatt", "kW", &[], DIM_POWER, 1e3);
pub const MW: BaseUnit = BaseUnit::new("megawatt", "MW", &[], DIM_POWER, 1e6);
pub const PA: BaseUnit = BaseUnit::new("pascal", "Pa", &[], DIM_PRESSURE, 1.0);
pub const C: BaseUnit = BaseUnit::new("coulomb", "C", &[], DIM_CHARGE, 1.0);
pub const V: BaseUnit = BaseUnit::new("volt", "V", &[], DIM_VOLTAGE, 1.0);
pub const F: BaseUnit = BaseUnit::new("farad", "F", &[], DIM_CAPACITANCE, 1.0);
pub const OHM: BaseUnit = BaseUnit::new("ohm", "Ohm", &["ohm"], DIM_RESISTANCE, 1.0);
pub const SIEMENS: BaseUnit = BaseUnit::new("siemens", "S", &[], DIM_CONDUCTANCE, 1.0);
pub const WB: BaseUnit = BaseUnit::new("weber", "Wb", &[], DIM_MAGNETIC_FLUX, 1.0);
pub const T: BaseUnit = BaseUnit::new("tesla", "T", &[], DIM_MAGNETIC_FIELD, 1.0);
pub const HENRY: BaseUnit = BaseUnit::new("henry", "H", &[], DIM_INDUCTANCE, 1.0);
pub const LM: BaseUnit = BaseUnit::new("lumen", "lm", &[], DIM_LUMINOUS_FLUX, 1.0);
pub const LX: BaseUnit = BaseUnit::new("lux", "lx", &[], DIM_ILLUMINANCE, 1.0);
pub const BQ: BaseUnit = BaseUnit::new("becquerel", "Bq", &[], DIM_FREQUENCY, 1.0);
pub const GY: BaseUnit = BaseUnit::new("gray", "Gy", &[], DIM_DOSE, 1.0);
pub const SV: BaseUnit = BaseUnit::new("sievert", "Sv", &[], DIM_DOSE, 1.0);
pub const DEG: BaseUnit = BaseUnit::new(
"degree",
"deg",
&["degree"],
Dimension::ANGLE,
std::f64::consts::PI / 180.0,
);
pub const ARCMIN: BaseUnit = BaseUnit::new(
"arcminute",
"arcmin",
&["arcminute"],
Dimension::ANGLE,
std::f64::consts::PI / 180.0 / 60.0,
);
pub const ARCSEC: BaseUnit = BaseUnit::new(
"arcsecond",
"arcsec",
&["arcsecond"],
Dimension::ANGLE,
std::f64::consts::PI / 180.0 / 3600.0,
);
pub const MAS: BaseUnit = BaseUnit::new(
"milliarcsecond",
"mas",
&[],
Dimension::ANGLE,
std::f64::consts::PI / 180.0 / 3600.0 / 1000.0,
);
pub const UAS: BaseUnit = BaseUnit::new(
"microarcsecond",
"uas",
&[],
Dimension::ANGLE,
std::f64::consts::PI / 180.0 / 3600.0 / 1e6,
);
pub const HOURANGLE: BaseUnit = BaseUnit::new(
"hourangle",
"hourangle",
&[],
Dimension::ANGLE,
std::f64::consts::PI / 12.0,
);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_km_to_m() {
let q = 1.0 * KM;
let q_m = q.to(M).unwrap();
assert!((q_m.value() - 1000.0).abs() < 1e-10);
}
#[test]
fn test_hour_to_second() {
let q = 1.0 * H;
let q_s = q.to(S).unwrap();
assert!((q_s.value() - 3600.0).abs() < 1e-10);
}
#[test]
fn test_degree_to_radian() {
let q = 180.0 * DEG;
let q_rad = q.to(RAD).unwrap();
assert!((q_rad.value() - std::f64::consts::PI).abs() < 1e-10);
}
#[test]
fn test_energy_unit() {
let energy = 1.0 * J;
let dim = energy.unit().dimension();
assert_eq!(dim.mass, Rational16::ONE);
assert_eq!(dim.length, Rational16::new(2, 1));
assert_eq!(dim.time, Rational16::new(-2, 1));
}
}