Boost logo

Boost :

From: vladimir josef sykora (vladimir.sykora_at_[hidden])
Date: 2002-10-18 08:41:11

"Jeffrey C. Jacobs" <darklord_at_[hidden]> wrote in message
> Interesting
> Well, IMHO I am bias as I too was working on something like this but am
> production-ready so if Vladimir is happy with it I suppose I can support
> if only for the like-minded sentiment that SOME units library would be
> useful.
> That having been said, in general I would prefer something a little more
> like the FermiLab approach as it seems more intuitive to me. Namely, it
> nice to simply be able to write:
> 5 * cm;

For convenience (not part of the library itself) I included some typedefs
(definitions/defs.hpp), for example:

namespace morpho { namespace defs {


  template <class T>
  struct centimeter_generator {
    typedef ::morpho::unit<T,centimeter_tl> type;

} }

Now as a user:
const morpho::defs::centimeter_generator<double>::type cm(1.0);
morpho::defs::kilometer_generator<long double>::type km(1.0);

km = 5 * cm; // is more comprehensive for me. 'cm' is not restricted to a
particular type or value.

[I must note that I forgot operator* and operator/ for scalars. I've
uploaded new version with both]

> Which is what is happening intuitively IMHO. I think the idea of
> pre-defining cm and ALSO not polluting the global namespace with it
> (si::abbreviation::cm) unless the client wants to is a nice touch. I do
> agree that compile-time structs are probably best and done via MPL strikes
> me as the right way to go.

We were tempted to use boost::mpl::vector<> as the unit-typelist, and then
use boost::mpl::at<> for accessing the members, but we decided not to for
portability reasons (specially for Borland). The shock came afterwards when
we realised that the ice(s) malfuntion on Borland and the type safety was
gone - because of the unit's orders (ice) were not calculated correctly
(we're still looking for a workaround -help!-). Anyway, it won't be
difficult to switch to boost::mpl::vector<> to achieve cleaner code.

>However, I am also a bit squeamish at any sign
> of code bloat. Happily you are only defining typedefs and empty structs
> which should not generate any compiled code so this I like!

I'm still not satisfied with the use of std::pow during conversions, even if
its used just for dimensions of order!=0; I think it is an incursion that
the user must be aware of. To get an idea of overhead incursion, I compared
operator* for a unit (using all available dimension-conversions) and a
fundamental type (double). The overhead is noticeable over 10 000
calculations. The cpp file is included in the library: libs/units/examples.
Still, I'm not certain wich is faster: std::pow(base, exp) or a loop. For
small exp the loop should be faster, whereas for big exp the std::pow
(series impl.) should be faster.

> FermiLab's approach does seem to lack an MPL touch so I will say in this
> sense I like what you have done.
> I am though a bit concerned more with practical issues. Generally,
> can fix the unreadable (IMHO) some_unit_t, like in the FermiLab software
> Length, Width, Area, etc. And clearly the "cm" is a object and thus takes
> up some space in run-time code where as your approach, in not allowing
> qualifiers, makes the code lean and mean.

As far as the user is not calling conversions. The difference with
Fermilab's is that we avoid the run-time access to the unit scale factors
Our impl. is based upon policies with static inline executes.

>IMHO, again I like the
> "modifiers" approach for building numbers, but to do so in such a way that
> they can be included modularly: if you don't use it, you don't pay for it.
> A hybrid between your Spartan impl and Fermi's bloated one is what I'd
> prefer as far as code readability.
> Now, as for output, I have to admit preference to a different approach.
> Basically, as I see it there should be unit types (Mass, Volume, Time,
> Luminescence, [Electric] Current, Temperature per Radian, etc.) as well as
> units (kg, l, yr, cd, a, K/r) and that the former should be true types and
> the later a modifier for immediates. Note also that although SI does not
> cognize the dimensionless Radian and Striation, I think as a part-time
> physicist I'd like to know when I'm dealing with "radian per second" it is
> not confused with Hz (cycles [1] per second).

Good point. One solution can be to add one more parameter to the typelist,
defaulted to dummy, and the user can add whatever type to it, just to
differentiate the type. F.E: struct radian{}; and pass radian to the TL.

>But for output, what strikes
> me is how you have each type return its representation. Granted, this is
> part of a "Policy" which I think is the right approach, but OTOH, I am
> currently of the mind that std::facet is an underused aspect of the
> library. IMHO the representation of kiloliters or meters cubed or m^3 or
> m**3 or m3 should be configurable via imbuing the output with a facet
> on unitRepresentation : public std::facet. Then, to change the output one
> can derive a class from unitRepresentation replacing "K" with "*K" or "K*"
> depending on the programmer's preference. Granted this is the same
> mechanism I would use to create a custom kelvinPolicy-derived class to
> replace the representation, but to me I like the idea of abstracting the
> output from the type.

To be completely honest, I'm a bit rusty with facets & imbuing, but still
it's a good point. We just provided a simple operator << to stream out the
unit's representation (base units). If there is still some interest in the
library, we can try to implement such an approach. Help would be appretiated
for this stuff.

> As for unit conversions, I think this, like any scientific Unit library in
> general, requires a "significant_digit" library like the one on which I am
> working. Thus, as I have already greatly researched, converting between
> and force-kg (kN) would be only as accurate as either a) your source data
> b) the conversion factor (about 7 digits IIRC). I have already
> a library based on the assumption that 2 numbers with given error x+/-dx,
> y+/-dy can be manipulated in any of the built-in operations including sin,
> exp, etc. under the assumption that x and y are both independent, random
> variables. If there is a dependant relationship between x and y, I would
> have to take the partial derivatives of xdy and ydx (normally 0) into
> account. This would then have to be implemented as a "sci_number" policy
> IMHO, but that is another thing I will save for later. Your library would
> allow abstract data types on the fly as it were, unlike FermiLab which has
> the type compiled in to the library.

We wrote a value-wrapper to handle ADTs, but we didn't included it in the
library (it can be an add on). If there's any interest in ADTs, I think we
should support it.

>I would therefore only caution that
> Unit Conversion should be easily separable (another Policy??) from the
> unit-library proper to allow for those who want numbers with errors and
> those who don't.

ADT support?

> I think that is all, but in any case thanks Vladimir for bringing this to
> our attention! It is IMHO a cool thing to add.

Thanks Jeffrey for the review! I think as well that a physical units library
would be really cool to add to boost. It will make our lives as a scientific
programmers much easier & type safe :-)

> Jeffrey.
> "vladimir josef sykora" <vladimir.sykora_at_[hidden]> wrote in message
> news:aok5bc$ne4$
> > Greetings boosters,
> > I've been working for some time now on a physical unit's library that
> > like to submit to boost. It uses the concept of generating units out of
> > physical dimensions. It provides type-safety and implicit conversion
> between
> > units using operators.
> >
> [more...]
> _______________________________________________
> Unsubscribe & other changes:

vladimir sykora & henrik kuhn
morphochem AG
gmunder str. 37-37a
81379 muenchen
tel. ++49-89-78005-0
fax  ++49-89-78005-555

Boost list run by bdawes at, gregod at, cpdaniel at, john at