
BoostCommit : 
From: steven_at_[hidden]
Date: 20070726 16:54:07
Author: steven_watanabe
Date: 20070726 16:54:06 EDT (Thu, 26 Jul 2007)
New Revision: 7552
URL: http://svn.boost.org/trac/boost/changeset/7552
Log:
Updated documentation for new systems
Text files modified:
sandbox/units/libs/units/doc/units.qbk  176 +++++++++++++++++++++
1 files changed, 93 insertions(+), 83 deletions()
Modified: sandbox/units/libs/units/doc/units.qbk
==============================================================================
 sandbox/units/libs/units/doc/units.qbk (original)
+++ sandbox/units/libs/units/doc/units.qbk 20070726 16:54:06 EDT (Thu, 26 Jul 2007)
@@ 21,7 +21,7 @@
[def __static_rational [classref boost::units::static_rational static_rational]]
[def __make_dimension_list [classref boost::units::make_dimension_list make_dimension_list]]
[def __unit [classref boost::units::unit unit]]
[def __unit_info [classref boost::units::unit_info unit_info]]
+[def __base_unit_info [classref boost::units::base_unit_info unit_info]]
[def __quantity [classref boost::units::quantity quantity]]
[def __conversion_helper [classref boost::units::conversion_helper conversion_helper]]
@@ 96,23 +96,23 @@
in the following :
* *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...
* *Derived dimension* : A collection of one or more base dimensions, each
 potentially raised to a different rational power. For example, area = \[L\]^2, velocity = \[L\]/\[T\], and
 energy = \[M\] \[L\]^2/\[T\]^2 are all derived dimensions.
* *Dimension* : The general term dimension is used to refer to either a base or a derived dimension.
* *Base unit* : A base unit represents a specific measure of a base dimension. While length is an abstract measure of
 distance, the meter is a concrete base unit of distance.
* *Derived unit* : Derived units represent a specific measure of a derived dimension.
* *Unit* : The general term unit is used to refer to either a base or a derived unit.
* *System* : A unit system is a collection of units representing all the measurable entities of interest for a
+ dimensional analysis, base dimensions include length (\[L\]), mass (\[M\]), time (\[T\]), etc....
+ Base dimensions are used only to define dimensions.
+* *Dimension* : A collection of zero or more base dimensions, each
+ potentially raised to a different rational power. For example, 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. 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 used soley to define new unitsquantities cannot use base units
+ directly.
+* *Unit* : A set of base units raised to rational exponents. e.g. newtons = kg^1 m^1 / s^2.
+ There are several ways of representing units see [link boost_units.Units].
+* *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.
* *Base quantity* : A base quantity represents a concrete amount of a base unit. Thus, while the meter is the base
 unit of length in the SI system, 5.5 meters is a base quantity in that system.
* *Derived quantity* : Derived quantities represent a concrete amount of a derived unit.
* *Quantity* : The general term quantity is used to refer to either a base or a derived quantity.
+* *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 base quantity in that system.
To begin, we present two short tutorials. [@../example/tutorial1.cpp Tutorial1] demonstrates the use of
[@http://en.wikipedia.org/wiki/SI_units SI] units. After including the appropriate system headers
@@ 122,7 +122,7 @@
and outputs the result to `std::cout`. The [___quantity] class accepts a second template parameter as its value type;
this parameter defaults to
`double` if not otherwise specified. To demonstrate the ease of using userdefined types in dimensional
calcuations, we also present code for computing the complex impedance using `std::complex<double>`
+calculations, we also present code for computing the complex impedance using `std::complex<double>`
as the value type :
[import ../example/tutorial.cpp]
@@ 136,8 +136,8 @@
While this library attempts to make simple dimensional computations easy to code, it is in no way
tied to any particular unit system (SI or otherwise). Instead, it provides a highly flexible compiletime
system for dimensional analysis, supporting arbitrary collections of base dimensions, rational
powers of units, and both explicit and implicit quantity conversions, controllable on a per fundamental
dimension basis. It accomplishes all of this via template metaprogramming techniques. With
+powers of units, and both explicit and implicit quantity conversions, controllable on a per base
+unit basis. It accomplishes all of this via template metaprogramming techniques. With
modern optimizing compilers, this results in zero runtime overhead for quantity computations relative to the
same code without unit checking.
@@ 197,39 +197,33 @@
# dimensions with zero exponent are elided. Note that reduced dimensions are never composed of more than
[$form_0.png] dimension tags, one for each distinct fundamental dimension, but may have fewer.
In our implementation, fundamental dimensions are associated with arbitrary tag types. As we will ultimately
+In our implementation, fundamental dimensions are associated with tag types. As we will ultimately
represent composite dimensions as typelists, we must provide some mechanism for
sorting dimension tags in order to make it possible to convert an arbitrary composite dimension into a reduced
dimension. A template class is provided for this purpose for convenience (found in [headerref boost/units/dimension_tag.hpp]),
or the tags themselves can provide an appropriate `typedef` for `value`:
+dimension. A CRTP base class is provided for this purpose (found in [headerref boost/units/base_dimension.hpp]):
 template<std::size_t N> struct ordinal { typedef typename boost::mpl::int_<N> value; };
+ template<class Derived, long N> struct base_dimension { ... };
With this, we can define the fundamental types for length, mass, and time as (noting the the specific ordering
+With this, we can define the fundamental types for length, mass, and time as (noting that the specific ordering
is not important, only the uniqueness of the ordinal values) :
[import ../example/test_system.hpp]
[test_system_snippet_1]
It is important to note that the choice of order is completely arbitrary as long as each tag has a unique enumerable
value. To define the fundamental dimensions themselves, we simply create MPLconformant typelists having unit
exponents by using the [___dim] class to encapsulate the fundamental dimension tag with a [___static_rational] exponent.
The [___make_dimension_list] class acts as a wrapper to ensure that the resulting type is in the form of a reduced dimension:
+value. Negative ordinals are reserved for use by the library. To define the fundamental dimensions themselves, we
+simply create MPLconformant typelists having unit exponents by using the [___dim] class to encapsulate the fundamental
+dimension tag with a [___static_rational] exponent. The [___make_dimension_list] class acts as a wrapper to ensure
+that the resulting type is in the form of a reduced dimension:
[test_system_snippet_2]
To facilitate definition of fundamental dimensions, a convenience class is provided:
+To facilitate definition of fundamental dimensions, a convenience typedef is provided:
[test_system_snippet_3]
so that the above code is identical to the full typelist definition.
We require that fundamental dimensions be represented by orthonormal basis vectors in the space of dimensions; this
requirement is not strictly necessary, as any set of basis vectors that span the vector space of dimensions can be used
as fundamental units. However, while it is conceptually interesting, allowing for nonorthonormal basis vectors adds
a tremendous amount of additional complexity (essentially it would require an implementation of basic compiletime
linear algebra) with little clear benefit for practical applications.

Naturally, we also define composite dimensions via a typelist:
[test_system_snippet_4]
@@ 249,18 +243,18 @@
Units obey the same algebra as dimensions do; the presence of the unit system serves to ensure that units having identical
reduced dimension in different systems (like feet and meters) cannot be inadvertently mixed in computations.
There are three distinct types of unit system that can be envisioned:
+There are two distinct types of unit system that can be envisioned:
* *Homogeneous systems* : Systems in which each fundamental dimension is measured in the same unit system (all SI, for
 example).
* *Mixed systems* : Systems in which each fundamental dimension is measured in one unit system, but the
 systems for different fundamental systems may come from different unit systems. For example, centimeterkilogramsecond
 units in which lengths are measured in the CGS system and masses and times are measured in the SI system. These
 systems can be treated in the same way as homogeneous systems for the most part.
* *Heterogeneous systems* : Mixed systems in which each fundamental dimension may be represented by two or more
 fundamental units. For example, an empirical equation for radar beam height (in feet) is H = (r/C)^2 where r is the
 radar range in nautical miles. In order for this equation to be dimensionally correct, the constant, C, must be expressed in
 nautical miles per foot^(1/2), which mixes two distinct fundamental length dimensions in a single unit.
+* *Homogeneous systems* : Systems composed of a set of base units, for example, meters, kilograms, and seconds.
+ Capable of representing any dimension that can be constructed from the dimensions of these base units.
+ Thus, energy in the SI system is meters^2 kilograms seconds^2. If the representation of any unit
+ is ambiguous then the system is illformed as in meters and feet.
+* *Heterogeneous systems* : Mixed systems consisting of base units raised to rational powers. Any
+ conceivable unit can be represented in some heterogeneous system. Unfortunately, a system of
+ this kind is only capable of representing one dimension because the exponents of all the base units
+ are fixed. For example, an empirical equation for radar beam height (in feet) is H = (r/C)^2 where r is the
+ radar range in nautical miles. In order for this equation to be dimensionally correct, the constant, C, must be expressed in
+ nautical miles per foot^(1/2), which mixes two distinct fundamental length dimensions in a single unit.
Units are implemented by the [___unit] template class defined in [headerref boost/units/unit.hpp] :
@@ 272,29 +266,32 @@
free functions [___pow] and [___root] that are templated on integer and [___static_rational] values and can take as an argument
any type for which the utility classes [___power_dimof_helper] and [___root_typeof_helper] have been defined.
+Base units are defined much like base dimensions.
+
+ template<class Derived, class Dimensions, long N> struct base_unit { ... };
+
+Again negative ordinals are reserved.
+
As an example, in the following we will implement a subset of the SI unit system based on the fundamental dimensions
given above, demonstrating all steps necessary for a completely functional system. First, we simply define a unit system
class that includes type definitions for commonly used units:
+that includes type definitions for commonly used units:
[test_system_snippet_6]
If the units in a given system are to be used as a part of a heterogeneous unit system, the system tag must have a
unique (among system tags) enumerable value. We reuse the [___ordinal] template for this application here.
System ordinal values up to 100 are reserved for library use; userdefined systems should use ordinal values greater
than 100. The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp]
+The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp]
to facilitate ODR and threadsafe constant definition in header files. We then define some constants for the supported units
to simplify variable definitions:
[test_system_snippet_7]
We also specialize the [___unit_info] class for each fundamental
+We also specialize the [___base_unit_info] class for each fundamental
dimension tag to provide information needed for I/O:
[test_system_snippet_8]
and similarly for `mass_tag` and `time_tag`. A future version of the library will provide a more flexible system
allowing for internationalization through a facet/localetype mechanism.
The `name()` and `symbol()` methods of [___unit_info] provide full and short names for the base unit. With these definitions,
+The `name()` and `symbol()` methods of [___base_unit_info] provide full and short names for the base unit. With these definitions,
we have the rudimentary beginnings of our unit system, which can be used to determine reduced dimensions for arbitrary
unit calculations.
@@ 313,45 +310,47 @@
template<class Unit,class Y = double> class quantity;
This class is templated on both unit type (`Unit`) and value type (`Y`), with the latter defaulting to doubleprecision
floating point if not otherwise specified. Operators +, , *, and / are provided for algebraic operations between
+floating point if not otherwise specified. The value type must have a normal copy constructor and copy
+assignment operator. Operators +, , *, and / are provided for algebraic operations between
scalars and units, scalars and quantities, units and quantities, and between quantities. In addition, integral and
rational powers and roots can be computed using the [___pow]<R> and [___root]<R> functions. Finally,
the standard set of boolean comparison operators ( `==, !=, <, <=, >, and >=` ) are provided to allow
comparison of quantities from the same unit system.
+comparison of quantities from the same unit system. All operators require simply delegate to the
+corresponding operator of the value type if the units permit.
[section:Quantity_Construction_and_Conversion Construction and Conversion of Quantities]
By default, this library is designed to emphasize safety above convenience when performing operations with dimensioned quantities.
Specifically, construction of quantities is required to fully specify both value and unit. Direct construction from a scalar value
is prohibited (though the static member function [___from_value] and the free function [___quantity_cast] are provided to enable
this functionality where it is necessary. In addition, the mutating [___value] member function allows direct access to the
underlying value of a [___quantity] variable. An explicit
constructor is provided to enable conversion between dimensionally compatible quantities in different unit systems.
Implicit conversions between unit systems are allowed only when every fundamental dimension present is convertible between the
starting and ending unit systems. This provides finegrained control over implicit unit system conversions, allowing, for example,
trivial conversions between equivalent units in different systems (such as SI seconds and CGS seconds) while simultaneoulsy
+is prohibited (though the static member function [___from_value] is provided to enable
+this functionality where it is necessary. In addition, a [___quantity_cast] to a reference allows direct access to the
+underlying value of a [___quantity] variable. An explicit constructor is provided to enable conversion between
+dimensionally compatible quantities in different unit systems. Implicit conversions between unit systems are
+allowed only between homogeneous units when every base unit in the source is implicitly convertible to the
+destination system. This provides finegrained control over implicit unit system conversions, allowing, for example,
+trivial conversions between equivalent units in different systems (such as SI seconds and CGS seconds) while simultaneously
enabling unintentional unit system mismatches to be caught
at compile time and preventing precision loss and performance overhead from unintended conversions.
+Assignment follows the same rules.
An exception is made for quantities for which the unit reduces to dimensionless; in this case, implicit conversion
to the underlying value type is allowed via class template specialization. Quantities of different value types are implicitly
convertible if the value types are themselves implicitly convertible. The [___quantity] class also defines mutating and
nonmutating `value()` members for directly accessing and/or setting the underlying value. Clearly, use of the mutating form
is to be reserved for cases where it is absolutely necessary as doing so voids the guarantee of dimensional correctness.
+convertible only if the value types are themselves implicitly convertible. The [___quantity] class also defines
+a `value()` member for directly accessing the underlying value.
To summarize, conversions are allowed under the following conditions :
* implicit conversion of `quantity<Unit,Y>` to `quantity<Unit,Z>` is allowed if `Y` and `Z` are convertible.
* implicit assignment between `quantity<Unit,Y>` and `quantity<Unit,Z>` is allowed if `Y` and `Z` are convertible.
* explicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` and `Unit2` are convertible
 and if `Y` and `Z` are convertible.
* implicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if every fundamental dimension of `Unit1`
 is implicitly convertible to the corresponding fundamental dimension in `Unit2` and if `Y` and `Z` are convertible.
* implicit assignment between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if every fundamental dimension of `Unit1`
 is implicitly convertible to the corresponding fundamental dimension in `Unit2` and if `Y` and `Z` are convertible.
+* implicit conversion of `quantity<Unit,Y>` to `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible.
+* implicit assignment between `quantity<Unit,Y>` and `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible.
+* explicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` and `Unit2` have the same dimensions
+ and if `Y` and `Z` are implicitly convertible.
+* implicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if every base unit of `Unit1`
+ is implicitly convertible to the corresponding unit in `Unit2` and if `Y` and `Z` are convertible.
+* implicit assignment between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if every base unit of `Unit1`
+ is implicitly convertible to the corresponding unit in `Unit2` and if `Y` and `Z` are convertible.
* `quantity<Unit,Y>` can be directly constructed from a value of type `Y` using the static member function [___from_value].
* `quantity<Unit,Y>` can be directly constructed from a value of type `Y` using the `quantity_cast< quantity<Unit,Y> >` function.
* `quantity<Unit,Y>` can be directly constructed from `quantity<Unit,X>` using the `quantity_cast<Y>` function.
* `quantity<Unit1,Y>` can be directly constructed from `quantity<Unit2,X>` using the `quantity_cast<Unit1>` function.
+* `quantity<Unit,Y>` can be directly constructed from a value of type `Y`.
+* `quantity<Unit,Y>` can be directly constructed from `quantity<Unit,X>`.
+* `quantity<Unit1,Y>` can be directly constructed from `quantity<Unit2,X>`.
Because dimensionless quantities have no associated units, they behave as normal scalars, and allow implicit conversion to and from
the underlying value type.
@@ 402,7 +401,8 @@
([@../examples/unit_example_1.cpp unit_example_1.cpp])
By using the template specializations for operations on composite dimensions defined in [headerref boost/units/dimension.hpp],
+By using MPL metafunctions and the template specializations for operations on composite dimensions
+defined in [headerref boost/units/dimension.hpp],
it is possible to perform compile time arithmetic according to the dimensional analysis rules described above
to produce new composite dimensions :
@@ 410,10 +410,6 @@
[unit_example_1_snippet_1]
 typedef static_multiply<length_dimension,mass_dimension>::type LM_type;
 typedef static_divide<length_dimension,time_dimension>::type L_T_type;
 typedef static_root<static_divide<energy_dimension,mass_dimension>::type,static_rational<2> >::type V_type;

outputting (with symbol demangling, implemented in [headerref boost/units/detail/utility.hpp])
[unit_example_1_output]
@@ 655,7 +651,7 @@
([@../examples/unit_example_6.cpp unit_example_6.cpp])
This example demonstrates use of a userdefined `scaled_value` value type that carries with it
a base and exponent as a compiletime prefactor and has a heterogenous algebra. That is, the result of the product
+a base and exponent as a compiletime prefactor and has a heterogeneous algebra. That is, the result of the product
of two scaled values is not normally the same scaled value as either of the arguments. This class can be
used, for example, to represent numbers in scientific notation over a dramatically larger range than even
double precision floating point variables. For example,
@@ 722,7 +718,7 @@
Here, the unary plus and minus and addition and subtraction operators function correctly. Unfortunately,
the multiplication and division operations fail because `quaternion` implements them in terms of the `*=` and
`/=` operators, respectively, which are incapable of representing the heterogenous unit algebra needed for
+`/=` operators, respectively, which are incapable of representing the heterogeneous unit algebra needed for
quantities (an identical problem
occurs with `std::complex<T>`, for the same reason). In order to compute rational powers and roots, we need to
specialize [___power_dimof_helper] and [___root_typeof_helper] as follows:
@@ 926,8 +922,7 @@
([@../example/unit_example_19.cpp unit_example_19.cpp])
This example demonstrates the fairly complete subset of the [@http://physics.nist.gov/cuu/Constants/index.html CODATA physical
constants] in SI units provided in [headerref boost/units/systems/si/codata_constants.hpp]. At present, these constants are
only available for compilers that support `typeof`.
+constants] in SI units provided in [headerref boost/units/systems/si/codata_constants.hpp].
[import ../example/unit_example_19.cpp]
@@ 1114,6 +1109,21 @@
[endsect]
+[section:Why_Homogeneous_Systems Why are there homogeneous systems? Aren't heterogeneous systems sufficient?]
+
+Consider the following code:
+
+ cout << sin(asin(180.0 * degrees));
+
+What should this print? If only heterogeneous
+systems are available it would print 3.14159+ rad
+Why? Well, asin would return a quantity<dimensionless>
+effectively losing the information that degrees
+are being used. In order to propogate this extra information
+we need homogeneous systems.
+
+[endsect]
+
[endsect]
[section:Acknowledgements Acknowledgements]
BoostCommit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk