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 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,d853e66024dcd092 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-08-04 16:32:08 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!headwall.stanford.edu!newshub.sdsu.edu!elnk-nf2-pas!newsfeed.earthlink.net!wn14feed!wn13feed!wn11feed!worldnet.att.net!204.127.198.203!attbi_feed3!attbi.com!rwcrnsc52.ops.asp.att.net.POSTED!not-for-mail Message-ID: <3F2EECCD.7010300@attbi.com> 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: Ada 64-bit IEEE compliant float & Oracle References: <3F2E94D5.610F50F4@raytheon.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 66.31.71.243 X-Complaints-To: abuse@comcast.net X-Trace: rwcrnsc52.ops.asp.att.net 1060039928 66.31.71.243 (Mon, 04 Aug 2003 23:32:08 GMT) NNTP-Posting-Date: Mon, 04 Aug 2003 23:32:08 GMT Organization: Comcast Online Date: Mon, 04 Aug 2003 23:32:08 GMT Xref: archiver1.google.com comp.lang.ada:41182 Date: 2003-08-04T23:32:08+00:00 List-Id: James A. Krzyzanowski wrote: > Problem: > > We are using Rational Ada and the IEEE compliant definition for 64-bit > floating point numbers. We recently changed our DB to Oracle which uses > a proprietary format for storing floating point numbers with greater > precision than the average software system could possibly need. Oracle > uses 17 bytes to store floating point numbers; but I have read > documentation that they use 126 bits (not 136) to store floating point > numbers. > > We have declared new types based on the IEEE standard 64-bit float that > have constrained ranges. For example, we have: > > type Radian_Type is new Float_64_Bit range -2_Pi .. +2_Pi; > subtype Latitude_Type is Radian_Type range -Pi_Over_2 .. +Pi_Over_2; > subtype Longitude_Type is Radian_Type range -Pi .. +Pi; > > When we store Latitude_Type'Last in the DB and then retrieve it, we get > a Constraint Error. Hmmm. I hope I don't come across as too judgmental in what I say, but... Your first mistake is apparently in assuming that your bounds correspond to Ada model numbers. If they don't, this could also happen in your Ada code independent of your database. The second problem is assuming that the bounds of a TYPE are members of any subtype. There is a guarentee (in a note at 3.5(57), but it deals with evaluating 'First and 'Last of a subtype and assigning them to values of the subtype. For most Ada types, this is no big deal. A type declaration creates an unnamed type and a first named subtype. Unfortunately this doesn't hold for floating point type declarations. There are attributes for floating-point types called 'Safe_First and 'Safe_Last, see A.5.3(71&72). What is the difference? Let me give some examples with your declarations above: Foo: Latitude_Type := +Pi_Over_2; -- may raise Constraint_Error; Bar: Latitude_Type := Latitude_Type'Last; -- will not cause exception. Foo1: Radian_Type := +2_Pi; -- may raise Constraint_Error Foo2: Radian_Type := Radian_Type'Last -- may raise Constraint_Error! Foo3: Radian_Type := Radian_Type'Safe_Last; -- will not cause exception. All of this has little to do with run-time semantics, and everything to do with how values in program text are converted to floating-point values. For example, the representation of your bounds could omit some (80-bit) values between the representation and the mathematical value. If on the other hand you have chosen "2_Pi" (which is not a legal Ada identifier but I left it), to represent some literal, the conversions to floating point of that literal could be inconsistant. Can you say can of worms? I remember an example I gave at a SigAda meeting in Dallas. Jerry Fischer was also on the panel, an he jumped up in alarm when I put up a slide that showed a type declaration and a subtype declaration: type My_Integer is range -2**31..2**31-1; subtype MI is My_Integer range -2**31..2**31-1; And said that a compiler would accept the type declaration and could either accept the subtype or reject it at compile time because it would raise an exception at run-time! Jerry spent about 2 minutes, following through aloud the chain of logic, said, "Oh, you're right!" and sat down. I thanked Jerry for giving my presentation, put up a slide that showed the identical logic, and concluded by showing which compilers, at the time accepted it, and which refused it because the subtype declaration would raise Constraint_Error. I never figured out if any of the applause was for me for bringing the issue up, but I assumed most of it was for Jerry. What is the right solution? You either have to ensure that all of your literals are model numbers of the base type--in this case 64-bit floating point, or use some other representation. I strongly recommend that whether your choose to measure angles in radians, degrees or grads, that the right TYPE for the job is a fixed point type. In this case you can choose to measure the angles in units of Pi/2**(62), and your only "problem" will be that there may only be one representation of -2_Pi. +2_Pi will be 'Last FOR THE TYPE, but it may be unrepresentable in the constrained subtype. You shouldn't have any problems with the subtypes given or the database, but you will always need to check that converted values are in range for the subtype. Nothing to do with Ada. If you are converting from some other representation to radians, the nature of computer arithmetic is such that an expression that is mathematically in range can evaluate at run-time to a point just outside the range. Imagine you have a rotating radar dish, to make it easy, it rotates once every 12 seconds. Given t in seconds since the dish started at azimuth 0, how do you compute the current dish angle? There is no easy answer. If t is represented in floating point, you can have a problem if t gets too large. (See Patriot2 in the Gulf War if you don't see the problem.) If you keep the time in say integer minutes plus seconds, that is better, but there might be a slight jitter at the end of every minute. For the record, at least one compiler accepts Pi/(2**62) as a 'Small: ---------------------------------------------------------------------------- with Ada.Numerics; use Ada.Numerics; with Ada.Text_IO; procedure Rad is type Radians is delta Pi/(2**62) range -2*Pi..2*Pi; for Radians'Small use Pi/(2**62); Foo: Radians := Pi/6; package Rad_IO is new Ada.Text_IO.Fixed_IO(Radians); begin Ada.Text_IO.Put(" Foo is "); Rad_IO.Put(Foo, 1,18,0); Ada.Text_IO.Put_Line(" radians."); Ada.Text_IO.Put(" Radians'First is "); Rad_IO.Put(Radians'First, 1,18,0); Ada.Text_IO.Put_Line(" radians."); Ada.Text_IO.Put(" Radians'Last is "); Rad_IO.Put(Radians'Last, 1,18,0); Ada.Text_IO.Put_Line(" radians."); end Rad; ------------------------------------------------------------------------------ E:\Ada\Test>gnatmake -gnato rad gnatmake -gnato rad gcc -c -gnato rad.adb gnatbind -x rad.ali gnatlink rad.ali E:\Ada\Test>rad rad Foo is 0.523598775598298873 radians. Radians'First is -6.283185307179586480 radians. Radians'Last is 6.283185307179586480 radians. E:\Ada\Test> ------------------------------------------------------------------------------ Looks fine to me, but you may want to check it out on your compiler... -- "As far as I'm concerned, war always means failure." -- Jacques Chirac, President of France "As far as France is concerned, you're right." -- Rush Limbaugh