12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475 |
- [library Boost.Units
- [quickbook 1.5]
- [version 1.1.0]
- [authors [Schabel, Matthias C.]]
- [authors [Watanabe, Steven]]
- [copyright 2003-2008 Matthias Christian Schabel, 2007-2010 Steven Watanabe]
- [license
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- [@http://www.boost.org/LICENSE_1_0.txt])
- ]
- [purpose zero-overhead compile-time dimensional analysis and unit computations]
- ]
- [/ Some links to external sources.]
- [def __boost [@http://www.boost.org/ Boost]]
- [def __boostroot [@boost: Boost root]]
- [def __boostlicense [@http://www.boost.org/LICENSE_1_0.txt Boost License]]
- [def __boost_mpl [@http://www.boost.org/libs/mpl/doc/index.html Boost Metaprogramming Library]]
- [def __mpl_forward_sequence [@http://www.boost.org/libs/mpl/doc/refmanual/forward-sequence.html MPL Forward Sequence]]
- [/Links within this document.]
- [def __ordinal [classref boost::units::ordinal ordinal]]
- [def __dim [classref boost::units::dim dim]]
- [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 __base_unit_info [classref boost::units::base_unit_info base_unit_info]]
- [def __quantity [classref boost::units::quantity quantity]]
- [def __conversion_helper [classref boost::units::conversion_helper conversion_helper]]
- [def __absolute [classref boost::units::absolute absolute]]
- [def __base_unit [classref boost::units::base_unit base_unit]]
- [def __base_dimension [classref boost::units::base_dimension base_dimension]]
- [def __scaled_base_unit [classref boost::units::scaled_base_unit base_unit]]
- [def __make_scaled_unit [classref boost::units::make_scaled_unit make_scaled_unit]]
- [def __unary_plus_typeof_helper [classref boost::units::unary_plus_typeof_helper unary_plus_typeof_helper]]
- [def __unary_minus_typeof_helper [classref boost::units::unary_minus_typeof_helper unary_minus_typeof_helper]]
- [def __add_typeof_helper [classref boost::units::add_typeof_helper add_typeof_helper]]
- [def __subtract_typeof_helper [classref boost::units::subtract_typeof_helper subtract_typeof_helper]]
- [def __multiply_typeof_helper [classref boost::units::multiply_typeof_helper multiply_typeof_helper]]
- [def __divide_typeof_helper [classref boost::units::divide_typeof_helper divide_typeof_helper]]
- [def __power_typeof_helper [classref boost::units::power_typeof_helper power_typeof_helper]]
- [def __root_typeof_helper [classref boost::units::root_typeof_helper root_typeof_helper]]
- [def __static_negate [classref boost::units::static_negate static_negate]]
- [def __static_add [classref boost::units::static_add static_add]]
- [def __static_subtract [classref boost::units::static_subtract static_subtract]]
- [def __static_multiply [classref boost::units::static_multiply static_multiply]]
- [def __static_divide [classref boost::units::static_divide static_divide]]
- [def __static_power [classref boost::units::static_power static_power]]
- [def __static_root [classref boost::units::static_root static_root]]
- [def __get_dimension [classref boost::units::get_dimension get_dimension]]
- [def __get_system [classref boost::units::get_system get_system]]
- [def __pow [funcref boost::units::pow pow]]
- [def __root [funcref boost::units::root root]]
- [def __quantity_cast [funcref boost::units::quantity_cast quantity_cast]]
- [def __from_value [memberref boost::units::quantity::from_value from_value]]
- [def __value [memberref boost::units::quantity::value value]]
- [def __reduce_unit [classref boost::units::reduce_unit reduce_unit]]
- [def __unscale [classref boost::units::unscale unscale]]
- [def __BOOST_UNITS_STATIC_CONSTANT [macroref BOOST_UNITS_STATIC_CONSTANT]]
- [def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR]]
- [def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE]]
- [def __BOOST_UNITS_DEFAULT_CONVERSION [macroref BOOST_UNITS_DEFAULT_CONVERSION]]
- [section:Introduction Introduction]
- The Boost.Units library is a C++ implementation of dimensional analysis in a general
- and extensible manner, treating it as a generic compile-time metaprogramming problem. With appropriate
- compiler optimization, no runtime execution cost is introduced, facilitating the use of this library to
- provide dimension checking in performance-critical code. Support for units
- and quantities (defined as a unit and associated value) for arbitrary unit system models and arbitrary
- value types is provided, as is a fine-grained general facility for unit conversions. Complete SI and CGS unit
- systems are provided, along with systems for
- angles measured in degrees, radians, gradians, and revolutions and
- systems for temperatures measured in Kelvin, degrees Celsius and degrees Fahrenheit.
- The library architecture has been designed with flexibility and extensibility in mind; demonstrations of the ease
- of adding new units and unit conversions are provided in the examples.
- In order to enable complex compile-time dimensional analysis calculations with no runtime overhead,
- Boost.Units relies heavily on the [___boost_mpl] (MPL) and on template metaprogramming techniques, and is, as a consequence,
- fairly demanding of compiler compliance to ISO standards. At present, it has been successfully
- compiled and tested on the following compilers/platforms :
- # g++ 4.0.1 on Mac OSX 10.4
- # Intel CC 9.1, 10.0, and 10.1 on Mac OSX 10.4
- # g++ 3.4.4, 4.2.3, and 4.3.0 on Windows XP
- # Microsoft Visual C++ 7.1, 8.0, and 9.0 on Windows XP
- # Comeau 4.3.10.1 beta2 on Windows XP
- # Metrowerks CodeWarrior 9.2 on Windows XP.
- # Sun CC 5.9 on Solaris and Linux
- The following compilers/platforms are known *not* to work :
- # g++ 3.3.x
- # Microsoft Visual C++ 6.0 on Windows XP
- # Microsoft Visual C++ 7.0 on Windows XP
- # Metrowerks CodeWarrior 8.0 on Windows XP.
- # All versions of Borland.
- [endsect]
- [section:Quick_Start Quick Start]
- Before discussing the basics of the library, we first define a few terms that will be used frequently
- 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... but there is
- no specific restriction on what base dimensions can be used. 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.
- To begin, we present two short tutorials. [@../../libs/units/tutorial/tutorial_1.cpp Tutorial1] demonstrates the use of
- [@http://en.wikipedia.org/wiki/SI_units SI] units. After including the appropriate system headers
- and the headers for the various SI units we will need (all SI units can be included with
- [headerref boost/units/systems/si.hpp]) and for quantity I/O ([headerref boost/units/io.hpp]), we define
- a function that computes the work, in joules, done by exerting a force in newtons over a specified distance in meters
- 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 user-defined types in dimensional
- calculations, we also present code for computing the complex impedance using `std::complex<double>`
- as the value type :
- [import ../example/tutorial.cpp]
- [tutorial_code]
- The intent and function of the above code should be obvious; the output produced is :
- [tutorial_output]
- 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 compile-time
- system for dimensional analysis, supporting arbitrary collections of base dimensions, rational
- powers of units, and explicit quantity conversions. 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.
- [endsect]
- [section:Dimensional_Analysis Dimensional Analysis]
- The concept of
- [@http://en.wikipedia.org/wiki/Dimensional_analysis dimensional analysis]
- is normally presented early on in introductory physics and engineering classes as a means of determining the
- correctness of an equation or computation by propagating the physical measurement
- [@http://en.wikipedia.org/wiki/Units_of_measurement units]
- of various quantities through the equation along with their numerical values. There are a number of standard
- unit systems in common use, the most prominent of which is the
- [@http://en.wikipedia.org/wiki/SI_units Systeme International]
- (also known as SI or MKS (meter-kilogram-second), which was a metric predecessor to the SI system named
- for three of the base units on which the system is based). The SI
- is the only official international standard unit system and is widely utilized in science and engineering.
- Other common systems include the [@http://en.wikipedia.org/wiki/Cgs_units CGS]
- (centimeter-gram-second) system and the
- [@http://en.wikipedia.org/wiki/English_units English]
- system still in use in some problem domains in the United States and elsewhere. In physics,
- there also exist a number of other systems that are in common use in specialized subdisciplines. These are
- collectively referred to as [@http://en.wikipedia.org/wiki/Natural_units natural units]. When
- quantities representing different measurables are combined, dimensional analysis provides the means of
- assessing the consistency of the resulting calculation. For example, the sum of two lengths is also a length,
- while the product of two lengths is an area, and the sum of a length and an area is undefined. The fact that the
- arguments to many functions (such as exp, log, etc...) must be dimensionless quantities can be easily demonstrated by
- examining their series expansions in the context of dimensional analysis. This library facilitates the enforcement
- of this type of restriction in code involving dimensioned quantities where appropriate.
- In the following discussion we view dimensional analysis as an abstraction in which an arbitrary set of
- [@http://en.wikipedia.org/wiki/Fundamental_units units] obey the rules of a specific algebra.
- We will refer to a pair of a base dimension and a rational exponent as a *fundamental dimension*,
- and a list composed of an arbitrary number of fundamental dimensions as a *composite dimension* or, simply,
- *dimension*. In particular, given a set of [$../../libs/units/images/form_0.png] fundamental dimensions
- denoted by [$../../libs/units/images/form_1.png] and a set of [$../../libs/units/images/form_0.png]
- rational exponents [$../../libs/units/images/form_2.png], any possible (composite) dimension can be written
- as [$../../libs/units/images/form_3.png].
- Composite dimensions obey the algebraic rules for dimensional analysis. In particular, for any scalar value,
- [$../../libs/units/images/form_4.png],
- and composite dimensions [$../../libs/units/images/form_5.png]
- and [$../../libs/units/images/form_6.png], where
- [$../../libs/units/images/form_7.png], we have:
- [$../../libs/units/images/form_8.png]
- Users of a dimensional analysis library should be able to specify an arbitrary list of base dimensions to
- produce a composite dimension. This potentially includes repeated tags. For example,
- it should be possible to express energy as [$../../libs/units/images/form_9.png], [$../../libs/units/images/form_10.png],
- [$../../libs/units/images/form_11.png], or any other permutation of mass, length, and time having aggregate exponents of
- 1, 2, and -2, respectively.
- In order to be able to perform computations on arbitrary sets of dimensions,
- all composite dimensions must be reducible to an unambiguous final composite dimension, which we will refer to as a
- *reduced dimension*, for which
- # fundamental dimensions are consistently ordered
- # dimensions with zero exponent are elided. Note that reduced dimensions never have more than
- [$../../libs/units/images/form_0.png] base dimensions, one for each distinct fundamental dimension, but may have fewer.
- In our implementation, base dimensions are associated with tag types. As we will ultimately
- represent composite dimensions as typelists, we must provide some mechanism for sorting
- base dimension tags in order to make it possible to convert an arbitrary composite dimension
- into a reduced dimension. For this purpose, we assign a unique integer to each base dimension.
- The [___base_dimension] class (found in [headerref boost/units/base_dimension.hpp]) uses the
- curiously recurring template pattern (CRTP) technique to ensure that ordinals specified for
- base dimensions are unique:
- template<class Derived, long N> struct base_dimension { ... };
- With this, we can define the base dimensions for length, mass, and time as:
- [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; non-unique ordinals are flagged as errors at compile-time. Negative ordinals are reserved for use by the library.
- To define composite dimensions corresponding to the base dimensions, we
- simply create MPL-conformant typelists of fundamental dimensions by using the [___dim] class to encapsulate pairs of base dimensions
- and [___static_rational] exponents. 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]
- This can also be easily accomplished using a convenience typedef provided by [___base_dimension]:
- [test_system_snippet_3]
- so that the above code is identical to the full typelist definition. Composite dimensions are similarly defined via a typelist:
- [test_system_snippet_4]
- A convenience class for composite dimensions with integer powers is also provided:
- [test_system_snippet_5]
- [endsect]
- [section:Units Units]
- We define a *unit* as a set of base units each of which can be raised to an arbitrary rational
- exponent. Thus, the SI unit corresponding to the dimension of force is kg m s^-2, where kg, m,
- and s are base units. We use the notion of a *unit system* such as SI to specify the mapping
- from a dimension to a particular unit so that instead of specifying the base units explicitly,
- we can just ask for the representation of a dimension in a particular system.
- Units are, like dimensions, purely compile-time variables with no associated value.
- 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 two distinct types of systems that can be envisioned:
- * *Homogeneous systems* : Systems which hold a linearly independent set of base units which
- can be used to represent many different dimensions. For example, the SI system has seven
- base dimensions and seven base units corresponding to them. It can represent any unit which
- uses only those seven base dimensions. Thus it is a homogeneous_system.
- * *Heterogeneous systems* : Systems which store the exponents of every base unit involved
- are termed heterogeneous. Some units can only be represented in this way. For example,
- area in m ft is intrinsically heterogeneous, because the base units of meters and feet
- have identical dimensions. As a result, simply storing a dimension and a set of base
- units does not yield a unique solution. A practical example of the need for heterogeneous
- units, is an empirical equation used in aviation: H = (r/C)^2 where H is the radar beam
- height in feet and r is the radar range in nautical miles. In order to enforce dimensional
- correctness of this equation, the constant, C, must be expressed in nautical miles per foot^(1/2),
- mixing two distinct base units of length.
- Units are implemented by the [___unit] template class defined in [headerref boost/units/unit.hpp] :
- template<class Dim,class System> class unit;
- In addition to supporting the compile-time dimensional analysis operations, the +, -, *, and / runtime operators are provided
- for [___unit] variables. Because the dimension associated with powers and roots must be computed at compile-time, it is not
- possible to provide overloads for `std::pow` that function correctly for [___unit]s. These operations are supported through
- 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_typeof_helper] and [___root_typeof_helper] have been defined.
- [section Base Units]
- 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
- that includes type definitions for commonly used units:
- [test_system_snippet_6]
- The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp]
- to facilitate ODR- and thread-safe constant definition in header files. We then define some constants for the supported units
- to simplify variable definitions:
- [test_system_snippet_7]
- If support for textual output of units is desired, we can also specialize the [___base_unit_info] class for each fundamental
- dimension tag:
- [test_system_snippet_8]
- and similarly for `kilogram_base_unit` and `second_base_unit`. A future version of the library will provide a more flexible system
- allowing for internationalization through a facet/locale-type mechanism.
- 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.
- [endsect] [/section Base Units]
- [section Scaled Base Units]
- Now, it is also possible to define a base unit as being a multiple of
- another base unit. For example, the way that `kilogram_base_unit` is
- actually defined by the library is along the following lines
- struct gram_base_unit : boost::units::base_unit<gram_base_unit, mass_dimension, 1> {};
- typedef scaled_base_unit<gram_base_unit, scale<10, static_rational<3> > > kilogram_base_unit;
- This basically defines a kilogram as being 10^3 times a gram.
- There are several advantages to this approach.
- * It reflects the real meaning of these units better than treating them as independent units.
- * If a conversion is defined between grams or kilograms and some other units,
- it will automatically work for both kilograms and grams, with only one specialization.
- * Similarly, if the symbol for grams is defined as "g", then the symbol for kilograms
- will be "kg" without any extra effort.
- [endsect] [/section Scaled Base Units]
- [section Scaled Units]
- We can also scale a [___unit] as a whole, rather than scaling the individual
- base units which comprise it. For this purpose, we use the metafunction
- [___make_scaled_unit]. The main motivation for this feature is the metric
- prefixes defined in [headerref boost/units/systems/si/prefixes.hpp].
- A simple example of its usage would be.
- typedef make_scaled_unit<si::time, scale<10, static_rational<-9> > >::type nanosecond;
- nanosecond is a specialization of [___unit], and can be used in a quantity normally.
- quantity<nanosecond> t(1.0 * si::seconds);
- std::cout << t << std::endl; // prints 1e9 ns
- [endsect] [/section Scaled Units]
- [endsect] [/section:Units Units]
- [section:Quantities Quantities]
- A *quantity* is defined as a value of an arbitrary value type that is associated with a specific unit. For example,
- while meter is a unit, 3.0 meters is a quantity. Quantities obey two separate algebras: the native algebra for their
- value type, and the dimensional analysis algebra for the associated unit. In addition, algebraic operations are defined
- between units and quantities to simplify the definition of quantities; it is effectively equivalent to algebra with
- a unit-valued quantity.
- Quantities are implemented by the [___quantity] template class defined in [headerref boost/units/quantity.hpp] :
- 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 double-precision
- 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. All operators simply delegate to the
- corresponding operator of the value type if the units permit.
- [section:Heterogeneous_Operators Heterogeneous Operators]
- For most common value types, the result type of arithmetic operators is the same as the value type itself. For example,
- the sum of two double precision floating point numbers is another double precision floating point number. However, there
- are instances where this is not the case. A simple example is given by the [@http://en.wikipedia.org/wiki/Natural_number
- natural numbers] where the operator arithmetic obeys the following rules (using the standard notation for
- [@http://en.wikipedia.org/wiki/Number number systems]):
- * [$../../libs/units/images/form_12.png]
- * [$../../libs/units/images/form_13.png]
- * [$../../libs/units/images/form_14.png]
- * [$../../libs/units/images/form_15.png]
- This library is designed to support arbitrary value type algebra for addition, subtraction, multiplication, division, and
- rational powers and roots. It uses Boost.Typeof to deduce the result of these operators. For compilers that
- support `typeof`, the appropriate value type will be automatically deduced. For compilers that do not provide
- language support for `typeof` it is necessary to register all the types used. For the case of natural numbers,
- this would amount to something like the following:
- BOOST_TYPEOF_REGISTER_TYPE(natural);
- BOOST_TYPEOF_REGISTER_TYPE(integer);
- BOOST_TYPEOF_REGISTER_TYPE(rational);
- [endsect]
- [section:Conversions Conversions]
- Conversion is only meaningful for quantities as it implies the presence of at
- least a multiplicative scale factor and, possibly, and affine linear offset.
- Macros for simplifying the definition of conversions between units can be found in
- [headerref boost/units/conversion.hpp] and [headerref boost/units/absolute.hpp]
- (for affine conversions with offsets).
- The macro [___BOOST_UNITS_DEFINE_CONVERSION_FACTOR] specifies a scale
- factor for conversion from the first unit type to the second. The
- first argument must be a [___base_unit]. The second argument
- can be either a [___base_unit] or a [___unit].
- Let's declare a simple base unit:
- struct foot_base_unit : base_unit<foot_base_unit, length_dimension, 10> { };
- Now, we want to be able to convert feet to meters and vice versa. The foot
- is defined as exactly 0.3048 meters, so we can write the following
- BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, meter_base_unit, double, 0.3048);
- Alternately, we could use the SI length `typedef`:
- BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, SI::length, double, 0.3048);
- Since the SI unit of length is the meter, these two definitions are equivalent.
- If these conversions have been defined, then converting between
- scaled forms of these units will also automatically work.
- The macro [___BOOST_UNITS_DEFAULT_CONVERSION] specifies a conversion
- that will be applied to a base unit when no direct conversion is
- possible. This can be used to make arbitrary conversions work
- with a single specialization:
- struct my_unit_tag : boost::units::base_unit<my_unit_tag, boost::units::force_type, 1> {};
- // define the conversion factor
- BOOST_UNITS_DEFINE_CONVERSION_FACTOR(my_unit_tag, SI::force, double, 3.14159265358979323846);
- // make conversion to SI the default.
- BOOST_UNITS_DEFAULT_CONVERSION(my_unit_tag, SI::force);
- [endsect]
- [section:Quantity_Construction_and_Conversion Construction and Conversion of Quantities]
- 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] 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 when the reduced units are identical, 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 potential loss of precision 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 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 implicitly convertible.
- * 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 `Unit1`
- reduces to exactly the same combination of base units as `Unit2` and if `Y` and `Z` are convertible.
- * assignment between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed under the same
- conditions as implicit conversion.
- * `quantity<Unit,Y>` can be directly constructed from a value of type `Y` using the static member function [___from_value]. Doing so,
- naturally, bypasses any type-checking of the newly assigned value, so this method should be used only when absolutely necessary.
- Of course, any time implicit conversion is allowed, an explicit conversion is
- also legal.
- Because dimensionless quantities have no associated units, they behave as normal scalars, and allow implicit conversion to and from
- the underlying value type or types that are convertible to/from that value type.
- [endsect]
- [endsect]
- [section:Examples Examples]
- [section:DimensionExample Dimension Example]
- ([@../../libs/units/example/dimension.cpp dimension.cpp])
- 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 [link boost_units.Dimensional_Analysis above]
- to produce new composite dimensions :
- [import ../example/dimension.cpp]
- [dimension_snippet_1]
- outputting (with symbol demangling, implemented in
- [@boost:/boost/units/detail/utility.hpp utility.hpp])
- [dimension_output]
- [endsect]
- [section:UnitExample Unit Example]
- ([@../../libs/units/example/unit.cpp unit.cpp])
- This example demonstrates the use of the simple but functional unit system implemented in
- [@boost:/libs/units/example/test_system.hpp test_system.hpp]
- [import ../example/unit.cpp]
- [unit_snippet_1]
- We can perform various algebraic operations on these units, resulting in the following output:
- [unit_output]
- [endsect]
- [section:QuantityExample Quantity Example]
- ([@../../libs/units/example/quantity.cpp quantity.cpp])
- This example demonstrates how to use quantities of our toy unit system :
- [import ../example/quantity.cpp]
- [quantity_snippet_1]
- giving us the basic quantity functionality :
- [quantity_output_double]
- As a further demonstration of the flexibility of the system, we replace the `double` value type
- with a `std::complex<double>` value type (ignoring the question of the meaningfulness of
- complex lengths and energies) :
- [quantity_snippet_2]
- and find that the code functions exactly as expected with no additional work, delegating operations
- to `std::complex<double>` and performing the appropriate dimensional analysis :
- [quantity_output_complex]
- [endsect]
- [section:KitchenSinkExample Kitchen Sink Example using SI units]
- ([@../../libs/units/example/kitchen_sink.cpp kitchen_sink.cpp])
- This example provides a fairly extensive set of tests covering most of the [___quantity] functionality.
- It uses the SI unit system defined in [headerref boost/units/systems/si.hpp].
- If we define a few units and associated quantities,
- [import ../example/kitchen_sink.cpp]
- [kitchen_sink_snippet_1]
- the various algebraic operations between scalars, units, and quantities give
- [kitchen_sink_output_1]
- Scalar/unit operations :
- [kitchen_sink_output_2]
- Unit/unit operations and integral/rational powers of units :
- [kitchen_sink_output_3]
- Scalar/quantity operations :
- [kitchen_sink_output_4]
- Unit/quantity operations :
- [kitchen_sink_output_5]
- Quantity/quantity operations and integral/rational powers of quantities :
- [kitchen_sink_output_6]
- Logical comparison operators are also defined between quantities :
- [kitchen_sink_snippet_2]
- giving
- [kitchen_sink_output_7]
- Implicit conversion is allowed between dimensionless quantities and their corresponding value types :
- [kitchen_sink_snippet_3]
- A generic function for computing mechanical work can be defined that takes force and distance arguments
- in an arbitrary unit system and returns energy in the same system:
- [kitchen_sink_function_snippet_3]
- [kitchen_sink_snippet_4]
- which functions as expected for SI quantities :
- [kitchen_sink_output_9]
- The ideal gas law can also be implemented in SI units :
- [kitchen_sink_function_snippet_4]
- [kitchen_sink_snippet_5]
- with the resulting output :
- [kitchen_sink_output_10]
- Trigonometric and inverse trigonometric functions can be implemented for any unit system
- that provides an angular base dimension. For radians, these functions are found in
- [headerref boost/units/cmath.hpp] These behave as one expects, with trigonometric functions
- taking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functions
- take a dimensionless quantity and return an angular quantity :
- Defining a few angular quantities,
- [kitchen_sink_snippet_6]
- yields
- [kitchen_sink_output_11]
- Dealing with complex quantities is trivial. Here is the calculation of complex impedance :
- [kitchen_sink_snippet_7]
- giving
- [kitchen_sink_output_12]
- [section:UDT_Quantities User-defined value types]
- User-defined value types that support the appropriate arithmetic operations are automatically supported
- as quantity value types. The operators that are supported by default for quantity value types are unary plus, unary minus,
- addition, subtraction, multiplication, division, equal-to, not-equal-to, less-than, less-or-equal-to,
- greater-than, and greater-or-equal-to. Support for rational powers and roots can be added by overloading
- the [___power_typeof_helper] and [___root_typeof_helper] classes. Here we implement a user-defined `measurement`
- class that models a numerical measurement with an associated measurement error and the appropriate algebra and
- demonstrates its use as a quantity value type; the full code is found in [@../../libs/units/example/measurement.hpp measurement.hpp].
- Then, defining some `measurement` [___quantity] variables
- [kitchen_sink_snippet_8]
- gives
- [kitchen_sink_output_13]
- If we implement the overloaded helper classes for rational powers and roots
- then we can also compute rational powers of measurement quantities :
- [kitchen_sink_output_14]
- [endsect]
- [endsect]
- [section:ConversionExample Conversion Example]
- ([@../../libs/units/example/conversion.cpp conversion.cpp])
- This example demonstrates the various allowed conversions between SI and CGS units. Defining some
- quantities
- [import ../example/conversion.cpp]
- [conversion_snippet_1]
- illustrates implicit conversion of quantities of different value types where implicit conversion
- of the value types themselves is allowed. N.B. The conversion from double to int is treated
- as an explicit conversion because there is no way to emulate the exact behavior of the built-in
- conversion. Explicit constructors allow conversions for two cases:
- * explicit casting of a [___quantity] to a different `value_type` :
- [conversion_snippet_3]
- * and explicit casting of a [___quantity] to a different unit :
- [conversion_snippet_4]
- giving the following output :
- [conversion_output_1]
- A few more explicit unit system conversions :
- [conversion_snippet_5]
- which produces the following output:
- [conversion_output_2]
- [endsect]
- [section:UDTExample User Defined Types]
- ([@../../libs/units/example/quaternion.cpp quaternion.cpp])
- This example demonstrates the use of `boost::math::quaternion` as a value type for [___quantity] and the converse.
- For the first case, we first define specializations of [___power_typeof_helper] and [___root_typeof_helper] for
- powers and roots, respectively:
- [import ../example/quaternion.cpp]
- [quaternion_class_snippet_1a]
- [quaternion_class_snippet_1b]
- We can now declare a [___quantity] of a `quaternion` :
- [quaternion_snippet_1]
- so that all operations that are defined in the `quaternion` class behave correctly. If rational
- powers were defined for this class, it would be possible to compute rational powers and roots with
- no additional changes.
- [quaternion_output_1]
- Now, if for some reason we preferred the [___quantity] to be the value type of the `quaternion` class we would have :
- [quaternion_snippet_2]
- 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 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_typeof_helper] and [___root_typeof_helper] as follows:
- [quaternion_class_snippet_2a]
- [quaternion_class_snippet_2b]
- giving:
- [quaternion_output_2]
- [endsect]
- [section:ComplexExample Complex Example]
- ([@../../libs/units/example/complex.cpp complex.cpp])
- This example demonstrates how to implement a replacement `complex` class that functions correctly both as a
- quantity value type and as a quantity container class, including heterogeneous multiplication and division
- operations and rational powers and roots. Naturally, heterogeneous operations are only supported on
- compilers that implement `typeof`. The primary differences are that binary operations are not implemented
- using the `op=` operators and use the utility classes [___add_typeof_helper], [___subtract_typeof_helper],
- [___multiply_typeof_helper], and [___divide_typeof_helper]. In addition, [___power_typeof_helper] and
- [___root_typeof_helper] are defined for both cases :
- [import ../example/complex.cpp]
- [complex_class_snippet_1]
- With this replacement `complex` class, we can declare a complex variable :
- [complex_snippet_1]
- to get the correct behavior for all cases supported by [___quantity] with a `complex` value type :
- [complex_output_1]
- and, similarly, `complex` with a [___quantity] value type
- [complex_snippet_2]
- gives
- [complex_output_2]
- [endsect]
- [section:PerformanceExample Performance Example]
- ([@../../libs/units/example/performance.cpp performance.cpp])
- This example provides an ad hoc performance test to verify that zero runtime overhead
- is incurred when using [___quantity] in place of `double`. Note that performance
- optimization and testing is not trivial, so some care must be taken in profiling. It
- is also critical to have a compiler capable of optimizing the many template instantiations
- and inline calls effectively to achieve maximal performance. Zero overhead for this test
- has been verified using gcc 4.0.1, and icc 9.0, 10.0, and 10.1 on Mac OS 10.4 and 10.5, and
- using msvc 8.0 on Windows XP.
- [endsect]
- [section:RadarBeamHeightExample Radar Beam Height]
- ([@../../libs/units/example/radar_beam_height.cpp radar_beam_height.cpp])
- [import ../example/radar_beam_height.cpp]
- This example demonstrates the implementation of two non-SI units of length, the
- nautical mile :
- [radar_beam_height_class_snippet_1]
- and the imperial foot :
- [radar_beam_height_class_snippet_2]
- These units include conversions between themselves and the meter. Three functions
- for computing radar beam height from radar range and the local earth radius are
- defined. The first takes arguments in one system and returns a value in the same
- system :
- [radar_beam_height_function_snippet_1]
- The second is similar, but is templated on return type, so that the arguments are
- converted to the return unit system internally :
- [radar_beam_height_function_snippet_2]
- Finally, the third function is an empirical approximation that is only valid for
- radar ranges specified in nautical miles, returning beam height in feet. This
- function uses the heterogeneous unit of nautical miles per square root of feet to
- ensure dimensional correctness :
- [radar_beam_height_function_snippet_3]
- With these, we can compute radar beam height in various unit systems :
- [radar_beam_height_snippet_1]
- giving
- [radar_beam_height_output]
- [endsect]
- [section:HeterogeneousUnitExample Heterogeneous Unit Example]
- ([@../../libs/units/example/heterogeneous_unit.cpp heterogeneous_unit.cpp])
- [import ../example/heterogeneous_unit.cpp]
- Mixed units and mixed unit conversions.
- This code:
- [heterogeneous_unit_snippet_1]
- gives
- [heterogeneous_unit_output_1]
- Arbitrary conversions also work:
- [heterogeneous_unit_snippet_2]
- yielding
- [heterogeneous_unit_output_2]
- [endsect]
- [section:AbsoluteRelativeTemperatureExample Absolute and Relative Temperature Example]
- ([@../../libs/units/example/temperature.cpp temperature.cpp])
- [import ../example/temperature.cpp]
- This example demonstrates using of absolute temperatures and relative temperature differences in Fahrenheit
- and converting between these and the Kelvin temperature scale. This issue touches on some surprisingly deep mathematical
- concepts (see [@http://en.wikipedia.org/wiki/Affine_space Wikipedia] for a basic review), but for our purposes here, we
- will simply observe that it is important to be able to differentiate between an absolute temperature measurement and a
- measurement of temperature difference. This is accomplished by using the [___absolute] wrapper class.
- First we define a system using the predefined fahrenheit base unit:
- [temperature_snippet_1]
- Now we can create some quantities:
- [temperature_snippet_3]
- Note the use of [___absolute] to wrap a unit. The resulting output is:
- [temperature_output_1]
- [endsect]
- [section:RuntimeConversionFactorExample Runtime Conversion Factor Example]
- ([@../../libs/units/example/runtime_conversion_factor.cpp runtime_conversion_factor.cpp])
- [import ../example/runtime_conversion_factor.cpp]
- The Boost.Units library does not require that the conversion factors be compile time constants,
- as is demonstrated in this example:
- [runtime_conversion_factor_snippet_1]
- [endsect]
- [section:UnitsWithNonbaseDimensions Units with Non-base Dimensions]
- ([@../../libs/units/example/non_base_dimension.cpp non_base_dimension.cpp])
- [import ../example/non_base_dimension.cpp]
- It is also possible to define base units that have derived rather than base dimensions:
- [non_base_dimension_snippet_1]
- [endsect]
- [section:OutputForCompositeUnits Output for Composite Units]
- ([@../../libs/units/example/composite_output.cpp composite_output.cpp])
- [import ../example/composite_output.cpp]
- If a unit has a special name and/or symbol, the free functions `name_string` and
- `symbol_string` can be overloaded directly.
- [composite_output_snippet_1]
- In this case, any unit that reduces
- to the overloaded unit will be output with the replacement symbol.
- Special names and symbols for the SI and CGS unit systems are found in
- [headerref boost/units/systems/si/io.hpp] and [headerref boost/units/systems/cgs/io.hpp],
- respectively. If these headers are not included, the output will simply follow
- default rules using the appropriate fundamental dimensions.
- Note that neither of these functions is defined for quantities
- because doing so would require making assumptions on how the corresponding value
- type should be formatted.
- Three `ostream` formatters, `symbol_format`, `name_format`, and `typename_format`
- are provided for convenience. These select the textual representation of units
- provided by `symbol_string` or `name_string` in the first two cases, while the
- latter returns a demangled typename for debugging purposes. Formatting of scaled
- unit is also done correctly.
- [endsect]
- [section:autoscale Automatically Scaled Units]
- It is often desirable to scale a [___unit] automatically, depending on its value,
- to keep the integral part in a limited range, usually between 1 and 999.
- For example, using [@http://en.wikipedia.org/wiki/Engineering_notation engineering notation prefixes],
- "1234.5 m" is more helpfully displayed as "1.234 km"
- "0.000000001234 m" is more clearly displayed as "1.2345 nanometer".
- The iostream manipulators `engineering_prefixes` or `binary_prefixes` make this easy.
- [import ../example/autoprefixes.cpp]
- [autoprefixes_snippet_1]
- (The complete set of [@http://physics.nist.gov/cuu/Units/prefixes.html engineering and scientific multiples]
- is not used (not centi or deci for example), but only powers of ten that are multiples of three, 10^3).
- Similarly, the equivalent [@http://en.wikipedia.org/wiki/Binary_prefixes binary prefixes]
- used for displaying computing kilobytes, megabytes, gigabytes...
- These are the 2^10 = 1024, 2^20 = 1 048 576, 2^30 ... multiples.
- (See also [@http://physics.nist.gov/cuu/Units/binary.html Prefixes for binary multiples]
- This scale is specified in IEC 60027-2, Second edition, 2000-11,
- Letter symbols to be used in electrical technology -
- Part 2: Telecommunications and electronics).
- [autoprefixes_snippet_2]
- But note that scalar dimensionless values, like int, float and double,
- are *not* prefixed automatically by the engineering_prefix or binary_prefix iostream manipulators.
- [autoprefixes_snippet_3]
- You can output the name or symbol of a unit (rather than the most common quantity of a unit).
- [autoprefixes_snippet_4]
- Note too that all the formatting flags are persistent,
- so that if you set engineering_prefix, then it applies to all future outputs,
- until you select binary_prefix, or explicitly switch autoprefix off.
- You can specify no prefix (the default of course) in two ways:
- [autoprefixes_snippet_5]
- And you can get the format flags for diagnosing problems.
- [autoprefixes_snippet_6]
- [endsect] [/section:autoscale Automatically Scaled Units]
- [section:ConversionFactor Conversion Factor]
- This code demonstrates the use of the `conversion_factor` free function to determine
- the scale factor between two units.
- ([@../../libs/units/example/conversion_factor.cpp conversion_factor.cpp])
- [import ../example/conversion_factor.cpp]
- [conversion_factor_snippet_1]
- Produces
- [conversion_factor_output]
- [endsect]
- [section:RuntimeUnits Runtime Units]
- ([@../../libs/units/example/runtime_unit.cpp runtime_unit.cpp])
- [import ../example/runtime_unit.cpp]
- This example shows how to implement an interface that
- allow different units at runtime while still maintaining
- type safety for internal calculations.
- [runtime_unit_snippet_1]
- [endsect]
- [section:lambda Interoperability with Boost.Lambda]
- ([@../../libs/units/example/lambda.cpp lambda.cpp])
- [import ../example/lambda.cpp]
- The header [headerref boost/units/lambda.hpp] provides overloads
- and specializations needed to make Boost.Units usable with the
- Boost.Lambda library.
- [lambda_snippet_1]
- [endsect]
- [endsect]
- [section:Utilities Utilities]
- Relatively complete SI and CGS unit systems are provided in [headerref boost/units/systems/si.hpp] and
- [headerref boost/units/systems/cgs.hpp], respectively.
- [section:Metaprogramming_Classes Metaprogramming Classes]
- template<long N> struct ordinal<N>;
- template<typename T,typename V> struct get_tag< dim<T,V> >;
- template<typename T,typename V> struct get_value< dim<T,V> >;
- template<class S,class DT> struct get_system_tag_of_dim<S,DT>;
- template<typename Seq> struct make_dimension_list<Seq>;
- template<class DT> struct fundamental_dimension<DT>;
- template<class DT1,int E1,...> struct composite_dimension<DT1,E1,...>;
- template<class Dim,class System> struct get_dimension< unit<Dim,System> >;
- template<class Unit,class Y> struct get_dimension< quantity<Unit,Y> >;
- template<class Dim,class System> struct get_system< unit<Dim,System> >;
- template<class Unit,class Y> struct get_system quantity<Unit,Y> >;
- struct dimensionless_type;
- template<class System> struct dimensionless_unit<System>;
- template<class System,class Y> struct dimensionless_quantity<System,Y>;
- struct implicitly_convertible;
- struct trivial_conversion;
- template<class T,class S1,class S2> struct base_unit_converter<T,S1,S2>;
- template<class Q1,class Q2> class conversion_helper<Q1,Q2>;
- [endsect]
- [section:Metaprogramming_Predicates Metaprogramming Predicates]
- template<typename T,typename V> struct is_dim< dim<T,V> >;
- template<typename T,typename V> struct is_empty_dim< dim<T,V> >;
- template<typename Seq> struct is_dimension_list<Seq>;
- template<class S> struct is_system< homogeneous_system<S> >;
- template<class S> struct is_system< heterogeneous_system<S> >;
- template<class S> struct is_homogeneous_system< homogeneous_system<S> >;
- template<class S> struct is_heterogeneous_system< heterogeneous_system<S> >;
- template<class Dim,class System> struct is_unit< unit<Dim,System> >;
- template<class Dim,class System> struct is_unit_of_system< unit<Dim,System>,System >;
- template<class Dim,class System> struct is_unit_of_dimension< unit<Dim,System>,Dim >;
- template<class Unit,class Y> struct is_quantity< quantity<Unit,Y> >;
- template<class Dim,class System,class Y> struct is_quantity_of_system< quantity<unit<Dim,System>,Y>,System >;
- template<class Dim,class System,class Y> struct is_quantity_of_dimension< quantity<unit<Dim,System>,Y>,Dim >;
- template<class System> struct is_dimensionless< unit<dimensionless_type,System> >;
- template<class System> struct is_dimensionless_unit< unit<dimensionless_type,System> >;
- template<class System,class Y> struct is_dimensionless< quantity<unit<dimensionless_type,System>,Y> >;
- template<class System,class Y> struct is_dimensionless_quantity< quantity<unit<dimensionless_type,System>,Y> >;
- [endsect]
- [endsect]
- [section:Reference Reference]
- [xinclude units_reference.xml]
- [xinclude dimensions_reference.xml]
- [xinclude si_reference.xml]
- [xinclude cgs_reference.xml]
- [xinclude trig_reference.xml]
- [xinclude temperature_reference.xml]
- [xinclude information_reference.xml]
- [xinclude abstract_reference.xml]
- [section Base Units by Category]
- [xinclude angle_base_units_reference.xml]
- [xinclude astronomical_base_units_reference.xml]
- [xinclude cgs_base_units_reference.xml]
- [xinclude imperial_base_units_reference.xml]
- [xinclude metric_base_units_reference.xml]
- [xinclude si_base_units_reference.xml]
- [xinclude temperature_base_units_reference.xml]
- [xinclude us_base_units_reference.xml]
- [endsect]
- [section Alphabetical Listing of Base Units]
- [include base_units.qbk]
- [endsect]
- [endsect]
- [section:Installation Installation]
- The core header files are located in `boost/units`. Unit system headers are
- located in `<boost/units/systems>`. There are no source files for the library
- itself - the library is header-only. Example programs demonstrating various aspects of the library can be found in
- `boost/libs/units/example`. Programs for unit testing are provided in `boost/libs/units/test`.
- [endsect]
- [section:FAQ FAQ]
- [section:Distinguishing_Quantities_With_Same_Units
- How does one distinguish between quantities that are physically different but have the same units (such as
- energy and torque)?]
- Because Boost.Units includes plane and solid angle units in the SI system, torque and energy
- are, in fact, distinguishable (see [@http://en.wikipedia.org/wiki/SI_units torque]).
- In addition, energy is a true
- [@http://mathworld.wolfram.com/Scalar.html scalar] quantity, while torque, despite
- having the same units as energy if plane angle is not included, is in fact a
- [@http://mathworld.wolfram.com/Pseudovector.html pseudovector]. Thus, a value type representing pseudovectors
- and encapsulating their algebra could also be implemented.
- There are,
- however, a few SI units that are dimensionally indistinguishable within the SI system. These
- include the [@http://en.wikipedia.org/wiki/Becquerel becquerel], which has units identical to
- frequency (Hz), and the [@http://en.wikipedia.org/wiki/Sievert sievert], which is degenerate
- with the [@http://en.wikipedia.org/wiki/Gray_%28unit%29 gray]. In cases such as this,
- the proper way to treat this difference is to recognize that expanding the set of base dimensions
- can provide disambiguation. For example, adding a base dimension for radioactive decays would
- allow the becquerel to be written as decays/second, differentiating it from the signature of hertz,
- which is simply 1/second.
- [endsect]
- [section:Angle_Are_Units Angles are treated as units]
- If you don't like this, you can just ignore the angle units and
- go on your merry way (periodically screwing up when a routine wants degrees and you give it
- radians instead...)
- [endsect]
- [section:Why_Homogeneous_Systems Why are there homogeneous systems? Aren't heterogeneous systems sufficient?]
- Consider the following code:
- cout << asin(sin(90.0 * degrees));
- What should this print? If only heterogeneous
- systems are available it would print 1.5708 rad
- Why? Well, `sin` 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]
- [section:NoConstructorFromValueType Why can't I construct a quantity directly from the value type?]
- This only breaks generic code--which ought to break anyway. The only
- literal value that ought to be converted to a quantity by generic code
- is zero, which should be handled by the default constructor. In addition,
- consider the search and replace problem allowing this poses:
- quantity<si::length> q(1.0);
-
- Here, the intent is clear - we want a length of one in the SI system, which is one meter. However,
- imagine some well-intentioned coder attempting to reuse this code, but to have it perform the
- calculations in the CGS unit system instead. After searching for `si::` and replacing it with `cgs::` ,
- we have:
- quantity<cgs::length> q(1.0);
-
- Unfortunately, the meaning of this statement has suddenly changed from one meter to one centimeter. In
- contrast, as implemented, we begin with:
- quantity<si::length> q(1.0*si::meter);
-
- and, after search and replace:
- quantity<cgs::length> q(1.0*cgs::meter);
-
- which gives us an error. Even if the code has a @using namespace boost::units::si; declaration, the latter
- is still safe, with:
- using namespace boost::units::si;
- quantity<length> q(1.0*meter);
-
- going to
- using namespace boost::units::cgs;
- quantity<length> q(1.0*meter);
-
- The latter will involve an explicit conversion from meters to centimeters, but the value remains correct.
- [endsect]
- [section:ExplicitConversions Why are conversions explicit by default?]
- Safety and the potential for unintended conversions leading to precision loss and hidden performance costs.
- Options are provided for forcing implicit conversions between specific units to be allowed.
- [endsect]
- [endsect]
- [section:Acknowledgements Acknowledgements]
- Matthias C. Schabel would like to acknowledge the Department of Defense for its support of this work under
- the Prostate Cancer Research Program New Investigator Award W81XWH-04-1-0042 and the National Institutes of Health for their
- support of this work under the NIBIB Mentored Quantitative Research Development Award K25EB005077.
- Thanks to David Walthall for his assistance in debugging and testing on a variety of platforms and Torsten Maehne for
- his work on interfacing the Boost Units and Boost Lambda libraries.
- Thanks to:
- * Paul Bristow,
- * Michael Fawcett,
- * Ben FrantzDale,
- * Ron Garcia,
- * David Greene,
- * Peder Holt,
- * Janek Kozicki,
- * Andy Little,
- * Kevin Lynch,
- * Torsten Maehne
- * Noah Roberts,
- * Andrey Semashev,
- * David Walthall,
- * Deane Yang,
- and all the members of the Boost mailing list who provided their input into
- the design and implementation of this library.
- [endsect] [/section:Acknowledgements Acknowledgements]
- [section:HelpWanted Help Wanted]
- Any help in the following areas would be much appreciated:
- * testing on other compilers and operating systems
- * performance testing on various architectures
- * tutorials
- [endsect]
- [section:version_id Version Info]
- __boostroot
- Last edit to Quickbook file __FILENAME__ was at __TIME__ on __DATE__.
- [tip This should appear on the pdf version (but may be redundant on html).]
- [/ Useful on pdf version. See also Last revised timestamp on first page of html version.]
- [/See also Adobe Reader pdf File Properties for creation date, and PDF producer, version and page count.]
- [endsect] [/section:version_id Version Info]
- [section:ReleaseNotes Release Notes]
- 1.2 (March 2010)
- * Added autoprefix ready for Boost 1.43
- 1.0.0 (August 1, 2008) :
- * Initial release with Boost 1.36
- 0.7.1 (March 14, 2007) :
- * Boost.Typeof emulation support.
- * attempting to rebind a heterogeneous_system to a different set of dimensions now fails.
- * cmath.hpp now works with como-win32.
- * minor changes to the tests and examples to make msvc 7.1 happy.
- 0.7.0 (March 13, 2007) :
- * heterogeneous and mixed system functionality added.
- * added fine-grained implicit unit conversion on a per fundamental dimension basis.
- * added a number of utility metafunction classes and predicates.
- * [headerref boost/units/operators.hpp] now uses `BOOST_TYPEOF` when possible.
- * angular units added in [headerref boost/units/systems/angle/gradians.hpp]
- and [headerref boost/units/systems/angle/gradians.hpp].
- Implicit conversion of radians between trigonometric, SI, and CGS systems is allowed.
- * a variety of [___unit] and [___quantity] tests added.
- * examples now provide self-tests.
- 0.6.2 (February 22, 2007) :
- * changed template order in `unit` so dimension precedes unit system
- * added `homogeneous_system<S>` for unit systems
- * incorporated changes to [headerref boost/units/dimension.hpp] (compile-time sorting by predicate),
- [headerref boost/units/conversion.hpp] (thread-safe implementation of quantity conversions),
- and [headerref boost/units/io.hpp] (now works with any `std::basic_ostream`) by SW
- * added abstract units in [headerref boost/units/systems/abstract.hpp] to allow abstract dimensional
- analysis
- * new example demonstrating implementation of code based on requirements from
- Michael Fawcett ([@../../libs/units/example/radar_beam_height.cpp radar_beam_height.cpp])
- 0.6.1 (February 13, 2007) :
- * added metafunctions to test if a type is
- * a valid dimension list (`is_dimension_list<D>`)
- * a unit (`is_unit<T>` and `is_unit_of_system<U,System>`)
- * a quantity (`is_quantity<T>` and `is_quantity_of_system<Q,System>`)
- * quantity conversion factor is now computed at compile time
- * static constants now avoid ODR problems
- * unit_example_14.cpp now uses Boost.Timer
- * numerous minor fixes suggested by SW
- 0.6.0 (February 8, 2007) :
- * incorporated Steven Watanabe's optimized code for dimension.hpp, leading to *dramatic*
- decreases in compilation time (nearly a factor of 10 for unit_example_4.cpp in my tests).
- 0.5.8 (February 7, 2007) :
- * fixed `#include` in [headerref boost/units/systems/si/base.hpp] (thanks to Michael Fawcett and
- Steven Watanabe)
- * removed references to obsolete `base_type` in [___unit_info] (thanks to Michael Fawcett)
- * moved functions in [headerref boost/units/cmath.hpp] into `boost::units` namespace
- (thanks to Steven Watanabe)
- * fixed `#include` guards to be consistently named `BOOST_UNITS_XXX` (thanks to Steven
- Watanabe)
- 0.5.7 (February 5, 2007) :
- * changed quantity conversion helper to increase flexibility
- * minor documentation changes
- * submitted for formal review as a Boost library
- 0.5.6 (January 22, 2007) :
- * added IEEE 1541 standard binary prefixes along with SI prefixes to and extended algebra of
- `scale` and `scaled_value` classes (thanks to Kevin Lynch)
- * split SI units into separate header files to minimize the "kitchen sink" include problem
- (thanks to Janek Kozicki)
- * added convenience classes for declaring fundamental dimensions and composite dimensions
- with integral powers (`fundamental_dimension` and `composite_dimension` respectively)
- 0.5.5 (January 18, 2007) :
- * template parameter order in `quantity` switched and default `value_type` of `double` added
- (thanks to Andrey Semashev and Paul Bristow)
- * added implicit `value_type` conversion where allowed (thanks to Andrey Semashev)
- * added `quantity_cast` for three cases (thanks to Andrey Semashev):
- * constructing `quantity` from raw `value_type`
- * casting from one `value_type` to another
- * casting from one `unit` to another (where conversion is allowed)
- * added` metre` and `metres` and related constants to the SI system for the convenience of
- our Commonwealth friends...
- 0.5.4 (January 12, 2007) :
- * completely reimplemented unit conversion to allow for arbitrary unit conversions
- between systems
- * strict quantity construction is default; quantities can be constructed from bare values
- by using static member `from_value`
- 0.5.3 (December 12, 2006) :
- * added Boost.Serialization support to `unit` and `quantity` classes
- * added option to enforce strict construction of quantities (only constructible
- by multiplication of scalar by unit or quantity by unit) by preprocessor
- `MCS_STRICT_QUANTITY_CONSTRUCTION` switch
- 0.5.2 (December 4, 2006) :
- * added `<cmath>` wrappers in the `std` namespace for functions that can support quantities
- 0.5.1 (November 3, 2006) :
- * converted to Boost Software License
- * boostified directory structure and file paths
- 0.5 (November 2, 2006) :
- * completely reimplemented SI and CGS unit systems and changed syntax for quantities
- * significantly streamlined `pow` and `root` so for most applications it is only
- necessary to define `power_typeof_helper` and `root_typeof_helper` to gain this
- functionality
- * added a selection of physical constants from the CODATA tables
- * added a skeleton `complex` class that correctly supports both `complex<quantity<Y,Unit> >`
- and `quantity<complex<Y>,Unit>` as an example
- * investigate using Boost.Typeof for compilers that do not support `typeof`
- 0.4 (October 13, 2006) :
- * `pow<R>` and `root<R>` improved for user-defined types
- * added unary + and unary - operators
- * added new example of interfacing with `boost::math::quaternion`
- * added optional preprocessor switch to enable implicit unit conversions
- (`BOOST_UNITS_ENABLE_IMPLICIT_UNIT_CONVERSIONS`)
- 0.3 (September 6, 2006) :
- * Support for `op(X x,Y y)` for g++ added. This is automatically
- active when compiling with gcc and can be optionally enabled by defining the preprocessor
- constant `BOOST_UNITS_HAS_TYPEOF`
- 0.2 (September 4, 2006) : Second alpha release based on slightly modified code from 0.1 release
- 0.1 (December 13, 2003) : written as a Boost demonstration of MPL-based dimensional analysis
- in 2003.
- [endsect]
- [section:TODO TODO]
- * Document concepts
- * Implementation of I/O is rudimentary; consider methods of i18n using facets
- * Consider runtime variant, perhaps using overload like `quantity<runtime,Y>`
- [endsect] [/section:TODO TODO]
|