From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=BAYES_00,INVALID_DATE autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,791ecb084fdaba75 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 1994-10-04 09:20:18 PST Path: bga.com!news.sprintlink.net!howland.reston.ans.net!europa.eng.gtefsd.com!news.umbc.edu!eff!blanket.mitre.org!linus.mitre.org!linus!mbunix!eachus From: eachus@spectre.mitre.org (Robert I. Eachus) Newsgroups: comp.lang.ada Subject: Re: Types with physical dimension Date: 4 Oct 94 11:51:07 Organization: The Mitre Corp., Bedford, MA. Message-ID: References: NNTP-Posting-Host: spectre.mitre.org In-reply-to: sal714@rs710.gsfc.nasa.gov's message of 03 Oct 1994 17:31:09 GMT Date: 1994-10-04T11:51:07+00:00 List-Id: In article sal714@rs710.gsfc.nasa.gov (Stephen A. Leake) writes: > I run robots with Ada, so I deal with real dimensions all the time. > Very early on, I started to write a package that enforced > dimensionality; I defined METERS, METERS_PER_SECOND, etc. I quickly > discovered that even simple equations need up to cubic dimensions, > in all combinations of length, mass and time. Defining all these > types and the associated operators was far too time-consuming to be > worth it. So now I rely on code reviews and careful testing. > The moral; strong typing is nice, but is no substitute for careful design > and thorough testing. Paul Hilfinger did a nice paper on using discriminants to check dimensionality. I don't have the paper in front of me but it works something like this: type Measure(Length,Mass,Time: Integer) is record Value: Float; end record; subtype Meters is Measure(1,0,0); subtype Kilograms is Measure(0,1,0); subtype Time is Measure(0,0,1); ...etc. Now you can define all the standard arithmetic operations on type Measure so that they keep the discriminants correct: function "*"(L,R: Measure) return Measure is begin return(L.Length+R.Length,L.Mass+R.Mass,L.Time+R.Time,L.Value*R.Value); end "*"; function "+"(L,R: Measure) return Measure is begin if L.Length /= R.Length or L.Mass /= R.Mass or L.Time /= R.Time then raise Constraint_Error; end if; return L.Value+R.Value; end "+"; In theory, if you use pragma INLINE, a good compiler should never store the discriminants and eliminate all the discriminant related code at compile time. In practice, when I used this technique, I had two versions of the specification of the types package, one with the discriminants and one which said "type Measure is Float;" and kept all the subtype declarations. I used the full package during unit test, and the streamlined package thereafter. The only problem I had was with square roots. I thought about changing the package to double all the dimensional values, so length would be (2,0,0), but I never did. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...