lcdm-core 0.1.0

Core logical units and specifications for ΛCDM cosmology
Documentation
// lcdm-core/src/units.rs

//! Strongly typed units for cosmology to prevent mixing up quantities.

use std::ops::{Add, Div, Mul, Sub};

macro_rules! define_unit {
    ($name:ident, $desc:expr) => {
        /// Newtype wrapper around `f64` representing a strongly-typed cosmological quantity.
        #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
        #[doc = $desc]
        pub struct $name(pub f64);

        impl $name {
            /// Construct a new value of this unit type.
            pub fn new(val: f64) -> Self {
                Self(val)
            }

            /// Extract the underlying numeric value.
            pub fn value(&self) -> f64 {
                self.0
            }
        }

        // ---------------------------------------------------------------------
        // Basic arithmetic (same-unit operations)
        // ---------------------------------------------------------------------

        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)
            }
        }

        // ---------------------------------------------------------------------
        // Scalar multiplication / division
        // ---------------------------------------------------------------------

        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.");

// -----------------------------------------------------------------------------
// Conversions between redshift and scale factor
// -----------------------------------------------------------------------------

impl From<Redshift> for ScaleFactor {
    /// Convert redshift to scale factor via a = 1 / (1 + z).
    fn from(z: Redshift) -> Self {
        ScaleFactor(1.0 / (1.0 + z.0))
    }
}

impl From<ScaleFactor> for Redshift {
    /// Convert scale factor to redshift via z = 1 / a - 1.
    fn from(a: ScaleFactor) -> Self {
        Redshift(1.0 / a.0 - 1.0)
    }
}