comp.lang.ada
 help / color / mirror / Atom feed
From: "Jeffrey R. Carter" <spam.jrcarter.not@nospam.acm.org>
Subject: Re: Question on types conversions - operations
Date: Sat, 13 Jun 2009 19:56:06 GMT
Date: 2009-06-13T19:56:06+00:00	[thread overview]
Message-ID: <qvTYl.740974$yE1.636062@attbi_s21> (raw)
In-Reply-To: <4a33cb0b$0$2848$ba620e4c@news.skynet.be>

Olivier Scalbert wrote:
> 
> I have the following three types:
>     type Length is new Float;
>     type Time   is new Float;
>     type Speed  is new Float;
> 
> Suppose I need to compute a speed given a length and a time.
> 
>     L: Length := 100.0;
>     T: Time   :=  10.0;
>     S: Speed;
> 
> How to do that ?
> 
> With S := Speed(Float(L) / Float(T)) ? Mmmm ... not nice.
> 
> With S := Speed(L / Length(T)), I am also not satisfy as I convert a 
> time in Length ...
> 
> I am sure you have better ideas !

If you want to do unit checking, you need a new abstraction:

type Scalar_Value is digits ...;

type Dimensioned_Value (Length : Integer; Mass : Integer; Time : Integer)
is private;

function To_Scalar (Value : in Dimensioned_Value) return Scalar_Value;

function To_Dimensioned (Length : in Integer;
                          Mass   : in Integer;
                          Time   : in Integer;
                          Value  : in Scalar_Value)
return Dimensioned_Value;

Dimension_Mismatch : exception;

function "+" (Left : in Dimensioned_Value; Right : in Dimensioned_Value)
return Dimensioned_Value;

-- "-", "*", "/", ...

subtype Length_Value is Dimensioned_Value (Length => 1, Mass => 0, Time =>  0);
subtype Time_Value   is Dimensioned_Value (Length => 0, Mass => 0, Time =>  1);
subtype Speed_Value  is Dimensioned_Value (Length => 1, Mass => 0, Time => -1);
subtype Area_Value   is Dimensioned_Value (Length => 2, Mass => 0, Time =>  0);
...

L: Length_Value := To_Dimensioned (1, 0, 0, 100.0);
T: Time_Value   := To_Dimensioned (0, 0, 1,  10.0);
S: Speed_Value;

S := L / T; -- OK.
L := L * L; -- Raises Constraint_Error: dimensions of L * L differ from L.
L := S + T; -- Raises Dimension_Mismatch.

Such an abstraction can be very useful if you have to do a lot of unit checking. 
It can also be noticeably slower than just using floating-point types.

An intermediate course is to derive a bunch of floating-point types from a 
common ancestor (as you have with Float), and define the appropriate operations 
to mix them, as others have suggested. The number of operations gets large very 
quickly. You can write a program to generate a package with the types and their 
operations; I have such a program, called Make_Units, if you'd like to see one 
(others do, too). One small problem when doing this is that the operations that 
have been "eliminated" by being declared abstract are still considered for 
overload resolution.

A low-level approach that still retains some unit checking is to derive a bunch 
of types from a common ancestor, then convert to that ancestor to perform 
operations that mix the types. This is something you've already said you don't 
like [S := Speed (Float (L) / Float (T) );].

The easiest thing from the point of writing the code is to use a single type and 
trust to inspection and testing to get the units right.

Which is best for you depends on your application.

-- 
Jeff Carter
"Beyond 100,000 lines of code you
should probably be coding in Ada."
P. J. Plauger
26



  parent reply	other threads:[~2009-06-13 19:56 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-06-13 15:51 Question on types conversions - operations Olivier Scalbert
2009-06-13 16:13 ` Robert Matthews
2009-06-13 16:55 ` anon
2009-06-13 16:58 ` Dmitry A. Kazakov
2009-06-13 16:59 ` sjw
2009-06-13 17:24   ` Martin
2009-06-13 19:35     ` sjw
2009-06-14  8:22     ` sjw
2009-06-15  8:40   ` Jean-Pierre Rosen
2009-06-15  9:30     ` Olivier Scalbert
2009-06-15  9:51       ` stefan-lucks
2009-06-15 10:33     ` AdaMagica
2009-06-15 19:37     ` sjw
2009-06-13 19:56 ` Jeffrey R. Carter [this message]
2009-06-14 15:55   ` Robert A Duff
2009-06-15  8:52 ` AdaMagica
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox