/PhysUnits-CT

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

Primary LanguageC++OtherNOASSERTION

PhysUnits-CT

A C++ 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 to compile with current compilers by Martin Moene.

This easy to use header-only library is intended to work with a wide range of compilers, including MSVC 6.

Example

#include "phys/units/quantity.hpp"

using namespace phys::units;

int main()
{
    quantity<speed_d> speed = 45 * kilo() * meter() / second();
}

Other libraries

- [PhysUnits-RT](https://github.com/martinmoene/PhysUnits-RT) - Run-time companion of this library. - [PhysUnits-CT-Cpp11](https://github.com/martinmoene/PhysUnits-CT-Cpp11) - C++11 compile-time companion of this library. - [Boost.Units](http://www.boost.org/doc/libs/1_51_0/libs/units/) - Zero-overhead dimensional analysis and unit/quantity manipulation and conversion in C++. - [unitscpp](http://code.google.com/p/unitscpp/) - A lightweight C++ library for physical calculation with units.

Usage

Definition of terms

Adapted from Boost.Units:

  • Base dimension: A base dimension is loosely defined as a measurable entity of interest; in conventional dimensional analysis, base dimensions include length ([L]), mass ([M]), time ([T]), etc.. Base dimensions are essentially a tag type and provide no dimensional analysis functionality themselves.
  • Dimension: A collection of zero or more base dimensions, each potentially raised to a different rational power. For example, length = [L]^1, area = [L]^2, velocity = [L]^1/[T]^1, and energy = [M]^1 [L]^2/[T]^2 are all dimensions.
  • Base unit: A base unit represents a specific measure of a dimension. For example, while length is an abstract measure of distance, the meter is a concrete base unit of distance. Conversions are defined using base units. Much like base dimensions, base units are a tag type used solely to define units and do not support dimensional analysis algebra.
  • Unit: A set of base units raised to rational exponents, e.g. m^1, kg^1, m^1/s^2.
  • System: A unit system is a collection of base units representing all the measurable entities of interest for a specific problem. For example, the SI unit system defines seven base units : length ([L]) in meters, mass ([M]) in kilograms, time ([T]) in seconds, current ([I]) in amperes, temperature ([theta]) in kelvin, amount ([N]) in moles, and luminous intensity ([J]) in candelas. All measurable entities within the SI system can be represented as products of various integer or rational powers of these seven base units.
  • Quantity: A quantity represents a concrete amount of a unit. Thus, while the meter is the base unit of length in the SI system, 5.5 meters is a quantity of length in that system.

Limitations

This library only supports the use of the SI unit system.

This library only supports integral powers of the dimensions.

The representation or value type in the implementation of quantity is fixed and cannot be defined separately for each quantity. However you can change the type for all uses within a translation unit by defining PHYS_UNITS_REP_TYPE before inclusion of header quantity.hpp. Default this type is double.

Output

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;

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.0 * newton());  // Define a quantity of force.
    quantity<length_d>      dx( 2.0 * meter() );  // 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;

int main()
{
    quantity<electric_resistance_d> R( 4.7 * kilo() * volt() / 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.7 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

Convenience functions

There are several convenience functions, such as:

  • std::string to_magnitude( quantity<...> const & q ) - the quantity's magnitude represented as string
  • std::string to_unit_name( quantity<...> const & q ) - the quantity's unit name, e.g. 'hertz'
  • std::string to_unit_symbol( quantity<...> const & q ) - the quantity's unit symbol, e.g. 'Hz'
  • std::string to_string( long double const value ) - the value of a long double represented as string

In namespace io:

  • std::string to_string( quantity<...> const & q ) - the quantity represented as string in scientific notation
  • std::ostream & operator<<( std::ostream & os, quantity<...> const & q ) - output the quantity to a stream in scientific notation

In namespace io::eng:

  • std::string to_string( quantity<...> const & q ) - the quantity represented as string in engineering notation
  • std::ostream & operator<<( std::ostream & os, quantity<...> const & q ) - output the quantity to a stream in engineering notation

Error handling

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

Mixing run-time and compile-time libraries

Although this library seems to be in the phys::units namespace, it does so through using the ct namespace in the global namespace. So this library actually lives in the ct::phys::units namespace. When you want to mix this library with its compile-time companion, the ct namespace must be applied. This can be accomplished by defining PHYS_UNITS_IN_CT_NAMESPACE.

Dependencies

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

Performance

TBD

Relative running time (lower is better)

Compiler        Option : double : quantity
-----------------------+--------+-------------
GCC 4.6.2         -O2  :  1     :  . (1)
MS VC6/VS6        -O2  :  .     :  . (1.x)
MS VC8/VS2005     -O2  :  .     :  . (1.x)
MS VC2010/VS2010  -O2  :  .     :  . (1.x)

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

Compilers known to work

  • GCC 4.5.2, 4.6.2
  • MS VC6/VS6 - (VC6 lacks ADL).
  • MS VC8/VS2005
  • MS VC2010/VS2010

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).

It may be nice if you can obtain a quantity in a unit representation of your choice, e.g. in kWh in stead of J [m+2 kg s-2]. See G.S. Novak. Conversion of units of measurement (PDF)". 1 August 1997.

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.