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