]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
75 | The Boost.Units library is a C++ implementation of dimensional analysis in a general | |
76 | and extensible manner, treating it as a generic compile-time metaprogramming problem. With appropriate | |
77 | compiler optimization, no runtime execution cost is introduced, facilitating the use of this library to | |
78 | provide dimension checking in performance-critical code. Support for units | |
79 | and quantities (defined as a unit and associated value) for arbitrary unit system models and arbitrary | |
80 | value types is provided, as is a fine-grained general facility for unit conversions. Complete SI and CGS unit | |
81 | systems are provided, along with systems for | |
82 | angles measured in degrees, radians, gradians, and revolutions and | |
83 | systems for temperatures measured in Kelvin, degrees Celsius and degrees Fahrenheit. | |
84 | The library architecture has been designed with flexibility and extensibility in mind; demonstrations of the ease | |
85 | of adding new units and unit conversions are provided in the examples. | |
86 | ||
87 | In order to enable complex compile-time dimensional analysis calculations with no runtime overhead, | |
88 | Boost.Units relies heavily on the [___boost_mpl] (MPL) and on template metaprogramming techniques, and is, as a consequence, | |
89 | fairly demanding of compiler compliance to ISO standards. At present, it has been successfully | |
90 | compiled 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 | ||
100 | The 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 | ||
112 | Before discussing the basics of the library, we first define a few terms that will be used frequently | |
113 | in 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 | ||
136 | To 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 | |
138 | and 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 | |
140 | a function that computes the work, in joules, done by exerting a force in newtons over a specified distance in meters | |
141 | and outputs the result to `std::cout`. The [___quantity] class accepts a second template parameter as its value type; | |
142 | this parameter defaults to | |
143 | `double` if not otherwise specified. To demonstrate the ease of using user-defined types in dimensional | |
144 | calculations, we also present code for computing the complex impedance using `std::complex<double>` | |
145 | as the value type : | |
146 | ||
147 | [import ../example/tutorial.cpp] | |
148 | ||
149 | [tutorial_code] | |
150 | ||
151 | The intent and function of the above code should be obvious; the output produced is : | |
152 | ||
153 | [tutorial_output] | |
154 | ||
155 | While this library attempts to make simple dimensional computations easy to code, it is in no way | |
156 | tied to any particular unit system (SI or otherwise). Instead, it provides a highly flexible compile-time | |
157 | system for dimensional analysis, supporting arbitrary collections of base dimensions, rational | |
158 | powers of units, and explicit quantity conversions. It accomplishes all of this via template metaprogramming techniques. | |
159 | With modern optimizing compilers, this results in zero runtime overhead for quantity computations relative to the | |
160 | same code without unit checking. | |
161 | ||
162 | [endsect] | |
163 | ||
164 | [section:Dimensional_Analysis Dimensional Analysis] | |
165 | ||
166 | The concept of | |
167 | [@http://en.wikipedia.org/wiki/Dimensional_analysis dimensional analysis] | |
168 | is normally presented early on in introductory physics and engineering classes as a means of determining the | |
169 | correctness of an equation or computation by propagating the physical measurement | |
170 | [@http://en.wikipedia.org/wiki/Units_of_measurement units] | |
171 | of various quantities through the equation along with their numerical values. There are a number of standard | |
172 | unit 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 | |
175 | for three of the base units on which the system is based). The SI | |
176 | is the only official international standard unit system and is widely utilized in science and engineering. | |
177 | Other 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] | |
180 | system still in use in some problem domains in the United States and elsewhere. In physics, | |
181 | there also exist a number of other systems that are in common use in specialized subdisciplines. These are | |
182 | collectively referred to as [@http://en.wikipedia.org/wiki/Natural_units natural units]. When | |
183 | quantities representing different measurables are combined, dimensional analysis provides the means of | |
184 | assessing the consistency of the resulting calculation. For example, the sum of two lengths is also a length, | |
185 | while the product of two lengths is an area, and the sum of a length and an area is undefined. The fact that the | |
186 | arguments to many functions (such as exp, log, etc...) must be dimensionless quantities can be easily demonstrated by | |
187 | examining their series expansions in the context of dimensional analysis. This library facilitates the enforcement | |
188 | of this type of restriction in code involving dimensioned quantities where appropriate. | |
189 | ||
190 | In 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. | |
192 | We will refer to a pair of a base dimension and a rational exponent as a *fundamental dimension*, | |
193 | and 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 | |
195 | denoted by [$../../libs/units/images/form_1.png] and a set of [$../../libs/units/images/form_0.png] | |
196 | rational exponents [$../../libs/units/images/form_2.png], any possible (composite) dimension can be written | |
197 | as [$../../libs/units/images/form_3.png]. | |
198 | ||
199 | Composite dimensions obey the algebraic rules for dimensional analysis. In particular, for any scalar value, | |
200 | [$../../libs/units/images/form_4.png], | |
201 | and composite dimensions [$../../libs/units/images/form_5.png] | |
202 | and [$../../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 | ||
207 | Users of a dimensional analysis library should be able to specify an arbitrary list of base dimensions to | |
208 | produce a composite dimension. This potentially includes repeated tags. For example, | |
209 | it 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 | |
211 | 1, 2, and -2, respectively. | |
212 | In order to be able to perform computations on arbitrary sets of dimensions, | |
213 | all 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 | ||
220 | In our implementation, base dimensions are associated with tag types. As we will ultimately | |
221 | represent composite dimensions as typelists, we must provide some mechanism for sorting | |
222 | base dimension tags in order to make it possible to convert an arbitrary composite dimension | |
223 | into a reduced dimension. For this purpose, we assign a unique integer to each base dimension. | |
224 | The [___base_dimension] class (found in [headerref boost/units/base_dimension.hpp]) uses the | |
225 | curiously recurring template pattern (CRTP) technique to ensure that ordinals specified for | |
226 | base dimensions are unique: | |
227 | ||
228 | template<class Derived, long N> struct base_dimension { ... }; | |
229 | ||
230 | With 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 | ||
235 | It is important to note that the choice of order is completely arbitrary as long as each tag has a unique enumerable | |
236 | value; non-unique ordinals are flagged as errors at compile-time. Negative ordinals are reserved for use by the library. | |
237 | To define composite dimensions corresponding to the base dimensions, we | |
238 | simply create MPL-conformant typelists of fundamental dimensions by using the [___dim] class to encapsulate pairs of base dimensions | |
239 | and [___static_rational] exponents. The [___make_dimension_list] class acts as a wrapper to ensure | |
240 | that the resulting type is in the form of a reduced dimension: | |
241 | ||
242 | [test_system_snippet_2] | |
243 | ||
244 | This can also be easily accomplished using a convenience typedef provided by [___base_dimension]: | |
245 | ||
246 | [test_system_snippet_3] | |
247 | ||
248 | so 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 | ||
252 | A 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 | ||
260 | We define a *unit* as a set of base units each of which can be raised to an arbitrary rational | |
261 | exponent. Thus, the SI unit corresponding to the dimension of force is kg m s^-2, where kg, m, | |
262 | and s are base units. We use the notion of a *unit system* such as SI to specify the mapping | |
263 | from a dimension to a particular unit so that instead of specifying the base units explicitly, | |
264 | we can just ask for the representation of a dimension in a particular system. | |
265 | ||
266 | Units are, like dimensions, purely compile-time variables with no associated value. | |
267 | Units obey the same algebra as dimensions do; the presence of the unit system serves to ensure that units having identical | |
268 | reduced dimension in different systems (like feet and meters) cannot be inadvertently mixed in computations. | |
269 | ||
270 | There 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 | ||
286 | Units are implemented by the [___unit] template class defined in [headerref boost/units/unit.hpp] : | |
287 | ||
288 | template<class Dim,class System> class unit; | |
289 | ||
290 | In addition to supporting the compile-time dimensional analysis operations, the +, -, *, and / runtime operators are provided | |
291 | for [___unit] variables. Because the dimension associated with powers and roots must be computed at compile-time, it is not | |
292 | possible to provide overloads for `std::pow` that function correctly for [___unit]s. These operations are supported through | |
293 | free functions [___pow] and [___root] that are templated on integer and [___static_rational] values and can take as an argument | |
294 | any type for which the utility classes [___power_typeof_helper] and [___root_typeof_helper] have been defined. | |
295 | ||
296 | [section Base Units] | |
297 | ||
298 | Base units are defined much like base dimensions. | |
299 | ||
300 | template<class Derived, class Dimensions, long N> struct base_unit { ... }; | |
301 | ||
302 | Again negative ordinals are reserved. | |
303 | ||
304 | As an example, in the following we will implement a subset of the SI unit system based on the fundamental dimensions | |
305 | given above, demonstrating all steps necessary for a completely functional system. First, we simply define a unit system | |
306 | that includes type definitions for commonly used units: | |
307 | ||
308 | [test_system_snippet_6] | |
309 | ||
310 | The macro [___BOOST_UNITS_STATIC_CONSTANT] is provided in [headerref boost/units/static_constant.hpp] | |
311 | to facilitate ODR- and thread-safe constant definition in header files. We then define some constants for the supported units | |
312 | to simplify variable definitions: | |
313 | ||
314 | [test_system_snippet_7] | |
315 | ||
316 | If support for textual output of units is desired, we can also specialize the [___base_unit_info] class for each fundamental | |
317 | dimension tag: | |
318 | ||
319 | [test_system_snippet_8] | |
320 | ||
321 | and similarly for `kilogram_base_unit` and `second_base_unit`. A future version of the library will provide a more flexible system | |
322 | allowing for internationalization through a facet/locale-type mechanism. | |
323 | The `name()` and `symbol()` methods of [___base_unit_info] provide full and short names for the base unit. With these definitions, | |
324 | we have the rudimentary beginnings of our unit system, which can be used to determine reduced dimensions for arbitrary | |
325 | unit calculations. | |
326 | ||
327 | [endsect] [/section Base Units] | |
328 | ||
329 | [section Scaled Base Units] | |
330 | ||
331 | Now, it is also possible to define a base unit as being a multiple of | |
332 | another base unit. For example, the way that `kilogram_base_unit` is | |
333 | actually 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 | ||
338 | This basically defines a kilogram as being 10^3 times a gram. | |
339 | ||
340 | There 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 | ||
352 | We can also scale a [___unit] as a whole, rather than scaling the individual | |
353 | base units which comprise it. For this purpose, we use the metafunction | |
354 | [___make_scaled_unit]. The main motivation for this feature is the metric | |
355 | prefixes defined in [headerref boost/units/systems/si/prefixes.hpp]. | |
356 | ||
357 | A simple example of its usage would be. | |
358 | ||
359 | typedef make_scaled_unit<si::time, scale<10, static_rational<-9> > >::type nanosecond; | |
360 | ||
361 | nanosecond 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 | ||
372 | A *quantity* is defined as a value of an arbitrary value type that is associated with a specific unit. For example, | |
373 | while meter is a unit, 3.0 meters is a quantity. Quantities obey two separate algebras: the native algebra for their | |
374 | value type, and the dimensional analysis algebra for the associated unit. In addition, algebraic operations are defined | |
375 | between units and quantities to simplify the definition of quantities; it is effectively equivalent to algebra with | |
376 | a unit-valued quantity. | |
377 | ||
378 | Quantities 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 | ||
382 | This class is templated on both unit type (`Unit`) and value type (`Y`), with the latter defaulting to double-precision | |
383 | floating point if not otherwise specified. The value type must have a normal copy constructor and copy | |
384 | assignment operator. Operators +, -, *, and / are provided for algebraic operations between | |
385 | scalars and units, scalars and quantities, units and quantities, and between quantities. In addition, integral and | |
386 | rational powers and roots can be computed using the [___pow]<R> and [___root]<R> functions. Finally, | |
387 | the standard set of boolean comparison operators ( `==, !=, <, <=, >, and >=` ) are provided to allow | |
388 | comparison of quantities from the same unit system. All operators simply delegate to the | |
389 | corresponding operator of the value type if the units permit. | |
390 | ||
391 | [section:Heterogeneous_Operators Heterogeneous Operators] | |
392 | ||
393 | For most common value types, the result type of arithmetic operators is the same as the value type itself. For example, | |
394 | the sum of two double precision floating point numbers is another double precision floating point number. However, there | |
395 | are instances where this is not the case. A simple example is given by the [@http://en.wikipedia.org/wiki/Natural_number | |
396 | natural 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 | ||
404 | This library is designed to support arbitrary value type algebra for addition, subtraction, multiplication, division, and | |
405 | rational powers and roots. It uses Boost.Typeof to deduce the result of these operators. For compilers that | |
406 | support `typeof`, the appropriate value type will be automatically deduced. For compilers that do not provide | |
407 | language support for `typeof` it is necessary to register all the types used. For the case of natural numbers, | |
408 | this 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 | ||
418 | Conversion is only meaningful for quantities as it implies the presence of at | |
419 | least a multiplicative scale factor and, possibly, and affine linear offset. | |
420 | Macros 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 | ||
424 | The macro [___BOOST_UNITS_DEFINE_CONVERSION_FACTOR] specifies a scale | |
425 | factor for conversion from the first unit type to the second. The | |
426 | first argument must be a [___base_unit]. The second argument | |
427 | can be either a [___base_unit] or a [___unit]. | |
428 | ||
429 | Let's declare a simple base unit: | |
430 | ||
431 | struct foot_base_unit : base_unit<foot_base_unit, length_dimension, 10> { }; | |
432 | ||
433 | Now, we want to be able to convert feet to meters and vice versa. The foot | |
434 | is 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 | ||
438 | Alternately, we could use the SI length `typedef`: | |
439 | ||
440 | BOOST_UNITS_DEFINE_CONVERSION_FACTOR(foot_base_unit, SI::length, double, 0.3048); | |
441 | ||
442 | Since the SI unit of length is the meter, these two definitions are equivalent. | |
443 | If these conversions have been defined, then converting between | |
444 | scaled forms of these units will also automatically work. | |
445 | ||
446 | The macro [___BOOST_UNITS_DEFAULT_CONVERSION] specifies a conversion | |
447 | that will be applied to a base unit when no direct conversion is | |
448 | possible. This can be used to make arbitrary conversions work | |
449 | with 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 | ||
461 | This library is designed to emphasize safety above convenience when performing operations with dimensioned quantities. | |
462 | Specifically, construction of quantities is required to fully specify both value and unit. Direct construction from a scalar value | |
463 | is prohibited (though the static member function [___from_value] is provided to enable | |
464 | this functionality where it is necessary. In addition, a [___quantity_cast] to a reference allows direct access to the | |
465 | underlying value of a [___quantity] variable. An explicit constructor is provided to enable conversion between | |
466 | dimensionally compatible quantities in different unit systems. Implicit conversions between unit systems are | |
467 | allowed only when the reduced units are identical, allowing, for example, trivial conversions between | |
468 | equivalent units in different systems (such as SI seconds and CGS seconds) while simultaneously enabling | |
469 | unintentional unit system mismatches to be caught at compile time and preventing potential loss of precision and | |
470 | performance overhead from unintended conversions. Assignment follows the same rules. | |
471 | An exception is made for quantities for which the unit reduces to dimensionless; in this case, implicit conversion | |
472 | to the underlying value type is allowed via class template specialization. Quantities of different value types are implicitly | |
473 | convertible only if the value types are themselves implicitly convertible. The [___quantity] class also defines | |
474 | a `value()` member for directly accessing the underlying value. | |
475 | ||
476 | To 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 | ||
489 | Of course, any time implicit conversion is allowed, an explicit conversion is | |
490 | also legal. | |
491 | ||
492 | Because dimensionless quantities have no associated units, they behave as normal scalars, and allow implicit conversion to and from | |
493 | the 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 | ||
505 | By 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 | |
507 | according to the dimensional analysis rules described [link boost_units.Dimensional_Analysis above] | |
508 | to produce new composite dimensions : | |
509 | ||
510 | [import ../example/dimension.cpp] | |
511 | ||
512 | [dimension_snippet_1] | |
513 | ||
514 | outputting (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 | ||
525 | This 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 | ||
532 | We 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 | ||
542 | This example demonstrates how to use quantities of our toy unit system : | |
543 | ||
544 | [import ../example/quantity.cpp] | |
545 | ||
546 | [quantity_snippet_1] | |
547 | ||
548 | giving us the basic quantity functionality : | |
549 | ||
550 | [quantity_output_double] | |
551 | ||
552 | As a further demonstration of the flexibility of the system, we replace the `double` value type | |
553 | with a `std::complex<double>` value type (ignoring the question of the meaningfulness of | |
554 | complex lengths and energies) : | |
555 | ||
556 | [quantity_snippet_2] | |
557 | ||
558 | and find that the code functions exactly as expected with no additional work, delegating operations | |
559 | to `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 | ||
569 | This example provides a fairly extensive set of tests covering most of the [___quantity] functionality. | |
570 | It uses the SI unit system defined in [headerref boost/units/systems/si.hpp]. | |
571 | ||
572 | If we define a few units and associated quantities, | |
573 | ||
574 | [import ../example/kitchen_sink.cpp] | |
575 | ||
576 | [kitchen_sink_snippet_1] | |
577 | ||
578 | the various algebraic operations between scalars, units, and quantities give | |
579 | ||
580 | [kitchen_sink_output_1] | |
581 | ||
582 | Scalar/unit operations : | |
583 | ||
584 | [kitchen_sink_output_2] | |
585 | ||
586 | Unit/unit operations and integral/rational powers of units : | |
587 | ||
588 | [kitchen_sink_output_3] | |
589 | ||
590 | Scalar/quantity operations : | |
591 | ||
592 | [kitchen_sink_output_4] | |
593 | ||
594 | Unit/quantity operations : | |
595 | ||
596 | [kitchen_sink_output_5] | |
597 | ||
598 | Quantity/quantity operations and integral/rational powers of quantities : | |
599 | ||
600 | [kitchen_sink_output_6] | |
601 | ||
602 | Logical comparison operators are also defined between quantities : | |
603 | ||
604 | [kitchen_sink_snippet_2] | |
605 | ||
606 | giving | |
607 | ||
608 | [kitchen_sink_output_7] | |
609 | ||
610 | Implicit conversion is allowed between dimensionless quantities and their corresponding value types : | |
611 | ||
612 | [kitchen_sink_snippet_3] | |
613 | ||
614 | A generic function for computing mechanical work can be defined that takes force and distance arguments | |
615 | in 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 | ||
621 | which functions as expected for SI quantities : | |
622 | ||
623 | [kitchen_sink_output_9] | |
624 | ||
625 | The ideal gas law can also be implemented in SI units : | |
626 | ||
627 | [kitchen_sink_function_snippet_4] | |
628 | ||
629 | [kitchen_sink_snippet_5] | |
630 | ||
631 | with the resulting output : | |
632 | ||
633 | [kitchen_sink_output_10] | |
634 | ||
635 | Trigonometric and inverse trigonometric functions can be implemented for any unit system | |
636 | that 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 | |
638 | taking an angular quantity and returning a dimensionless quantity, while the inverse trigonometric functions | |
639 | take a dimensionless quantity and return an angular quantity : | |
640 | ||
641 | Defining a few angular quantities, | |
642 | ||
643 | [kitchen_sink_snippet_6] | |
644 | ||
645 | yields | |
646 | ||
647 | [kitchen_sink_output_11] | |
648 | ||
649 | Dealing with complex quantities is trivial. Here is the calculation of complex impedance : | |
650 | ||
651 | [kitchen_sink_snippet_7] | |
652 | ||
653 | giving | |
654 | ||
655 | [kitchen_sink_output_12] | |
656 | ||
657 | [section:UDT_Quantities User-defined value types] | |
658 | ||
659 | User-defined value types that support the appropriate arithmetic operations are automatically supported | |
660 | as quantity value types. The operators that are supported by default for quantity value types are unary plus, unary minus, | |
661 | addition, subtraction, multiplication, division, equal-to, not-equal-to, less-than, less-or-equal-to, | |
662 | greater-than, and greater-or-equal-to. Support for rational powers and roots can be added by overloading | |
663 | the [___power_typeof_helper] and [___root_typeof_helper] classes. Here we implement a user-defined `measurement` | |
664 | class that models a numerical measurement with an associated measurement error and the appropriate algebra and | |
665 | demonstrates its use as a quantity value type; the full code is found in [@../../libs/units/example/measurement.hpp measurement.hpp]. | |
666 | ||
667 | Then, defining some `measurement` [___quantity] variables | |
668 | ||
669 | [kitchen_sink_snippet_8] | |
670 | ||
671 | gives | |
672 | ||
673 | [kitchen_sink_output_13] | |
674 | ||
675 | If we implement the overloaded helper classes for rational powers and roots | |
676 | then 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 | ||
688 | This example demonstrates the various allowed conversions between SI and CGS units. Defining some | |
689 | quantities | |
690 | ||
691 | [import ../example/conversion.cpp] | |
692 | ||
693 | [conversion_snippet_1] | |
694 | ||
695 | illustrates implicit conversion of quantities of different value types where implicit conversion | |
696 | of the value types themselves is allowed. N.B. The conversion from double to int is treated | |
697 | as an explicit conversion because there is no way to emulate the exact behavior of the built-in | |
698 | conversion. 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 | ||
708 | giving the following output : | |
709 | ||
710 | [conversion_output_1] | |
711 | ||
712 | A few more explicit unit system conversions : | |
713 | ||
714 | [conversion_snippet_5] | |
715 | ||
716 | which 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 | ||
726 | This example demonstrates the use of `boost::math::quaternion` as a value type for [___quantity] and the converse. | |
727 | For the first case, we first define specializations of [___power_typeof_helper] and [___root_typeof_helper] for | |
728 | powers and roots, respectively: | |
729 | ||
730 | [import ../example/quaternion.cpp] | |
731 | ||
732 | [quaternion_class_snippet_1a] | |
733 | ||
734 | [quaternion_class_snippet_1b] | |
735 | ||
736 | We can now declare a [___quantity] of a `quaternion` : | |
737 | ||
738 | [quaternion_snippet_1] | |
739 | ||
740 | so that all operations that are defined in the `quaternion` class behave correctly. If rational | |
741 | powers were defined for this class, it would be possible to compute rational powers and roots with | |
742 | no additional changes. | |
743 | ||
744 | [quaternion_output_1] | |
745 | ||
746 | Now, 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 | ||
750 | Here, the unary plus and minus and addition and subtraction operators function correctly. Unfortunately, | |
751 | the 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 | |
753 | quantities (an identical problem | |
754 | occurs with `std::complex<T>`, for the same reason). In order to compute rational powers and roots, we need to | |
755 | specialize [___power_typeof_helper] and [___root_typeof_helper] as follows: | |
756 | ||
757 | [quaternion_class_snippet_2a] | |
758 | ||
759 | [quaternion_class_snippet_2b] | |
760 | ||
761 | giving: | |
762 | ||
763 | [quaternion_output_2] | |
764 | ||
765 | [endsect] | |
766 | ||
767 | [section:ComplexExample Complex Example] | |
768 | ||
769 | ([@../../libs/units/example/complex.cpp complex.cpp]) | |
770 | ||
771 | This example demonstrates how to implement a replacement `complex` class that functions correctly both as a | |
772 | quantity value type and as a quantity container class, including heterogeneous multiplication and division | |
773 | operations and rational powers and roots. Naturally, heterogeneous operations are only supported on | |
774 | compilers that implement `typeof`. The primary differences are that binary operations are not implemented | |
775 | using 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 | ||
783 | With this replacement `complex` class, we can declare a complex variable : | |
784 | ||
785 | [complex_snippet_1] | |
786 | ||
787 | to get the correct behavior for all cases supported by [___quantity] with a `complex` value type : | |
788 | ||
789 | [complex_output_1] | |
790 | ||
791 | and, similarly, `complex` with a [___quantity] value type | |
792 | ||
793 | [complex_snippet_2] | |
794 | ||
795 | gives | |
796 | ||
797 | [complex_output_2] | |
798 | ||
799 | [endsect] | |
800 | ||
801 | [section:PerformanceExample Performance Example] | |
802 | ||
803 | ([@../../libs/units/example/performance.cpp performance.cpp]) | |
804 | ||
805 | This example provides an ad hoc performance test to verify that zero runtime overhead | |
806 | is incurred when using [___quantity] in place of `double`. Note that performance | |
807 | optimization and testing is not trivial, so some care must be taken in profiling. It | |
808 | is also critical to have a compiler capable of optimizing the many template instantiations | |
809 | and inline calls effectively to achieve maximal performance. Zero overhead for this test | |
810 | 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 | |
811 | using 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 | ||
821 | This example demonstrates the implementation of two non-SI units of length, the | |
822 | nautical mile : | |
823 | ||
824 | [radar_beam_height_class_snippet_1] | |
825 | ||
826 | and the imperial foot : | |
827 | ||
828 | [radar_beam_height_class_snippet_2] | |
829 | ||
830 | These units include conversions between themselves and the meter. Three functions | |
831 | for computing radar beam height from radar range and the local earth radius are | |
832 | defined. The first takes arguments in one system and returns a value in the same | |
833 | system : | |
834 | ||
835 | [radar_beam_height_function_snippet_1] | |
836 | ||
837 | The second is similar, but is templated on return type, so that the arguments are | |
838 | converted to the return unit system internally : | |
839 | ||
840 | [radar_beam_height_function_snippet_2] | |
841 | ||
842 | Finally, the third function is an empirical approximation that is only valid for | |
843 | radar ranges specified in nautical miles, returning beam height in feet. This | |
844 | function uses the heterogeneous unit of nautical miles per square root of feet to | |
845 | ensure dimensional correctness : | |
846 | ||
847 | [radar_beam_height_function_snippet_3] | |
848 | ||
849 | With these, we can compute radar beam height in various unit systems : | |
850 | ||
851 | [radar_beam_height_snippet_1] | |
852 | ||
853 | giving | |
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 | ||
865 | Mixed units and mixed unit conversions. | |
866 | ||
867 | This code: | |
868 | ||
869 | [heterogeneous_unit_snippet_1] | |
870 | ||
871 | gives | |
872 | ||
873 | [heterogeneous_unit_output_1] | |
874 | ||
875 | Arbitrary conversions also work: | |
876 | ||
877 | [heterogeneous_unit_snippet_2] | |
878 | ||
879 | yielding | |
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 | ||
891 | This example demonstrates using of absolute temperatures and relative temperature differences in Fahrenheit | |
892 | and converting between these and the Kelvin temperature scale. This issue touches on some surprisingly deep mathematical | |
893 | concepts (see [@http://en.wikipedia.org/wiki/Affine_space Wikipedia] for a basic review), but for our purposes here, we | |
894 | will simply observe that it is important to be able to differentiate between an absolute temperature measurement and a | |
895 | measurement of temperature difference. This is accomplished by using the [___absolute] wrapper class. | |
896 | ||
897 | First we define a system using the predefined fahrenheit base unit: | |
898 | ||
899 | [temperature_snippet_1] | |
900 | ||
901 | Now we can create some quantities: | |
902 | ||
903 | [temperature_snippet_3] | |
904 | ||
905 | Note 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 | ||
917 | The Boost.Units library does not require that the conversion factors be compile time constants, | |
918 | as 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 | ||
930 | It 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 | ||
942 | If 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 | ||
947 | In this case, any unit that reduces | |
948 | to the overloaded unit will be output with the replacement symbol. | |
949 | ||
950 | Special 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], | |
952 | respectively. If these headers are not included, the output will simply follow | |
953 | default rules using the appropriate fundamental dimensions. | |
954 | Note that neither of these functions is defined for quantities | |
955 | because doing so would require making assumptions on how the corresponding value | |
956 | type should be formatted. | |
957 | ||
958 | Three `ostream` formatters, `symbol_format`, `name_format`, and `typename_format` | |
959 | are provided for convenience. These select the textual representation of units | |
960 | provided by `symbol_string` or `name_string` in the first two cases, while the | |
961 | latter returns a demangled typename for debugging purposes. Formatting of scaled | |
962 | unit is also done correctly. | |
963 | ||
964 | [endsect] | |
965 | ||
966 | [section:autoscale Automatically Scaled Units] | |
967 | ||
968 | It is often desirable to scale a [___unit] automatically, depending on its value, | |
969 | to keep the integral part in a limited range, usually between 1 and 999. | |
970 | ||
971 | For 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 | ||
976 | The 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] | |
983 | is not used (not centi or deci for example), but only powers of ten that are multiples of three, 10^3). | |
984 | ||
985 | Similarly, the equivalent [@http://en.wikipedia.org/wiki/Binary_prefixes binary prefixes] | |
986 | used for displaying computing kilobytes, megabytes, gigabytes... | |
987 | ||
988 | These 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 | ||
992 | This scale is specified in IEC 60027-2, Second edition, 2000-11, | |
993 | Letter symbols to be used in electrical technology - | |
994 | Part 2: Telecommunications and electronics). | |
995 | ||
996 | [autoprefixes_snippet_2] | |
997 | ||
998 | But note that scalar dimensionless values, like int, float and double, | |
999 | are *not* prefixed automatically by the engineering_prefix or binary_prefix iostream manipulators. | |
1000 | ||
1001 | [autoprefixes_snippet_3] | |
1002 | ||
1003 | You can output the name or symbol of a unit (rather than the most common quantity of a unit). | |
1004 | ||
1005 | [autoprefixes_snippet_4] | |
1006 | ||
1007 | Note too that all the formatting flags are persistent, | |
1008 | so that if you set engineering_prefix, then it applies to all future outputs, | |
1009 | until you select binary_prefix, or explicitly switch autoprefix off. | |
1010 | You can specify no prefix (the default of course) in two ways: | |
1011 | ||
1012 | [autoprefixes_snippet_5] | |
1013 | ||
1014 | And 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 | ||
1022 | This code demonstrates the use of the `conversion_factor` free function to determine | |
1023 | the 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 | ||
1031 | Produces | |
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 | ||
1043 | This example shows how to implement an interface that | |
1044 | allow different units at runtime while still maintaining | |
1045 | type 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 | ||
1057 | The header [headerref boost/units/lambda.hpp] provides overloads | |
1058 | and specializations needed to make Boost.Units usable with the | |
1059 | Boost.Lambda library. | |
1060 | ||
1061 | [lambda_snippet_1] | |
1062 | ||
1063 | [endsect] | |
1064 | ||
1065 | [endsect] | |
1066 | ||
1067 | [section:Utilities Utilities] | |
1068 | ||
1069 | Relatively 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 | ||
1162 | The core header files are located in `boost/units`. Unit system headers are | |
1163 | located in `<boost/units/systems>`. There are no source files for the library | |
1164 | itself - 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 | |
1172 | How does one distinguish between quantities that are physically different but have the same units (such as | |
1173 | energy and torque)?] | |
1174 | ||
1175 | Because Boost.Units includes plane and solid angle units in the SI system, torque and energy | |
1176 | are, in fact, distinguishable (see [@http://en.wikipedia.org/wiki/SI_units torque]). | |
1177 | In addition, energy is a true | |
1178 | [@http://mathworld.wolfram.com/Scalar.html scalar] quantity, while torque, despite | |
1179 | having 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 | |
1181 | and encapsulating their algebra could also be implemented. | |
1182 | ||
1183 | There are, | |
1184 | however, a few SI units that are dimensionally indistinguishable within the SI system. These | |
1185 | include the [@http://en.wikipedia.org/wiki/Becquerel becquerel], which has units identical to | |
1186 | frequency (Hz), and the [@http://en.wikipedia.org/wiki/Sievert sievert], which is degenerate | |
1187 | with the [@http://en.wikipedia.org/wiki/Gray_%28unit%29 gray]. In cases such as this, | |
1188 | the proper way to treat this difference is to recognize that expanding the set of base dimensions | |
1189 | can provide disambiguation. For example, adding a base dimension for radioactive decays would | |
1190 | allow the becquerel to be written as decays/second, differentiating it from the signature of hertz, | |
1191 | which is simply 1/second. | |
1192 | ||
1193 | [endsect] | |
1194 | ||
1195 | [section:Angle_Are_Units Angles are treated as units] | |
1196 | ||
1197 | If you don't like this, you can just ignore the angle units and | |
1198 | go on your merry way (periodically screwing up when a routine wants degrees and you give it | |
1199 | radians instead...) | |
1200 | ||
1201 | [endsect] | |
1202 | ||
1203 | [section:Why_Homogeneous_Systems Why are there homogeneous systems? Aren't heterogeneous systems sufficient?] | |
1204 | ||
1205 | Consider the following code: | |
1206 | ||
1207 | cout << sin(asin(180.0 * degrees)); | |
1208 | ||
1209 | What should this print? If only heterogeneous | |
1210 | systems are available it would print 3.14159+ rad | |
1211 | Why? Well, `asin` would return a `quantity<dimensionless>` | |
1212 | effectively losing the information that degrees | |
1213 | are being used. In order to propogate this extra information | |
1214 | we need homogeneous systems. | |
1215 | ||
1216 | [endsect] | |
1217 | ||
1218 | [section:NoConstructorFromValueType Why can't I construct a quantity directly from the value type?] | |
1219 | ||
1220 | This only breaks generic code--which ought to break anyway. The only | |
1221 | literal value that ought to be converted to a quantity by generic code | |
1222 | is zero, which should be handled by the default constructor. In addition, | |
1223 | consider the search and replace problem allowing this poses: | |
1224 | ||
1225 | quantity<si::length> q(1.0); | |
1226 | ||
1227 | Here, the intent is clear - we want a length of one in the SI system, which is one meter. However, | |
1228 | imagine some well-intentioned coder attempting to reuse this code, but to have it perform the | |
1229 | calculations in the CGS unit system instead. After searching for `si::` and replacing it with `cgs::` , | |
1230 | we have: | |
1231 | ||
1232 | quantity<cgs::length> q(1.0); | |
1233 | ||
1234 | Unfortunately, the meaning of this statement has suddenly changed from one meter to one centimeter. In | |
1235 | contrast, as implemented, we begin with: | |
1236 | ||
1237 | quantity<si::length> q(1.0*si::meter); | |
1238 | ||
1239 | and, after search and replace: | |
1240 | ||
1241 | quantity<cgs::length> q(1.0*cgs::meter); | |
1242 | ||
1243 | which gives us an error. Even if the code has a @using namespace boost::units::si; declaration, the latter | |
1244 | is still safe, with: | |
1245 | ||
1246 | using namespace boost::units::si; | |
1247 | quantity<length> q(1.0*meter); | |
1248 | ||
1249 | going to | |
1250 | ||
1251 | using namespace boost::units::cgs; | |
1252 | quantity<length> q(1.0*meter); | |
1253 | ||
1254 | The 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 | ||
1260 | Safety and the potential for unintended conversions leading to precision loss and hidden performance costs. | |
1261 | Options are provided for forcing implicit conversions between specific units to be allowed. | |
1262 | ||
1263 | [endsect] | |
1264 | ||
1265 | [endsect] | |
1266 | ||
1267 | [section:Acknowledgements Acknowledgements] | |
1268 | ||
1269 | Matthias C. Schabel would like to acknowledge the Department of Defense for its support of this work under | |
1270 | the Prostate Cancer Research Program New Investigator Award W81XWH-04-1-0042 and the National Institutes of Health for their | |
1271 | support of this work under the NIBIB Mentored Quantitative Research Development Award K25EB005077. | |
1272 | ||
1273 | Thanks to David Walthall for his assistance in debugging and testing on a variety of platforms and Torsten Maehne for | |
1274 | his work on interfacing the Boost Units and Boost Lambda libraries. | |
1275 | ||
1276 | Thanks 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 | ||
1293 | and all the members of the Boost mailing list who provided their input into | |
1294 | the 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 | ||
1312 | Last 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 | ||
1322 | 1.2 (March 2010) | |
1323 | ||
1324 | * Added autoprefix ready for Boost 1.43 | |
1325 | ||
1326 | 1.0.0 (August 1, 2008) : | |
1327 | ||
1328 | * Initial release with Boost 1.36 | |
1329 | ||
1330 | 0.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 | ||
1337 | 0.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 | ||
1349 | 0.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 | ||
1361 | 0.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 | ||
1372 | 0.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 | ||
1377 | 0.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 | ||
1387 | 0.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 | ||
1393 | 0.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 | ||
1402 | 0.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 | ||
1414 | 0.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 | ||
1421 | 0.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 | ||
1428 | 0.5.2 (December 4, 2006) : | |
1429 | ||
1430 | * added `<cmath>` wrappers in the `std` namespace for functions that can support quantities | |
1431 | ||
1432 | 0.5.1 (November 3, 2006) : | |
1433 | ||
1434 | * converted to Boost Software License | |
1435 | * boostified directory structure and file paths | |
1436 | ||
1437 | 0.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 | ||
1448 | 0.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 | ||
1456 | 0.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 | ||
1462 | 0.2 (September 4, 2006) : Second alpha release based on slightly modified code from 0.1 release | |
1463 | ||
1464 | 0.1 (December 13, 2003) : written as a Boost demonstration of MPL-based dimensional analysis | |
1465 | in 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] |