quanta 0.1.0
Type-safe units for temperature, frequency, electrical and spatial quantities, modeled after std::chrono
Loading...
Searching...
No Matches
decibel.hpp File Reference

Logarithmic ratios (dB) and absolute levels (dBm, dBW, dBµV, ...). More...

#include <cassert>
#include <cmath>
#include <quanta/electro.hpp>

Go to the source code of this file.

Classes

struct  quanta::electro::decibel_unit
 A dimensionless logarithmic ratio, measured in decibels. More...
 
struct  quanta::electro::milliwatt_reference
 Reference of 1 mW, for dBm. More...
 
struct  quanta::electro::watt_reference
 Reference of 1 W, for dBW. More...
 
struct  quanta::electro::volt_reference
 Reference of 1 V, for dBV. More...
 
struct  quanta::electro::millivolt_reference
 Reference of 1 mV, for dBmV. More...
 
struct  quanta::electro::microvolt_reference
 Reference of 1 µV, for dBµV. More...
 
struct  quanta::electro::is_level< T >
 Trait to detect level specializations. More...
 
struct  quanta::electro::is_level< level< Reference, Rep, Precision > >
 
class  quanta::electro::level< Reference, Rep, Precision >
 An absolute point on a logarithmic scale, relative to a reference. More...
 
struct  quanta::electro::quantity_suffix< decibel_unit, Precision >
 Decibels opt out of the generic SI-prefix suffix machinery. More...
 

Namespaces

namespace  quanta
 Type-safe units modeled after std::chrono.
 
namespace  quanta::electro
 Electrical unit types and utilities.
 
namespace  std
 
namespace  quanta::literals
 
namespace  quanta::literals::electro_literals
 

Concepts

concept  quanta::electro::decibel_reference
 Concept for decibel reference tags.
 

Typedefs

template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::gain = quantity< decibel_unit, Rep, Precision >
 A logarithmic ratio with configurable representation and precision.
 
using quanta::electro::decibels = gain< int64_t >
 Gain with 1 dB precision.
 
using quanta::electro::centidecibels = gain< int64_t, std::centi >
 Gain with 0.01 dB precision.
 
using quanta::electro::millidecibels = gain< int64_t, std::milli >
 Gain with 0.001 dB precision.
 
template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::dbm_level = level< milliwatt_reference, Rep, Precision >
 A level referenced to 1 mW.
 
template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::dbw_level = level< watt_reference, Rep, Precision >
 A level referenced to 1 W.
 
template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::dbv_level = level< volt_reference, Rep, Precision >
 A level referenced to 1 V.
 
template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::dbmv_level = level< millivolt_reference, Rep, Precision >
 A level referenced to 1 mV.
 
template<typename Rep , typename Precision = std::ratio<1>>
using quanta::electro::dbuv_level = level< microvolt_reference, Rep, Precision >
 A level referenced to 1 µV.
 
using quanta::electro::dbm = dbm_level< int64_t >
 Power level in dBm, with 1 dB precision.
 
using quanta::electro::centi_dbm = dbm_level< int64_t, std::centi >
 Power level in dBm, with 0.01 dB precision.
 
using quanta::electro::dbw = dbw_level< int64_t >
 Power level in dBW, with 1 dB precision.
 
using quanta::electro::dbv = dbv_level< int64_t >
 Voltage level in dBV, with 1 dB precision.
 
using quanta::electro::dbmv = dbmv_level< int64_t >
 Voltage level in dBmV, with 1 dB precision.
 
using quanta::electro::dbuv = dbuv_level< int64_t >
 Voltage level in dBµV, with 1 dB precision.
 
using quanta::electro::centi_dbuv = dbuv_level< int64_t, std::centi >
 Voltage level in dBµV, with 0.01 dB precision.
 

Functions

template<typename ToLevel , typename Reference , typename Rep , typename Precision >
requires (!std::is_same_v<typename ToLevel::reference, Reference>) || detail::_quantity_cast_requirements<gain<Rep, Precision>, typename ToLevel::offset>
constexpr ToLevel quanta::electro::level_cast (const level< Reference, Rep, Precision > &l)
 Converts a level to a different precision or representation.
 
template<typename ToLevel , typename Reference , typename Rep , typename Precision >
constexpr ToLevel quanta::electro::floor (const level< Reference, Rep, Precision > &l)
 Converts a level to the target type, rounding toward negative infinity.
 
template<typename ToLevel , typename Reference , typename Rep , typename Precision >
constexpr ToLevel quanta::electro::ceil (const level< Reference, Rep, Precision > &l)
 Converts a level to the target type, rounding toward positive infinity.
 
template<typename ToLevel , typename Reference , typename Rep , typename Precision >
constexpr ToLevel quanta::electro::trunc (const level< Reference, Rep, Precision > &l)
 Converts a level to the target type, rounding toward zero (as level_cast does).
 
template<typename ToLevel , typename Reference , typename Rep , typename Precision >
constexpr ToLevel quanta::electro::round (const level< Reference, Rep, Precision > &l)
 Converts a level to the target type, rounding to nearest (ties to even).
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
constexpr auto quanta::electro::operator+ (const level< Reference, Rep1, Precision1 > &l, const quantity< decibel_unit, Rep2, Precision2 > &g)
 Applies a gain to a level.
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
constexpr auto quanta::electro::operator+ (const quantity< decibel_unit, Rep2, Precision2 > &g, const level< Reference, Rep1, Precision1 > &l)
 Applies a gain to a level.
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
constexpr auto quanta::electro::operator- (const level< Reference, Rep1, Precision1 > &l, const quantity< decibel_unit, Rep2, Precision2 > &g)
 Applies a loss to a level.
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
constexpr auto quanta::electro::operator- (const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
 The difference between two levels is a gain.
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
constexpr bool quanta::electro::operator== (const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
requires std::three_way_comparable<std::common_type_t<Rep1, Rep2>>
constexpr auto quanta::electro::operator<=> (const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
 
template<typename Reference , typename Rep , typename Precision >
auto quanta::electro::to_linear (const level< Reference, Rep, Precision > &l)
 Converts a level to the equivalent linear quantity.
 
template<typename ToLevel , typename Unit , typename Rep , typename Precision >
ToLevel quanta::electro::to_level (const quantity< Unit, Rep, Precision > &q)
 Converts a linear quantity to a level.
 
template<typename Rep , typename Precision >
double quanta::electro::power_ratio (const quantity< decibel_unit, Rep, Precision > &g)
 The linear power ratio a gain represents (10^(dB/10)).
 
template<typename Rep , typename Precision >
double quanta::electro::amplitude_ratio (const quantity< decibel_unit, Rep, Precision > &g)
 The linear amplitude ratio a gain represents (10^(dB/20)).
 
gain< double > quanta::electro::power_gain (double ratio)
 The gain corresponding to a linear power ratio (10*log10(ratio)).
 
gain< double > quanta::electro::amplitude_gain (double ratio)
 The gain corresponding to a linear amplitude ratio (20*log10(ratio)).
 
template<typename Reference , typename Rep1 , typename Precision1 , typename Rep2 , typename Precision2 >
requires is_power_reference_v<Reference>
auto quanta::electro::add_powers (const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
 Combines the powers of two uncorrelated signals.
 
template<typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const quantity< decibel_unit, Rep, Precision > &g)
 Converts a gain to a string, e.g.
 
template<typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const quantity< decibel_unit, Rep, Precision > &g, base_unit_t)
 Converts a gain to a string in decibels, e.g.
 
template<typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const quantity< decibel_unit, Rep, Precision > &g, scaled_t)
 Converts a gain to a string in decibels, e.g.
 
template<typename Reference , typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const level< Reference, Rep, Precision > &l)
 Converts a level to a string, e.g.
 
template<typename Reference , typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const level< Reference, Rep, Precision > &l, base_unit_t)
 Converts a level to a string against its reference, e.g.
 
template<typename Reference , typename Rep , typename Precision >
requires _is_decimal_precision<typename Precision::type>
std::string quanta::electro::to_string (const level< Reference, Rep, Precision > &l, scaled_t)
 Converts a level to a string against its reference, e.g.
 
template<char... Digits>
constexpr quanta::electro::decibels quanta::literals::electro_literals::operator""_dB ()
 Literal for decibels (e.g., 20_dB).
 
template<char... Digits>
constexpr quanta::electro::centidecibels quanta::literals::electro_literals::operator""_cdB ()
 Literal for centidecibels, i.e.
 
template<char... Digits>
constexpr quanta::electro::dbm quanta::literals::electro_literals::operator""_dBm ()
 Literal for dBm (e.g., 20_dBm, or -73_dBm).
 
template<char... Digits>
constexpr quanta::electro::centi_dbm quanta::literals::electro_literals::operator""_cdBm ()
 Literal for dBm in 0.01 dB steps (e.g., 1301_cdBm is 13.01 dBm).
 
template<char... Digits>
constexpr quanta::electro::dbw quanta::literals::electro_literals::operator""_dBW ()
 Literal for dBW (e.g., 10_dBW).
 
template<char... Digits>
constexpr quanta::electro::dbv quanta::literals::electro_literals::operator""_dBV ()
 Literal for dBV (e.g., 6_dBV).
 
template<char... Digits>
constexpr quanta::electro::dbmv quanta::literals::electro_literals::operator""_dBmV ()
 Literal for dBmV (e.g., 40_dBmV).
 
template<char... Digits>
constexpr quanta::electro::dbuv quanta::literals::electro_literals::operator""_dBuV ()
 Literal for dBµV (e.g., 120_dBuV).
 
template<char... Digits>
constexpr quanta::electro::dbuv quanta::literals::electro_literals::operator""_dBµV ()
 Literal for dBµV (e.g., 120_dBµV).
 

Variables

template<typename Reference >
constexpr bool quanta::electro::is_power_reference_v = false
 True if the reference measures a power quantity (10*log10).
 
template<decibel_reference Reference>
constexpr bool quanta::electro::is_power_reference_v< Reference > = Reference::factor == 10
 
template<typename Reference >
constexpr bool quanta::electro::is_field_reference_v = false
 True if the reference measures a field quantity (20*log10).
 
template<decibel_reference Reference>
constexpr bool quanta::electro::is_field_reference_v< Reference > = Reference::factor == 20
 
template<typename T >
constexpr bool quanta::electro::is_level_v = is_level<T>::value
 

Detailed Description

Logarithmic ratios (dB) and absolute levels (dBm, dBW, dBµV, ...).

Decibels come in two flavours, and conflating them is the classic source of bugs. This header keeps them apart with the same distinction std::chrono draws between a duration and a time_point:

  • A gain (dB) is a dimensionless ratio - the duration analog. Gains add, subtract, and scale by a scalar.
  • A level (dBm, dBW, dBµV, ...) is an absolute point on a logarithmic scale, measured against a reference - the time_point analog.

The resulting algebra is enforced at compile time:

using namespace quanta::electro;
using namespace quanta::electro_literals;
auto tx = 20_dBm;
auto eirp = tx + 6_dB - 2_dB; // level +/- gain -> level
auto rx = eirp - 90_dB; // path loss -> -66 dBm
auto margin = rx - (-100_dBm); // level - level -> 34 dB
// tx + tx; // ill-formed: adding two levels is meaningless
// tx * 2; // ill-formed: scaling an absolute level is meaningless
Electrical unit types and utilities.
Definition decibel.hpp:61

Crossing into the linear domain

Conversions to and from linear quantities are explicit, named functions rather than constructors, because they are non-constexpr (they need std::log10 and std::pow), they are nonlinear (so the implicit/explicit constructor convention used elsewhere in electro - which signals precision loss - would be misleading), and they have domain errors that a constructor cannot report.

to_linear(30_dBm); // 1000.0 mW, as power<double, std::milli>
to_level<dbm>(milliwatts(1)); // 0 dBm
power< int64_t, std::milli > milliwatts
Power with 1 mW precision.
Definition electro.hpp:954

Power references and field references

A reference tag records both the reference quantity and whether the underlying linear quantity is a power (10*log10, e.g. dBm) or a field such as voltage (20*log10, e.g. dBµV). Callers never have to remember which factor applies; it travels with the type.

For the same reason a bare dB value cannot be turned into a linear ratio unambiguously - 3 dB is a factor of 2 in power but ~1.41 in amplitude - so power_ratio() and amplitude_ratio() are separate, explicitly named functions.

Definition in file decibel.hpp.