Skip to main content

logicaffeine_base/
si.rs

1//! SI-dimensioned f64 newtypes — the characterized-descriptor surface types.
2//!
3//! Each type NAMES its unit and KNOWS its physical dimension, checked against the exact
4//! [`Dimension`] algebra (rational exponents included — `VoltsPerRootHz` is `V·Hz^(−1/2)`).
5//! The payload stays in the NAMED unit — `Nanoseconds(8.0)` is 8 ns, no hidden conversion —
6//! so flipping a bare `f64` field to its newtype never moves a pinned value, only the type.
7//! Payloads are plain `f64` because the certified engines stay outward-rounded f64; exact
8//! `Rational` arithmetic lives at unit-conversion boundaries (`quantity.rs`).
9
10use crate::dimension::Dimension;
11
12macro_rules! si_newtype {
13    ($(#[$doc:meta])* $name:ident, $dim:expr) => {
14        $(#[$doc])*
15        #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
16        pub struct $name(pub f64);
17
18        impl $name {
19            /// The exact physical dimension this type carries.
20            pub fn dimension() -> Dimension {
21                $dim
22            }
23        }
24    };
25}
26
27si_newtype!(
28    /// Volts — electric potential.
29    Volts,
30    Dimension::voltage()
31);
32si_newtype!(
33    /// Seconds — time.
34    Seconds,
35    Dimension::time()
36);
37si_newtype!(
38    /// Nanoseconds — time, payload in ns (the unit rides the NAME, not a hidden scale).
39    Nanoseconds,
40    Dimension::time()
41);
42si_newtype!(
43    /// Hertz — frequency (s⁻¹).
44    Hertz,
45    Dimension::frequency()
46);
47si_newtype!(
48    /// Siemens — conductance (Ω⁻¹), the transconductor's gm unit.
49    Siemens,
50    Dimension::conductance()
51);
52si_newtype!(
53    /// Kelvin — thermodynamic temperature.
54    Kelvin,
55    Dimension::temperature()
56);
57si_newtype!(
58    /// Watts — power, the thermal solver's injection unit.
59    Watts,
60    Dimension::power()
61);
62si_newtype!(
63    /// Per-kelvin — temperature coefficients (tempco), K⁻¹.
64    PerKelvin,
65    Dimension::temperature().recip()
66);
67si_newtype!(
68    /// Volts per root hertz — noise spectral density, the rational-exponent payoff:
69    /// `V·Hz^(−1/2)`.
70    VoltsPerRootHz,
71    Dimension::voltage().div(Dimension::frequency().nth_root(2))
72);