electro 0.4.1
Type-safe electrical units library modeled after std::chrono
Loading...
Searching...
No Matches
decibel.hpp
Go to the documentation of this file.
1#pragma once
2
57#include <cassert>
58#include <cmath>
59#include <electro/electro.hpp>
60
61namespace electro {
62
63// ============================================================================
64// Gain: a dimensionless logarithmic ratio
65// ============================================================================
66
75 static constexpr const char* symbol = "dB";
76};
77
79template<typename Rep, typename Precision = std::ratio<1>>
81
88
89// ============================================================================
90// References
91// ============================================================================
92
106 using precision = std::milli;
107 static constexpr int factor = 10;
108 static constexpr const char* symbol = "dBm";
109};
110
114 using precision = std::ratio<1>;
115 static constexpr int factor = 10;
116 static constexpr const char* symbol = "dBW";
117};
118
122 using precision = std::ratio<1>;
123 static constexpr int factor = 20;
124 static constexpr const char* symbol = "dBV";
125};
126
130 using precision = std::milli;
131 static constexpr int factor = 20;
132 static constexpr const char* symbol = "dBmV";
133};
134
138 using precision = std::micro;
139 static constexpr int factor = 20;
140 static constexpr const char* symbol = "dBµV";
141};
142
// end of References group
144
152template<typename Reference>
153concept decibel_reference = requires {
154 typename Reference::unit;
155 typename Reference::precision;
156 { Reference::factor } -> std::convertible_to<int>;
157 { Reference::symbol } -> std::convertible_to<const char*>;
158} && (Reference::factor == 10 || Reference::factor == 20);
159
161template<typename Reference>
162inline constexpr bool is_power_reference_v = false;
163
164template<decibel_reference Reference>
165inline constexpr bool is_power_reference_v<Reference> = Reference::factor == 10;
166
168template<typename Reference>
169inline constexpr bool is_field_reference_v = false;
170
171template<decibel_reference Reference>
172inline constexpr bool is_field_reference_v<Reference> = Reference::factor == 20;
173
174// ============================================================================
175// level
176// ============================================================================
177
178template<typename Reference, typename Rep, typename Precision = std::ratio<1>>
179class level;
180
185template<typename T>
186struct is_level : std::false_type {};
187
188template<typename Reference, typename Rep, typename Precision>
189struct is_level<level<Reference, Rep, Precision>> : std::true_type {};
190
191template<typename T>
192inline constexpr bool is_level_v = is_level<T>::value;
193
211template<typename Reference, typename Rep, typename Precision>
212class level {
213 static_assert(decibel_reference<Reference>, "Reference must satisfy the decibel_reference concept");
214
215public:
217 using reference = Reference;
219 using rep = Rep;
221 using precision = typename Precision::type;
224
226 constexpr level() = default;
227 level(const level&) = default;
228
237 template<typename Rep2>
238 requires std::convertible_to<const Rep2&, rep> && (treat_as_inexact_v<rep> || !treat_as_inexact_v<Rep2>)
239 constexpr explicit level(const Rep2& r)
240 : _o(static_cast<rep>(r)) {}
241
243 constexpr explicit level(const offset& o)
244 : _o(o) {}
245
251 template<typename Rep2, typename Precision2>
252 requires std::convertible_to<gain<Rep2, Precision2>, offset>
255
257 template<typename Rep2, typename Precision2>
258 requires(!std::is_same_v<level, level<Reference, Rep2, Precision2>>) &&
259 (!std::convertible_to<gain<Rep2, Precision2>, offset>) &&
260 std::constructible_from<offset, gain<Rep2, Precision2>>
261 constexpr explicit level(const level<Reference, Rep2, Precision2>& l)
262 : _o(offset(l.offset_from_reference())) {}
263
264 ~level() = default;
265 level& operator=(const level&) = default;
266
268 constexpr offset offset_from_reference() const { return _o; }
269
271 constexpr rep count() const { return _o.count(); }
272
281 constexpr level operator-() const { return level(-_o); }
282 constexpr level operator+() const { return *this; }
283
284 constexpr level& operator+=(const offset& o) {
285 _o += o;
286 return *this;
287 }
288
289 constexpr level& operator-=(const offset& o) {
290 _o -= o;
291 return *this;
292 }
293
295 static constexpr level reference_level() noexcept { return level(offset::zero()); }
296
298 static constexpr level min() noexcept { return level(offset::min()); }
299
301 static constexpr level max() noexcept { return level(offset::max()); }
302
303private:
304 offset _o{};
305};
306
312template<typename ToLevel, typename Reference, typename Rep, typename Precision>
314 static_assert(
315 std::is_same_v<typename ToLevel::reference, Reference>, "level_cast cannot convert between different references"
316 );
317 return ToLevel(quantity_cast<typename ToLevel::offset>(l.offset_from_reference()));
318}
319
321template<typename ToLevel, typename Reference, typename Rep, typename Precision>
323 static_assert(std::is_same_v<typename ToLevel::reference, Reference>, "floor cannot convert between references");
324 return ToLevel(floor<typename ToLevel::offset>(l.offset_from_reference()));
325}
326
328template<typename ToLevel, typename Reference, typename Rep, typename Precision>
330 static_assert(std::is_same_v<typename ToLevel::reference, Reference>, "ceil cannot convert between references");
331 return ToLevel(ceil<typename ToLevel::offset>(l.offset_from_reference()));
332}
333
335template<typename ToLevel, typename Reference, typename Rep, typename Precision>
337 static_assert(std::is_same_v<typename ToLevel::reference, Reference>, "round cannot convert between references");
338 return ToLevel(round<typename ToLevel::offset>(l.offset_from_reference()));
339}
340
341// ============================================================================
342// Affine arithmetic: level +/- gain -> level, level - level -> gain
343// ============================================================================
344
346template<typename R1, typename P1, typename R2, typename P2>
347using _common_gain = std::common_type_t<gain<R1, P1>, gain<R2, P2>>;
351template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
352constexpr auto
358
360template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
361constexpr auto
365
367template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
368constexpr auto
374
382template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
384 return a.offset_from_reference() - b.offset_from_reference();
385}
386
387template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
389 return a.offset_from_reference() == b.offset_from_reference();
390}
391
392template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
393 requires std::three_way_comparable<std::common_type_t<Rep1, Rep2>>
395 return a.offset_from_reference() <=> b.offset_from_reference();
396}
397
398// ============================================================================
399// Linear domain conversions (not constexpr before C++26)
400// ============================================================================
401
403template<typename Offset>
404constexpr double _db_value(const Offset& o) {
405 return quantity_cast<gain<double>>(o).count();
406}
407
408// The inverse of _db_value, rounding to nearest for integral reps. This exists
409// because quantity_cast (and floor/ceil/round) truncate when converting from
410// an inexact rep, and truncation would round e.g. -73.5 dB the wrong way.
411template<typename Offset>
412inline Offset _db_offset(double db) {
415 } else {
416 using p = typename Offset::precision;
417 const double ticks = db * static_cast<double>(p::den) / static_cast<double>(p::num);
418 return Offset(static_cast<typename Offset::rep>(std::llround(ticks)));
419 }
420}
437template<typename Reference, typename Rep, typename Precision>
440 return linear(std::pow(10.0, _db_value(l.offset_from_reference()) / Reference::factor));
441}
442
461template<typename ToLevel, typename Unit, typename Rep, typename Precision>
463 using ref = typename ToLevel::reference;
464 static_assert(
465 std::is_same_v<typename ref::unit, Unit>, "to_level: quantity unit does not match the level reference"
466 );
467
469 const double ratio = quantity_cast<linear>(q).count();
470 if (!(ratio > 0.0)) {
471 assert(ratio >= 0.0 && "to_level: a negative quantity has no logarithmic level");
472 return ToLevel::min();
473 }
474 return ToLevel(_db_offset<typename ToLevel::offset>(ref::factor * std::log10(ratio)));
475}
476
486template<typename Rep, typename Precision>
488 return std::pow(10.0, _db_value(g) / 10.0);
489}
490
500template<typename Rep, typename Precision>
502 return std::pow(10.0, _db_value(g) / 20.0);
503}
504
507 assert(ratio > 0.0 && "power_gain: ratio must be positive");
508 return gain<double>(10.0 * std::log10(ratio));
509}
510
513 assert(ratio > 0.0 && "amplitude_gain: ratio must be positive");
514 return gain<double>(20.0 * std::log10(ratio));
515}
516
533template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
540
541// ============================================================================
542// Type aliases
543// ============================================================================
544
551template<typename Rep, typename Precision = std::ratio<1>>
553
555template<typename Rep, typename Precision = std::ratio<1>>
557
559template<typename Rep, typename Precision = std::ratio<1>>
561
563template<typename Rep, typename Precision = std::ratio<1>>
565
567template<typename Rep, typename Precision = std::ratio<1>>
569
584
// end of LevelTypes group
586
587// ============================================================================
588// String conversion and formatting
589// ============================================================================
590
606template<typename Precision>
608
610// The number of decimal places needed to render a count at the given precision
611// as a fixed-point decimal, or -1 when the precision is not 1, 1/10, 1/100, ...
612consteval int _decimal_places(intmax_t num, intmax_t den) {
613 if (num != 1) {
614 return -1;
615 }
616 int places = 0;
617 while (den % 10 == 0) {
618 den /= 10;
619 ++places;
620 }
621 return den == 1 ? places : -1;
622}
623
624template<typename Precision>
625inline constexpr bool _is_decimal_precision = _decimal_places(Precision::num, Precision::den) >= 0;
626
627// A count at the given precision, in decibels, as a double.
628template<typename Precision, typename Rep>
629constexpr double _db_double(const Rep& count) {
630 return static_cast<double>(count) * Precision::num / Precision::den;
631}
632
633// A count at the given precision rendered without a format spec, in decibels.
634// Integer counts are shown exactly with one decimal place per decade of
635// precision ("10.50"); floating-point counts in the shortest fixed notation
636// that round-trips (never scientific).
637template<typename Precision, typename Rep>
638inline std::string _format_db(const Rep& count) {
639 static_assert(_is_decimal_precision<Precision>, "precision cannot be rendered as a fixed-point decimal");
640 if constexpr (std::floating_point<Rep>) {
641 Rep value = count;
642 if constexpr (Precision::den != 1) {
643 value /= static_cast<Rep>(Precision::den);
644 }
645 return _fixed_string(value);
646 } else if constexpr (treat_as_inexact_v<Rep>) {
648 } else {
649 constexpr int places = _decimal_places(Precision::num, Precision::den);
650 if constexpr (places == 0) {
651 return std::to_string(count);
652 } else {
653 const bool negative = count < Rep(0);
654 // Compute the magnitude in unsigned arithmetic so that the most
655 // negative representable count does not overflow on negation.
656 const unsigned long long magnitude =
657 negative ? 0ULL - static_cast<unsigned long long>(count) : static_cast<unsigned long long>(count);
658
659 const unsigned long long whole = magnitude / Precision::den;
660 const unsigned long long frac = magnitude % Precision::den;
661
662 std::string frac_digits = std::to_string(frac);
663 frac_digits.insert(0, static_cast<size_t>(places) - frac_digits.size(), '0');
664
665 return (negative ? "-" : "") + std::to_string(whole) + "." + frac_digits;
666 }
667 }
668}
677template<typename Rep, typename Precision>
682
690template<typename Rep, typename Precision>
695
702template<typename Rep, typename Precision>
705 return to_string(g, base_unit);
706}
707
711template<typename Reference, typename Rep, typename Precision>
713inline std::string to_string(const level<Reference, Rep, Precision>& l) {
714 return _format_db<typename Precision::type>(l.count()) + Reference::symbol;
715}
716
724template<typename Reference, typename Rep, typename Precision>
727 return _fixed_string(_db_double<typename Precision::type>(l.count())) + Reference::symbol;
728}
729
736template<typename Reference, typename Rep, typename Precision>
739 return to_string(l, base_unit);
740}
741
742} // namespace electro
743
744namespace std {
745
746template<typename Reference, typename Rep1, typename Precision1, typename Rep2, typename Precision2>
747struct common_type<electro::level<Reference, Rep1, Precision1>, electro::level<Reference, Rep2, Precision2>> {
748private:
749 using common_offset = std::common_type_t<electro::gain<Rep1, Precision1>, electro::gain<Rep2, Precision2>>;
750
751public:
753};
754
755} // namespace std
756
757#if CONFIG_ELECTRO_STD_FORMAT
759namespace electro {
760
761// Shared formatter for gains and levels. "{}" renders the exact value as a
762// fixed-point decimal ("10.50dB"). A non-empty spec controls only how the
763// value (in decibels, as double) is rendered, never the unit:
764// std::format("{:.1f}", 1050_cdB) == "10.5dB". The 'b' and 's' markers are
765// accepted for consistency with the other quantities; decibels have no other
766// unit, so they render in the same unit, and with nothing after the marker
767// the value is rendered in the shortest fixed notation that round-trips:
768// std::format("{:b}", 1050_cdB) == "10.5dB".
769template<typename Precision>
770struct _db_formatter {
771private:
772 std::formatter<double> _num;
773 bool _has_spec = false;
774 bool _marker = false;
775
776public:
777 constexpr auto parse(std::format_parse_context& ctx) {
778 auto it = ctx.begin();
779 if (it != ctx.end() && (*it == 'b' || *it == 's')) {
780 _marker = true;
781 ctx.advance_to(++it);
782 }
783 if (it == ctx.end() || *it == '}') {
784 return it;
785 }
786 _has_spec = true;
787 return _num.parse(ctx);
788 }
789
790 template<typename Rep, typename FormatContext>
791 auto format(const Rep& count, const char* symbol, FormatContext& ctx) const {
792 auto out = ctx.out();
793 if (_has_spec) {
794 out = _num.format(_db_double<Precision>(count), ctx);
795 } else if (_marker) {
796 out = std::format_to(out, "{}", _fixed_string(_db_double<Precision>(count)));
797 } else {
798 out = std::format_to(out, "{}", _format_db<Precision>(count));
799 }
800 return _format_append(out, symbol);
801 }
802};
803
804} // namespace electro
807namespace std {
808
809// See electro::_db_formatter: "{}" -> "10.50dB", "{:.1f}" -> "10.5dB".
810template<typename Rep, typename Precision>
812struct formatter<electro::quantity<electro::decibel_unit, Rep, Precision>, char>
813 : electro::_db_formatter<typename Precision::type> {
814 template<typename FormatContext>
815 auto format(const electro::quantity<electro::decibel_unit, Rep, Precision>& g, FormatContext& ctx) const {
816 return electro::_db_formatter<typename Precision::type>::format(g.count(), electro::decibel_unit::symbol, ctx);
817 }
818};
819
820// See electro::_db_formatter; the level's reference symbol is appended
821// ("13.01dBm", "{:.1f}" -> "13.0dBm").
822template<typename Reference, typename Rep, typename Precision>
824struct formatter<electro::level<Reference, Rep, Precision>, char> : electro::_db_formatter<typename Precision::type> {
825 template<typename FormatContext>
826 auto format(const electro::level<Reference, Rep, Precision>& l, FormatContext& ctx) const {
827 return electro::_db_formatter<typename Precision::type>::format(l.count(), Reference::symbol, ctx);
828 }
829};
830
831} // namespace std
832#endif
833
835
837template<char... Digits>
838constexpr electro::decibels operator""_dB() {
839 return detail::check_overflow<electro::decibels, Digits...>();
840}
841
843template<char... Digits>
844constexpr electro::centidecibels operator""_cdB() {
845 return detail::check_overflow<electro::centidecibels, Digits...>();
846}
847
849template<char... Digits>
850constexpr electro::dbm operator""_dBm() {
851 return electro::dbm(detail::check_overflow<electro::decibels, Digits...>());
852}
853
855template<char... Digits>
856constexpr electro::centi_dbm operator""_cdBm() {
857 return electro::centi_dbm(detail::check_overflow<electro::centidecibels, Digits...>());
858}
859
861template<char... Digits>
862constexpr electro::dbw operator""_dBW() {
863 return electro::dbw(detail::check_overflow<electro::decibels, Digits...>());
864}
865
867template<char... Digits>
868constexpr electro::dbv operator""_dBV() {
869 return electro::dbv(detail::check_overflow<electro::decibels, Digits...>());
870}
871
873template<char... Digits>
874constexpr electro::dbmv operator""_dBmV() {
875 return electro::dbmv(detail::check_overflow<electro::decibels, Digits...>());
876}
877
879template<char... Digits>
880constexpr electro::dbuv operator""_dBuV() {
881 return electro::dbuv(detail::check_overflow<electro::decibels, Digits...>());
882}
883
884#if ELECTRO_HAS_UTF8_LITERALS
886template<char... Digits>
887constexpr electro::dbuv operator""_dBµV() {
888 return electro::dbuv(detail::check_overflow<electro::decibels, Digits...>());
889}
890#endif
891
892} // namespace electro_literals
An absolute point on a logarithmic scale, relative to a reference.
Definition decibel.hpp:212
level(const level &)=default
constexpr level & operator-=(const offset &o)
Definition decibel.hpp:289
constexpr level()=default
Constructs a level at the reference point (0 dB offset).
constexpr level(const Rep2 &r)
Constructs from an offset count in dB.
Definition decibel.hpp:239
gain< Rep, Precision > offset
The gain type measuring the offset from the reference.
Definition decibel.hpp:223
level & operator=(const level &)=default
~level()=default
Reference reference
The reference tag type.
Definition decibel.hpp:217
static constexpr level min() noexcept
Returns the minimum representable level.
Definition decibel.hpp:298
constexpr level operator+() const
Definition decibel.hpp:282
static constexpr level max() noexcept
Returns the maximum representable level.
Definition decibel.hpp:301
Rep rep
The representation type.
Definition decibel.hpp:219
static constexpr level reference_level() noexcept
Returns the reference point itself (a 0 dB offset).
Definition decibel.hpp:295
constexpr offset offset_from_reference() const
Returns the offset from the reference point.
Definition decibel.hpp:268
constexpr level & operator+=(const offset &o)
Definition decibel.hpp:284
constexpr level(const level< Reference, Rep2, Precision2 > &l)
Explicit constructor for lossy precision conversions.
Definition decibel.hpp:261
typename Precision::type precision
The offset precision, in dB, as a std::ratio.
Definition decibel.hpp:221
constexpr rep count() const
Returns the raw offset count, in units of Precision.
Definition decibel.hpp:271
constexpr level(const level< Reference, Rep2, Precision2 > &l)
Converts from a level with the same reference.
Definition decibel.hpp:253
constexpr level operator-() const
Reflects the level about its reference point.
Definition decibel.hpp:281
constexpr level(const offset &o)
Constructs from an offset relative to the reference.
Definition decibel.hpp:243
A quantity of an electrical unit with a representation and precision.
Definition electro.hpp:324
static constexpr quantity zero() noexcept
Returns a zero quantity.
Definition electro.hpp:448
static constexpr quantity max() noexcept
Returns the maximum representable quantity.
Definition electro.hpp:454
constexpr rep count() const
Returns the tick count.
Definition electro.hpp:389
static constexpr quantity min() noexcept
Returns the minimum representable quantity.
Definition electro.hpp:451
Concept for decibel reference tags.
Definition decibel.hpp:153
Electrical unit types and arithmetic, modeled after std::chrono.
dbw_level< int64_t > dbw
Power level in dBW, with 1 dB precision.
Definition decibel.hpp:575
dbm_level< int64_t > dbm
Power level in dBm, with 1 dB precision.
Definition decibel.hpp:571
dbmv_level< int64_t > dbmv
Voltage level in dBmV, with 1 dB precision.
Definition decibel.hpp:579
dbm_level< int64_t, std::centi > centi_dbm
Power level in dBm, with 0.01 dB precision.
Definition decibel.hpp:573
dbv_level< int64_t > dbv
Voltage level in dBV, with 1 dB precision.
Definition decibel.hpp:577
dbuv_level< int64_t > dbuv
Voltage level in dBµV, with 1 dB precision.
Definition decibel.hpp:581
User-defined literals for electrical quantity types.
Definition decibel.hpp:834
Electrical unit types and utilities.
Definition decibel.hpp:61
auto to_linear(const level< Reference, Rep, Precision > &l)
Converts a level to the equivalent linear quantity.
Definition decibel.hpp:438
gain< double > amplitude_gain(double ratio)
The gain corresponding to a linear amplitude ratio (20*log10(ratio)).
Definition decibel.hpp:512
auto add_powers(const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
Combines the powers of two uncorrelated signals.
Definition decibel.hpp:535
gain< double > power_gain(double ratio)
The gain corresponding to a linear power ratio (10*log10(ratio)).
Definition decibel.hpp:506
constexpr auto operator+(const level< Reference, Rep1, Precision1 > &l, const quantity< decibel_unit, Rep2, Precision2 > &g)
Applies a gain to a level.
Definition decibel.hpp:353
double amplitude_ratio(const quantity< decibel_unit, Rep, Precision > &g)
The linear amplitude ratio a gain represents (10^(dB/20)).
Definition decibel.hpp:501
constexpr auto operator-(const level< Reference, Rep1, Precision1 > &l, const quantity< decibel_unit, Rep2, Precision2 > &g)
Applies a loss to a level.
Definition decibel.hpp:369
gain< int64_t > decibels
Gain with 1 dB precision.
Definition decibel.hpp:83
constexpr auto operator<=>(const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
Definition decibel.hpp:394
constexpr bool is_field_reference_v
True if the reference measures a field quantity (20*log10).
Definition decibel.hpp:169
ToLevel to_level(const quantity< Unit, Rep, Precision > &q)
Converts a linear quantity to a level.
Definition decibel.hpp:462
constexpr bool is_field_reference_v< Reference >
Definition decibel.hpp:172
constexpr base_unit_t base_unit
Selects the base-unit form in to_string().
Definition electro.hpp:1444
constexpr ToLevel ceil(const level< Reference, Rep, Precision > &l)
Converts a level to the target type, rounding toward positive infinity.
Definition decibel.hpp:329
constexpr bool is_level_v
Definition decibel.hpp:192
constexpr bool is_power_reference_v< Reference >
Definition decibel.hpp:165
constexpr bool treat_as_inexact_v
Definition electro.hpp:200
gain< int64_t, std::centi > centidecibels
Gain with 0.01 dB precision.
Definition decibel.hpp:85
constexpr ToLevel round(const level< Reference, Rep, Precision > &l)
Converts a level to the target type, rounding to nearest (ties to even).
Definition decibel.hpp:336
constexpr bool is_power_reference_v
True if the reference measures a power quantity (10*log10).
Definition decibel.hpp:162
double power_ratio(const quantity< decibel_unit, Rep, Precision > &g)
The linear power ratio a gain represents (10^(dB/10)).
Definition decibel.hpp:487
constexpr ToLevel level_cast(const level< Reference, Rep, Precision > &l)
Converts a level to a different precision or representation.
Definition decibel.hpp:313
constexpr ToLevel floor(const level< Reference, Rep, Precision > &l)
Converts a level to the target type, rounding toward negative infinity.
Definition decibel.hpp:322
std::string to_string(const quantity< decibel_unit, Rep, Precision > &g)
Converts a gain to a string, e.g.
Definition decibel.hpp:679
constexpr bool operator==(const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
Definition decibel.hpp:388
Tag type selecting the base-unit form, see base_unit.
Definition electro.hpp:1424
A dimensionless logarithmic ratio, measured in decibels.
Definition decibel.hpp:74
static constexpr const char * symbol
Definition decibel.hpp:75
Trait to detect level specializations.
Definition decibel.hpp:186
Reference of 1 µV, for dBµV.
Definition decibel.hpp:136
static constexpr const char * symbol
Definition decibel.hpp:140
static constexpr int factor
Definition decibel.hpp:139
Reference of 1 mV, for dBmV.
Definition decibel.hpp:128
static constexpr int factor
Definition decibel.hpp:131
static constexpr const char * symbol
Definition decibel.hpp:132
Reference of 1 mW, for dBm.
Definition decibel.hpp:104
static constexpr int factor
Definition decibel.hpp:107
static constexpr const char * symbol
Definition decibel.hpp:108
Trait giving the display suffix for a (unit, precision) pair.
Definition electro.hpp:1208
Tag type selecting the scaled form, see scaled.
Definition electro.hpp:1449
Reference of 1 V, for dBV.
Definition decibel.hpp:120
static constexpr const char * symbol
Definition decibel.hpp:124
std::ratio< 1 > precision
Definition decibel.hpp:122
static constexpr int factor
Definition decibel.hpp:123
Voltage, measured in volts.
Definition electro.hpp:253
Reference of 1 W, for dBW.
Definition decibel.hpp:112
static constexpr const char * symbol
Definition decibel.hpp:116
static constexpr int factor
Definition decibel.hpp:115
std::ratio< 1 > precision
Definition decibel.hpp:114
Power, measured in watts.
Definition electro.hpp:268