experimental.units

Type-based, i.e. statically checked, units of measurement.

A quantity is a wrapper struct around an arbitrary value type, parametrized with a certain unit. A unit is basically little more than a marker type to keep different kinds of quantities apart, but might additionally have an associated name and symbol string, and – more more importantly – define conversions to other units. While all of the possible conversions must be defined statically for type-checking, arbitrary callables are supported for actually converting the values, which do not necessarily need to be evauatable at compile time.

Conversions only happen if explicitly requested and there is no different internal representation of values – for example 1 * kilo(metre) is stored just as 1 in memory, not as 1000 or relative to any other »canonical unit«.

On top of the template core of the module, to which units are types only, a layer making use of »dummy« unit instances with operators defined on them makes it possible to work with quantities and units in a natural way, such that the actual unit types never need to be user directly in client code (see the example below).

In the design of this module, the explicit concept of dimensions does not appear, because it would add a fair amount of complication to both the interface and the implementation for little benefit. Rather, the notion is established implicitly by defining conversions between pairs of units – to see if two units share the same dimension, just check for convertibility.

The std.si module defines SI prefixes and units for use with this module.

Modules

si
module experimental.units.si

International System of Units (SI) units and prefixes for use with std.units.

Members

Aliases

Foo
alias Foo = BaseUnit!("foo", "f")

Shordhand for creating a basic unit with a name and a symbol, and no conversions defined.

Enums

UnitString
enum UnitString

Possible string representations of units.

Functions

affine
auto affine(U u)

An affine unit – the most common case being a unit that is related to other units representing the same physical quantity not by a scale factor, but by a shift in the zero point.

convert
auto convert(Q q)
auto convert(Q q)

Converts a quantity to another unit.

isConvertibleTo
bool isConvertibleTo(Q q)
bool isConvertibleTo(Q q)

Checks whether a quantity is convertible to a certain unit.

pow
auto pow(U u)
auto pow(U u)

Raises a unit instance to a given power.

pow
auto pow(Q q)
auto pow(Q q)

Raises a quantity to a given power.

Mixin templates

DefinePrefixSystem
mixin template DefinePrefixSystem(alias System)

Mixin template for creating prefix functions for all the prefixes in a prefix system. See PrefixedUnit and prefixTemplate.

UnitImpl
mixin template UnitImpl()

Mixin template containing the implementation of the unit instance operators.

Structs

AffineUnit
struct AffineUnit(BaseUnit, alias toBaseOffset, string name, string symbol = null)

An affine unit – the most common case being a unit that is related to other units representing the same physical quantity not by a scale factor, but by a shift in the zero point.

BaseUnit
struct BaseUnit(string name, string symbol = null)

Shordhand for creating a basic unit with a name and a symbol, and no conversions defined.

BaseUnitExp
struct BaseUnitExp(B, R)

A pair of a (base) unit and a compile-time rational exponent.

Conversion
struct Conversion(T, alias R, alias I)

A conversion »link« to a target unit, consisting of a callable converting a value to the target, and one for converting it back.

Dimensionless
struct Dimensionless

A special unit used to represent dimensionless quantities.

Prefix
struct Prefix

A named prefix, part of a PrefixSystem.

PrefixedUnit
struct PrefixedUnit(BaseUnit, int exponent, alias System)

A unit with a scaling prefix applied, e.g. kilo(metre).

Quantity
struct Quantity(Unit, ValueType = double)

A quantity consisting of a value and an associated unit of measurement.

ScaledUnit
struct ScaledUnit(BaseUnit, alias toBaseFactor, string name, string symbol = null)

Shorthands for defining base units with a single conversion factor to another base unit.

Templates

AffineUnit
template AffineUnit(alias baseUnit, alias toBaseOffset, string name, string symbol = null)

An affine unit – the most common case being a unit that is related to other units representing the same physical quantity not by a scale factor, but by a shift in the zero point.

Conversion
template Conversion(alias t, alias R, alias I)

A conversion »link« to a target unit, consisting of a callable converting a value to the target, and one for converting it back.

DerivedUnit
template DerivedUnit(T...)

Constructs a derived unit, consisting of a number of base units and associated exponents.

Difference
template Difference(Lhs, Rhs)

The difference between two compile-time rational numbers.

PrefixSystem
template PrefixSystem(long systemBase, alias getPrefixes)

A prefix system, used with PrefixedUnit.

PrefixedUnit
template PrefixedUnit(BaseUnit, int exponent, alias System)
template PrefixedUnit(alias baseUnit, int exponent, alias System)

A unit with a scaling prefix applied, e.g. kilo(metre).

Product
template Product(Lhs, Rhs)

The product of two compile-time rational numbers.

Quantity
template Quantity(alias unit, ValueType = double)

A quantity consisting of a value and an associated unit of measurement.

Rational
template Rational(int n, uint d = 1u)

A compile-time rational number.

ScaledUnit
template ScaledUnit(alias baseUnit, alias toBaseFactor, string name, string symbol = null)

Shorthands for defining base units with a single conversion factor to another base unit.

Sum
template Sum(Lhs, Rhs)

The sum of two compile-time rational numbers.

prefixTemplate
template prefixTemplate(int exponent, alias System)

Shorthand for defining prefix templates like kilo!().

scale
template scale(alias baseUnit, alias toBaseFactor, string name, string symbol = null)

Shorthands for defining base units with a single conversion factor to another base unit.

Examples

1 enum foo = baseUnit!("foo", "f");
2 enum bar = scale!(foo, 21, "bar", "b");
3 
4 auto a = 2 * bar;
5 assert(convert!foo(a) == 42 * foo);

Todo:

  • Integration with the rest of Phobos (std.datetime, std.math, …)
  • Replace the proof-of-concept unit conversion implementation with an optimized one – currently some unneeded function calls are generated.
  • For scale/ScaledUnit, use runtime rational/two longs instead of double conversion per default, to avoid precision issues?
  • Benchmark quantity operations vs. plain value type operations.
  • Make quantities of the same unit implicitly convertible if the value types are – e.g. via ImplicitConversionTargets once multiple alias this statements are allowed.
  • Are multiple conversion targets for a unit really needed? Disallowing that would remove some odd corner cases.
  • Just forward Quantity instanciations with unit dimensionless to the value type altogether to avoid the current limitations regarding alias this?

Meta