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=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,1f0e8beefacb537e X-Google-Attributes: gid103376,public From: Hyman Rosen Subject: Re: Engineering types hierarchy Date: 1999/09/08 Message-ID: #1/1 X-Deja-AN: 522630283 Sender: hymie@calumny.jyacc.com References: <7r50i7$e893@svlss.lmms.lmco.com> Content-Type: text/plain; charset=us-ascii X-Complaints-To: abuse@panix.com X-Trace: news.panix.com 936816101 27320 209.49.126.226 (8 Sep 1999 18:41:41 GMT) Organization: PANIX Public Access Internet and UNIX, NYC Mime-Version: 1.0 User-Agent: Gnus/5.070096 (Pterodactyl Gnus v0.96) Emacs/20.3 NNTP-Posting-Date: 8 Sep 1999 18:41:41 GMT Newsgroups: comp.lang.ada Date: 1999-09-08T18:41:41+00:00 List-Id: dkristol@see-my.sig (David Kristola) writes: > I am trying to put together a robust and easily usable > hierarchy of types packages to support a collection of > engineering units (kilograms, meters, seconds, etc.) > in scalar, vector, and matrix forms. > > So far, i have a list of the base types and combined > types (meters per second and so on) that are going to > be used on this project. > > There is an explosion of operators that i have to > implement. "/" for meters and second returning > meters per seconds, and on, and on, and on. > Of course, there is nothing special about these > operators beyond the typing they do. > > Is there a better way? Although this is an Ada group, I am moved to demonstrate a C++ solution which is applicable when all units are known at compile time. It's from Barton & Nackman's excellant "Scientific and Engineering C++", and is quite beautiful. Perhaps it can be transformed into Ada by someone who knows more about the language than I do. I'll write the code assuming three units - mass, time, distance - but the technique easily scales to as many as you need. The units are kept track of by virtue of the type system - the objects themselves carry no data other than their values. The type system allows multiplication and division of arbitrary units, while allowing addition and subtraction only of like units. Type mismatches result in compile-time errors. The scaffolding is wordy, but the punchline is down in main(), where the units are used in a very natural way, with the compiler deducing types. #include template struct unit { double value; unit(double initial = 0) : value(initial) { } }; template unit operator+(const unit &a, const unit &b) { return unit(a.value + b.value); } template unit operator-(const unit &a, const unit &b) { return unit(a.value - b.value); } template unit operator*(const unit &a, const unit &b) { return unit(a.value * b.value); } template unit operator/(const unit &a, const unit &b) { return unit(a.value / b.value); } template ostream &operator<<(ostream &out, const unit &u) { cout << u.value; if (M != 0) { out << " gm"; if (M != 1) out << "^" << M; } if (D != 0) { out << " cm"; if (D != 1) out << "^" << D; } if (T != 0) { out << " sec"; if (T != 1) out << "^" << T; } return out; } typedef unit<0,0,0> Scalar; typedef unit<1,0,0> Mass; typedef unit<0,1,0> Time; typedef unit<0,0,1> Distance; typedef unit<0,-1,1> Herz; typedef unit<1,-2,2> Energy; typedef unit<0,-1,1> Velocity; // etc. // gram-second-centimeter system const Mass gram = 1; const Mass kilogram = 1000; const Distance centimeter = 1; const Distance meter = 100; const Time second = 1; // etc. int main() { Distance d = Scalar(3) * meter + Scalar(21) * centimeter; Time t = 10; Mass m = Scalar(5) * kilogram + Mass(672); Energy e = (m * d * d / t / t); cout << e << endl; }