Kinds of quantity¶
A voltage gain (V/V), a current gain (A/A), a power gain (W/W) and a duty cycle are all plain numbers: dimension one. A resistance (Ω) and a transimpedance (V/A) have one dimension too. Yet adding a gain to a duty cycle is a bug.
A unit's kind is part of its type, next to its dimension. convert refuses to cross kinds.
graph TD
ONE["dimension one"] --> R["Ratio<br/>a duty, a probability"]
ONE --> VV["Per<Volt, Volt><br/>voltage gain, 20·lg"]
ONE --> AA["Per<Ampere, Ampere><br/>current gain, 20·lg"]
ONE --> WW["Per<Watt, Watt><br/>power gain, 10·lg"]
OHM["dimension of V/A"] --> O["Ohm<br/>resistance"]
OHM --> T["Per<Volt, Ampere><br/>transimpedance"]
The rules¶
- A unit is plain (only its dimension) unless its declaration names a kind (
Ohmis a resistance). - A quotient of one dimension keeps what cancelled: V/V is a ratio of voltages, not a plain
Ratio. - A dimension-one factor keeps the other side's kind: V/V · V is a plain V, and V/V · V/V is still a voltage gain.
- Any other product or quotient is plain: V/A is a transimpedance, not a resistance.
The rules follow ISO 80000-1's kinds of quantity, as the C++ library mp-units implements them.
What doesn't convert¶
use exact_units::{Fixed, prefix::One, units::{Per, Ratio, Volt}};
let gain: Fixed<Per<Volt, Volt>, One, f32> = Fixed::new(4.0);
let _ = gain.convert::<Ratio, One, f32>(); // a gain is not a duty cycle
use exact_units::{Fixed, prefix::Mega, units::{Ampere, Ohm, Per, Volt}};
let tia: Fixed<Per<Volt, Ampere>, Mega, f32> = Fixed::new(1.0);
let _ = tia.convert::<Ohm, Mega, f32>(); // a transimpedance is not a resistor
A scale still converts within a kind: mV/V to V/V is fine.
Crossing on purpose¶
Where crossing is right, it is a named step that keeps the number:
| From | Step | To |
|---|---|---|
| any dimension-one kind | as_ratio() |
Ratio |
Ratio |
as_gain::<Volt>() |
Per<Volt, Volt> |
Ohm |
as_transimpedance() |
Per<Volt, Ampere> |
Per<Volt, Ampere> |
as_resistance() |
Ohm |
Siemens |
as_transconductance() |
Per<Ampere, Volt> |
| a cycle count per second | to_hertz() |
Hertz |
use exact_units::{Fixed, prefix::{Mega, Micro, One}, units::{Ampere, Ohm, Per, Volt}};
// a transimpedance amplifier: its feedback resistor sets its V/A
let feedback = Fixed::<Ohm, Mega, f32>::new(1.0);
let tia: Fixed<Per<Volt, Ampere>, Mega, f32> = feedback.as_transimpedance();
// µA · MV/A is V
let photo = Fixed::<Ampere, Micro, f32>::new(0.3);
let out: Fixed<Volt, One, f32> = (tia * photo).convert().unwrap();
assert!((out.get() - 0.3).abs() < 1e-6);
Why it matters for levels¶
A gain's level in dB depends on its kind: \(20 \lg\) for V/V and A/A, \(10 \lg\) for W/W. A plain Ratio has no level at all, so 0.5 duty can't become −3 dB by accident. See Decibels.