Home

Awesome

PhysUnits C++11 (compile-time)

Language Standard License Build Status master Version download hunter

A small C++11 header-only library for compile-time dimensional analysis and unit/quantity manipulation and conversion.

This library is based on the quantity compile-time library by Michael S. Kenniston[1] and expanded and adapted for C++11 by Martin Moene.

Contents

Hello quantity

#include "phys/units/quantity.hpp"

using namespace phys::units;
using namespace phys::units::literals;

int main()
{
    quantity<speed_d> speed = 45_km / hour;
}

Other libraries

Dependencies

This library has no dependencies other than the standard C++ library.

Limitations

This library only supports the use of the <em>SI unit system</em>.

This library only supports <em>integral powers</em> of the dimensions.

Error handling

Error handling with respect to mixing incompatible dimensions occurs at compile-time.

Definition of terms

Adapted from Boost.Units:

Dimensions, units and literals

The seven fundamental SI [2] dimensions are length, mass, time interval, electric current, thermodynamic temperature, quantity of substance and luminous intensity. The base units are meter (m), kilogram (kg), second (s), ampere (A), mole (mol) and candela (cd).

The library defines dimensions such as length_d and mass_d and it defines quantities that represent their units as meter and kilogram. The library also defines user-defined literal suffixes with prefixes ranging from yocto (1e-24L) through yotta (1e+24). Thus you can write quantity literals such as 1_ns and 42.195_km.

To use literals of non-base units, include the file io.hpp or io_symbols.hpp, or one or more of the following files named quantity_io_ unit .hpp where unit is becquerel, celsius, coulomb, farad, gray, henry, hertz, joule, lumen, lux, newton, ohm, pascal, radian, siemens, sievert, speed, steradian, tesla, volt, watt, weber.

Include files

Configuration

-D<b>PHYS_UNITS_REP_TYPE</b>=double
Define this to the <em>representation or value type</em> for the magnitude of quantity. Default is double. You can change the type for all uses within a translation unit by defining PHYS_UNITS_REP_TYPE before inclusion of header quantity.hpp.

-D<b>PHYS_UNITS_COLLAPSE_TO_REP</b>=1
The library can collapse dimensionless results to the representation type or continue with type quantity<dimensionless_d>. Define PHYS_UNITS_COLLAPSE_TO_REP to 0 to allow dimensionless quantities. Default is 1.

Types and declarations

#include "phys/units/quantity.hpp"

using namespace phys::units;

quantity<mass_d> q_rep;           // magnitude has type Rep (PHYS_UNITS_REP_TYPE)
quantity<mass_d, float> q_float;  // magnitude has type float

The default <em>representation or value type</em> Rep for the magnitude of quantity is double. You can change the type for all uses within a translation unit by defining PHYS_UNITS_REP_TYPE before inclusion of header quantity.hpp.

Operations and expressions

OperationOperand Type(s)Result Type
Constructionquantity()quantity
quantity( quantity )quantity
Assignmentquantity = quantityquantity &
Addition &quantity += quantityquantity &
Subtractionquantity -= quantityquantity &
+quantityquantity
-quantityquantity
quantity + quantityquantity
quantity - quantityquantity
Multiplicationquantity *= numquantity &
quantity * numquantity
num * quantityquantity
quantity1 * quantity1quantity2
quantity1 * quantity2num or quantity3
Divisionquantity /= numquantity &
quantity / numquantity
num / quantity1quantity2
quantity / quantitynum
quantity1 / quantity2quantity3
Powersnth_power<N>( quantity1 )num if N=0, quantity1 if N=1, quantity2 otherwise
square( quantity1 )quantity2
cube( quantity1 )quantity2
Rootsnth_root<N>( quantity1 )quantity2, iff dimensions of quantity1 are all even multiples of N
sqrt( quantity1 )quantity2, iff dimensions of quantity1 are all even multiples of 2
Conversionquantity1.to( quantity2 )num or quantity3 (quantity1/quantity2)
Zeroquantity.zero()quantity with magnitude 0

Convenience functions

The following convenience functions are provided.

In namespace phys::units:

In namespace phys::units::io:

In namespace phys::units::io::eng:

Output variations

The following example shows the quantity type in the computation of work from force and distance and the printing of the result on standard output.

#include <iostream>

#include "phys/units/io.hpp"
#include "phys/units/quantity.hpp"

using namespace phys::units;
using namespace phys::units::io;
using namespace phys::units::literals;

quantity<energy_d>
work( const quantity<force_d> & F, const quantity<length_d> & dx )
{
    return F * dx; // Defines the relation: work = force * distance.
}

int main()
{
    // Test calculation of work.
    quantity<force_d>       F { 2_N           };  // Define a quantity of force.
    quantity<length_d>      dx{ 2_m           };  // and a distance,
    quantity<energy_d>      E { work( F, dx ) };  // and calculate the work done.

    std::cout << "F  = " << F  << std::endl
              << "dx = " << dx << std::endl
              << "E  = " << E  << std::endl;
}

The output produced is:

F  = 2 N
dx = 2 m
E  = 4 J

The following example demonstrates printing in default floating point notation and in engineering notation, using metric prefixes.

#include <iostream>

#include "phys/units/io.hpp"
#include "phys/units/quantity.hpp"

using namespace phys::units;
using namespace phys::units::literals;

int main()
{
    quantity<electric_resistance_d> R{ 4.7_kV / ampere };

    {
        using namespace phys::units::io;
        std::cout << "R = " << R << std::endl;
    }
    {
        using namespace phys::units::io::eng;
        std::cout << "R = " << R << std::endl;
    }
}

The output produced is:

R = 4700 Ohm
R = 4.70 kOhm

See namespaces io and io::eng for further information.

Instead of unit names such as J, you can also obtain the unit expressed in base dimensions.

#include <iostream>

#include "phys/units/quantity.hpp"
#include "phys/units/quantity_io.hpp"

using namespace phys::units;
using namespace phys::units::io;

int main()
{
    std::cout << "J = " << joule << std::endl;
}

The output produced is:

J = m+2 kg s-2

To get the presentation in base dimensions, you should not include quantity_io_joule, io_symbols.hpp or io.hpp.

Reported to work with

Performance

Relative running time (lower is better)

Compiler        Option : double : quantity
-----------------------+--------+-------------
GCC 4.8.1         -O0  :  1     :  7
GCC 4.8.1         -O2  :  1     :  1
Clang 3.2         -O0  :  .     :  .
Clang 3.2         -O2  :  .     :  .

Measured on a AMD Athlon 64 X2 Dual Core Processor 5600+, 64kB L1 Data, 64kB L1 Instruction, 512kB L2, 3.2 GB RAM

Ideas for improvement

Allow to specify a conversion offset between two units, e.g. to make conversion between 'C and K possible (see Boost.Units).

References

[1] Michael Kenniston. The Quantity Library. (Rationale, Quantity folder). 16 July 2001, rev 0.4.

[2] Ambler Thompson and Barry N. Taylor. Guide for the Use of the International System of Units (SI). NIST Special Publication 811 2008 Edition.

[3] David B. Newell and Eite Tiesinga, Editors. The International System of Units (SI). NIST Special Publication 330 2019 Edition.

[4] Gaston Hillar. Quantities and Units in Python. Dr. Dobb's. 10 September 2013.