CODATA Fundamental Physical Constants¶
The CODATA recommended values of the fundamental physical constants, expressed in SI units.
#include <mp-units/systems/codata.h>
using namespace mp_units;
quantity mu = measurement_of(codata::magnetic_constant).in(si::henry / si::metre);
std::cout << mu << "\n"; // 1.25664e-06 ± 2e-16 H/m
Why a separate system¶
The SI fixes exactly seven constants, and those live in the
SI system where they belong (every adjustment namespace
below aliases them, so codata::planck_constant is the very same entity as
si::si2019::planck_constant). Everything CODATA publishes beyond them is measured:
each value carries a standard uncertainty and shifts with every adjustment.
Keeping them here rather than in si is a deliberate cost decision.
<mp-units/systems/si.h> is the header most translation units reach for, and most of them
never name a CODATA constant. Making everyone pay for the full table so that a minority
need not write one extra #include is the wrong trade. Include this header when you want
these constants.
Generated from the source tables¶
The headers of this system are generated by scripts/codata_constants.py directly from
the NIST "allascii" tables,
which are checked into the repository verbatim. The generator accounts for every row of
every table and then verifies its own output by recomputing each emitted value in the
row's own unit and comparing it against the printed digits. The rationale behind
generating rather than transcribing is that:
- a measured constant transcribes the published value and the published absolute standard uncertainty digit for digit, so nothing in these headers is rounded by us,
- values that NIST prints truncated with an ellipsis (
8.617 333 262... e-5) are exact but non-terminating decimals, so they are defined by their exact symbolic relation (for example, the Boltzmann constant divided by the elementary charge) instead of by copied digits that would silently define an inexact constant while labelling it exact, - rows that merely restate a constant in another unit ("... in MeV", "energy equivalent", unit relationships) are not repeated, because constants are units in this library and such forms are a conversion at the point of use.
Header layout¶
Each adjustment ships in two headers spelling the very same constant types:
<mp-units/systems/codata/codataYYYY_essential.h>provides the NIST "Frequently used constants" selection (the Newtonian constant of gravitation, the fine-structure constant, particle masses, and friends),<mp-units/systems/codata/codataYYYY.h>includes the essential header and adds the complete table (roughly 230 constants per adjustment).
The split is a compile-time trade. The essential tier costs nothing measurable on top of
the framework headers it includes, while the complete table instantiates thousands of
magnitude types and adds a few seconds per translation unit, so code that only needs G
should not pay for the atomic unit of the second hyperpolarizability.
<mp-units/systems/codata.h> remains the umbrella for all adjustments in full.
Two more headers hold the constants that do not belong to any single adjustment:
<mp-units/systems/codata/adopted_values.h>provides NIST's "adopted values": the conventional constants fixed by CGPM/CIPM resolutions rather than measured (the standard gravity, the standard atmosphere, the standard-state pressure, and the conventional Josephson and von Klitzing values). They are identical in every adjustment, which the generator verifies, so they live directly inmp_units::codataas single adjustment-invariant entities. This also makes the header the right dependency for units defined through them:yard_pound'spound_forcebuilds oncodata::standard_gravityand includes only this tiny header rather than a whole adjustment.<mp-units/systems/codata/math_constants.h>defines the two solutions of the Wien displacement transcendental equations. Likeπ, they are exact mathematical constants, and the post-2019 Wien displacement law constants are defined through them instead of through truncated decimals.
Adjustments¶
Each CODATA adjustment gets its own namespace, because a measured constant has no single correct value:
quantity now = measurement_of(codata::magnetic_constant); // current
quantity pinned = measurement_of(codata::codata2018::magnetic_constant); // a specific one
The most recent adjustment is inline, so the unqualified name always refers to it while
older ones stay reachable by spelling them out. Moving that inline to a newer adjustment
is a deliberate, documented change of the default rather than something that happens
silently.
Constants that are exact under a given adjustment carry no uncertainty at all, which makes the exact-versus-measured distinction visible to the type system:
static_assert(MeasuredConstant<decltype(codata::codata2022::magnetic_constant)>);
static_assert(!MeasuredConstant<decltype(codata::codata2014::magnetic_constant)>);
The magnetic constant μ₀ (IEC 80000-6, item 6-26.1) shows why. Before 2019 the ampere was defined through μ₀, which made it exactly \(4\pi \times 10^{-7}\) H/m. The 2019 redefinition tied the ampere to the elementary charge instead, so μ₀ became measured, and its value departs from \(4\pi \times 10^{-7}\) in the tenth digit.
Not interchangeable with the hep constants
The HEP system provides codata2014/codata2018/codata2022 namespaces of
its own, but those constants are not the same entities. HEP declares its own system
of quantities, with energy as a base quantity and no mass dimension at all, so its
constants are unrelated types that no conversion can reach.
Their published uncertainties can differ as well. Before 2019 the elementary charge was itself measured, so a mass expressed in kg and the same mass expressed in MeV/c² are separate CODATA table entries with different \(u_r\). Deriving one from the other would combine correlated uncertainties in quadrature and overstate them.
Working with the uncertainties¶
These constants are ordinary units, so they cost nothing until a conversion actually needs
their value, and they cancel symbolically when they appear on both sides. To obtain a
quantity that carries the uncertainty, use measurement_of, described in
Working with Measurement Uncertainty.