Skip to content

Metrology

Introducing Photometric Conditions

A "1000 lm" LED lamp and a "1000 lm" low-pressure sodium lamp do not look equally bright at night. The number on both boxes is a photopic value: it weights the lamp's spectrum with \(V(\lambda)\), the spectral sensitivity of the eye's cone cells, which drive vision in daylight. At night, rod cells take over, the sensitivity curve shifts towards blue (\(V'(\lambda)\)), and the same two lamps deliver roughly 2000 and 250 scotopic lumens respectively. Both figures are luminous fluxes expressed in lumens, and a program that adds or compares them computes a result that is wrong by up to a factor of eight:

auto led = 1000. * lm;     // photopic value from the datasheet
auto sodium = 250. * lm;   // scotopic value from a night-visibility model
auto total = led + sodium; // compiles everywhere, means nothing

To the best of our knowledge, no units library catches this today, because every one of them (including mp-units until now) models a lumen as a lumen. This post introduces photometric conditions: a way to keep photopic, scotopic, mesopic, and custom quantities in separate quantity hierarchies, so that the mistake above breaks at compile time, while everything the physics does allow keeps working.

Measurement uncertainty and measured constants

When you write constexpr double G = 6.674e-11; in your code, the type says the value is exact, and it is not. The Newtonian constant of gravitation is one of the least precisely known constants in physics. CODATA 2018 lists it as 6.674 30(15) × 10⁻¹¹ m³ kg⁻¹ s⁻², and the (15) means the fifth significant digit is already uncertain. Only four digits of G are actually known. Every result derived from that double inherits an uncertainty that the program neither tracks nor reports, and nothing stops it from printing ten significant digits of a solar mass computed from a constant that guarantees four.

mp-units now has a way to model this. This post introduces the uncertain<T> representation type, the standard_uncertainty and relative_standard_uncertainty metadata for measured constants, and the measurement_of helper that connects them.

Introducing Logarithmic Quantities and Units

Decibels are everywhere in engineering. Signal levels in dBm, sound pressure in dB SPL, voltage gain in dB, filter slopes in dB/octave. The neper, pH, and stellar magnitude share the same structure. Yet, to the best of our knowledge, no general-purpose units library models logarithmic quantities correctly. Most do not model them at all. The few that do treat a decibel as a non-linear scale or an offset unit, and that choice gets the arithmetic wrong in ways that compile silently.

This article is a request for feedback. We believe we have a correct design, derived from the same affine-space model we introduced for absolute quantities. It also aims to stay consistent with the ISO/IEC 80000 standards: especially IEC 80000-15:2026, Logarithmic quantities and their units, which consolidates the logarithmic-quantity rules once held in ISO 80000-1:2009 (Annex C); together with ISO 80000-2 (the logarithm functions lb, ln, lg), ISO 80000-8 (acoustics), and IEC 80000-13 (information theory). We have read those against this design, cite them throughout, and call out the one place we knowingly diverge from them (Open Question 5).

This post describes the design in full, from the quantity spec to the named units, the arithmetic, the conversions, and every domain we surveyed. Then it lays out the open questions, each with the alternatives we considered and our current preference. Before we implement any of this in mp-units, we want the people who work with these quantities to tell us where we are wrong.

Bringing Safety to HEP

High-Energy Physics software runs detector geometries spanning millions of volumes, tracking and reconstruction algorithms, and multi-day simulations on the Grid. A single silent unit mismatch in a double can invalidate an entire analysis or produce detector geometry that is 10× the wrong size. This post shows how mp-units can bring compile-time safety to HEP codebases (including a dedicated HEP system of quantities and units) and how large projects like ATLAS can adopt it incrementally.

Why a Quantity Has a Character

A few years ago at CppCon, an engineer who works with electrical power systems every day stopped me after a talk. He told me that his team confuses active power, reactive power, apparent power, and complex power all the time, and that the mistake is easy to make and expensive to find. Then he said the sentence that has stuck with me since: a units library that will not make those four incompatible types is of no use in his industry.

He is right, and the same confusion shows up in other domains.


Note: Revised on July 5, 2026 to incorporate the feedback in the comments below.

Preventing Integer Overflow in Physical Computations

Integers overflow. What is more surprising is how easily overflow can hide behind the abstraction of a units library.

Most developers immediately think of explicit or implicit scaling operations: calling .in(unit) to convert a quantity, constructing a quantity from a different unit, or assigning between quantities with different units. These are indeed places where overflow can occur, and the library cannot prevent it at compile time when the values are only known at runtime. But at least these operations are visible in your code: you wrote the conversion, you asked for the scaling, and you can reason about whether the multiplication or division might overflow your integer type.

The harder problem is what happens when you do not ask for a conversion.

When you write 1 * m + 1 * ft, the library must automatically convert both operands to a common unit before performing the addition. That conversion, which you never explicitly requested, involves multiplication or division by scaling factors. With integer representations, those scaling operations can overflow silently, producing garbage results that propagate through your calculations undetected.

No compile-time programming can prevent this. The values are only known at runtime. But very few libraries provide proper tools to detect it.

Range-Validated Quantity Points

Physical units libraries are good at preventing dimensional errors and unit mismatches. They have not addressed a different category of correctness: domain constraints on quantity point values.

A latitude is not just a length divided by a radius. It is a value that lives in \([-90°, +90°]\), and anything outside that range is physically meaningless. An angle used in bearing navigation wraps cyclically around a circle, and treating it as an unbounded real number ignores a fundamental property of the domain. A clinical body-temperature sensor should reject a reading of \(44\ \mathrm{°C}\) at the API boundary rather than silently pass it downstream.

Type-level constraint enforcement for quantity points with this level of flexibility is a relatively unexplored area in mainstream physical units libraries. The approach described here is experimental, and there are certainly edge cases and design considerations we have not discovered yet.

Understanding Safety Levels in Physical Units Libraries

Physical quantities and units libraries exist primarily to prevent errors at compile time. Some of them focus only on dimensional analysis and unit conversions. Others go further and prevent representation errors, semantic misuse of same-dimension quantities, and even errors in the mathematical structure of equations.

This article describes six safety levels that a quantities and units library can provide, with examples for each of them. Then it compares how leading C++ libraries and units libraries from other languages score across those levels, together with their performance and memory costs.

Two of the upper levels are the focus here. Quantity kind safety distinguishes dimensionally equivalent concepts such as work vs. torque, or Hz vs. Bq. Quantity safety enforces correct quantity hierarchies and scalar/vector/tensor mathematical rules. Both are well-established concepts in metrology and physics, and both remain widely overlooked in the C++ ecosystem. They go well beyond dimensional analysis and prevent subtle semantic errors that unit conversions alone cannot catch.

Introducing Absolute Quantities

Until now, mp-units forced users to choose between points, which do not provide arithmetic, and deltas, which do not provide physical semantics. Neither of them covers the most common case, which is a non-negative absolute amount.

An absolute quantity represents an absolute amount of a physical property, measured from a true, physically meaningful zero. Examples include mass in kilograms, temperature in Kelvin, or length in meters (as a size, not a position). Such quantities live on a ratio scale and are anchored at a physically meaningful zero. Negative values are typically meaningless.

Absolute quantities stand in contrast to:

  • Affine points (e.g., \(20\ \mathrm{°C}\), \(100\ \mathrm{m}\ \mathrm{AMSL}\)) are values measured relative to an arbitrary or conventional origin.
  • Deltas (e.g., \(10\ \mathrm{K}\), \(–5\ \mathrm{kg}\)) are differences between two values.

Arithmetic on absolute quantities behaves like ordinary algebra: addition, subtraction, and scaling are well-defined and map naturally to physical reasoning. This article proposes making absolute quantities the default abstraction in mp-units V3, reflecting how scientists express equations in practice.


Note: Revised on May 12, 2026.

Bringing Quantity-Safety To The Next Level

All quantities and units libraries need to be unit-safe. Most of the libraries on the market do this correctly. Some of them are also dimension-safe, which adds another level of protection for their users.

mp-units is probably the only library on the market that additionally is quantity-safe. This gives a new quality and possibilities. I've described the major idea behind it, implementation details, and benefits to the users in the series of posts about the International System of Quantities.

However, this is only the beginning. We've always planned more and worked on the extensions in our free time. In this post, I will describe:

  • What a quantity character is?
  • The importance of using proper representation types for the quantities.
  • The power of providing character-specific operations for the quantities.
  • Discuss implementation challenges and possible solutions.