use std::ops::{Add, Div, Mul, Sub};
macro_rules! define_unit {
($name:ident, $desc:expr) => {
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
#[doc = $desc]
pub struct $name(pub f64);
impl $name {
pub fn new(val: f64) -> Self {
Self(val)
}
pub fn value(&self) -> f64 {
self.0
}
}
impl Add for $name {
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub for $name {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Mul<f64> for $name {
type Output = Self;
fn mul(self, rhs: f64) -> Self {
Self(self.0 * rhs)
}
}
impl Mul<$name> for f64 {
type Output = $name;
fn mul(self, rhs: $name) -> $name {
$name(self * rhs.0)
}
}
impl Div<f64> for $name {
type Output = Self;
fn div(self, rhs: f64) -> Self {
Self(self.0 / rhs)
}
}
};
}
define_unit!(Mpc, "Distance in megaparsecs (Mpc).");
define_unit!(Gyr, "Time in gigayears (Gyr).");
define_unit!(Redshift, "Cosmological redshift z (dimensionless).");
define_unit!(ScaleFactor, "Scale factor a (dimensionless).");
define_unit!(KmPerSecMpc, "Hubble parameter in km/s/Mpc.");
impl From<Redshift> for ScaleFactor {
fn from(z: Redshift) -> Self {
ScaleFactor(1.0 / (1.0 + z.0))
}
}
impl From<ScaleFactor> for Redshift {
fn from(a: ScaleFactor) -> Self {
Redshift(1.0 / a.0 - 1.0)
}
}