comp.lang.ada
 help / color / mirror / Atom feed
From: stt@dsd.camb.inmet.com (Tucker Taft)
Subject: Re: Types with physical dimension
Date: Wed, 28 Sep 1994 21:41:44 GMT
Date: 1994-09-28T21:41:44+00:00	[thread overview]
Message-ID: <Cwv09K.Ep4@inmet.camb.inmet.com> (raw)
In-Reply-To: GRAHAM.94Sep27181841@canopus.clsi.com

In article <GRAHAM.94Sep27181841@canopus.clsi.com>,
Paul Graham <graham@clsi.COM> wrote:

>While Ada's strong typing mechanism can catch errors like this:
>
>    d : dollars;
>    f : francs;
>...
>    d := d + f;		-- error
>
>it does allow such nonsensical constructs as
>
>    d := d * d;		-- what does it mean to multiply dollars by dollars?
>    d := d ** 10;	-- ??
>
>VHDL provides physical types to model values with physical dimensions.  A
>VHDL physical type lacks certain predefined multiplication operations, lacks
>exponentiation, and its division operation returns a universal_integer (or
>root_integer in Ada 9x terminolgy).  
> ...

>One can model physical types in Ada by using private types, but this
>involves writing a lot of operators.  What do Ada programmers do to guard
>against dimensional errors?

In Ada 9X, there is a new option.  You can override the
predefined operators of a numeric type with an abstract
function.  This flags any attempt to use the operation.

For example, here we define 3 types and override their predefined
multiplying and exponentiating operators with abstract versions:

    type Cm is digits 6;
    type Seconds is digits 6;
    type Cm_Per_Sec is digits 6;

    function "*"(Left, Right : Cm) return Cm is abstract;
    function "/"(Left, Right : Cm) return Cm is abstract;
    function "**"(Left : Cm; Right : Integer) return Cm is abstract;

    function "*"(Left, Right : Seconds) return Seconds is abstract;
    function "/"(Left, Right : Seconds) return Seconds is abstract;
    function "**"(Left : Seconds; Right : Integer) return Seconds is abstract;

    function "*"(Left, Right : Cm_Per_Sec) return Cm_Per_Sec is abstract;
    function "/"(Left, Right : Cm_Per_Sec) return Cm_Per_Sec is abstract;
    function "**"(Left : Cm_Per_Sec; Right : Integer) 
      return Cm_Per_Sec is abstract;

Then you can define the appropriate combinations:

    function "/"(Left : Cm; Right : Sec) return Cm_Per_Sec;
    function "*"(Left : Cm_Per_Sec; Right : Sec) return Cm;
    function "*"(Left : Sec; Right : Cm_Per_Sec) return Cm;

You would probably want to put pragma Inline on these.
You could actually define a generic to simplify this,
so you wouldn't have to write the trivial bodies repeatedly:

   generic
      type Left_Type is digits <>;
      type Right_Type is digits <>;
      type Result_Type is digits <>;
   function Mul(Left : Left_Type; Right : Right_Type) return Result_Type;
   pragma Inline("*");  -- This means to inline calls on any instantiation

   function Mul(Left : Left_Type; Right : Right_Type) 
     return Result_Type is
   begin
       return Result_Type(Left) * Result_Type(Right);
	  -- Note that predefined operators "reemerge" in generics
	  -- This is probably one of the few times where that is useful!
   end Mul;

... Ditto for a generic Div.

Now you can just write:

    function "/" is new Div(Cm, Sec, Cm_Per_Sec);
    function "*" is new Mul(Cm_Per_Sec, Sec, Cm);
    function "*" is new Mul(Sec, Cm_Per_Sec, Cm);

... which is relatively painless.

Of course it would be nice to have more direct support for
units (given infinite resources, that is ;-), but at least 
with "abstract" and "generics" you can build your own consistency
checks.

>Paul
>--
>Paul Graham 	graham@compass-da.com	Compass Design Automation, Inc.
>(speaking only for myself)	"Cekoslovakyalilastiramadiklarimizdanmissiniz."

S. Tucker Taft
Ada 9X Mapping/Revision Team
Intermetrics, Inc.
Cambridge, MA  02138

P.S. "abstract" subprograms weren't invented for this purpose,
but they seem to do the job fairly nicely.
Note that any untagged type may have an "abstract" primitive
subprogram.  But if a tagged type has an "abstract" primitive,
then it must itself be "abstract."
-T



  parent reply	other threads:[~1994-09-28 21:41 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <GRAHAM.94Sep27181841@canopus.clsi.com>
1994-09-28 17:36 ` Types with physical dimension William Brennan
1994-09-28 21:41 ` Tucker Taft [this message]
1994-09-29  4:11   ` Robert Dewar
1994-09-29 11:19     ` Peter Hermann
1994-09-30 10:17       ` Dr John Stockton
1994-10-03  4:37       ` Robert Dewar
1994-09-29 13:37     ` Tucker Taft
1994-10-03  4:40       ` Robert Dewar
1994-09-28 19:28 Paul Pukite
  -- strict thread matches above, loose matches on Subject: below --
1994-09-28 10:55 Simtel20 Transfer
1994-09-28 18:56 ` Mark A Biggar
1994-10-04  2:06 ` lmiller
1994-09-27 22:18 Paul Graham
1994-09-28 13:59 ` Robert Dewar
1994-09-30  2:06   ` R_Tim_Coslet
1994-10-03 17:31 ` Stephen A. Leake
1994-10-04 11:51   ` Robert I. Eachus
1994-10-04 19:45     ` Mark A Biggar
     [not found]       ` <CxBBx8.7L@irvine.com>
1994-10-13 22:15         ` gamache
1994-10-12  3:43     ` Matt Kennel
1994-10-04 14:56   ` Robert Dewar
1994-10-05 14:53     ` Bob Gilbert
1994-10-05  8:38   ` Jean-Pierre Rosen
1994-10-05 10:35     ` Stephen J Bevan
1994-10-05 13:17       ` Jean-Pierre Rosen
1994-10-05 15:48     ` Norman H. Cohen
replies disabled

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