Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2004-10-31 07:25:03


>From: "Andy Little" <andy_at_[hidden]>

> > "Terje Slettebø" wrote
> > > "Andy Little" wrote
>
> > Some of the issues I ran into, when playing with such a library, were:
> >
> > How to handle input/output, especially formatting the prefix and unit
> > information. For example, one may write the same unit as:
> >
> > 1 MJ
> > 1000 kJ
> > 1000000 J
> > 1 megajoule
> > 10^6 J
> > 10^6 kg·m^2·s^-2
> > 10^6 kg·m^2/s^2
> > etc.
> >
> > In other words, it may be written in an infinite variety of forms.
> Moreover,
> > the user may want the various forms in different contexts.
>
> Of the 7 above 5 are doable (approximately) with the current setup via
> casting :
> casting to different units changes the actual value of the quantity. here
> 'e' has a numeric value of 1., casting to kJ changes the numeric value to
> 1000.
>
> os.setf(std::ios_base::fixed,std::ios_base::floatfield);
> os.precision(0);
> energy::MJ e(1);
> os << e << '\n';
> os << energy::kJ(e) << '\n';
> os << energy::J(e) << '\n';
> os.setf(std::ios_base::scientific);
> os << energy::J(e) << '\n';
> os << anonymous_cast(energy::J(e)) << '\n';
>
> gives:
>
> 1 MJ
> 1000 kJ
> 1000000 J
> 1e+006 J
> 1e+006 kg.m+2.s-2

That's great. :)

> ( BTW
> The difference between named-quantities and anonymous-quantities is
> significant. Otherwise one could not differentiate (say) energy and
torque.
> The anonymous_cast function removes the named-quantity connotations:
>
> pqs::energy::J e(1);
> pqs::torque::N_m t(1);
>
> os << e << '\n';
> os << t << '\n';
> os << anonymous_cast(e) <<'\n';
> os << anonymous_cast (t) <<'\n';
>
> gives:
>
> 1 J
> 1 N.m
> 1 kg.m+2.s-2
> 1 kg.m+2.s-2

Yes, it's good that you can differentiate between various units having the
same base units. It's similar with scalar values, which may be e.g. radians
or steradians, but without any base units.

> > Looking at the docs, it seems that this issue has been considered, and
> that
> > it's possible to provide custom output. Could you perhaps have shown how
> to
> > output some of the formats above, given the quantity 1 MJ?
>
> Yes I guess I could. The docs need a complete restart !
>
> > I've mentioned SI, here. That should be an "alarm bell", because another
> > issue to consider is if the library should be SI specific,
> > or be able to
> > handle units in general, including user-supplied ones.
>
> Its not SI specific, and it is possible to use other so-called
> anonymous-abstract-quantities ( so long as they conform to the
> AnonymousAbstractQuantityImplementation Concept), however by doing that
you
> need to fill in a large amount of detail.

Well, as long as it's possible to write your own custom formatting, that's
what is important. If you provide accessors for numerical value, unit name
(possibly also base units), in some way, then that is catered for.

> > If we were to get a quantity library in Boost, I think it should be able
> to
> > handle other quantities than the physical ones, as well (I didn't think
of
> > the money example in the previous post, so I couldn't think of a
> > non-physical quantity example, but I was concerned about the library
being
> > SI-specific. As I said above, this might be ok, but should be something
> that
> > should be explicitly addressed, perhaps in the FAQ).
>
> Ok. Basically anything (any set of things) that conforms to the rules (Ok
..
> what are the rules? ;-) ) will fit. However, as you pointed out previously
> its the output etc thats tricky, once you move out of SI you will need to
> provide a lot of that functionality yourself, so the 'simple to use'
aspect
> is lost. Its these details that take the time, not the actual
> dimensional-analysis part.

Well, making the "simple things simple, and the hard things possible", seems
like a good design. :)

> > Absolutely. When I played with my library, it was rather fun to write,
> e.g. (to use the syntax in your library):
> >
> > length::m m=123;
>
> [snip]
>
> (explicit value_type ctor )...
>
> length::m m(123);
> mass::kg kg(234);
> time::s s(10);
>
> > std::cout << kg*m*m/(s*s);
> >
> > and get the output:
> >
> > 35.40186 kJ
> >
> > :)
>
> PQs used to do that, however it'll now return an anonymous-quantity here,
> because dimensionally-equivalent types may be representing different
> quantities, so this would require casting the result to either torque or
> energy, else you will just get the 'anonymous-quantity' output in the
above
> example. But it was .. a cool trick :-)

Yes, good point.

> > In other words, it told you what the named unit was, if it existed. The
> > output was done by having some stream state decide the formatting.
> However,
> > as mentioned, this was rather experimental: I ended up using a
formatting
> > string, for more or less maximum flexibility, i.e. "%v %p%u<n>", where
<n>
> > was a number from 0 and up. 1 would give the output in the base units
> > ("kg·m^2·s^-2"); 2 would give the next "level" up ("N·m"), and 3 would
> give
> > the level after that (if existed) "J". %v gives the numerical value
> > (excluding the prefix value), "%p" gives the prefix - "k" here, and "%u"
> > gave the unit, "J". I had "tons" of these format specifiers, so I could
> get
> > "35.40186 kilojoule", etc., as well.
>
> cool.... but complicated ...
>
> > To sidestep this "implicit"/stream-stored formatting, it might be better
> to
> > use casting, as you use in the library, provided that you can then print
> the
> > resulting quantity any way you want.
>
> Well if you still have the code ....

It was written using Spirit to parse the formatting string and fill it in,
but unfortunately, I don't have it around, anymore. However, with a little
knowledge of Spirit, it shouldn't be that hard to make it again. In any
case, if the quantity objects provides accessors for its various properties,
then such a formatter is really orthogonal to PQS, and people may write
their own.

Regards,

Terje


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