www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Preliminary submission - std.rational and std.typelist

reply "Arlen" <arlen.ng gmx.com> writes:
I'll have more to say about the design in the future.  At the moment for me
porting Boost.Units to D is the fastest and the safest path to take.  Besides,
the math behind it is sound and and many years of hard work has gone into it.
 The problem with it, in my opionion, is that it's implemented in C++, :-).

I do want to mention that the distinction between dimension and unit is
important.  I rather see this:

Quantity!(length, float) a = 2 * metre;

than this:

Quantity!(metre, float) a = 2 * metre;

I'll spend more time going over you library once I have some free time.

Thanks,

Arlen

 ----- Original Message -----
 From: David Nadlinger
 Sent: 10/06/12 12:58 PM
 To: digitalmars-d puremagic.com
 Subject: Re: Preliminary submission - std.rational and std.typelist
 
 I wrote a units library in D last year: 
 http://klickverbot.at/code/units/. Before setting out, I 
 extensively researched existing solutions in other languages, 
 Boost.Units being on of them, and I believe that I managed to 
 come up with a design which takes advantage of D's advanced 
 metaprogramming capabilities, and as such is more powerful while 
 being much less clunky.
 
 For example, in comparison to Boost.Units, I didn't introduce a 
 notion of "dimension" separate from the concept of units, which 
 seemed to ultimately serve no purpose besides making valid 
 conversions easier to determine given the limitations of C++. I'd 
 love to hear your comments on the design!
 
 
 David

Oct 06 2012
parent "David Nadlinger" <see klickverbot.at> writes:
On Saturday, 6 October 2012 at 19:40:10 UTC, Arlen wrote:
 Besides, the math behind it is sound and and many years of hard 
 work has gone into it.

Also, it is extremely complicated by the fact that it somehow has to work withing the boundaries of C++ and boost::mpl and friends.
 I do want to mention that the distinction between dimension and 
 unit is important.

Why? From a theorist standpoint, there of course is a distinction between the two, yes. In practice, however, a dimension is simply a connected component in the graph of (non-composite) units, where the edges represent known conversions, i.e. a dimension is just a name for a set of units which can converted into each other. The concept of dimensions arises naturally, and no rigor is lost by not explicitly having it; there is no need to force the redundancy on the programmer. In fact, my library was also based on dimensions originally, but at some point, they became an annoyance in the code I wrote using it, and I discovered that I could do perfectly fine without them.
 I rather see this:

 Quantity!(length, float) a = 2 * metre;

 than this:

 Quantity!(metre, float) a = 2 * metre;

Really? The first has the problem that you have absolutely no idea what a is really represented like in memory – you need to have a canonical base unit all other units are automatically converted to. One consequence of that is that you are forced to do a lot of unneeded conversions if you can't completely work in that base unit, for example for interfacing with code that doesn't use your unit system. You also can't just transparently tack a unit on a quantity in places where the actual value is important, think serialization, ABI boundaries, etc. Not being able to chose your representation might also lead to precision issues if you are working with base types of limited width. In contrast, the concept of dimensions is easy to implement in terms of units. For example, you could just define 'isLength' as 'canConvert!meter' (it will accept any unit which can somehow, maybe not directly, converted into meters), and then implement a function like this: --- auto squareArea(T)(T side) if (isQuantity!T && isLength!(T.unit)) { return side * side; } --- squareArea now works transparently and without overhead with all unit types. Of course, you could also define the parameter as just Quantity!(meter, T) or Quantity!(meter, float) if for some reason you want to, for example because you are only working in meters anyway and you don't want to have a template function to avoid the (compile-time) overhead. I think the main reason why Boost.Units went with dimensions is that having a distinguished "canonical" unit for each dimension relieves the burden on the implementation in so far as you never have to synthesize code for arbitrary conversions, as your data is always stored in that canonical unit. David
Oct 06 2012