Skip to main content

space_units/quantities/
electromagnetic.rs

1use super::DisplayWithUnit;
2
3// -------------------------
4// Electric charge
5// -------------------------
6
7/// An electric charge quantity, stored internally in coulombs (C).
8///
9/// # Construction
10/// ```
11/// # use space_units::ElectricCharge;
12/// let q = ElectricCharge::from_mah(2500.0);
13/// ```
14///
15/// # Typed arithmetic
16/// - [`ElectricCharge`] / [`Time`](crate::Time) → [`ElectricCurrent`]
17/// - [`ElectricCharge`] / [`Voltage`] → [`Capacitance`]
18#[must_use]
19#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
20pub struct ElectricCharge(pub(crate) f64);
21
22/// Display/conversion units for [`ElectricCharge`].
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum ElectricChargeUnit {
25    /// Coulombs (C).
26    Coulomb,
27    /// Millicoulombs (mC).
28    MilliCoulomb,
29    /// Microcoulombs (uC).
30    MicroCoulomb,
31    /// Ampere-hours (Ah).
32    AmpereHour,
33    /// Milliampere-hours (mAh).
34    MilliAmpereHour,
35}
36
37impl ElectricChargeUnit {
38    const fn symbol(self) -> &'static str {
39        match self {
40            Self::Coulomb => "C",
41            Self::MilliCoulomb => "mC",
42            Self::MicroCoulomb => "uC",
43            Self::AmpereHour => "Ah",
44            Self::MilliAmpereHour => "mAh",
45        }
46    }
47
48    const fn coulombs_per_unit(self) -> f64 {
49        match self {
50            Self::Coulomb => 1.0,
51            Self::MilliCoulomb => 1e-3,
52            Self::MicroCoulomb => 1e-6,
53            Self::AmpereHour => 3_600.0,
54            Self::MilliAmpereHour => 3.6,
55        }
56    }
57}
58
59impl ElectricCharge {
60    /// Create from coulombs (canonical unit).
61    pub const fn from_c(val: f64) -> Self {
62        Self(val)
63    }
64
65    /// Create from millicoulombs. 1 mC = 1e-3 C.
66    pub const fn from_mc(val: f64) -> Self {
67        Self(val * 1e-3)
68    }
69
70    /// Create from microcoulombs. 1 uC = 1e-6 C.
71    pub const fn from_uc(val: f64) -> Self {
72        Self(val * 1e-6)
73    }
74
75    /// Create from ampere-hours. 1 Ah = 3600 C.
76    pub const fn from_ah(val: f64) -> Self {
77        Self(val * 3_600.0)
78    }
79
80    /// Create from milliampere-hours. 1 mAh = 3.6 C.
81    pub const fn from_mah(val: f64) -> Self {
82        Self(val * 3.6)
83    }
84
85    /// Get value in coulombs.
86    pub const fn in_c(self) -> f64 {
87        self.0
88    }
89
90    /// Get value in millicoulombs.
91    pub const fn in_mc(self) -> f64 {
92        self.0 / 1e-3
93    }
94
95    /// Get value in microcoulombs.
96    pub const fn in_uc(self) -> f64 {
97        self.0 / 1e-6
98    }
99
100    /// Get value in ampere-hours.
101    pub const fn in_ah(self) -> f64 {
102        self.0 / 3_600.0
103    }
104
105    /// Get value in milliampere-hours.
106    pub const fn in_mah(self) -> f64 {
107        self.0 / 3.6
108    }
109
110    /// Get value in the specified [`ElectricChargeUnit`].
111    pub fn in_unit(self, unit: ElectricChargeUnit) -> f64 {
112        self.0 / unit.coulombs_per_unit()
113    }
114
115    /// Return a display wrapper that formats this charge in the given unit.
116    pub fn display_as(self, unit: ElectricChargeUnit) -> DisplayWithUnit {
117        DisplayWithUnit {
118            value: self.in_unit(unit),
119            symbol: unit.symbol(),
120        }
121    }
122
123    /// Return the absolute value of this charge.
124    pub fn abs(self) -> Self {
125        Self(self.0.abs())
126    }
127}
128
129impl_quantity_display!(ElectricCharge, "C");
130
131impl_common_ops!(ElectricCharge);
132
133// -------------------------
134// Electric current
135// -------------------------
136
137/// An electric current quantity, stored internally in amperes (A).
138///
139/// # Construction
140/// ```
141/// # use space_units::ElectricCurrent;
142/// let i = ElectricCurrent::from_ma(500.0);
143/// ```
144///
145/// # Typed arithmetic
146/// - [`ElectricCurrent`] × [`Time`](crate::Time) → [`ElectricCharge`]
147#[must_use]
148#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
149pub struct ElectricCurrent(pub(crate) f64);
150
151/// Display/conversion units for [`ElectricCurrent`].
152#[derive(Debug, Clone, Copy, PartialEq, Eq)]
153pub enum ElectricCurrentUnit {
154    /// Amperes (A).
155    Ampere,
156    /// Milliamperes (mA).
157    MilliAmpere,
158    /// Microamperes (uA).
159    MicroAmpere,
160    /// Kiloamperes (kA).
161    KiloAmpere,
162}
163
164impl ElectricCurrentUnit {
165    const fn symbol(self) -> &'static str {
166        match self {
167            Self::Ampere => "A",
168            Self::MilliAmpere => "mA",
169            Self::MicroAmpere => "uA",
170            Self::KiloAmpere => "kA",
171        }
172    }
173
174    const fn amperes_per_unit(self) -> f64 {
175        match self {
176            Self::Ampere => 1.0,
177            Self::MilliAmpere => 1e-3,
178            Self::MicroAmpere => 1e-6,
179            Self::KiloAmpere => 1e3,
180        }
181    }
182}
183
184impl ElectricCurrent {
185    /// Create from amperes (canonical unit).
186    pub const fn from_a(val: f64) -> Self {
187        Self(val)
188    }
189
190    /// Create from milliamperes. 1 mA = 1e-3 A.
191    pub const fn from_ma(val: f64) -> Self {
192        Self(val * 1e-3)
193    }
194
195    /// Create from microamperes. 1 uA = 1e-6 A.
196    pub const fn from_ua(val: f64) -> Self {
197        Self(val * 1e-6)
198    }
199
200    /// Create from kiloamperes. 1 kA = 1e3 A.
201    pub const fn from_ka(val: f64) -> Self {
202        Self(val * 1e3)
203    }
204
205    /// Get value in amperes.
206    pub const fn in_a(self) -> f64 {
207        self.0
208    }
209
210    /// Get value in milliamperes.
211    pub const fn in_ma(self) -> f64 {
212        self.0 / 1e-3
213    }
214
215    /// Get value in microamperes.
216    pub const fn in_ua(self) -> f64 {
217        self.0 / 1e-6
218    }
219
220    /// Get value in kiloamperes.
221    pub const fn in_ka(self) -> f64 {
222        self.0 / 1e3
223    }
224
225    /// Get value in the specified [`ElectricCurrentUnit`].
226    pub fn in_unit(self, unit: ElectricCurrentUnit) -> f64 {
227        self.0 / unit.amperes_per_unit()
228    }
229
230    /// Return a display wrapper that formats this current in the given unit.
231    pub fn display_as(self, unit: ElectricCurrentUnit) -> DisplayWithUnit {
232        DisplayWithUnit {
233            value: self.in_unit(unit),
234            symbol: unit.symbol(),
235        }
236    }
237
238    /// Return the absolute value of this current.
239    pub fn abs(self) -> Self {
240        Self(self.0.abs())
241    }
242}
243
244impl_quantity_display!(ElectricCurrent, "A");
245
246impl_common_ops!(ElectricCurrent);
247
248// -------------------------
249// Voltage
250// -------------------------
251
252/// A voltage (electric potential difference) quantity, stored internally in volts (V).
253///
254/// # Construction
255/// ```
256/// # use space_units::Voltage;
257/// let v = Voltage::from_kv(3.3);
258/// ```
259///
260/// # Typed arithmetic
261/// - [`Voltage`] × [`ElectricCurrent`] → [`Power`](crate::Power)
262/// - [`Voltage`] / [`ElectricCurrent`] → [`Resistance`]
263#[must_use]
264#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
265pub struct Voltage(pub(crate) f64);
266
267/// Display/conversion units for [`Voltage`].
268#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269pub enum VoltageUnit {
270    /// Volts (V).
271    Volt,
272    /// Millivolts (mV).
273    MilliVolt,
274    /// Kilovolts (kV).
275    KiloVolt,
276    /// Megavolts (MV).
277    MegaVolt,
278}
279
280impl VoltageUnit {
281    const fn symbol(self) -> &'static str {
282        match self {
283            Self::Volt => "V",
284            Self::MilliVolt => "mV",
285            Self::KiloVolt => "kV",
286            Self::MegaVolt => "MV",
287        }
288    }
289
290    const fn volts_per_unit(self) -> f64 {
291        match self {
292            Self::Volt => 1.0,
293            Self::MilliVolt => 1e-3,
294            Self::KiloVolt => 1e3,
295            Self::MegaVolt => 1e6,
296        }
297    }
298}
299
300impl Voltage {
301    /// Create from volts (canonical unit).
302    pub const fn from_v(val: f64) -> Self {
303        Self(val)
304    }
305
306    /// Create from millivolts. 1 mV = 1e-3 V.
307    pub const fn from_mv(val: f64) -> Self {
308        Self(val * 1e-3)
309    }
310
311    /// Create from kilovolts. 1 kV = 1e3 V.
312    pub const fn from_kv(val: f64) -> Self {
313        Self(val * 1e3)
314    }
315
316    /// Create from megavolts. 1 MV = 1e6 V.
317    pub const fn from_megav(val: f64) -> Self {
318        Self(val * 1e6)
319    }
320
321    /// Get value in volts.
322    pub const fn in_v(self) -> f64 {
323        self.0
324    }
325
326    /// Get value in millivolts.
327    pub const fn in_mv(self) -> f64 {
328        self.0 / 1e-3
329    }
330
331    /// Get value in kilovolts.
332    pub const fn in_kv(self) -> f64 {
333        self.0 / 1e3
334    }
335
336    /// Get value in megavolts.
337    pub const fn in_megav(self) -> f64 {
338        self.0 / 1e6
339    }
340
341    /// Get value in the specified [`VoltageUnit`].
342    pub fn in_unit(self, unit: VoltageUnit) -> f64 {
343        self.0 / unit.volts_per_unit()
344    }
345
346    /// Return a display wrapper that formats this voltage in the given unit.
347    pub fn display_as(self, unit: VoltageUnit) -> DisplayWithUnit {
348        DisplayWithUnit {
349            value: self.in_unit(unit),
350            symbol: unit.symbol(),
351        }
352    }
353
354    /// Return the absolute value of this voltage.
355    pub fn abs(self) -> Self {
356        Self(self.0.abs())
357    }
358}
359
360impl_quantity_display!(Voltage, "V");
361
362impl_common_ops!(Voltage);
363
364// -------------------------
365// Resistance
366// -------------------------
367
368/// An electrical resistance quantity, stored internally in ohms (Ohm).
369///
370/// # Construction
371/// ```
372/// # use space_units::Resistance;
373/// let r = Resistance::from_kohm(4.7);
374/// ```
375///
376/// # Typed arithmetic
377/// - [`Resistance`] × [`ElectricCurrent`] → [`Voltage`]
378#[must_use]
379#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
380pub struct Resistance(pub(crate) f64);
381
382/// Display/conversion units for [`Resistance`].
383#[derive(Debug, Clone, Copy, PartialEq, Eq)]
384pub enum ResistanceUnit {
385    /// Ohms (Ohm).
386    Ohm,
387    /// Milliohms (mOhm).
388    MilliOhm,
389    /// Kilohms (kOhm).
390    KiloOhm,
391    /// Megaohms (`MOhm`).
392    MegaOhm,
393}
394
395impl ResistanceUnit {
396    const fn symbol(self) -> &'static str {
397        match self {
398            Self::Ohm => "Ohm",
399            Self::MilliOhm => "mOhm",
400            Self::KiloOhm => "kOhm",
401            Self::MegaOhm => "MOhm",
402        }
403    }
404
405    const fn ohms_per_unit(self) -> f64 {
406        match self {
407            Self::Ohm => 1.0,
408            Self::MilliOhm => 1e-3,
409            Self::KiloOhm => 1e3,
410            Self::MegaOhm => 1e6,
411        }
412    }
413}
414
415impl Resistance {
416    /// Create from ohms (canonical unit).
417    pub const fn from_ohm(val: f64) -> Self {
418        Self(val)
419    }
420
421    /// Create from milliohms. 1 mOhm = 1e-3 Ohm.
422    pub const fn from_mohm(val: f64) -> Self {
423        Self(val * 1e-3)
424    }
425
426    /// Create from kilohms. 1 kOhm = 1e3 Ohm.
427    pub const fn from_kohm(val: f64) -> Self {
428        Self(val * 1e3)
429    }
430
431    /// Create from megaohms. 1 `MOhm` = 1e6 Ohm.
432    pub const fn from_megaohm(val: f64) -> Self {
433        Self(val * 1e6)
434    }
435
436    /// Get value in ohms.
437    pub const fn in_ohm(self) -> f64 {
438        self.0
439    }
440
441    /// Get value in milliohms.
442    pub const fn in_mohm(self) -> f64 {
443        self.0 / 1e-3
444    }
445
446    /// Get value in kilohms.
447    pub const fn in_kohm(self) -> f64 {
448        self.0 / 1e3
449    }
450
451    /// Get value in megaohms.
452    pub const fn in_megaohm(self) -> f64 {
453        self.0 / 1e6
454    }
455
456    /// Get value in the specified [`ResistanceUnit`].
457    pub fn in_unit(self, unit: ResistanceUnit) -> f64 {
458        self.0 / unit.ohms_per_unit()
459    }
460
461    /// Return a display wrapper that formats this resistance in the given unit.
462    pub fn display_as(self, unit: ResistanceUnit) -> DisplayWithUnit {
463        DisplayWithUnit {
464            value: self.in_unit(unit),
465            symbol: unit.symbol(),
466        }
467    }
468
469    /// Return the absolute value of this resistance.
470    pub fn abs(self) -> Self {
471        Self(self.0.abs())
472    }
473}
474
475impl_quantity_display!(Resistance, "Ω");
476
477impl_common_ops!(Resistance);
478
479// -------------------------
480// Magnetic flux density
481// -------------------------
482
483/// A magnetic flux density quantity, stored internally in tesla (T).
484///
485/// # Construction
486/// ```
487/// # use space_units::MagneticFluxDensity;
488/// let b = MagneticFluxDensity::from_gauss(0.5);
489/// ```
490///
491/// # Typed arithmetic
492/// - [`MagneticFluxDensity`] × [`Area`](crate::Area) → [`MagneticFlux`]
493#[must_use]
494#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
495pub struct MagneticFluxDensity(pub(crate) f64);
496
497/// Display/conversion units for [`MagneticFluxDensity`].
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
499pub enum MagneticFluxDensityUnit {
500    /// Tesla (T).
501    Tesla,
502    /// Millitesla (mT).
503    MilliTesla,
504    /// Microtesla (uT).
505    MicroTesla,
506    /// Nanotesla (nT).
507    NanoTesla,
508    /// Gauss (G). 1 G = 1e-4 T.
509    Gauss,
510}
511
512impl MagneticFluxDensityUnit {
513    const fn symbol(self) -> &'static str {
514        match self {
515            Self::Tesla => "T",
516            Self::MilliTesla => "mT",
517            Self::MicroTesla => "uT",
518            Self::NanoTesla => "nT",
519            Self::Gauss => "G",
520        }
521    }
522
523    const fn tesla_per_unit(self) -> f64 {
524        match self {
525            Self::Tesla => 1.0,
526            Self::MilliTesla => 1e-3,
527            Self::MicroTesla => 1e-6,
528            Self::NanoTesla => 1e-9,
529            Self::Gauss => 1e-4,
530        }
531    }
532}
533
534impl MagneticFluxDensity {
535    /// Create from tesla (canonical unit).
536    pub const fn from_t(val: f64) -> Self {
537        Self(val)
538    }
539
540    /// Create from millitesla. 1 mT = 1e-3 T.
541    pub const fn from_mt(val: f64) -> Self {
542        Self(val * 1e-3)
543    }
544
545    /// Create from microtesla. 1 uT = 1e-6 T.
546    pub const fn from_ut(val: f64) -> Self {
547        Self(val * 1e-6)
548    }
549
550    /// Create from nanotesla. 1 nT = 1e-9 T.
551    pub const fn from_nt(val: f64) -> Self {
552        Self(val * 1e-9)
553    }
554
555    /// Create from gauss. 1 G = 1e-4 T.
556    pub const fn from_gauss(val: f64) -> Self {
557        Self(val * 1e-4)
558    }
559
560    /// Get value in tesla.
561    pub const fn in_t(self) -> f64 {
562        self.0
563    }
564
565    /// Get value in millitesla.
566    pub const fn in_mt(self) -> f64 {
567        self.0 / 1e-3
568    }
569
570    /// Get value in microtesla.
571    pub const fn in_ut(self) -> f64 {
572        self.0 / 1e-6
573    }
574
575    /// Get value in nanotesla.
576    pub const fn in_nt(self) -> f64 {
577        self.0 / 1e-9
578    }
579
580    /// Get value in gauss.
581    pub const fn in_gauss(self) -> f64 {
582        self.0 / 1e-4
583    }
584
585    /// Get value in the specified [`MagneticFluxDensityUnit`].
586    pub fn in_unit(self, unit: MagneticFluxDensityUnit) -> f64 {
587        self.0 / unit.tesla_per_unit()
588    }
589
590    /// Return a display wrapper that formats this flux density in the given unit.
591    pub fn display_as(self, unit: MagneticFluxDensityUnit) -> DisplayWithUnit {
592        DisplayWithUnit {
593            value: self.in_unit(unit),
594            symbol: unit.symbol(),
595        }
596    }
597
598    /// Return the absolute value of this magnetic flux density.
599    pub fn abs(self) -> Self {
600        Self(self.0.abs())
601    }
602}
603
604impl_quantity_display!(MagneticFluxDensity, "T");
605
606impl_common_ops!(MagneticFluxDensity);
607
608// -------------------------
609// Magnetic flux
610// -------------------------
611
612/// A magnetic flux quantity, stored internally in webers (Wb).
613///
614/// # Construction
615/// ```
616/// # use space_units::MagneticFlux;
617/// let phi = MagneticFlux::from_mwb(12.0);
618/// ```
619///
620/// # Typed arithmetic
621/// - [`MagneticFlux`] / [`Area`](crate::Area) → [`MagneticFluxDensity`]
622/// - [`MagneticFlux`] / [`ElectricCurrent`] → [`Inductance`]
623#[must_use]
624#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
625pub struct MagneticFlux(pub(crate) f64);
626
627/// Display/conversion units for [`MagneticFlux`].
628#[derive(Debug, Clone, Copy, PartialEq, Eq)]
629pub enum MagneticFluxUnit {
630    /// Webers (Wb).
631    Weber,
632    /// Milliwebers (mWb).
633    MilliWeber,
634    /// Microwebers (uWb).
635    MicroWeber,
636}
637
638impl MagneticFluxUnit {
639    const fn symbol(self) -> &'static str {
640        match self {
641            Self::Weber => "Wb",
642            Self::MilliWeber => "mWb",
643            Self::MicroWeber => "uWb",
644        }
645    }
646
647    const fn webers_per_unit(self) -> f64 {
648        match self {
649            Self::Weber => 1.0,
650            Self::MilliWeber => 1e-3,
651            Self::MicroWeber => 1e-6,
652        }
653    }
654}
655
656impl MagneticFlux {
657    /// Create from webers (canonical unit).
658    pub const fn from_wb(val: f64) -> Self {
659        Self(val)
660    }
661
662    /// Create from milliwebers. 1 mWb = 1e-3 Wb.
663    pub const fn from_mwb(val: f64) -> Self {
664        Self(val * 1e-3)
665    }
666
667    /// Create from microwebers. 1 uWb = 1e-6 Wb.
668    pub const fn from_uwb(val: f64) -> Self {
669        Self(val * 1e-6)
670    }
671
672    /// Get value in webers.
673    pub const fn in_wb(self) -> f64 {
674        self.0
675    }
676
677    /// Get value in milliwebers.
678    pub const fn in_mwb(self) -> f64 {
679        self.0 / 1e-3
680    }
681
682    /// Get value in microwebers.
683    pub const fn in_uwb(self) -> f64 {
684        self.0 / 1e-6
685    }
686
687    /// Get value in the specified [`MagneticFluxUnit`].
688    pub fn in_unit(self, unit: MagneticFluxUnit) -> f64 {
689        self.0 / unit.webers_per_unit()
690    }
691
692    /// Return a display wrapper that formats this flux in the given unit.
693    pub fn display_as(self, unit: MagneticFluxUnit) -> DisplayWithUnit {
694        DisplayWithUnit {
695            value: self.in_unit(unit),
696            symbol: unit.symbol(),
697        }
698    }
699
700    /// Return the absolute value of this magnetic flux.
701    pub fn abs(self) -> Self {
702        Self(self.0.abs())
703    }
704}
705
706impl_quantity_display!(MagneticFlux, "Wb");
707
708impl_common_ops!(MagneticFlux);
709
710// -------------------------
711// Capacitance
712// -------------------------
713
714/// A capacitance quantity, stored internally in farads (F).
715///
716/// # Construction
717/// ```
718/// # use space_units::Capacitance;
719/// let c = Capacitance::from_uf(100.0);
720/// ```
721///
722/// # Typed arithmetic
723/// - [`Capacitance`] × [`Voltage`] → [`ElectricCharge`]
724#[must_use]
725#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
726pub struct Capacitance(pub(crate) f64);
727
728/// Display/conversion units for [`Capacitance`].
729#[derive(Debug, Clone, Copy, PartialEq, Eq)]
730pub enum CapacitanceUnit {
731    /// Farads (F).
732    Farad,
733    /// Millifarads (mF).
734    MilliFarad,
735    /// Microfarads (uF).
736    MicroFarad,
737    /// Nanofarads (nF).
738    NanoFarad,
739    /// Picofarads (pF).
740    PicoFarad,
741}
742
743impl CapacitanceUnit {
744    const fn symbol(self) -> &'static str {
745        match self {
746            Self::Farad => "F",
747            Self::MilliFarad => "mF",
748            Self::MicroFarad => "uF",
749            Self::NanoFarad => "nF",
750            Self::PicoFarad => "pF",
751        }
752    }
753
754    const fn farads_per_unit(self) -> f64 {
755        match self {
756            Self::Farad => 1.0,
757            Self::MilliFarad => 1e-3,
758            Self::MicroFarad => 1e-6,
759            Self::NanoFarad => 1e-9,
760            Self::PicoFarad => 1e-12,
761        }
762    }
763}
764
765impl Capacitance {
766    /// Create from farads (canonical unit).
767    pub const fn from_f(val: f64) -> Self {
768        Self(val)
769    }
770
771    /// Create from millifarads. 1 mF = 1e-3 F.
772    pub const fn from_mf(val: f64) -> Self {
773        Self(val * 1e-3)
774    }
775
776    /// Create from microfarads. 1 uF = 1e-6 F.
777    pub const fn from_uf(val: f64) -> Self {
778        Self(val * 1e-6)
779    }
780
781    /// Create from nanofarads. 1 nF = 1e-9 F.
782    pub const fn from_nf(val: f64) -> Self {
783        Self(val * 1e-9)
784    }
785
786    /// Create from picofarads. 1 pF = 1e-12 F.
787    pub const fn from_pf(val: f64) -> Self {
788        Self(val * 1e-12)
789    }
790
791    /// Get value in farads.
792    pub const fn in_f(self) -> f64 {
793        self.0
794    }
795
796    /// Get value in millifarads.
797    pub const fn in_mf(self) -> f64 {
798        self.0 / 1e-3
799    }
800
801    /// Get value in microfarads.
802    pub const fn in_uf(self) -> f64 {
803        self.0 / 1e-6
804    }
805
806    /// Get value in nanofarads.
807    pub const fn in_nf(self) -> f64 {
808        self.0 / 1e-9
809    }
810
811    /// Get value in picofarads.
812    pub const fn in_pf(self) -> f64 {
813        self.0 / 1e-12
814    }
815
816    /// Get value in the specified [`CapacitanceUnit`].
817    pub fn in_unit(self, unit: CapacitanceUnit) -> f64 {
818        self.0 / unit.farads_per_unit()
819    }
820
821    /// Return a display wrapper that formats this capacitance in the given unit.
822    pub fn display_as(self, unit: CapacitanceUnit) -> DisplayWithUnit {
823        DisplayWithUnit {
824            value: self.in_unit(unit),
825            symbol: unit.symbol(),
826        }
827    }
828
829    /// Return the absolute value of this capacitance.
830    pub fn abs(self) -> Self {
831        Self(self.0.abs())
832    }
833}
834
835impl_quantity_display!(Capacitance, "F");
836
837impl_common_ops!(Capacitance);
838
839// -------------------------
840// Inductance
841// -------------------------
842
843/// An inductance quantity, stored internally in henrys (H).
844///
845/// # Construction
846/// ```
847/// # use space_units::Inductance;
848/// let l = Inductance::from_mh(10.0);
849/// ```
850///
851/// # Typed arithmetic
852/// - [`Inductance`] × [`ElectricCurrent`] → [`MagneticFlux`]
853#[must_use]
854#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
855pub struct Inductance(pub(crate) f64);
856
857/// Display/conversion units for [`Inductance`].
858#[derive(Debug, Clone, Copy, PartialEq, Eq)]
859pub enum InductanceUnit {
860    /// Henrys (H).
861    Henry,
862    /// Millihenrys (mH).
863    MilliHenry,
864    /// Microhenrys (uH).
865    MicroHenry,
866    /// Nanohenrys (nH).
867    NanoHenry,
868}
869
870impl InductanceUnit {
871    const fn symbol(self) -> &'static str {
872        match self {
873            Self::Henry => "H",
874            Self::MilliHenry => "mH",
875            Self::MicroHenry => "uH",
876            Self::NanoHenry => "nH",
877        }
878    }
879
880    const fn henrys_per_unit(self) -> f64 {
881        match self {
882            Self::Henry => 1.0,
883            Self::MilliHenry => 1e-3,
884            Self::MicroHenry => 1e-6,
885            Self::NanoHenry => 1e-9,
886        }
887    }
888}
889
890impl Inductance {
891    /// Create from henrys (canonical unit).
892    pub const fn from_h(val: f64) -> Self {
893        Self(val)
894    }
895
896    /// Create from millihenrys. 1 mH = 1e-3 H.
897    pub const fn from_mh(val: f64) -> Self {
898        Self(val * 1e-3)
899    }
900
901    /// Create from microhenrys. 1 uH = 1e-6 H.
902    pub const fn from_uh(val: f64) -> Self {
903        Self(val * 1e-6)
904    }
905
906    /// Create from nanohenrys. 1 nH = 1e-9 H.
907    pub const fn from_nh(val: f64) -> Self {
908        Self(val * 1e-9)
909    }
910
911    /// Get value in henrys.
912    pub const fn in_h(self) -> f64 {
913        self.0
914    }
915
916    /// Get value in millihenrys.
917    pub const fn in_mh(self) -> f64 {
918        self.0 / 1e-3
919    }
920
921    /// Get value in microhenrys.
922    pub const fn in_uh(self) -> f64 {
923        self.0 / 1e-6
924    }
925
926    /// Get value in nanohenrys.
927    pub const fn in_nh(self) -> f64 {
928        self.0 / 1e-9
929    }
930
931    /// Get value in the specified [`InductanceUnit`].
932    pub fn in_unit(self, unit: InductanceUnit) -> f64 {
933        self.0 / unit.henrys_per_unit()
934    }
935
936    /// Return a display wrapper that formats this inductance in the given unit.
937    pub fn display_as(self, unit: InductanceUnit) -> DisplayWithUnit {
938        DisplayWithUnit {
939            value: self.in_unit(unit),
940            symbol: unit.symbol(),
941        }
942    }
943
944    /// Return the absolute value of this inductance.
945    pub fn abs(self) -> Self {
946        Self(self.0.abs())
947    }
948}
949
950impl_quantity_display!(Inductance, "H");
951
952impl_common_ops!(Inductance);