comp.lang.ada
 help / color / mirror / Atom feed
* Ada 64-bit IEEE compliant float & Oracle
@ 2003-08-04 17:16 James A. Krzyzanowski
  2003-08-04 19:49 ` Stephen Leake
  2003-08-04 23:32 ` Robert I. Eachus
  0 siblings, 2 replies; 3+ messages in thread
From: James A. Krzyzanowski @ 2003-08-04 17:16 UTC (permalink / raw)


OK folks,

Here's what I hope you'll consider an interesting problem.  I hope that
someone else has already tackled this issue so we can have some
alternative solutions to choose from.

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.

Possible Solutions:

1) Extend the range of Latitude_Type & Longitude_Type slightly (by some
Epsilon) and prohibit ever using 'First or 'Last.
==> easy solution; kind of a kludge

2) In the interface with the DB, catch the exception and assign to
'First or 'Last as necessary.
==> not sure if we can determine if constraint was on the negative side
or positive side

3) On the DB side, specify 18 digits of precision and force the 18th
digit to be zero or 4 or 5 and rely on rounding for consistent results.
==> twiddling with digits seems like a kludge and will add processing
time to an already slow interface

4) When storing floats to the DB, use unchecked conversion to 64-bit
integer and store it.  Do the inverse on retrieve.
==> provides exact digital equivalence, but prohibits taking advantage
of any built in DB operations for floating point processing since DB
would no longer realize number is a float

Any comments or ideas out there?

--
---------------------------------------------------------------------------

         James A. Krzyzanowski - Staff Software Engineer - AFATDS
%c%
[*=] Raytheon Systems Company * Fort Wayne, IN 46808 * (219) 429-6446
cus
                 mailto:James_A_Krzyzanowski@raytheon.com
%s%
---------------------------------------------------------------------------






^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Ada 64-bit IEEE compliant float & Oracle
  2003-08-04 17:16 Ada 64-bit IEEE compliant float & Oracle James A. Krzyzanowski
@ 2003-08-04 19:49 ` Stephen Leake
  2003-08-04 23:32 ` Robert I. Eachus
  1 sibling, 0 replies; 3+ messages in thread
From: Stephen Leake @ 2003-08-04 19:49 UTC (permalink / raw)


"James A. Krzyzanowski" <James_A_Krzyzanowski@raytheon.com> writes:

> 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.

This all makes sense.

> 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;

I've tried this in the past; it always causes more problems than it's
worth.

What do you actually gain from this? If you ever get a
Constraint_Error, it's because of a bug in the software. So write unit
tests that check for outputs being in the proper range. Using these
subtypes means you are running those tests in the real application,
wasting CPU time and code ram.

> When we store Latitude_Type'Last in the DB and then retrieve it, we
> get a Constraint Error.

This is clearly a bug in the database and/or compiler. What do the
vendors say?


> Possible Solutions:

-1) report bug to Oracle and/or Rational (IBM?).

(who says solution numbers start at 1 :)

0) Eliminate constrained types, check for constraints in unit tests only.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Ada 64-bit IEEE compliant float & Oracle
  2003-08-04 17:16 Ada 64-bit IEEE compliant float & Oracle James A. Krzyzanowski
  2003-08-04 19:49 ` Stephen Leake
@ 2003-08-04 23:32 ` Robert I. Eachus
  1 sibling, 0 replies; 3+ messages in thread
From: Robert I. Eachus @ 2003-08-04 23:32 UTC (permalink / raw)


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




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2003-08-04 23:32 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-04 17:16 Ada 64-bit IEEE compliant float & Oracle James A. Krzyzanowski
2003-08-04 19:49 ` Stephen Leake
2003-08-04 23:32 ` Robert I. Eachus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox