Boost logo

Boost :

From: Deane Yang (deane_yang_at_[hidden])
Date: 2003-11-06 09:59:34


Andy Little wrote:
> Hi ,
>
> In the previous debate about Physical Quantities,
> An interesting question that came up was
> What should the resulting units of a calculation between two different
> types of units be?
>
> (solution proposed)

I confess that I am a little mystified to why this is even needed,
and it leads me to wonder if how I envision using such a
library is different from everyone else. I apologize if this has
already been discussed, but could someone explain exactly why
something like:

inferred_type add_units(units_type first, other_units_type second)

is useful?

My immediate reaction, on the contrary, is that this leads to
the compiler quietly allowing changing of units without any
warning to the programmer, which can have undesirable consequences
(such as loss of precision).

Let me describe what I have always had in mind. It seems to me that
within the implementation of any single class or function, all of
the computations should be done within a consistent set of units,
and it is useful to have a units library that catches at compile-time
inconsistent calculations.

So within any given class or function, I do not see (but correct me if I
am wrong!) any need for unit conversions. The ONLY need for conversions
for me is in the interface. If you want to feed an output from a module
that uses one set of units into a module that uses a different set of
units, there should be a convenient way of converting the units. The
need becomes even more important when you want to write a generic class
that internally uses a consistent set of units but needs to interface
with other code that might use different units.

Even here I seem to disagree with others. It would appear that many
want this done automatically without any explicit casting. I have
learned to absolutely detest any kind of implicit casting like this
for a low-level library like this(I make any constructor with one input
"explicit" almost without exception). Of course, the interface of a
client library can often do this "unit cast" automatically.

(A corollary of this is that I no longer understand what a pure
"dimensions library" is. As far as I can tell, any physical calculation
requires a consistent set of units, so any dimensions library would
still require inside its implementation representations of the
dimensions with respect to some chosen set of units. Wouldn't you want a
lower level units library that allows for compile-time verification of
the consistency of this code? What I want, to be precise, is a
generic units library. I still believe that the dimensions library
being proposed by others can be implemented using the generic units
library.)

Let me illustrate what I would want a generic units library to do with a
very simple hypothetical client of the units library that computes
distance from average speed.

template <class time_units, class distance_units>
class average_speed
{
public:

   using boost::ratio_units;
   using boost::product_units;
   using boost::unit_cast;

   typedef ratio_units<distance_units, time_units>
        speed_units;

   template <class input_time_units, class input_distance_units>
   distance_from_velocity(input_time_units time,
                          input_distance_units distance)
  :speed_(unit_cast<distance_units,input_distance_units>(distance)
           / unit_cast<time_units,input_time_units>(time)
  {}

    template <
        class input_time_units,
        class input_speed_units
        class output_distance_units
          = typename boost::product_units<
                              input_time_units,
                              input_speed_units
>::type
>
    output_distance_units
    compute_distance(input_time_units time, input_speed_units speed)
    {
      time_units
      internal_time(unit_cast<time_units,input_time_units>(time));

      speed_units
     internal_speed(unit_cast<time_units,input_time_units>(time));

      distance_units
      internal_distance(internal_comput_distance(internal_time,
                                                 internal_speed);
      return unit_cast<output_distance_units,distance_units>
             (internal_distance);
    }

private:
     time_units time_;
     speed_units speed_;

     distance_units internal_compute_distance(time_units time,
                                              speed_units speed)
     {
        return speed * time;
     }
};


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