#[cfg(test)]
mod test;
use super::{
Action, Amount, Area, Charge, Dimensionless, Energy, Entropy, Force, ForcePerLength, Length,
MolarEnergy, MolarEntropy, PowerPerLengthTemperature, Rate, ReciprocalAmount,
ReciprocalTemperature, Stress, StressPerLength, Temperature, Time, Velocity, Viscosity, Volume,
};
use crate::math::{Quantity, TensorRank0};
const ZERO_CELSIUS: TensorRank0 = 273.15;
pub type Scale<U> = fn(TensorRank0) -> Quantity<U>;
pub fn length_scale(label: &str) -> Option<Scale<Length>> {
Some(match label.trim().to_lowercase().as_str() {
"m" | "meter" | "meters" | "metre" | "metres" => Length::meters,
"mm" | "millimeter" | "millimeters" | "millimetre" | "millimetres" => Length::millimeters,
"cm" | "centimeter" | "centimeters" | "centimetre" | "centimetres" => Length::centimeters,
"um" | "\u{b5}m" | "\u{3bc}m" | "micrometer" | "micrometers" | "micrometre"
| "micrometres" | "micron" | "microns" => Length::micrometers,
"nm" | "nanometer" | "nanometers" | "nanometre" | "nanometres" => Length::nanometers,
"km" | "kilometer" | "kilometers" | "kilometre" | "kilometres" => Length::kilometers,
"in" | "inch" | "inches" => Length::inches,
"ft" | "foot" | "feet" => Length::feet,
_ => return None,
})
}
macro_rules! scales {
($($unit:ident { $($name:ident / $reader:ident = $factor:expr, $doc:expr),+ $(,)? })+) => {
$(
impl $unit {
$(
#[doc = concat!("A quantity of ", $doc, ".")]
pub const fn $name(value: TensorRank0) -> Quantity<$unit> {
Quantity::new(value * $factor)
}
)+
}
impl Quantity<$unit> {
$(
#[doc = concat!("How many ", $doc, " the quantity is.")]
pub const fn $reader(&self) -> TensorRank0 {
self.value() / $factor
}
)+
}
)+
};
}
scales!(
Length {
meters / in_meters = 1.0, "metres",
millimeters / in_millimeters = 1e-3, "millimetres",
micrometers / in_micrometers = 1e-6, "micrometres",
nanometers / in_nanometers = 1e-9, "nanometres",
centimeters / in_centimeters = 1e-2, "centimetres",
kilometers / in_kilometers = 1e3, "kilometres",
inches / in_inches = 2.54e-2, "inches",
feet / in_feet = 3.048e-1, "feet",
}
Area {
square_meters / in_square_meters = 1.0, "square metres",
square_millimeters / in_square_millimeters = 1e-6, "square millimetres",
square_centimeters / in_square_centimeters = 1e-4, "square centimetres",
}
Volume {
cubic_meters / in_cubic_meters = 1.0, "cubic metres",
cubic_millimeters / in_cubic_millimeters = 1e-9, "cubic millimetres",
cubic_centimeters / in_cubic_centimeters = 1e-6, "cubic centimetres",
liters / in_liters = 1e-3, "litres",
}
Time {
seconds / in_seconds = 1.0, "seconds",
milliseconds / in_milliseconds = 1e-3, "milliseconds",
microseconds / in_microseconds = 1e-6, "microseconds",
minutes / in_minutes = 6e1, "minutes",
hours / in_hours = 3.6e3, "hours",
}
Rate {
per_second / in_per_second = 1.0, "reciprocal seconds",
per_minute / in_per_minute = 1.0 / 6e1, "reciprocal minutes",
per_hour / in_per_hour = 1.0 / 3.6e3, "reciprocal hours",
hertz / in_hertz = 1.0, "hertz",
}
Stress {
pascals / in_pascals = 1.0, "pascals",
kilopascals / in_kilopascals = 1e3, "kilopascals",
megapascals / in_megapascals = 1e6, "megapascals",
gigapascals / in_gigapascals = 1e9, "gigapascals",
bars / in_bars = 1e5, "bars",
psi / in_psi = 6.894_757_293_168_361e3, "pounds per square inch",
ksi / in_ksi = 6.894_757_293_168_361e6, "kips per square inch",
}
Force {
newtons / in_newtons = 1.0, "newtons",
millinewtons / in_millinewtons = 1e-3, "millinewtons",
kilonewtons / in_kilonewtons = 1e3, "kilonewtons",
meganewtons / in_meganewtons = 1e6, "meganewtons",
pounds_force / in_pounds_force = 4.448_221_615_260_5, "pounds force",
}
Energy {
joules / in_joules = 1.0, "joules",
millijoules / in_millijoules = 1e-3, "millijoules",
kilojoules / in_kilojoules = 1e3, "kilojoules",
electronvolts / in_electronvolts = 1.602_176_634e-19, "electronvolts",
}
Entropy {
joules_per_kelvin / in_joules_per_kelvin = 1.0, "joules per kelvin",
}
Action {
joule_seconds / in_joule_seconds = 1.0, "joule seconds",
}
Amount {
moles / in_moles = 1.0, "moles",
millimoles / in_millimoles = 1e-3, "millimoles",
}
ReciprocalAmount {
per_mole / in_per_mole = 1.0, "reciprocal moles",
}
MolarEntropy {
joules_per_mole_kelvin / in_joules_per_mole_kelvin = 1.0, "joules per mole kelvin",
}
MolarEnergy {
joules_per_mole / in_joules_per_mole = 1.0, "joules per mole",
kilojoules_per_mole / in_kilojoules_per_mole = 1e3, "kilojoules per mole",
}
ForcePerLength {
newtons_per_meter / in_newtons_per_meter = 1.0, "newtons per metre",
piconewtons_per_nanometer / in_piconewtons_per_nanometer = 1e-3,
"piconewtons per nanometre",
}
Velocity {
meters_per_second / in_meters_per_second = 1.0, "metres per second",
millimeters_per_second / in_millimeters_per_second = 1e-3, "millimetres per second",
kilometers_per_hour / in_kilometers_per_hour = 1.0 / 3.6, "kilometres per hour",
}
Charge {
coulombs / in_coulombs = 1.0, "coulombs",
}
Viscosity {
pascal_seconds / in_pascal_seconds = 1.0, "pascal seconds",
poise / in_poise = 1e-1, "poise",
centipoise / in_centipoise = 1e-3, "centipoise",
}
Temperature {
kelvin / in_kelvin = 1.0, "kelvin",
}
ReciprocalTemperature {
per_kelvin / in_per_kelvin = 1.0, "reciprocal kelvin",
per_celsius / in_per_celsius = 1.0, "reciprocal degrees celsius",
}
StressPerLength {
pascals_per_meter / in_pascals_per_meter = 1.0, "pascals per metre",
megapascals_per_millimeter / in_megapascals_per_millimeter = 1e9,
"megapascals per millimetre",
}
PowerPerLengthTemperature {
watts_per_meter_kelvin / in_watts_per_meter_kelvin = 1.0, "watts per metre kelvin",
}
Dimensionless {
percent / in_percent = 1e-2, "percent",
}
);
impl Dimensionless {
pub const fn of(value: TensorRank0) -> Quantity<Dimensionless> {
Quantity::new(value)
}
}
impl Temperature {
pub const fn celsius(value: TensorRank0) -> Quantity<Temperature> {
Quantity::new(value + ZERO_CELSIUS)
}
pub const fn fahrenheit(value: TensorRank0) -> Quantity<Temperature> {
Quantity::new((value - 32.0) * 5.0 / 9.0 + ZERO_CELSIUS)
}
}
impl Quantity<Temperature> {
pub const fn in_celsius(&self) -> TensorRank0 {
self.value() - ZERO_CELSIUS
}
pub const fn in_fahrenheit(&self) -> TensorRank0 {
(self.value() - ZERO_CELSIUS) * 9.0 / 5.0 + 32.0
}
}