1[library Boost.Units 2 [quickbook 1.5] 3 [version 1.1.0] 4 [authors [Schabel, Matthias C.]] 5 [authors [Watanabe, Steven]] 6 [copyright 2003-2008 Matthias Christian Schabel, 2007-2010 Steven Watanabe] 7 [license 8 Distributed under the Boost Software License, Version 1.0. 9 (See accompanying file LICENSE_1_0.txt or copy at 10 [@http://www.boost.org/LICENSE_1_0.txt]) 11 ] 12 [purpose zero-overhead compile-time dimensional analysis and unit computations] 13] 14 15[/ Some links to external sources.] 16[def __boost [@http://www.boost.org/ Boost]] 17[def __boostroot [@boost: Boost root]] 18[def __boostlicense [@http://www.boost.org/LICENSE_1_0.txt Boost License]] 19[def __boost_mpl [@http://www.boost.org/libs/mpl/doc/index.html Boost Metaprogramming Library]] 20 21[def __mpl_forward_sequence [@http://www.boost.org/libs/mpl/doc/refmanual/forward-sequence.html MPL Forward Sequence]] 22 23[/Links within this document.] 24[def __ordinal [classref boost::units::ordinal ordinal]] 25[def __dim [classref boost::units::dim dim]] 26[def __static_rational [classref boost::units::static_rational static_rational]] 27[def __make_dimension_list [classref boost::units::make_dimension_list make_dimension_list]] 28[def __unit [classref boost::units::unit unit]] 29[def __base_unit_info [classref boost::units::base_unit_info base_unit_info]] 30[def __quantity [classref boost::units::quantity quantity]] 31[def __conversion_helper [classref boost::units::conversion_helper conversion_helper]] 32[def __absolute [classref boost::units::absolute absolute]] 33[def __base_unit [classref boost::units::base_unit base_unit]] 34[def __base_dimension [classref boost::units::base_dimension base_dimension]] 35[def __scaled_base_unit [classref boost::units::scaled_base_unit base_unit]] 36[def __make_scaled_unit [classref boost::units::make_scaled_unit make_scaled_unit]] 37 38[def __unary_plus_typeof_helper [classref boost::units::unary_plus_typeof_helper unary_plus_typeof_helper]] 39[def __unary_minus_typeof_helper [classref boost::units::unary_minus_typeof_helper unary_minus_typeof_helper]] 40[def __add_typeof_helper [classref boost::units::add_typeof_helper add_typeof_helper]] 41[def __subtract_typeof_helper [classref boost::units::subtract_typeof_helper subtract_typeof_helper]] 42[def __multiply_typeof_helper [classref boost::units::multiply_typeof_helper multiply_typeof_helper]] 43[def __divide_typeof_helper [classref boost::units::divide_typeof_helper divide_typeof_helper]] 44[def __power_typeof_helper [classref boost::units::power_typeof_helper power_typeof_helper]] 45[def __root_typeof_helper [classref boost::units::root_typeof_helper root_typeof_helper]] 46 47[def __static_negate [classref boost::units::static_negate static_negate]] 48[def __static_add [classref boost::units::static_add static_add]] 49[def __static_subtract [classref boost::units::static_subtract static_subtract]] 50[def __static_multiply [classref boost::units::static_multiply static_multiply]] 51[def __static_divide [classref boost::units::static_divide static_divide]] 52[def __static_power [classref boost::units::static_power static_power]] 53[def __static_root [classref boost::units::static_root static_root]] 54 55[def __get_dimension [classref boost::units::get_dimension get_dimension]] 56[def __get_system [classref boost::units::get_system get_system]] 57 58[def __pow [funcref boost::units::pow pow]] 59[def __root [funcref boost::units::root root]] 60[def __quantity_cast [funcref boost::units::quantity_cast quantity_cast]] 61 62[def __from_value [memberref boost::units::quantity::from_value from_value]] 63[def __value [memberref boost::units::quantity::value value]] 64 65[def __reduce_unit [classref boost::units::reduce_unit reduce_unit]] 66[def __unscale [classref boost::units::unscale unscale]] 67 68[def __BOOST_UNITS_STATIC_CONSTANT [macroref BOOST_UNITS_STATIC_CONSTANT]] 69[def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR]] 70[def __BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE [macroref BOOST_UNITS_DEFINE_CONVERSION_FACTOR_TEMPLATE]] 71[def __BOOST_UNITS_DEFAULT_CONVERSION [macroref BOOST_UNITS_DEFAULT_CONVERSION]] 72 73[section:Introduction Introduction] 74 75The Boost.Units library is a C++ implementation of dimensional analysis in a general 76and extensible manner, treating it as a generic compile-time metaprogramming problem. With appropriate 77compiler optimization, no runtime execution cost is introduced, facilitating the use of this library to 78provide dimension checking in performance-critical code. Support for units 79and quantities (defined as a unit and associated value) for arbitrary unit system models and arbitrary 80value types is provided, as is a fine-grained general facility for unit conversions. Complete SI and CGS unit 81systems are provided, along with systems for 82angles measured in degrees, radians, gradians, and revolutions and 83systems for temperatures measured in Kelvin, degrees Celsius and degrees Fahrenheit. 84The library architecture has been designed with flexibility and extensibility in mind; demonstrations of the ease 85of adding new units and unit conversions are provided in the examples. 86 87In order to enable complex compile-time dimensional analysis calculations with no runtime overhead, 88Boost.Units relies heavily on the [___boost_mpl] (MPL) and on template metaprogramming techniques, and is, as a consequence, 89fairly demanding of compiler compliance to ISO standards. At present, it has been successfully 90compiled and tested on the following compilers/platforms : 91 92# g++ 4.0.1 on Mac OSX 10.4 93# Intel CC 9.1, 10.0, and 10.1 on Mac OSX 10.4 94# g++ 3.4.4, 4.2.3, and 4.3.0 on Windows XP 95# Microsoft Visual C++ 7.1, 8.0, and 9.0 on Windows XP 96# Comeau 4.3.10.1 beta2 on Windows XP 97# Metrowerks CodeWarrior 9.2 on Windows XP. 98# Sun CC 5.9 on Solaris and Linux 99 100The following compilers/platforms are known *not* to work : 101 102# g++ 3.3.x 103# Microsoft Visual C++ 6.0 on Windows XP 104# Microsoft Visual C++ 7.0 on Windows XP 105# Metrowerks CodeWarrior 8.0 on Windows XP. 106# All versions of Borland. 107 108[endsect] 109 110[section:Quick_Start Quick Start] 111 112Before discussing the basics of the library, we first define a few terms that will be used frequently 113in the following : 114 115* *Base dimension* : A base dimension is loosely defined as a measurable entity of interest; in conventional 116 dimensional analysis, base dimensions include length (\[L\]), mass (\[M\]), time (\[T\]), etc... but there is 117 no specific restriction on what base dimensions can be used. Base dimensions are essentially a tag type and 118 provide no dimensional analysis functionality themselves. 119* *Dimension* : A collection of zero or more base dimensions, each 120 potentially raised to a different rational power. 121 For example, length = \[L\]^1, area = \[L\]^2, velocity = \[L\]^1/\[T\]^1, and 122 energy = \[M\]^1 \[L\]^2/\[T\]^2 are all dimensions. 123* *Base unit* : A base unit represents a specific measure of a dimension. For example, while length is an abstract measure of 124 distance, the meter is a concrete base unit of distance. Conversions are defined using base units. 125 Much like base dimensions, base units are a tag type used solely to define units and do not support dimensional 126 analysis algebra. 127* *Unit* : A set of base units raised to rational exponents, e.g. m^1, kg^1, m^1/s^2. 128* *System* : A unit system is a collection of base units representing all the measurable entities of interest for a 129 specific problem. For example, the SI unit system defines seven base units : length (\[L\]) in meters, 130 mass (\[M\]) in kilograms, time (\[T\]) in seconds, current (\[I\]) in amperes, temperature (\[theta\]) in kelvin, 131 amount (\[N\]) in moles, and luminous intensity (\[J\]) in candelas. All measurable entities within the SI system can 132 be represented as products of various integer or rational powers of these seven base units. 133* *Quantity* : A quantity represents a concrete amount of a unit. Thus, while the meter is the base 134 unit of length in the SI system, 5.5 meters is a quantity of length in that system. 135 136To begin, we present two short tutorials. [@../../libs/units/tutorial/tutorial_1.cpp Tutorial1] demonstrates the use of 137[@http://en.wikipedia.org/wiki/SI_units SI] units. After including the appropriate system headers 138and the headers for the various SI units we will need (all SI units can be included with 139[headerref boost/units/systems/si.hpp]) and for quantity I/O ([headerref boost/units/io.hpp]), we define 140a function that computes the work, in joules, done by exerting a force in newtons over a specified distance in meters 141and outputs the result to `std::cout`. The [___quantity] class accepts a second template parameter as its value type; 142this parameter defaults to 143`double` if not otherwise specified. To demonstrate the ease of using user-defined types in dimensional 144calculations, we also present code for computing the complex impedance using `std::complex<double>` 145as the value type : 146 147[import ../example/tutorial.cpp] 148 149[tutorial_code] 150 151The intent and function of the above code should be obvious; the output produced is : 152 153[tutorial_output] 154 155While this library attempts to make simple dimensional computations easy to code, it is in no way 156tied to any particular unit system (SI or otherwise). Instead, it provides a highly flexible compile-time 157system for dimensional analysis, supporting arbitrary collections of base dimensions, rational 158powers of units, and explicit quantity conversions. It accomplishes all of this via template metaprogramming techniques. 159With modern optimizing compilers, this results in zero runtime overhead for quantity computations relative to the 160same code without unit checking. 161 162[endsect] 163 164[section:Dimensional_Analysis Dimensional Analysis] 165 166The concept of 167[@http://en.wikipedia.org/wiki/Dimensional_analysis dimensional analysis] 168is normally presented early on in introductory physics and engineering classes as a means of determining the 169correctness of an equation or computation by propagating the physical measurement 170[@http://en.wikipedia.org/wiki/Units_of_measurement units] 171of various quantities through the equation along with their numerical values. There are a number of standard 172unit systems in common use, the most prominent of which is the 173[@http://en.wikipedia.org/wiki/SI_units Systeme International] 174(also known as SI or MKS (meter-kilogram-second), which was a metric predecessor to the SI system named 175for three of the base units on which the system is based). The SI 176is the only official international standard unit system and is widely utilized in science and engineering. 177Other common systems include the [@http://en.wikipedia.org/wiki/Cgs_units CGS] 178(centimeter-gram-second) system and the 179[@http://en.wikipedia.org/wiki/English_units English] 180system still in use in some problem domains in the United States and elsewhere. In physics, 181there also exist a number of other systems that are in common use in specialized subdisciplines. These are 182collectively referred to as [@http://en.wikipedia.org/wiki/Natural_units natural units]. When 183quantities representing different measurables are combined, dimensional analysis provides the means of 184assessing the consistency of the resulting calculation. For example, the sum of two lengths is also a length, 185while the product of two lengths is an area, and the sum of a length and an area is undefined. The fact that the 186arguments to many functions (such as exp, log, etc...) must be dimensionless quantities can be easily demonstrated by 187examining their series expansions in the context of dimensional analysis. This library facilitates the enforcement 188of this type of restriction in code involving dimensioned quantities where appropriate. 189 190In the following discussion we view dimensional analysis as an abstraction in which an arbitrary set of 191[@http://en.wikipedia.org/wiki/Fundamental_units units] obey the rules of a specific algebra. 192We will refer to a pair of a base dimension and a rational exponent as a *fundamental dimension*, 193and a list composed of an arbitrary number of fundamental dimensions as a *composite dimension* or, simply, 194*dimension*. In particular, given a set of [$../../libs/units/images/form_0.png] fundamental dimensions 195denoted by [$../../libs/units/images/form_1.png] and a set of [$../../libs/units/images/form_0.png] 196rational exponents [$../../libs/units/images/form_2.png], any possible (composite) dimension can be written 197as [$../../libs/units/images/form_3.png]. 198 199Composite dimensions obey the algebraic rules for dimensional analysis. In particular, for any scalar value, 200[$../../libs/units/images/form_4.png], 201and composite dimensions [$../../libs/units/images/form_5.png] 202and [$../../libs/units/images/form_6.png], where 203[$../../libs/units/images/form_7.png], we have: 204 205[$../../libs/units/images/form_8.png] 206 207Users of a dimensional analysis library should be able to specify an arbitrary list of base dimensions to 208produce a composite dimension. This potentially includes repeated tags. For example, 209it should be possible to express energy as [$../../libs/units/images/form_9.png], [$../../libs/units/images/form_10.png], 210[$../../libs/units/images/form_11.png], or any other permutation of mass, length, and time having aggregate exponents of 2111, 2, and -2, respectively. 212In order to be able to perform computations on arbitrary sets of dimensions, 213all composite dimensions must be reducible to an unambiguous final composite dimension, which we will refer to as a 214*reduced dimension*, for which 215 216# fundamental dimensions are consistently ordered 217# dimensions with zero exponent are elided. Note that reduced dimensions never have more than 218 [$../../libs/units/images/form_0.png] base dimensions, one for each distinct fundamental dimension, but may have fewer. 219 220In our implementation, base dimensions are associated with tag types. As we will ultimately 221represent composite dimensions as typelists, we must provide some mechanism for sorting 222base dimension tags in order to make it possible to convert an arbitrary composite dimension 223into a reduced dimension. For this purpose, we assign a unique integer to each base dimension. 224The [___base_dimension] class (found in [headerref boost/units/base_dimension.hpp]) uses the 225curiously recurring template pattern (CRTP) technique to ensure that ordinals specified for 226base dimensions are unique: 227 228 template<class Derived, long N> struct base_dimension { ... }; 229 230With this, we can define the base dimensions for length, mass, and time as: 231 232[import ../example/test_system.hpp] 233[test_system_snippet_1] 234 235It is important to note that the choice of order is completely arbitrary as long as each tag has a unique enumerable 236value; non-unique ordinals are flagged as errors at compile-time. Negative ordinals are reserved for use by the library. 237To define composite dimensions corresponding to the base dimensions, we 238simply create MPL-conformant typelists of fundamental dimensions by using the [___dim] class to encapsulate pairs of base dimensions 239and [___static_rational] exponents. The [___make_dimension_list] class acts as a wrapper to ensure 240that the resulting type is in the form of a reduced dimension: 241 242[test_system_snippet_2] 243 244This can also be easily accomplished using a convenience typedef provided by [___base_dimension]: 245 246[test_system_snippet_3] 247 248so that the above code is identical to the full typelist definition. Composite dimensions are similarly defined via a typelist: 249 250[test_system_snippet_4] 251 252A convenience class for composite dimensions with integer powers is also provided: 253 254[test_system_snippet_5] 255 256[endsect] 257 258[section:Units Units] 259 260We define a *unit* as a set of base units each of which can be raised to an arbitrary rational 261exponent. Thus, the SI unit corresponding to the dimension of force is kg m s^-2, where kg, m, 262and s are base units. We use the notion of a *unit system* such as SI to specify the mapping 263from a dimension to a particular unit so that instead of specifying the base units explicitly, 264we can just ask for the representation of a dimension in a particular system. 265 266Units are, like dimensions, purely compile-time variables with no associated value. 267Units obey the same algebra as dimensions do; the presence of the unit system serves to ensure that units having identical 268reduced dimension in different systems (like feet and meters) cannot be inadvertently mixed in computations. 269 270There are two distinct types of systems that can be envisioned: 271 272* *Homogeneous systems* : Systems which hold a linearly independent set of base units which 273 can be used to represent many different dimensions. For example, the SI system has seven 274 base dimensions and seven base units corresponding to them. It can represent any unit which 275 uses only those seven base dimensions. Thus it is a homogeneous_system. 276* *Heterogeneous systems* : Systems which store the exponents of every base unit involved 277 are termed heterogeneous. Some units can only be represented in this way. For example, 278 area in m ft is intrinsically heterogeneous, because the base units of meters and feet 279 have identical dimensions. As a result, simply storing a dimension and a set of base 280 units does not yield a unique solution. A practical example of the need for heterogeneous 281 units, is an empirical equation used in aviation: H = (r/C)^2 where H is the radar beam 282 height in feet and r is the radar range in nautical miles. In order to enforce dimensional 283 correctness of this equation, the constant, C, must be expressed in nautical miles per foot^(1/2), 284 mixing two distinct base units of length. 285 286Units are implemented by the [___unit] template class defined in [headerref boost/units/unit.hpp] : 287 288 template<class Dim,class System> class unit; 289 290In addition to supporting the compile-time dimensional analysis operations, the +, -, *, and / runtime operators are provided 291for [___unit] variables. Because the dimension associated with powers and roots must be computed at compile-time, it is not 292possible to provide overloads for `std::pow` that function correctly for [___unit]s. These operations are supported through 293free functions [___pow] and [___root] that are templated on integer and [___static_rational] values and can take as an argument 294any type for which the utility classes [___power_typeof_helper] and [___root_typeof_helper] have been defined. 295 296[section Base Units] 297 298Base units are defined much like base dimensions. 299 300 template<class Derived, class Dimensions, long N> struct base_unit { ... }; 301 302Again negative ordinals are reserved. 303 304As an example, in the following we will implement a subset of the SI unit system based on the fundamental dimensions 305given above, demonstrating all steps necessary for a completely functional system. First, we simply define a unit system 306that includes type definitions for commonly used units: 307 308[test_system_snippet_6] 309 310The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp] 311to facilitate ODR- and thread-safe constant definition in header files. We then define some constants for the supported units 312to simplify variable definitions: 313 314[test_system_snippet_7] 315 316If support for textual output of units is desired, we can also specialize the [___base_unit_info] class for each fundamental 317dimension tag: 318 319[test_system_snippet_8] 320 321and similarly for `kilogram_base_unit` and `second_base_unit`. A future version of the library will provide a more flexible system 322allowing for internationalization through a facet/locale-type mechanism. 323The `name()` and `symbol()` methods of [___base_unit_info] provide full and short names for the base unit. With these definitions, 324we have the rudimentary beginnings of our unit system, which can be used to determine reduced dimensions for arbitrary 325unit calculations. 326 327[endsect] [/section Base Units] 328 329[section Scaled Base Units] 330 331Now, it is also possible to define a base unit as being a multiple of 332another base unit. For example, the way that `kilogram_base_unit` is 333actually defined by the library is along the following lines 334 335 struct gram_base_unit : boost::units::base_unit<gram_base_unit, mass_dimension, 1> {}; 336 typedef scaled_base_unit<gram_base_unit, scale<10, static_rational<3> > > kilogram_base_unit; 337 338This basically defines a kilogram as being 10^3 times a gram. 339 340There are several advantages to this approach. 341 342* It reflects the real meaning of these units better than treating them as independent units. 343* If a conversion is defined between grams or kilograms and some other units, 344 it will automatically work for both kilograms and grams, with only one specialization. 345* Similarly, if the symbol for grams is defined as "g", then the symbol for kilograms 346 will be "kg" without any extra effort. 347 348[endsect] [/section Scaled Base Units] 349 350[section Scaled Units] 351 352We can also scale a [___unit] as a whole, rather than scaling the individual 353base units which comprise it. For this purpose, we use the metafunction 354[___make_scaled_unit]. The main motivation for this feature is the metric 355prefixes defined in [headerref boost/units/systems/si/prefixes.hpp]. 356 357A simple example of its usage would be. 358 359 typedef make_scaled_unit<si::time, scale<10, static_rational<-9> > >::type nanosecond; 360 361nanosecond is a specialization of [___unit], and can be used in a quantity normally. 362 363 quantity<nanosecond> t(1.0 * si::seconds); 364 std::cout << t << std::endl; // prints 1e9 ns 365 366[endsect] [/section Scaled Units] 367 368[endsect] [/section:Units Units] 369 370[section:Quantities Quantities] 371 372A *quantity* is defined as a value of an arbitrary value type that is associated with a specific unit. For example, 373while meter is a unit, 3.0 meters is a quantity. Quantities obey two separate algebras: the native algebra for their 374value type, and the dimensional analysis algebra for the associated unit. In addition, algebraic operations are defined 375between units and quantities to simplify the definition of quantities; it is effectively equivalent to algebra with 376a unit-valued quantity. 377 378Quantities are implemented by the [___quantity] template class defined in [headerref boost/units/quantity.hpp] : 379 380 template<class Unit,class Y = double> class quantity; 381 382This class is templated on both unit type (`Unit`) and value type (`Y`), with the latter defaulting to double-precision 383floating point if not otherwise specified. The value type must have a normal copy constructor and copy 384assignment operator. Operators +, -, *, and / are provided for algebraic operations between 385scalars and units, scalars and quantities, units and quantities, and between quantities. In addition, integral and 386rational powers and roots can be computed using the [___pow]<R> and [___root]<R> functions. Finally, 387the standard set of boolean comparison operators ( `==, !=, <, <=, >, and >=` ) are provided to allow 388comparison of quantities from the same unit system. All operators simply delegate to the 389corresponding operator of the value type if the units permit. 390 391[section:Heterogeneous_Operators Heterogeneous Operators] 392 393For most common value types, the result type of arithmetic operators is the same as the value type itself. For example, 394the sum of two double precision floating point numbers is another double precision floating point number. However, there 395are instances where this is not the case. A simple example is given by the [@http://en.wikipedia.org/wiki/Natural_number 396natural numbers] where the operator arithmetic obeys the following rules (using the standard notation for 397[@http://en.wikipedia.org/wiki/Number number systems]): 398 399* [$../../libs/units/images/form_12.png] 400* [$../../libs/units/images/form_13.png] 401* [$../../libs/units/images/form_14.png] 402* [$../../libs/units/images/form_15.png] 403 404This library is designed to support arbitrary value type algebra for addition, subtraction, multiplication, division, and 405rational powers and roots. It uses Boost.Typeof to deduce the result of these operators. For compilers that 406support `typeof`, the appropriate value type will be automatically deduced. For compilers that do not provide 407language support for `typeof` it is necessary to register all the types used. For the case of natural numbers, 408this would amount to something like the following: 409 410 BOOST_TYPEOF_REGISTER_TYPE(natural); 411 BOOST_TYPEOF_REGISTER_TYPE(integer); 412 BOOST_TYPEOF_REGISTER_TYPE(rational); 413 414[endsect] 415 416[section:Conversions Conversions] 417 418Conversion is only meaningful for quantities as it implies the presence of at 419least a multiplicative scale factor and, possibly, and affine linear offset. 420Macros for simplifying the definition of conversions between units can be found in 421[headerref boost/units/conversion.hpp] and [headerref boost/units/absolute.hpp] 422(for affine conversions with offsets). 423 424The macro [___BOOST_UNITS_DEFINE_CONVERSION_FACTOR] specifies a scale 425factor for conversion from the first unit type to the second. The 426first argument must be a [___base_unit]. The second argument 427can be either a [___base_unit] or a [___unit]. 428 429Let's declare a simple base unit: 430 431 struct foot_base_unit : base_unit<foot_base_unit, length_dimension, 10> { }; 432 433Now, we want to be able to convert feet to meters and vice versa. The foot 434is defined as exactly 0.3048 meters, so we can write the following 435 436 BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, meter_base_unit, double, 0.3048); 437 438Alternately, we could use the SI length `typedef`: 439 440 BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, SI::length, double, 0.3048); 441 442Since the SI unit of length is the meter, these two definitions are equivalent. 443If these conversions have been defined, then converting between 444scaled forms of these units will also automatically work. 445 446The macro [___BOOST_UNITS_DEFAULT_CONVERSION] specifies a conversion 447that will be applied to a base unit when no direct conversion is 448possible. This can be used to make arbitrary conversions work 449with a single specialization: 450 451 struct my_unit_tag : boost::units::base_unit<my_unit_tag, boost::units::force_type, 1> {}; 452 // define the conversion factor 453 BOOST_UNITS_DEFINE_CONVERSION_FACTOR(my_unit_tag, SI::force, double, 3.14159265358979323846); 454 // make conversion to SI the default. 455 BOOST_UNITS_DEFAULT_CONVERSION(my_unit_tag, SI::force); 456 457[endsect] 458 459[section:Quantity_Construction_and_Conversion Construction and Conversion of Quantities] 460 461This library is designed to emphasize safety above convenience when performing operations with dimensioned quantities. 462Specifically, construction of quantities is required to fully specify both value and unit. Direct construction from a scalar value 463is prohibited (though the static member function [___from_value] is provided to enable 464this functionality where it is necessary. In addition, a [___quantity_cast] to a reference allows direct access to the 465underlying value of a [___quantity] variable. An explicit constructor is provided to enable conversion between 466dimensionally compatible quantities in different unit systems. Implicit conversions between unit systems are 467allowed only when the reduced units are identical, allowing, for example, trivial conversions between 468equivalent units in different systems (such as SI seconds and CGS seconds) while simultaneously enabling 469unintentional unit system mismatches to be caught at compile time and preventing potential loss of precision and 470performance overhead from unintended conversions. Assignment follows the same rules. 471An exception is made for quantities for which the unit reduces to dimensionless; in this case, implicit conversion 472to the underlying value type is allowed via class template specialization. Quantities of different value types are implicitly 473convertible only if the value types are themselves implicitly convertible. The [___quantity] class also defines 474a `value()` member for directly accessing the underlying value. 475 476To summarize, conversions are allowed under the following conditions : 477 478* implicit conversion of `quantity<Unit,Y>` to `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible. 479* assignment between `quantity<Unit,Y>` and `quantity<Unit,Z>` is allowed if `Y` and `Z` are implicitly convertible. 480* explicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` and `Unit2` have the same dimensions 481 and if `Y` and `Z` are implicitly convertible. 482* implicit conversion between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed if `Unit1` 483 reduces to exactly the same combination of base units as `Unit2` and if `Y` and `Z` are convertible. 484* assignment between `quantity<Unit1,Y>` and `quantity<Unit2,Z>` is allowed under the same 485 conditions as implicit conversion. 486* `quantity<Unit,Y>` can be directly constructed from a value of type `Y` using the static member function [___from_value]. Doing so, 487 naturally, bypasses any type-checking of the newly assigned value, so this method should be used only when absolutely necessary. 488 489Of course, any time implicit conversion is allowed, an explicit conversion is 490also legal. 491 492Because dimensionless quantities have no associated units, they behave as normal scalars, and allow implicit conversion to and from 493the underlying value type or types that are convertible to/from that value type. 494 495[endsect] 496 497[endsect] 498 499[section:Examples Examples] 500 501[section:DimensionExample Dimension Example] 502 503([@../../libs/units/example/dimension.cpp dimension.cpp]) 504 505By using MPL metafunctions and the template specializations for operations on composite dimensions 506(defined in [headerref boost/units/dimension.hpp]) it is possible to perform compile time arithmetic 507according to the dimensional analysis rules described [link boost_units.Dimensional_Analysis above] 508to produce new composite dimensions : 509 510[import ../example/dimension.cpp] 511 512[dimension_snippet_1] 513 514outputting (with symbol demangling, implemented in 515[@boost:/boost/units/detail/utility.hpp utility.hpp]) 516 517[dimension_output] 518 519[endsect] 520 521[section:UnitExample Unit Example] 522 523([@../../libs/units/example/unit.cpp unit.cpp]) 524 525This example demonstrates the use of the simple but functional unit system implemented in 526[@boost:/libs/units/example/test_system.hpp test_system.hpp] 527 528[import ../example/unit.cpp] 529 530[unit_snippet_1] 531 532We can perform various algebraic operations on these units, resulting in the following output: 533 534[unit_output] 535 536[endsect] 537 538[section:QuantityExample Quantity Example] 539 540([@../../libs/units/example/quantity.cpp quantity.cpp]) 541 542This example demonstrates how to use quantities of our toy unit system : 543 544[import ../example/quantity.cpp] 545 546[quantity_snippet_1] 547 548giving us the basic quantity functionality : 549 550[quantity_output_double] 551 552As a further demonstration of the flexibility of the system, we replace the `double` value type 553with a `std::complex<double>` value type (ignoring the question of the meaningfulness of 554complex lengths and energies) : 555 556[quantity_snippet_2] 557 558and find that the code functions exactly as expected with no additional work, delegating operations 559to `std::complex<double>` and performing the appropriate dimensional analysis : 560 561[quantity_output_complex] 562 563[endsect] 564 565[section:KitchenSinkExample Kitchen Sink Example using SI units] 566 567([@../../libs/units/example/kitchen_sink.cpp kitchen_sink.cpp]) 568 569This example provides a fairly extensive set of tests covering most of the [___quantity] functionality. 570It uses the SI unit system defined in [headerref boost/units/systems/si.hpp]. 571 572If we define a few units and associated quantities, 573 574[import ../example/kitchen_sink.cpp] 575 576[kitchen_sink_snippet_1] 577 578the various algebraic operations between scalars, units, and quantities give 579 580[kitchen_sink_output_1] 581 582Scalar/unit operations : 583 584[kitchen_sink_output_2] 585 586Unit/unit operations and integral/rational powers of units : 587 588[kitchen_sink_output_3] 589 590Scalar/quantity operations : 591 592[kitchen_sink_output_4] 593 594Unit/quantity operations : 595 596[kitchen_sink_output_5] 597 598Quantity/quantity operations and integral/rational powers of quantities : 599 600[kitchen_sink_output_6] 601 602Logical comparison operators are also defined between quantities : 603 604[kitchen_sink_snippet_2] 605 606giving 607 608[kitchen_sink_output_7] 609 610Implicit conversion is allowed between dimensionless quantities and their corresponding value types : 611 612[kitchen_sink_snippet_3] 613 614A generic function for computing mechanical work can be defined that takes force and distance arguments 615in an arbitrary unit system and returns energy in the same system: 616 617[kitchen_sink_function_snippet_3] 618 619[kitchen_sink_snippet_4] 620 621which functions as expected for SI quantities : 622 623[kitchen_sink_output_9] 624 625The ideal gas law can also be implemented in SI units : 626 627[kitchen_sink_function_snippet_4] 628 629[kitchen_sink_snippet_5] 630 631with the resulting output : 632 633[kitchen_sink_output_10] 634 635Trigonometric and inverse trigonometric functions can be implemented for any unit system 636that provides an angular base dimension. For radians, these functions are found in 637[headerref boost/units/cmath.hpp] These behave as one expects, with trigonometric functions 638taking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functions 639take a dimensionless quantity and return an angular quantity : 640 641Defining a few angular quantities, 642 643[kitchen_sink_snippet_6] 644 645yields 646 647[kitchen_sink_output_11] 648 649Dealing with complex quantities is trivial. Here is the calculation of complex impedance : 650 651[kitchen_sink_snippet_7] 652 653giving 654 655[kitchen_sink_output_12] 656 657[section:UDT_Quantities User-defined value types] 658 659User-defined value types that support the appropriate arithmetic operations are automatically supported 660as quantity value types. The operators that are supported by default for quantity value types are unary plus, unary minus, 661addition, subtraction, multiplication, division, equal-to, not-equal-to, less-than, less-or-equal-to, 662greater-than, and greater-or-equal-to. Support for rational powers and roots can be added by overloading 663the [___power_typeof_helper] and [___root_typeof_helper] classes. Here we implement a user-defined `measurement` 664class that models a numerical measurement with an associated measurement error and the appropriate algebra and 665demonstrates its use as a quantity value type; the full code is found in [@../../libs/units/example/measurement.hpp measurement.hpp]. 666 667Then, defining some `measurement` [___quantity] variables 668 669[kitchen_sink_snippet_8] 670 671gives 672 673[kitchen_sink_output_13] 674 675If we implement the overloaded helper classes for rational powers and roots 676then we can also compute rational powers of measurement quantities : 677 678[kitchen_sink_output_14] 679 680[endsect] 681 682[endsect] 683 684[section:ConversionExample Conversion Example] 685 686([@../../libs/units/example/conversion.cpp conversion.cpp]) 687 688This example demonstrates the various allowed conversions between SI and CGS units. Defining some 689quantities 690 691[import ../example/conversion.cpp] 692 693[conversion_snippet_1] 694 695illustrates implicit conversion of quantities of different value types where implicit conversion 696of the value types themselves is allowed. N.B. The conversion from double to int is treated 697as an explicit conversion because there is no way to emulate the exact behavior of the built-in 698conversion. Explicit constructors allow conversions for two cases: 699 700* explicit casting of a [___quantity] to a different `value_type` : 701 702[conversion_snippet_3] 703 704* and explicit casting of a [___quantity] to a different unit : 705 706[conversion_snippet_4] 707 708giving the following output : 709 710[conversion_output_1] 711 712A few more explicit unit system conversions : 713 714[conversion_snippet_5] 715 716which produces the following output: 717 718[conversion_output_2] 719 720[endsect] 721 722[section:UDTExample User Defined Types] 723 724([@../../libs/units/example/quaternion.cpp quaternion.cpp]) 725 726This example demonstrates the use of `boost::math::quaternion` as a value type for [___quantity] and the converse. 727For the first case, we first define specializations of [___power_typeof_helper] and [___root_typeof_helper] for 728powers and roots, respectively: 729 730[import ../example/quaternion.cpp] 731 732[quaternion_class_snippet_1a] 733 734[quaternion_class_snippet_1b] 735 736We can now declare a [___quantity] of a `quaternion` : 737 738[quaternion_snippet_1] 739 740so that all operations that are defined in the `quaternion` class behave correctly. If rational 741powers were defined for this class, it would be possible to compute rational powers and roots with 742no additional changes. 743 744[quaternion_output_1] 745 746Now, if for some reason we preferred the [___quantity] to be the value type of the `quaternion` class we would have : 747 748[quaternion_snippet_2] 749 750Here, the unary plus and minus and addition and subtraction operators function correctly. Unfortunately, 751the multiplication and division operations fail because `quaternion` implements them in terms of the `*=` and 752`/=` operators, respectively, which are incapable of representing the heterogeneous unit algebra needed for 753quantities (an identical problem 754occurs with `std::complex<T>`, for the same reason). In order to compute rational powers and roots, we need to 755specialize [___power_typeof_helper] and [___root_typeof_helper] as follows: 756 757[quaternion_class_snippet_2a] 758 759[quaternion_class_snippet_2b] 760 761giving: 762 763[quaternion_output_2] 764 765[endsect] 766 767[section:ComplexExample Complex Example] 768 769([@../../libs/units/example/complex.cpp complex.cpp]) 770 771This example demonstrates how to implement a replacement `complex` class that functions correctly both as a 772quantity value type and as a quantity container class, including heterogeneous multiplication and division 773operations and rational powers and roots. Naturally, heterogeneous operations are only supported on 774compilers that implement `typeof`. The primary differences are that binary operations are not implemented 775using the `op=` operators and use the utility classes [___add_typeof_helper], [___subtract_typeof_helper], 776[___multiply_typeof_helper], and [___divide_typeof_helper]. In addition, [___power_typeof_helper] and 777[___root_typeof_helper] are defined for both cases : 778 779[import ../example/complex.cpp] 780 781[complex_class_snippet_1] 782 783With this replacement `complex` class, we can declare a complex variable : 784 785[complex_snippet_1] 786 787to get the correct behavior for all cases supported by [___quantity] with a `complex` value type : 788 789[complex_output_1] 790 791and, similarly, `complex` with a [___quantity] value type 792 793[complex_snippet_2] 794 795gives 796 797[complex_output_2] 798 799[endsect] 800 801[section:PerformanceExample Performance Example] 802 803([@../../libs/units/example/performance.cpp performance.cpp]) 804 805This example provides an ad hoc performance test to verify that zero runtime overhead 806is incurred when using [___quantity] in place of `double`. Note that performance 807optimization and testing is not trivial, so some care must be taken in profiling. It 808is also critical to have a compiler capable of optimizing the many template instantiations 809and inline calls effectively to achieve maximal performance. Zero overhead for this test 810has 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 811using msvc 8.0 on Windows XP. 812 813[endsect] 814 815[section:RadarBeamHeightExample Radar Beam Height] 816 817([@../../libs/units/example/radar_beam_height.cpp radar_beam_height.cpp]) 818 819[import ../example/radar_beam_height.cpp] 820 821This example demonstrates the implementation of two non-SI units of length, the 822nautical mile : 823 824[radar_beam_height_class_snippet_1] 825 826and the imperial foot : 827 828[radar_beam_height_class_snippet_2] 829 830These units include conversions between themselves and the meter. Three functions 831for computing radar beam height from radar range and the local earth radius are 832defined. The first takes arguments in one system and returns a value in the same 833system : 834 835[radar_beam_height_function_snippet_1] 836 837The second is similar, but is templated on return type, so that the arguments are 838converted to the return unit system internally : 839 840[radar_beam_height_function_snippet_2] 841 842Finally, the third function is an empirical approximation that is only valid for 843radar ranges specified in nautical miles, returning beam height in feet. This 844function uses the heterogeneous unit of nautical miles per square root of feet to 845ensure dimensional correctness : 846 847[radar_beam_height_function_snippet_3] 848 849With these, we can compute radar beam height in various unit systems : 850 851[radar_beam_height_snippet_1] 852 853giving 854 855[radar_beam_height_output] 856 857[endsect] 858 859[section:HeterogeneousUnitExample Heterogeneous Unit Example] 860 861([@../../libs/units/example/heterogeneous_unit.cpp heterogeneous_unit.cpp]) 862 863[import ../example/heterogeneous_unit.cpp] 864 865Mixed units and mixed unit conversions. 866 867This code: 868 869[heterogeneous_unit_snippet_1] 870 871gives 872 873[heterogeneous_unit_output_1] 874 875Arbitrary conversions also work: 876 877[heterogeneous_unit_snippet_2] 878 879yielding 880 881[heterogeneous_unit_output_2] 882 883[endsect] 884 885[section:AbsoluteRelativeTemperatureExample Absolute and Relative Temperature Example] 886 887([@../../libs/units/example/temperature.cpp temperature.cpp]) 888 889[import ../example/temperature.cpp] 890 891This example demonstrates using of absolute temperatures and relative temperature differences in Fahrenheit 892and converting between these and the Kelvin temperature scale. This issue touches on some surprisingly deep mathematical 893concepts (see [@http://en.wikipedia.org/wiki/Affine_space Wikipedia] for a basic review), but for our purposes here, we 894will simply observe that it is important to be able to differentiate between an absolute temperature measurement and a 895measurement of temperature difference. This is accomplished by using the [___absolute] wrapper class. 896 897First we define a system using the predefined fahrenheit base unit: 898 899[temperature_snippet_1] 900 901Now we can create some quantities: 902 903[temperature_snippet_3] 904 905Note the use of [___absolute] to wrap a unit. The resulting output is: 906 907[temperature_output_1] 908 909[endsect] 910 911[section:RuntimeConversionFactorExample Runtime Conversion Factor Example] 912 913([@../../libs/units/example/runtime_conversion_factor.cpp runtime_conversion_factor.cpp]) 914 915[import ../example/runtime_conversion_factor.cpp] 916 917The Boost.Units library does not require that the conversion factors be compile time constants, 918as is demonstrated in this example: 919 920[runtime_conversion_factor_snippet_1] 921 922[endsect] 923 924[section:UnitsWithNonbaseDimensions Units with Non-base Dimensions] 925 926([@../../libs/units/example/non_base_dimension.cpp non_base_dimension.cpp]) 927 928[import ../example/non_base_dimension.cpp] 929 930It is also possible to define base units that have derived rather than base dimensions: 931 932[non_base_dimension_snippet_1] 933 934[endsect] 935 936[section:OutputForCompositeUnits Output for Composite Units] 937 938([@../../libs/units/example/composite_output.cpp composite_output.cpp]) 939 940[import ../example/composite_output.cpp] 941 942If a unit has a special name and/or symbol, the free functions `name_string` and 943`symbol_string` can be overloaded directly. 944 945[composite_output_snippet_1] 946 947In this case, any unit that reduces 948to the overloaded unit will be output with the replacement symbol. 949 950Special names and symbols for the SI and CGS unit systems are found in 951[headerref boost/units/systems/si/io.hpp] and [headerref boost/units/systems/cgs/io.hpp], 952respectively. If these headers are not included, the output will simply follow 953default rules using the appropriate fundamental dimensions. 954Note that neither of these functions is defined for quantities 955because doing so would require making assumptions on how the corresponding value 956type should be formatted. 957 958Three `ostream` formatters, `symbol_format`, `name_format`, and `typename_format` 959are provided for convenience. These select the textual representation of units 960provided by `symbol_string` or `name_string` in the first two cases, while the 961latter returns a demangled typename for debugging purposes. Formatting of scaled 962unit is also done correctly. 963 964[endsect] 965 966[section:autoscale Automatically Scaled Units] 967 968It is often desirable to scale a [___unit] automatically, depending on its value, 969to keep the integral part in a limited range, usually between 1 and 999. 970 971For example, using [@http://en.wikipedia.org/wiki/Engineering_notation engineering notation prefixes], 972 973 "1234.5 m" is more helpfully displayed as "1.234 km" 974 "0.000000001234 m" is more clearly displayed as "1.2345 nanometer". 975 976The iostream manipulators `engineering_prefixes` or `binary_prefixes` make this easy. 977 978[import ../example/autoprefixes.cpp] 979 980[autoprefixes_snippet_1] 981 982(The complete set of [@http://physics.nist.gov/cuu/Units/prefixes.html engineering and scientific multiples] 983is not used (not centi or deci for example), but only powers of ten that are multiples of three, 10^3). 984 985Similarly, the equivalent [@http://en.wikipedia.org/wiki/Binary_prefixes binary prefixes] 986used for displaying computing kilobytes, megabytes, gigabytes... 987 988These are the 2^10 = 1024, 2^20 = 1 048 576, 2^30 ... multiples. 989 990(See also [@http://physics.nist.gov/cuu/Units/binary.html Prefixes for binary multiples] 991 992This scale is specified in IEC 60027-2, Second edition, 2000-11, 993Letter symbols to be used in electrical technology - 994Part 2: Telecommunications and electronics). 995 996[autoprefixes_snippet_2] 997 998But note that scalar dimensionless values, like int, float and double, 999are *not* prefixed automatically by the engineering_prefix or binary_prefix iostream manipulators. 1000 1001[autoprefixes_snippet_3] 1002 1003You can output the name or symbol of a unit (rather than the most common quantity of a unit). 1004 1005[autoprefixes_snippet_4] 1006 1007Note too that all the formatting flags are persistent, 1008so that if you set engineering_prefix, then it applies to all future outputs, 1009until you select binary_prefix, or explicitly switch autoprefix off. 1010You can specify no prefix (the default of course) in two ways: 1011 1012[autoprefixes_snippet_5] 1013 1014And you can get the format flags for diagnosing problems. 1015 1016[autoprefixes_snippet_6] 1017 1018[endsect] [/section:autoscale Automatically Scaled Units] 1019 1020[section:ConversionFactor Conversion Factor] 1021 1022This code demonstrates the use of the `conversion_factor` free function to determine 1023the scale factor between two units. 1024 1025([@../../libs/units/example/conversion_factor.cpp conversion_factor.cpp]) 1026 1027[import ../example/conversion_factor.cpp] 1028 1029[conversion_factor_snippet_1] 1030 1031Produces 1032 1033[conversion_factor_output] 1034 1035[endsect] 1036 1037[section:RuntimeUnits Runtime Units] 1038 1039([@../../libs/units/example/runtime_unit.cpp runtime_unit.cpp]) 1040 1041[import ../example/runtime_unit.cpp] 1042 1043This example shows how to implement an interface that 1044allow different units at runtime while still maintaining 1045type safety for internal calculations. 1046 1047[runtime_unit_snippet_1] 1048 1049[endsect] 1050 1051[section:lambda Interoperability with Boost.Lambda] 1052 1053([@../../libs/units/example/lambda.cpp lambda.cpp]) 1054 1055[import ../example/lambda.cpp] 1056 1057The header [headerref boost/units/lambda.hpp] provides overloads 1058and specializations needed to make Boost.Units usable with the 1059Boost.Lambda library. 1060 1061[lambda_snippet_1] 1062 1063[endsect] 1064 1065[endsect] 1066 1067[section:Utilities Utilities] 1068 1069Relatively complete SI and CGS unit systems are provided in [headerref boost/units/systems/si.hpp] and 1070[headerref boost/units/systems/cgs.hpp], respectively. 1071 1072[section:Metaprogramming_Classes Metaprogramming Classes] 1073 1074 template<long N> struct ordinal<N>; 1075 1076 template<typename T,typename V> struct get_tag< dim<T,V> >; 1077 template<typename T,typename V> struct get_value< dim<T,V> >; 1078 template<class S,class DT> struct get_system_tag_of_dim<S,DT>; 1079 template<typename Seq> struct make_dimension_list<Seq>; 1080 template<class DT> struct fundamental_dimension<DT>; 1081 template<class DT1,int E1,...> struct composite_dimension<DT1,E1,...>; 1082 1083 template<class Dim,class System> struct get_dimension< unit<Dim,System> >; 1084 template<class Unit,class Y> struct get_dimension< quantity<Unit,Y> >; 1085 template<class Dim,class System> struct get_system< unit<Dim,System> >; 1086 template<class Unit,class Y> struct get_system quantity<Unit,Y> >; 1087 1088 struct dimensionless_type; 1089 template<class System> struct dimensionless_unit<System>; 1090 template<class System,class Y> struct dimensionless_quantity<System,Y>; 1091 1092 struct implicitly_convertible; 1093 struct trivial_conversion; 1094 template<class T,class S1,class S2> struct base_unit_converter<T,S1,S2>; 1095 1096 template<class Q1,class Q2> class conversion_helper<Q1,Q2>; 1097 1098[endsect] 1099 1100[section:Metaprogramming_Predicates Metaprogramming Predicates] 1101 1102 template<typename T,typename V> struct is_dim< dim<T,V> >; 1103 template<typename T,typename V> struct is_empty_dim< dim<T,V> >; 1104 1105 template<typename Seq> struct is_dimension_list<Seq>; 1106 1107 template<class S> struct is_system< homogeneous_system<S> >; 1108 template<class S> struct is_system< heterogeneous_system<S> >; 1109 template<class S> struct is_homogeneous_system< homogeneous_system<S> >; 1110 template<class S> struct is_heterogeneous_system< heterogeneous_system<S> >; 1111 1112 template<class Dim,class System> struct is_unit< unit<Dim,System> >; 1113 template<class Dim,class System> struct is_unit_of_system< unit<Dim,System>,System >; 1114 template<class Dim,class System> struct is_unit_of_dimension< unit<Dim,System>,Dim >; 1115 1116 template<class Unit,class Y> struct is_quantity< quantity<Unit,Y> >; 1117 template<class Dim,class System,class Y> struct is_quantity_of_system< quantity<unit<Dim,System>,Y>,System >; 1118 template<class Dim,class System,class Y> struct is_quantity_of_dimension< quantity<unit<Dim,System>,Y>,Dim >; 1119 1120 template<class System> struct is_dimensionless< unit<dimensionless_type,System> >; 1121 template<class System> struct is_dimensionless_unit< unit<dimensionless_type,System> >; 1122 template<class System,class Y> struct is_dimensionless< quantity<unit<dimensionless_type,System>,Y> >; 1123 template<class System,class Y> struct is_dimensionless_quantity< quantity<unit<dimensionless_type,System>,Y> >; 1124 1125[endsect] 1126 1127[endsect] 1128 1129[section:Reference Reference] 1130 1131[xinclude units_reference.xml] 1132 1133[xinclude dimensions_reference.xml] 1134[xinclude si_reference.xml] 1135[xinclude cgs_reference.xml] 1136[xinclude trig_reference.xml] 1137[xinclude temperature_reference.xml] 1138[xinclude information_reference.xml] 1139[xinclude abstract_reference.xml] 1140 1141[section Base Units by Category] 1142 1143[xinclude angle_base_units_reference.xml] 1144[xinclude astronomical_base_units_reference.xml] 1145[xinclude cgs_base_units_reference.xml] 1146[xinclude imperial_base_units_reference.xml] 1147[xinclude metric_base_units_reference.xml] 1148[xinclude si_base_units_reference.xml] 1149[xinclude temperature_base_units_reference.xml] 1150[xinclude us_base_units_reference.xml] 1151 1152[endsect] 1153 1154[section Alphabetical Listing of Base Units] 1155[include base_units.qbk] 1156[endsect] 1157 1158[endsect] 1159 1160[section:Installation Installation] 1161 1162The core header files are located in `boost/units`. Unit system headers are 1163located in `<boost/units/systems>`. There are no source files for the library 1164itself - the library is header-only. Example programs demonstrating various aspects of the library can be found in 1165`boost/libs/units/example`. Programs for unit testing are provided in `boost/libs/units/test`. 1166 1167[endsect] 1168 1169[section:FAQ FAQ] 1170 1171[section:Distinguishing_Quantities_With_Same_Units 1172How does one distinguish between quantities that are physically different but have the same units (such as 1173energy and torque)?] 1174 1175Because Boost.Units includes plane and solid angle units in the SI system, torque and energy 1176are, in fact, distinguishable (see [@http://en.wikipedia.org/wiki/SI_units torque]). 1177In addition, energy is a true 1178[@http://mathworld.wolfram.com/Scalar.html scalar] quantity, while torque, despite 1179having the same units as energy if plane angle is not included, is in fact a 1180[@http://mathworld.wolfram.com/Pseudovector.html pseudovector]. Thus, a value type representing pseudovectors 1181and encapsulating their algebra could also be implemented. 1182 1183There are, 1184however, a few SI units that are dimensionally indistinguishable within the SI system. These 1185include the [@http://en.wikipedia.org/wiki/Becquerel becquerel], which has units identical to 1186frequency (Hz), and the [@http://en.wikipedia.org/wiki/Sievert sievert], which is degenerate 1187with the [@http://en.wikipedia.org/wiki/Gray_%28unit%29 gray]. In cases such as this, 1188the proper way to treat this difference is to recognize that expanding the set of base dimensions 1189can provide disambiguation. For example, adding a base dimension for radioactive decays would 1190allow the becquerel to be written as decays/second, differentiating it from the signature of hertz, 1191which is simply 1/second. 1192 1193[endsect] 1194 1195[section:Angle_Are_Units Angles are treated as units] 1196 1197If you don't like this, you can just ignore the angle units and 1198go on your merry way (periodically screwing up when a routine wants degrees and you give it 1199radians instead...) 1200 1201[endsect] 1202 1203[section:Why_Homogeneous_Systems Why are there homogeneous systems? Aren't heterogeneous systems sufficient?] 1204 1205Consider the following code: 1206 1207 cout << asin(sin(90.0 * degrees)); 1208 1209What should this print? If only heterogeneous 1210systems are available it would print 1.5708 rad 1211Why? Well, `sin` would return a `quantity<dimensionless>` 1212effectively losing the information that degrees 1213are being used. In order to propogate this extra information 1214we need homogeneous systems. 1215 1216[endsect] 1217 1218[section:NoConstructorFromValueType Why can't I construct a quantity directly from the value type?] 1219 1220This only breaks generic code--which ought to break anyway. The only 1221literal value that ought to be converted to a quantity by generic code 1222is zero, which should be handled by the default constructor. In addition, 1223consider the search and replace problem allowing this poses: 1224 1225 quantity<si::length> q(1.0); 1226 1227Here, the intent is clear - we want a length of one in the SI system, which is one meter. However, 1228imagine some well-intentioned coder attempting to reuse this code, but to have it perform the 1229calculations in the CGS unit system instead. After searching for `si::` and replacing it with `cgs::` , 1230we have: 1231 1232 quantity<cgs::length> q(1.0); 1233 1234Unfortunately, the meaning of this statement has suddenly changed from one meter to one centimeter. In 1235contrast, as implemented, we begin with: 1236 1237 quantity<si::length> q(1.0*si::meter); 1238 1239and, after search and replace: 1240 1241 quantity<cgs::length> q(1.0*cgs::meter); 1242 1243which gives us an error. Even if the code has a @using namespace boost::units::si; declaration, the latter 1244is still safe, with: 1245 1246 using namespace boost::units::si; 1247 quantity<length> q(1.0*meter); 1248 1249going to 1250 1251 using namespace boost::units::cgs; 1252 quantity<length> q(1.0*meter); 1253 1254The latter will involve an explicit conversion from meters to centimeters, but the value remains correct. 1255 1256[endsect] 1257 1258[section:ExplicitConversions Why are conversions explicit by default?] 1259 1260Safety and the potential for unintended conversions leading to precision loss and hidden performance costs. 1261Options are provided for forcing implicit conversions between specific units to be allowed. 1262 1263[endsect] 1264 1265[endsect] 1266 1267[section:Acknowledgements Acknowledgements] 1268 1269Matthias C. Schabel would like to acknowledge the Department of Defense for its support of this work under 1270the Prostate Cancer Research Program New Investigator Award W81XWH-04-1-0042 and the National Institutes of Health for their 1271support of this work under the NIBIB Mentored Quantitative Research Development Award K25EB005077. 1272 1273Thanks to David Walthall for his assistance in debugging and testing on a variety of platforms and Torsten Maehne for 1274his work on interfacing the Boost Units and Boost Lambda libraries. 1275 1276Thanks to: 1277 1278* Paul Bristow, 1279* Michael Fawcett, 1280* Ben FrantzDale, 1281* Ron Garcia, 1282* David Greene, 1283* Peder Holt, 1284* Janek Kozicki, 1285* Andy Little, 1286* Kevin Lynch, 1287* Torsten Maehne 1288* Noah Roberts, 1289* Andrey Semashev, 1290* David Walthall, 1291* Deane Yang, 1292 1293and all the members of the Boost mailing list who provided their input into 1294the design and implementation of this library. 1295 1296[endsect] [/section:Acknowledgements Acknowledgements] 1297 1298[section:HelpWanted Help Wanted] 1299 1300 Any help in the following areas would be much appreciated: 1301 1302* testing on other compilers and operating systems 1303* performance testing on various architectures 1304* tutorials 1305 1306[endsect] 1307 1308[section:version_id Version Info] 1309 1310__boostroot 1311 1312Last edit to Quickbook file __FILENAME__ was at __TIME__ on __DATE__. 1313 1314[tip This should appear on the pdf version (but may be redundant on html).] 1315[/ Useful on pdf version. See also Last revised timestamp on first page of html version.] 1316[/See also Adobe Reader pdf File Properties for creation date, and PDF producer, version and page count.] 1317 1318[endsect] [/section:version_id Version Info] 1319 1320[section:ReleaseNotes Release Notes] 1321 13221.2 (March 2010) 1323 1324* Added autoprefix ready for Boost 1.43 1325 13261.0.0 (August 1, 2008) : 1327 1328* Initial release with Boost 1.36 1329 13300.7.1 (March 14, 2007) : 1331 1332* Boost.Typeof emulation support. 1333* attempting to rebind a heterogeneous_system to a different set of dimensions now fails. 1334* cmath.hpp now works with como-win32. 1335* minor changes to the tests and examples to make msvc 7.1 happy. 1336 13370.7.0 (March 13, 2007) : 1338 1339* heterogeneous and mixed system functionality added. 1340* added fine-grained implicit unit conversion on a per fundamental dimension basis. 1341* added a number of utility metafunction classes and predicates. 1342* [headerref boost/units/operators.hpp] now uses `BOOST_TYPEOF` when possible. 1343* angular units added in [headerref boost/units/systems/angle/gradians.hpp] 1344 and [headerref boost/units/systems/angle/gradians.hpp]. 1345 Implicit conversion of radians between trigonometric, SI, and CGS systems is allowed. 1346* a variety of [___unit] and [___quantity] tests added. 1347* examples now provide self-tests. 1348 13490.6.2 (February 22, 2007) : 1350 1351* changed template order in `unit` so dimension precedes unit system 1352* added `homogeneous_system<S>` for unit systems 1353* incorporated changes to [headerref boost/units/dimension.hpp] (compile-time sorting by predicate), 1354 [headerref boost/units/conversion.hpp] (thread-safe implementation of quantity conversions), 1355 and [headerref boost/units/io.hpp] (now works with any `std::basic_ostream`) by SW 1356* added abstract units in [headerref boost/units/systems/abstract.hpp] to allow abstract dimensional 1357 analysis 1358* new example demonstrating implementation of code based on requirements from 1359 Michael Fawcett ([@../../libs/units/example/radar_beam_height.cpp radar_beam_height.cpp]) 1360 13610.6.1 (February 13, 2007) : 1362 1363* added metafunctions to test if a type is 1364 * a valid dimension list (`is_dimension_list<D>`) 1365 * a unit (`is_unit<T>` and `is_unit_of_system<U,System>`) 1366 * a quantity (`is_quantity<T>` and `is_quantity_of_system<Q,System>`) 1367* quantity conversion factor is now computed at compile time 1368* static constants now avoid ODR problems 1369* unit_example_14.cpp now uses Boost.Timer 1370* numerous minor fixes suggested by SW 1371 13720.6.0 (February 8, 2007) : 1373 1374* incorporated Steven Watanabe's optimized code for dimension.hpp, leading to *dramatic* 1375 decreases in compilation time (nearly a factor of 10 for unit_example_4.cpp in my tests). 1376 13770.5.8 (February 7, 2007) : 1378 1379* fixed `#include` in [headerref boost/units/systems/si/base.hpp] (thanks to Michael Fawcett and 1380 Steven Watanabe) 1381* removed references to obsolete `base_type` in [___unit_info] (thanks to Michael Fawcett) 1382* moved functions in [headerref boost/units/cmath.hpp] into `boost::units` namespace 1383 (thanks to Steven Watanabe) 1384* fixed `#include` guards to be consistently named `BOOST_UNITS_XXX` (thanks to Steven 1385 Watanabe) 1386 13870.5.7 (February 5, 2007) : 1388 1389* changed quantity conversion helper to increase flexibility 1390* minor documentation changes 1391* submitted for formal review as a Boost library 1392 13930.5.6 (January 22, 2007) : 1394 1395* added IEEE 1541 standard binary prefixes along with SI prefixes to and extended algebra of 1396 `scale` and `scaled_value` classes (thanks to Kevin Lynch) 1397* split SI units into separate header files to minimize the "kitchen sink" include problem 1398 (thanks to Janek Kozicki) 1399* added convenience classes for declaring fundamental dimensions and composite dimensions 1400 with integral powers (`fundamental_dimension` and `composite_dimension` respectively) 1401 14020.5.5 (January 18, 2007) : 1403 1404* template parameter order in `quantity` switched and default `value_type` of `double` added 1405 (thanks to Andrey Semashev and Paul Bristow) 1406* added implicit `value_type` conversion where allowed (thanks to Andrey Semashev) 1407* added `quantity_cast` for three cases (thanks to Andrey Semashev): 1408 * constructing `quantity` from raw `value_type` 1409 * casting from one `value_type` to another 1410 * casting from one `unit` to another (where conversion is allowed) 1411* added` metre` and `metres` and related constants to the SI system for the convenience of 1412 our Commonwealth friends... 1413 14140.5.4 (January 12, 2007) : 1415 1416* completely reimplemented unit conversion to allow for arbitrary unit conversions 1417 between systems 1418* strict quantity construction is default; quantities can be constructed from bare values 1419 by using static member `from_value` 1420 14210.5.3 (December 12, 2006) : 1422 1423* added Boost.Serialization support to `unit` and `quantity` classes 1424* added option to enforce strict construction of quantities (only constructible 1425 by multiplication of scalar by unit or quantity by unit) by preprocessor 1426 `MCS_STRICT_QUANTITY_CONSTRUCTION` switch 1427 14280.5.2 (December 4, 2006) : 1429 1430* added `<cmath>` wrappers in the `std` namespace for functions that can support quantities 1431 14320.5.1 (November 3, 2006) : 1433 1434* converted to Boost Software License 1435* boostified directory structure and file paths 1436 14370.5 (November 2, 2006) : 1438 1439* completely reimplemented SI and CGS unit systems and changed syntax for quantities 1440* significantly streamlined `pow` and `root` so for most applications it is only 1441 necessary to define `power_typeof_helper` and `root_typeof_helper` to gain this 1442 functionality 1443* added a selection of physical constants from the CODATA tables 1444* added a skeleton `complex` class that correctly supports both `complex<quantity<Y,Unit> >` 1445 and `quantity<complex<Y>,Unit>` as an example 1446* investigate using Boost.Typeof for compilers that do not support `typeof` 1447 14480.4 (October 13, 2006) : 1449 1450* `pow<R>` and `root<R>` improved for user-defined types 1451* added unary + and unary - operators 1452* added new example of interfacing with `boost::math::quaternion` 1453* added optional preprocessor switch to enable implicit unit conversions 1454 (`BOOST_UNITS_ENABLE_IMPLICIT_UNIT_CONVERSIONS`) 1455 14560.3 (September 6, 2006) : 1457 1458* Support for `op(X x,Y y)` for g++ added. This is automatically 1459 active when compiling with gcc and can be optionally enabled by defining the preprocessor 1460 constant `BOOST_UNITS_HAS_TYPEOF` 1461 14620.2 (September 4, 2006) : Second alpha release based on slightly modified code from 0.1 release 1463 14640.1 (December 13, 2003) : written as a Boost demonstration of MPL-based dimensional analysis 1465in 2003. 1466 1467[endsect] 1468 1469[section:TODO TODO] 1470 1471* Document concepts 1472* Implementation of I/O is rudimentary; consider methods of i18n using facets 1473* Consider runtime variant, perhaps using overload like `quantity<runtime,Y>` 1474 1475[endsect] [/section:TODO TODO] 1476