The name, symbol, standard factor, SI and exactness status of a non-prefixable and a prefixable base unit must be defined when defining the unit. The respective properties of a prefixed unit are generated from the prefixable base unit and (if necessary) modified by consideration of the unit prefix. The properties of a compose base and a composed unit are automatically generated at compile time from the components' properties and (as regards the standard factor) the standard factor of the compose base unit.
+
= one or more occurences):
unit-symbol = primitive-symbol | composed;
composed = +(component, [' ']);
component = symbol, exponent;
exponent = [('^', numerator, '/', denominator) | ('^', numerator)];
numerator = long-integer;
denominator = unsigned-long-integer;
long-integer = ['-'], +digit;
unsigned-long-integer = +digit;
symbol = primitive-symbol | composed-symbol;
primitive-symbol = +alpha;
composed-symbol = '(', +unit-symbol, ')';
alpha = alphabetic character;
Unit symbols of non-prefixable and prefixed units are primitive symbols, consisting of alphabetical characters. A symbol of a composed unit, on the other hand, is composed of one or more components, separated by a space. A component consists of a symbol and an exponent. The latter is a rational number in fractional notation and purely optional, but if it is present, it starts with a `^' character followed by a numerator (a long integer). If a denominator is present, it is preceded by a '/'. The component symbol is either primitive (consisting of one or more alphanumerical characters), or it is a composed-symbol, which is enclosed in parentheses, and recursively contains other unit-symbols.
prefix name | prefix symbol | prefix value |
deci | d | 10e-1 |
centi | c | 10e-2 |
milli | m | 10e-3 |
micro | u | 10e-6 |
nano | n | 10e-9 |
pico | p | 10e-12 |
femto | f | 10e-15 |
atto | a | 10e-18 |
zepto | z | 10e-21 |
yocto | y | 10e-24 |
deca | da | 10 |
hecto | h | 10e2 |
kilo | k | 10e3 |
Mega | M | 10e6 |
Giga | G | 10e9 |
Tera | T | 10e12 |
Peta | P | 10e15 |
Exa | E | 10e18 |
Zetta | Z | 10e21 |
Yotta | Y | 10e24 |
Additionally, an empty prefix is defined:
prefix name | prefix symbol | prefix value |
empty prefix | - | 1 |
std::string Name ()
std::string Symbol ()
bool IsSI ()
bool IsExact ()
double Factor ()
Standard<U>
- (struct) static member function T VAL (const T &value)
returns the value given in unit U transformed into the standard unitReverse<U>
- (struct) static member function T VAL (const T &value)
returns the value (given in the standard unit) transformed into unit UValidUnit<U, UL>
- (struct) member RET returns a unit type U if this is present in unit list ULThese structures are supported by the following helpers:
InvalidUnit
UnitListError
Component
StandardComposed
ReverseComposed
ValidPrefixedUnit
ValidComposedUnit
ComposingUnits
Power
- power string representationstandard<UL, N, D>
- (struct) dynamic standardization by static member function T VAL (const T &value, const std::string &symbol)
; transform the value given in the unit defined by symbol
into the standard unit, provided symbol
is found in the unit list UL
and honor N
and D
as numerator and denominator of the exponent (both long integers with default: 1L)reverse<UL, N, D>
- (struct) dynamic reverse standardization by static member function T VAL (const T&value, const std::string &symbol)
; transform the value given in the standard unit into the unit defined by symbol
, provided symbol
is found in the unit list UL
and honor N
and D
as numerator and denominator of the exponent (both long integers with default: 1L)The functionality is supported by the following static helper functions and helper classes:
standardPrefixed
reversePrefixed
standardComposed
- transform value for a composed unit.reverseComposed
- transform value for a composed unit.push_back_impl
- implementation detail (to be deleted with more recent versions of Spirit)ComposedGrammar
- the grammar for composed unit symbolsComposedClosure
- store some details for grammar
These exceptions can occur whenever run-time use is made of a unit symbol in dynamic (reverse) standardization.
On the other hand, for each base quantity, however, there may be several types, which have the same characteristic features, but differ in some other respect. For example, among electric charge quantities we might have variable or constant values. Moreover, we might have special electric charge quantities, which have fixed values in every context, for example, the electron and the proton charge. All the electric charge quantities share the dimension of electric charge and the units in which the values can be expressed. We will call such sub-types of quantities derived quantities (again not to be confused with the concept of SI derived quantities).
In many cases, a physical quantity can be regarded as a variable, which might attain different values in the course of the calculation. In some cases, the value must be fixed at first use, and not be changable thereafter. As discussed in the quantities concepts section, such a physical quantity will be denoted a constant. In still other cases, the value of a constant is universally fixed and can never be changed. A particular case of such unique constants are fundamental physical constants [Cohen/Cvitas/etal_2007] (p.111). We will refer to these also as natural constants. Recommended values for fundamental physical constants are compiled and accessible online [CODATA]. Their values may be experimentally determined (e.g., the elementary charge), calculated from other such constants' values (e.g., the Faraday constant), or defined (e.g., the zero of the Celsius scale) [Cohen/Cvitas/etal_2007] (p.111). The numerical values may be subject to changes with experimental progress.
A quantity may have various modes of accessibility. This will influence its use.
... storage type ... storage unit ...
... Dynamic ... Generated (generic?) -> do only consider dimension for convertibility, since coherent unit is used (special case!) ...
It will turn out advantageously to group quantities together according to some of their basic properties: among others the dimension and the list of units which can be used with the quantity. Such quantities belonging to the same quantity type may differ for example in the particular unit in which the numerical value is measured, or in the way the numerical value is expressed (e.g., with or without a decimal point).
A quantity will be realized a C++ object.
Conversions might be realized as copy (see above) or assignment (see below) operations.
=
.
Addition (common symbol: ) and multiplication (common symbol:
or
or
) are commutative operations. The two operands in an addition operation must be commensurable. The same is true for subtraction. On the other hand, no restriction is placed on the operands of multiplication and division operations in terms of commensurability.
... other arithmetical operations ...
Unary + and - operations work on the sign of a quantity, either leaving it as it is or changing it into the opposite. As a result, unary + does not change its operand at all. It was added to the ANSI C standard as a symmetry complement to unary - [Kernighan/Ritchie_1988](p. 204).
Increment and decrement operations should be designed in analogy to the predefined counterparts for for built-in types. Thus, prefix and postfix variants are considered. All these operations change the value of the quantity object. Consequently, only variable forms of a quantity can be incremented or decremented, and these operations are not defined for constant or unique-constant mode.
Unary + and - operations work on the sign of a quantity, either leaving it as it is or changing it into the opposite. As a result, unary + does not change its operand at all. It was added to the ANSI C standard as a symmetry complement to unary - [Kernighan/Ritchie_1988](p. 204).
Increment and decrement operations should be designed in analogy to the predefined counterparts for for built-in types. Thus, prefix and postfix variants are considered. All these operations change the value of the quantity object. Consequently, only variable forms of a quantity can be incremented or decremented, and these operations are not defined for constant or unique-constant mode.
... other arithmetical operations ...
==
, !=
, >
, <
, >=
, and <=
. Note, that comparison operations need to be restricted to particular combinations of quantities. For example, temperatures in different scales (thermodynamic, Celsius, etc.) can be compared, while a comparison between a length and a time quantity should be forbidden.... other concepts ...
The Quantities
package provides header files and libraries which facilitate to write C++ programs incorporating quantity calculus. This is basically done by defining various types which have built-in abilities to follow and enforce the rules of quantity calculus. Thus, commensurability is tested for numerical and assignment operations, and units are taken into account. Furthermore, other operations are provided (Quantity
library). There is also a collection of often used scientific (physical) quantities (see, Physical Quantities) in the PhysicalQuantities
library, which is part of Quantities
.
Once a C++ program has declared objects with the types mentioned, they can be used to perform quantity calculus. Such an object is generally referred to as a quantity object in the following. The type of such an object is the quantity type. We will further categorize quantity objects by their mode, i.e. whether they refer to a variable, a constant, a unique constant, or an unnamed transient variable.
Unnamed transient quantity objects are often internally created (generated quantity objects), for example as return values of a function. Such objects can be used in operations, but in lieu of a name within the program it is not possible to assign or change the value. Other sources of such quantity objects are certain constructor calls. If this is the constructor of a well-defined quantity, the resulting object carries full unit information. However, generated quantity objects have only limited knowledge about the unit in which the value is stored. In particular, it is assumed that the standardization factor of the unit is 1.0. Thus, generated quantity objects should be used with great care (see below).
In rare cases, dynamic quantity objects are generated and returned from a function. Such an object has a type Dynamic<ST>, where ST is the storage type used (see, quantitiesUserObjects). A dynamic quantity object's properties can not be tested a compile time, since they are only defined at run time. Thus, they are not subject to the usual rules within this package, and could result in errors, which are only detected when the program runs. Consequently, such objects should be avoided as far as possible. At least, they should be converted into or assigned to normal quantity objects as soon as possible after they are returned from a function.
Quantities
, serialization is used to save the content of a quantity object to a file and later load it into an equivalent object within the same or a separate program run. This is not necessary for unique constants, since a quantity object of this mode has a defined value (and, consequently, a fixed state).unity
with a value of 1 in the storage unitzero
with a value of 0 in the storage unitNaN
infinity
For a quantity type X
, the respective function callsSpecialValues<X>::unity ()
SpecialValues<X>::zero ()
SpecialValues<X>::NaN ()
andSpecialValues<X>::infinity ()
return a constant quantity object with the respective value.A VariableVectorTuple is a non-homogeneous collection of VariableVectors of equal length. Thus, the VariableVectors can be based on different types of quantities. Equal length ensures that it is always possible to retrieve a set of one value each from each vector as a common tuple of the corresponding quantities. An example would be the two or three coordinates of a point in a two- or three-dimensional space, respectively.
Other aggregates, which have not been implemented yet are a VariableMatrix and a VariableTable.
A variable vector behaves in most situations much like a std::vector
. However, all member functions of std::vector<> that use iterators or use vector elements as parameter(s) or return value are reimplemented, and their behavior differs from that of the corresponding std::vector
functions.
A VariableVector
is defined by the following template parameters:
Some physical quantities provide definitions of appropriate variable vectors.
VariableVector
defines the following types:
BV
- protected, the variable vector's base QuantityVectorSU
- protected, the storage unit for the numerical valuesV
- protected, the corresponding variablevalue_type
- public, the type of quantity to be stored and returned (identical to V
reference
- public, the reference type of the quantity to be storedconst_reference
- public, the const reference type of the quantity to be storediterator
- public, a normal iterator into the variable vectorreverse_iterator
- public, a reverse iterator into the variable vectorconst_iterator
- public, a const iterator into the variable vectorconst_reverse_iterator
- public, a const reverse iterator into the variable vector(for the iterator types, see Variable vector iterators).
The types size_type
and difference_type
are taken from the underlying std::vector
.
A VariableVector
provides the following funtionality:
VariableVector ()
- default constructor, creates empty variable vectorVariableVector (size_type n)
creates variable vector with n
elements corresponding to the default variable objectVariableVector (size_type n, const Q &element)
- with n copies corresponding to a convertible quantity object element
; Q
must be a type that can be converted into V
.VariableVector (VV &vector)
- creates a copy of variable vector vector
; type VV
is a type of a variable vector that contains elements that are convertible into elements of the variable vector to be created. This operation is a conversion of vector
into the created object.VariableVector (const VVI begin, const VVI end)
- create a variable vector and copy the range (begin, end] from another variable vector; the elements in the vector pointed to by the iterator pair begin
and end
must be convertible into elements of the variable vector to be created. VVI
is the type of a variable vector iterator for a variable vector that fulfils this condition.std::vector
of numerical values is not allowed.==
, !=
, >
, <
, >=
and <=
are defined. In all cases, the underlying std::vector
is compared. The right hand side object of such an operator must be a variable vector that is convertible into the type of the left hand side variable vector. Comparison between a VariableVector
and a std::vector
is not allowed.VariableVector & operator= (const VV &vector)
- assigns the source variable vector vector
(which is of a type VV
with elements that are convertible into elements of the present variable vector) to the target variable vector object; numerical values are converted into the target variable vector unit.assign (size_type n, const Q &element)
- assigns n
times the element
, which must be of a type Q
which is convertible into the target variable vector's element type.assign (VVI beg, VVI end)
- assign the range (begin, end] from another variable vector; the elements in the vector pointed to by the iterator pair begin
and end
must be convertible into elements of the target variable vector. VVI
is the type of a variable vector iterator for a variable vector that fulfils this condition.swap (VV &vector)
- swaps the target vector and vector
which must be of a convertibe type.swap (VV1 &vector1, VV2 &vector2)
- swaps the vectors vector1
and vector2
with types VV1
and VV2
, respectively, that contain convertible quantity elements. This is a global function.std::vector
of numerical values is not allowed.std::vector
element access, the return is by value and not by reference. Return in a convertible quantity type is not possible. However, the returned objects may be converted.V at(size_type index) const
- returns a copy of the element located at index index
; may throw a std::vector<>
range exceptionV operator[] (size_type index) const
- returns a copy of the element located at index index
in array style without range checkingV front () const
- return the first element without range checkingV back () const
- return the last element without range checkingVVI insert (VVI pos, const Q &quantity)
- insert quantity
at position pos
. The returned iterator points to the inserted object.insert (VVI pos, size_type n, const Q &quantity)
- insert n
instances of the object quantity
at position pos
; nothing is returned. quantity
must be convertible into an object of type V
.insert (VVI pos, VVI1 beg, VVI1 end)
- insert the elements contained between beg
and end
at position pos
. The elements must be convertible into an object of type V
.push_back (const Q &quantity)
- append an element; quantity
must be convertible into an object of type V
.VVI erase (VVI pos)
- erase the element at position pos
; returns the position of the next element. (test return ...)erase (VVI beg, VVI end)
- erase the elements between positions beg
and end
; returns the position of the next element. (test return ...)pop_back ()
- remove the last element; returns nothing.clear()
- remove all elements; the vector is empty.
The following functionality differs from std::vector
:
VariableVector
supports the use of iterators with the following functions:
begin ()
returns an iterator
to the first elementend ()
returns an iterator
to the element after the lastrbegin ()
returns a reverse_iterator
to the first elementrend ()
returns a reverse_iterator
to the element after the lastbegin () const
returns an const_iterator
to the first elementend () const
returns an const_iterator
to the element after the lastrbegin () const
returns a const_reverse_iterator
to the first elementrend () const
returns a const_reverse_iterator
to the element after the lastThe iterators returned and decribed in more detail below (see, Variable vector iterators) return upon dereferencing variable objects rather than numerical values.
std::vector<>
iterators with some additional properties. In particular, dereferencing of a variable vector iterator retrieves a quantity object rather than the numerical value stored in the variable vector at the respective place. Normal, const, reverse, and const reverse versions of a variable vector iterator are provided.Dereferencing a VariableVectorIterator returns a reference to a Variable object, but not to the respective element in the underlying std::vector<>. It does not make sense to assign to this reference or otherwise manipulate it. This is different from a STL vector.
[Matta/Massa/etal_2010] C.F. Matta, L. Massa, A.V. Gubskaya and E. Knoll, J. Chem. Educ. 88, 67 - 70 (2010).
[Kernighan/Ritchie_1988] B.W. Kernighan and D.M. Ritchie, The C Programming Language, 2nd edition, Prentice Hall, Engelwood Cliffs, 1988.
[Josuttis_1999] N.M. Josuttis, The C++ Standard Library. A Tutorial and Reference, Addison-Wesley, Reading, 1999.
[BoostSerialization] http://www.boost.org/libs/serialization/doc/index.html [Serialization] http://www.parashift.com/c++-faq-lite/serialization.html
back to top
back to Quantities start page