electro 0.4.1
Type-safe electrical units library 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 <electro/electro.hpp>

Go to the source code of this file.

Classes

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

Namespaces

namespace  electro
 Electrical unit types and utilities.
 
namespace  std
 
namespace  electro_literals
 User-defined literals for electrical quantity types.
 

Concepts

concept  electro::decibel_reference
 Concept for decibel reference tags.
 

Typedefs

template<typename Rep , typename Precision = std::ratio<1>>
using electro::gain = quantity< decibel_unit, Rep, Precision >
 A logarithmic ratio with configurable representation and precision.
 
using electro::decibels = gain< int64_t >
 Gain with 1 dB precision.
 
using electro::centidecibels = gain< int64_t, std::centi >
 Gain with 0.01 dB precision.
 
using electro::millidecibels = gain< int64_t, std::milli >
 Gain with 0.001 dB precision.
 
template<typename Rep , typename Precision = std::ratio<1>>
using electro::dbm_level = level< milliwatt_reference, Rep, Precision >
 A level referenced to 1 mW.
 
template<typename Rep , typename Precision = std::ratio<1>>
using electro::dbw_level = level< watt_reference, Rep, Precision >
 A level referenced to 1 W.
 
template<typename Rep , typename Precision = std::ratio<1>>
using electro::dbv_level = level< volt_reference, Rep, Precision >
 A level referenced to 1 V.
 
template<typename Rep , typename Precision = std::ratio<1>>
using electro::dbmv_level = level< millivolt_reference, Rep, Precision >
 A level referenced to 1 mV.
 
template<typename Rep , typename Precision = std::ratio<1>>
using electro::dbuv_level = level< microvolt_reference, Rep, Precision >
 A level referenced to 1 µV.
 
using electro::dbm = dbm_level< int64_t >
 Power level in dBm, with 1 dB precision.
 
using electro::centi_dbm = dbm_level< int64_t, std::centi >
 Power level in dBm, with 0.01 dB precision.
 
using electro::dbw = dbw_level< int64_t >
 Power level in dBW, with 1 dB precision.
 
using electro::dbv = dbv_level< int64_t >
 Voltage level in dBV, with 1 dB precision.
 
using electro::dbmv = dbmv_level< int64_t >
 Voltage level in dBmV, with 1 dB precision.
 
using electro::dbuv = dbuv_level< int64_t >
 Voltage level in dBµV, with 1 dB precision.
 
using 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 >
constexpr ToLevel 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 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 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 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 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 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 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 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 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 electro::operator<=> (const level< Reference, Rep1, Precision1 > &a, const level< Reference, Rep2, Precision2 > &b)
 
template<typename Reference , typename Rep , typename Precision >
auto 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 electro::to_level (const quantity< Unit, Rep, Precision > &q)
 Converts a linear quantity to a level.
 
template<typename Rep , typename Precision >
double 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 electro::amplitude_ratio (const quantity< decibel_unit, Rep, Precision > &g)
 The linear amplitude ratio a gain represents (10^(dB/20)).
 
gain< double > electro::power_gain (double ratio)
 The gain corresponding to a linear power ratio (10*log10(ratio)).
 
gain< double > 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 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 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 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 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 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 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 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 electro::decibels electro_literals::operator""_dB ()
 Literal for decibels (e.g., 20_dB).
 
template<char... Digits>
constexpr electro::centidecibels electro_literals::operator""_cdB ()
 Literal for centidecibels, i.e.
 
template<char... Digits>
constexpr electro::dbm electro_literals::operator""_dBm ()
 Literal for dBm (e.g., 20_dBm, or -73_dBm).
 
template<char... Digits>
constexpr electro::centi_dbm electro_literals::operator""_cdBm ()
 Literal for dBm in 0.01 dB steps (e.g., 1301_cdBm is 13.01 dBm).
 
template<char... Digits>
constexpr electro::dbw electro_literals::operator""_dBW ()
 Literal for dBW (e.g., 10_dBW).
 
template<char... Digits>
constexpr electro::dbv electro_literals::operator""_dBV ()
 Literal for dBV (e.g., 6_dBV).
 
template<char... Digits>
constexpr electro::dbmv electro_literals::operator""_dBmV ()
 Literal for dBmV (e.g., 40_dBmV).
 
template<char... Digits>
constexpr electro::dbuv electro_literals::operator""_dBuV ()
 Literal for dBµV (e.g., 120_dBuV).
 
template<char... Digits>
constexpr electro::dbuv electro_literals::operator""_dBµV ()
 Literal for dBµV (e.g., 120_dBµV).
 

Variables

template<typename Reference >
constexpr bool electro::is_power_reference_v = false
 True if the reference measures a power quantity (10*log10).
 
template<decibel_reference Reference>
constexpr bool electro::is_power_reference_v< Reference > = Reference::factor == 10
 
template<typename Reference >
constexpr bool electro::is_field_reference_v = false
 True if the reference measures a field quantity (20*log10).
 
template<decibel_reference Reference>
constexpr bool electro::is_field_reference_v< Reference > = Reference::factor == 20
 
template<typename T >
constexpr bool 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 electro;
using namespace 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
User-defined literals for electrical quantity types.
Definition decibel.hpp:834
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
A quantity of an electrical unit with a representation and precision.
Definition electro.hpp:324

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.