Boost logo

Boost :

From: Matthias Schabel (boost_at_[hidden])
Date: 2007-02-16 18:05:01


> Does anyone really have software with code like
>
> ( 1.0 * SI::meters + 1.0 * imperial::feet ) * ( 2.0 *
> CGS::centimeters +
> 1.0 * imperial::feet )

This was a misinterpretation of what I was suggesting. The problem I'm
trying to deal with is that of things like

kilowatt hours
flops / dollar
m cm in

Right now mcs::units provides two options:

1) define unit quantities for the odd units in terms of units in some
chosen
unit system:

static const quantity<SI::power> kilowatt = 1000.0*SI::watt;
static const quantity<SI::time> hours = 3600.0*SI::seconds;

and

2) define a new unit system that contains all the units that you want
to mix
together

The problem with 1) is that you are converting, which incurs added
computation and, potentially, precision loss. The problem with 2) is
that it involves more coding and also that you can't easily support
cases where you have different units of the same physical quantity
such as volumes in meters*centimeters*inches. The simplification
would be for users of mixed systems, who would only have to have
the appropriate systems defined once somewhere and could then
freely mix and match units. My feeling at the moment is that getting
this to work may add too much additional complexity and compile-
time overhead for what is essentially an edge case. It's still an
intriguing challenge, though...

> So my code often looks something like this:
>
> class ComputeObject
> {
> typedef meters internal_distance_type;
> typedef kilograms internal_mass_type;
>
> template <class DistanceType, class MassType>
> ComputeObject(DistanceType distance, MassType mass)
> :distance_(unit_cast<internal_distance_type>(distance)),
> mass_(unit_cast<internal_mass_type>(mass))
> {
> ...(do computations using internal units)...
> }
>
> // Output functions
>
> template <class MassType>
> MassType some_calculated_mass() const
> {
> ...(do calculations using internal types)...
>
> return unit_cast<MassType>(answer);
> }
> };

This is how you would write it in mcs::units:

class ComputeObject
{
        typedef quantity<SI::length> internal_distance_type;
        typedef quantity<SI::mass> internal_mass_type;

        template<class System>
        ComputeObject(quantity<unit<System,length_type> > distance,
                                      quantity<unit<System,mass_type> > mass) :
                distance_(distance),
                mass_(mass)
        { ... }

        template<class System>
        quantity<unit<System,mass_type> >
        some_calculated_mass() const
        {
                ...

                return quantity<unit<System,mass_type> >(answer);
        }
};

> 1) I do not need a library that insists on defining some "system of
> units" to which everything gets converted.

A major design goal of mcs::units was to allow users to work in a system
that matches their problem. These can be physical units, but can be
anything else, also...

> 2) I am strongly against implicit conversion of units. If any line
> of my
> code has something in the wrong set of units, it means to me I screwed
> up the interface of the function that line of code is in. For me,
> units
> conversion *only* occurs at the interface of a function or constructor
> and never anywhere after that.

There is a small but vocal camp in favor of implicit unit
conversions. By
default, mcs::units allows _explicit_ conversion in quantity
constructors,
but implicit conversions are prohibited unless specifically enabled via

#define MCS_UNITS_ENABLE_IMPLICIT_CONVERSIONS

> At best, it appears to me that how I use the dimension/unit library is
> very different from what everybody is doing. So I will retire from the

I don't think so.

Matthias


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk