|
Boost : |
From: Matthias Schabel (boost_at_[hidden])
Date: 2003-10-26 12:17:12
A couple of other issues that have arisen :
1) the integer conversion question (I have implemented unit conversion
using the
left hand rule in my library so LHS op RHS -> LHS. There are two
potential problems
with this approach : first, if the ultimate unit type desired is that
of the RHS,
there is the potential for two conversions (from RHS to LHS then back
again), with
accompanying precision issues (though if you're operating at or near
the precision limit
you probably will get what you deserve regardless...). Second, the
integer problem
raised in an earlier post : int(2)*_meters + int(5)*_centimeters
would give 2m while
the reverse would give 205cm. While there are good reasons to not
allow integers as
value_type for dimensioned quantities (in conversions between, e.g.
SI and natural units
there are very large exponents which far exceed the range of any
current or planned integer
type, it is probably worthwhile considering whether implicit unit
conversion should be
disallowed. The added ugliness is probably a good thing, as in
C++-style casting :
CGS<float>::Length L1 = 5*_centimeters;
SI<float>::Length L2 = 2*_meters + SI<float>::Length(L1);
Expression templates were suggested as a possible solution to this
question. I see two
problems with this solution : first, it doesn't solve the issue of
limited integer precision
discussed above. Second, if all internal calculations are forced to
long double, we are
forcing more precision than may be necessary or desired and at the
same time preventing the
use of class value_types which have higher precision (like a quad
precision double or BCD value).
2) comparison operators also may have problems with unit conversions
due to numeric precision issues.
It is probably best to prohibit implicit unit conversions for this
reason as well.
As a further demonstration, I've written a quick-n-dirty Measurement
class which encapsulates both
values and errors, along with standard error propagation for basic
arithmetic operations. Its use
in conjunction with the units library is shown in mcs_units_2.zip in
the files section on yahoo.
> Since the main non-SI requirements are for subatomic particle physics,
> astronomy, and Imperial/US, these would be very useful demos.
It's just a matter of coming up with the conversion factors between
the relevant units and SI - I guess I'd rather not spend a tremendous
amount
of time assembling obscure units and unit systems until there's some
clear consensus on the direction, if any, the boost::units library will
take.
> What about radians, and trig functions etc?
As has been noted (also see
http://physics.nist.gov/cuu/Units/units.html), angles and solid angles
are technically dimensionless,
representing the ratio between a length along a circle and its
perimeter and an area on a sphere and it's total area. It would
certainly
be possible to add two more template parameters to the list of
dimensions in class Dimension to represent these. However, I'm
concerned that trying to accommodate arbitrary conversions between any
units of measure for anything may become too complex -
for example, currency conversions would require historical databases
of exchange rates at any instant and would depend on the
time of the conversion.
I think the idea of implementing the Dimension class as a some sort of
MPL list is a good one, as it allows extensibility with an arbitrary
list of tags. I discuss some possibilities in the README included
with my implementation of the library.
> Log scales like dB are also widely used - have you any ideas about
> dealing with
> these, if 'far out'.
The problem with nonlinear units is that, in order to support them in
a general way you would need to have an arbitrary system of
arithmetic for the basic operations which depends on the specific
unit. For example, it is unclear how to multiply two dB measurements
since they are relative power units... What should the result of
10dB*25dB be? 250 dB^2? Again, using an extensible MPL list this
could be done formally, assuming the library wasn't required to do
anything fancy arithmetically...
For example,
template<Tag,Value>
struct TV // tagged value
{
typedef Tag tag_type;
typedef Value value_type;
}
struct length_tag { };
struct time_tag { };
struct angle_tag { };
DimList<TV<length_tag,1>,TV<time_tag,2> > // m s^2 (in SI)
DimList<TV<time_tag,-1>,TV<angle_tag,1> > // rad s^-1 (in SI)
// multiplying these two dimensions would give
DimList<TV<length_tag,1>,TV<time_tag,1>,TV<angle_tag,1> > // m
s rad
If this was done, there could be a set of seven (or nine) standard
tags :
length_tag
mass_tag
time_tag
current_tag
temperature_tag
quantity_tag
intensity_tag
angle_tag
solid_angle_tag
reserved for use for physical quantities. Other quantities could be
added by users. Then, the
unit model could define templates for unit names and conversions
supporting the tag set desired.
tagSymbol<tag_type> in place of dimensionXSymbol() now used
tagToBase<tag_type> in place of dimensionXToBase() now used
It looks to me like we need an MPL guru to volunteer some help here...
Matthias
------------------------------------------------------------------------
---------------------------
Matthias Schabel, Ph.D.
Utah Center for Advanced Imaging Research
729 Arapeen Drive
Salt Lake City, UT 84108
801-587-9413 (work)
801-585-3592 (fax)
801-706-5760 (cell)
801-484-0811 (home)
mschabel at ucair med utah edu
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk