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.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6a77269912f77a70 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-10-25 15:40:09 PST Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!newsfeed.mathworks.com!wn13feed!worldnet.att.net!204.127.198.203!attbi_feed3!attbi.com!attbi_s54.POSTED!not-for-mail Message-ID: <3F9AFB67.5080401@comcast.net> From: "Robert I. Eachus" User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.0.2) Gecko/20021120 Netscape/7.01 X-Accept-Language: en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Why no 'Floor for fixed point types References: <3F99FBE1.1030601@comcast.net> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.34.139.183 X-Complaints-To: abuse@comcast.net X-Trace: attbi_s54 1067121603 24.34.139.183 (Sat, 25 Oct 2003 22:40:03 GMT) NNTP-Posting-Date: Sat, 25 Oct 2003 22:40:03 GMT Organization: Comcast Online Date: Sat, 25 Oct 2003 22:40:07 GMT Xref: archiver1.google.com comp.lang.ada:1680 Date: 2003-10-25T22:40:07+00:00 List-Id: Nick Roberts wrote: >I said: >> Ignore this. To quote RM 3.5.9(8): "The set of values of a fixed >> point type comprise the integral multiples of a number called the >> small of the type." So the effect of all the code above can be better >> accomplished by: >> >> function Mantissa(X: in Tf) return Ti is >> begin return Ti(X/Tf'Small); end Mantissa; > > > No, Robert. Wrong! This function fails to do the 'floor' part of the > calculation. The name 'Mantissa' is misleading, since the result will > not be the mantissa (the decimal digits to the left of the decimal > point) unless Tf'Small happens to be 1.0 (and I did explicitly exclude > this case). First, the mantissa is not "the decimal digits to the left of the decimal point." For a number written in scaled notation: 1.2345E6 it is the part of the number before the exponent. Since in your program you are attempting to remove the scaling from a fixed-point type, the name Mantissa seemed appropriate. Change it if you wish. But you didn't pay attention above. The compiler allows you to think about fixed-point types as if they are real (non-integer) values. But they are not implemented that way. Any compiler that uses floating-point arithmetic to do fixed-point computations has a lot of bugs in it. They just havent been found yet. (And I think it was ACVC 1.4 that added a lot of tests which found such bugs.) Fixed point values are represented as integers. Their "actual" value is the integer times a scale factor 'Small. If you divide a fixed point number by its 'Small, you get an integer. Doing the arithmetic right can be tricky in theory, but most compilers are smart enough to recognize that all they need to do is nothing. That was why I advised you to write it that way--compilers are sensitive to that special case: >> -- Of course, any decent compiler should be able to recognize this >> -- special case and do nothing. If your compiler doesn't recognize this >> -- you could rewrite Mantissa as an instance of Unchecked_Conversion. > Yuk! I would suggest you either put up with the redundant operation or > get a new compiler. I assume that the Yuk! was about the reference to Unchecked_Conversion. But I think you didn't understand why it was there. I was not encouraging anyone to write that way, but to use 'Small in an idiom the compiler should recognize. I only mentioned the Unchecked_Conversion possibility to help people recognize what is going on in this function: NOTHING. It is a notation to tell the compiler to switch from treating the value as having fixed-point type, and to instead look at the value as an integer. > Maybe an example would help. Okay. > Suppose we have a temperature in variable Temp, of type Temperature (in > degrees celsius): > > type Temperature is delta 0.2 range -15.0 .. 90.0; > > Temp: Temperature := Read_Sensor(...); > > Now suppose we have a subsystem that can display two decimal digits > (perhaps on a 7-segment LED display), and we can use the following > procedure to do it: > > type Two_Decimal_Digits is range 00..99; > > procedure Display (Digits: in Two_Decimal_Digits); > > What we need to be able to do is to convert the fixed point type > Temperature into the integer type Two_Decimal_Digits. It might be in the > specification that the figure displayed should be the mantissa of the > value in Temp; this implies a 'floor' function (rounding down to the > nearest whole degree celsius). > > Having declared: > > Scale: constant := 1/Temperature'Small; > > > range Temperature'First*Scale .. Temperature'Last*Scale; At this point the compiler will give you an error message. Let's say we fix it: type Scaled_Temperature is range Integer(Temperature'First/Temperature'Small) ..Integer(Temperature'Last/Temperature'Small); > function Scaled_Floor (X: in Temperature) return Scaled_Temperature is > subtype ST is Scaled_Temperature; > begin > return ST(X*Scale) - ST(X*Scale) mod ST(Scale); > end; ...Now I understand the problem you think you are solving with this code. With the fix above so it compiles, for lots of values of Temperature'Small you will end up dividing by zero. With other values of Temperature'Small you will have overflows. So the range where your method works is fairly small. For this particular problem though, Integer(Float'Floor(Float(X))); Should do what you want. (Or what you should want, or something like that.) -- Robert I. Eachus "Quality is the Buddha. Quality is scientific reality. Quality is the goal of Art. It remains to work these concepts into a practical, down-to-earth context, and for this there is nothing more practical or down-to-earth than what I have been talking about all along...the repair of an old motorcycle." -- from Zen and the Art of Motorcycle Maintenance by Robert Pirsig