
Boost : 
From: Matthias Schabel (boost_at_[hidden])
Date: 20070118 14:03:18
Hi Ben,
> I do think it would be great to distinguish between affine and
> vector spaces
> in a library like this, but in practical terms it seems like there
> are three
> levels of commitment that users might have to dimensional analysis:
> 1. Type of dimension (length versus temperature).
> 2. Units of measure (meters versus feet).
> 3. Absolute versus relative quantities (°C = K+273.15 versus °C = K).
The way I've developed the abstractions for this library is similar
to the way you describe :
1) "raw" dimensional analysis as demonstrated in unit_example_1.cpp.
This is purely
compiletime metaprogramming, and is a little messy because of that.
However, I suspect
that this will be a relatively rare use case for end users of the
library. Furthermore, if it
turned out to be useful, it would certainly be possible to add some
metaprogramming
and/or preprocessor support to simplify the syntax and handling of
dimensional analysis
typelists.
2) units, defined as you do, a type of dimension with an associated
unit system but no
numeric value : SI::length, SI::energy, SI::power, etc...
3) quantities, defined as a quantity of a specified unit :
1.5*meters, (1.5+0.2*i)*ohms, etc...
Quantities need to implement two algebras : the compiletime
dimensional analysis algebra
and the algebra for the underlying value_type. This is where handling
of the difference
between absolute and relative quantities would happen. The advantage
of this is that I
have already implemented quantity algebra in such a way that the
value_type algebra should
just delegate to the value_type itself (this requires typeof support
or manual specialization
of operator helpers for heterogeneous algebras), so the dimensional
analysis is completely
decoupled from the value_type algebra.
> I'm thinking usage like this:
> // First: type of dimension
> quantity<double, distance> x1 = 42.0 * distance;
As it stands, the library assumes that quantities are values
associated with a specific unit system.
That being said, you can easily implement a unit system for
"abstract" dimensioned quantities so
you would write
quantity<double,abstract::length> x1 = 42.0*abstract::length;
> // Second: units of measure
> quantity<double, meters> x2 = 20.0 * meters;
This is basically identical to the existing SI system as implemented.
> // Casting to explicitly add units of measure to unitless
> quantities.
> x2 = quantity_cast<quantity<double, meters> >(x1); // The user
> claims x1
> is in meters.
This will hopefully be implemented for the next release.
> // Allow casting a reference or pointer, too (important for
> interfacing
> with numerical solvers).
> quantity<double, meters>& xref = quantity_cast<quantity<double,
> meters>&>(x1);
> quantity<double, meters>* xptr = quantity_cast<quantity<double,
> meters>*>(x1);
This is a good idea; of course, since it involves pointers and
references, I'm sure the actual
implementation will be ugly to get constness and everything else
right...
> // Third, since most people won't want to get into this, let
> quantity be
> what
> // most would expect (i.e., a linear space) but add absolute_ and
> relative_ to be clear.
> absolute_quantity<double, temperature> t1 = 1000.0 * temperature; //
> Unspecified temperature type.
> absolute_quantity<double, temperature> t2 = 1010.0 * temperature;
>
> relative_quantity<double, temperature> tdiff = t2  t1; // tdiff
> is now 10
> temperature units.
[snip]
The way I'd propose to do this within the existing framework is to
implement two different
value_types:
template<class Y> class absolute_measure;
template<class Y> class difference_measure;
with the appropriate algebra defined within and between the two
classes (don't quote me
on this  I'd need to think carefully about the exact algebra):
absoute_measure  absolute_measure = difference_measure
absolute_measure + difference_measure = absolute_measure
absolute_measure +*/ absolute_measure = error
absolute_measure */ scalar = absolute_measure (?)
difference_measure > normal quantity algebra, implicitly convertible
to value_type (Y)
Then you would have
quantity<absolute_measure<double>,SI::temperature> t1 =
1000.0*SI::kelvin,
t2 = 1010.0*SI::kelvin;
quantity<difference_measure<double>,SI::temperature> tdiff = t2t1;
quantity_casts would just work by delegating to the appropriate
value_type constructor when
converting explicitly between absolute_measure and relative_measure...
> PS
> Temperature is particularly odd in that absolute temperature it is
> (almost)
> a linear space even though temperature differences are in a
> different linear
> space. That is,
> 0°C × 2 = 273.15K × 2 = 546.3K = 273.15°C.
> (I say "almost" because there's no negative absolute temperature,
> so it
> can't really be a linear space.)
I'm not sure I follow the significance here...
> PPS
> Where can I find the code under discussion?
It's in the Boost Vault :
http://www.boostconsulting.com/vault/index.php?
&direction=0&order=&directory=Units
file is mcs_units_v0.5.4.zip
Thanks for the feedback.
Matthias
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk