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 Path: utzoo!attcan!uunet!husc6!spdcc!merk!alliant!linus!eachus From: eachus@aries.mitre.org (Robert I. Eachus) Newsgroups: comp.lang.ada Subject: Re: language support for fixed-point arithmetic Message-ID: Date: 21 Mar 90 22:17:27 GMT References: <787@eedsp.eedsp.gatech.edu> <1990Mar19.175559.17109@planck.uucp> Sender: news@linus.UUCP Followup-To: comp.lang.ada Organization: The Mitre Corporation, Bedford, MA In-reply-to: westley@corsair.uucp's message of 19 Mar 90 17:55:59 GMT List-Id: In article <1990Mar19.175559.17109@planck.uucp> westley@corsair.uucp (Terry J. Westley) writes: > Fixed point types are potentially very useful, but I have run into a > number of interesting educational challenges, all originating from > users' expectations. (This is in a real-time system running on a > distributed network of M68030 and Sun workstation environment.) > 1. Designers and programmers understand why 'small must be a power of > two, but they wish they could have it be any arbitrary size. In > principle, this seems very possible, but I can see the performance > problems that would crop up because people use a powerful feature > without realizing what is really happening in the machine. Huh? Why must 'SMALL be a power of two? By default 'SMALL is a power of two, but this is an arbitrary choice which can be overridden by a "for foo'SMALL use ..." declaration. Compilers are not required to support ARBITRARY values for 'SMALL, because there would be an ACVC test with something like "for foo'SMALL use 7#0.0000005# - 5#0.000000000000000004# / 3#0.22222222#;" or some other dubious expression. However, the good compilers support most reasonable specifications, and the ARG is working on a definition of what a "reasonable" value is. (At which point there probably will be an ACVC test...) > 2. Users see the potential of fixed point types to give them the best of > both worlds of real and integer types, and they want more of each. > For example, they see a number as a real and expect to use the math > co-processor. Naturally, converting back and forth to a floating point > type destroys much the integer representation advantages. When you find an Ada compiler generating floating point code for fixed point operations, bitch. This is not a feature--it is almost always a bug. For example, the expresion A := foo(B*C) should never generate floating point code if A, B and C are of the same (fixed point) type. (Speak carefully here, you are being watched. :-) This does not mean that operations involving fixed point may not use mixed mode instructions, or scaling functions in a floating point chip, just that in the general case, using a floating point multiply or divide will result in loss of accuracy. Please, no flames from implementers saying we use lots of guard bits...many fixed point multiplication results must be exact, and RTFM, exact may mean many more bits than are required to represent either of the operand types. > I am slowly beginning to get across the responsibility of the designer > in choosing data types and the flexibility there is to add operations as > needed. > You give them an inch and they'll take a mile. Then, they complain that > the compiler doesn't support the mile. Then, they realize they can > bridge the mile themselves with not too much effort. Great stuff!! Agreed. If the implementer gets fixed point right, and the user does a little bit of thinking, operations in fixed point are both much faster and much more accurate than floating point arithmetic. My favorite example is: type Meters is delta 0.000_001 range -2.0**31/0.000_001..2.0**31/0.000_001-0.000_001; for Meters'SMALL use 0.000_001; type Nautical_Miles is delta Meters'SMALL / 1852.0 range Meters'FIRST / 1852.0 .. Meters'LAST / 1852.0; for Nautical_Miles'SMALL use Meters'SMALL / 1852.0; function To_Meters (X: in Nautical_Miles) return Meters is begin return Meters (X*1852); end To_Meters; function To_Nautical_Miles (X: in Meters) return Nautical_Miles is begin return Nautical_Miles (X/1852); end To_Nautical_Miles; pragma INLINE (To_Meters, To_Nautical_Miles); If your compiler is really good it will not generate any code for the conversions. Of course, if it has trouble you can write the conversion functions as instantiations of UNCHECKED_CONVERSION... -- Robert I. Eachus with STANDARD_DISCLAIMER; use STANDARD_DISCLAIMER; function MESSAGE (TEXT: in CLEVER_IDEAS) return BETTER_IDEAS is...