comp.lang.ada
 help / color / mirror / Atom feed
* I think - it's a bug...
@ 2002-03-10  8:24 Anatoly Chernyshev
  2002-03-10 12:58 ` David C. Hoos, Sr.
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Anatoly Chernyshev @ 2002-03-10  8:24 UTC (permalink / raw)


Hello everybody!

Look at this piece of code:

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

WITH ada.text_io,ada.numerics.elementary_functions;
USE ada.text_io, ada.numerics.elementary_functions;
PROCEDURE el_stat_fun IS
   b            : float := 7.5;
   a:float:=4.0;
   rr, z : float;
   r            : float := 4.0;
   dz           : float := 0.3;
BEGIN
   FOR k IN 0..integer(b/dz) LOOP
      z:=float(k)*dz;
      put_line (float'image(1.0-(z/b)));
      rr:=-a*sqrt((1.0-(z/b)**2))+a+r;
   END LOOP;
END el_stat_fun;
----------------------------------------------------------------------------------------------------




When compiled using GNAT 3.14 (WinNT sp 6) it raises
ADA.NUMERICS.ARGUMENT_ERROR in sqrt function when k goes to 25 because
the argument for sqrt becomes
negative (like -X.XXXXXE-07 ... And this is a headache No 1).
However, if one comments out the put_line string - everything works
fine.

I don't know whether this is a bug or feature, but any kind of help for
how to avoid the situation when 1.0-1.0/1.0 yields  something different
from 0.0 will be greatly appreciated.

Thanks in advance,

Anatoly.









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

* Re: I think - it's a bug...
  2002-03-10  8:24 I think - it's a bug Anatoly Chernyshev
@ 2002-03-10 12:58 ` David C. Hoos, Sr.
  2002-03-11  5:33   ` Anatoly Chernyshev
                     ` (2 more replies)
  2002-03-11  5:32 ` Jeffrey Carter
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 12+ messages in thread
From: David C. Hoos, Sr. @ 2002-03-10 12:58 UTC (permalink / raw)


This is not a bug.  The problem comes about by not being aware of
the nature of floating point representation in computers.

In your example, the value of dz (0.3) is not exactly representable in
binary -- it is an infinitely repeating binary fraction. Hence, all values of
z that you compute are not exactly representable.

Thus, if the value of dz was rounded upward to the next lsb when
converting from decimal to binary, all values of z will be slightly
larger than their true value.

The only solution is to test the values of which you are about to take
the square root, and if the absolute value is less than some very small
threshold, set the value to 0.0.

Alternatively, if you are sure (given the nature of the problem you
are solving) that z can never be greater than b, you could replace
(z/b) by Float'Min (1.0, z/b).

Additionally, you might want to consider the following statement
from the GNAT User's Guide:
In particular, if the Ada code will do any floating-point operations,
then the FPU must be setup in an appropriate manner. For the case
of the x86, for example, full precision mode is required. The
procedure GNAT.Float_Control.Reset may be used to ensure that
the FPU is in the right state.

Finally you can obtain greater precision by using Long_Float or
Long_Long_Float instead of Float.

----- Original Message -----
From: "Anatoly Chernyshev" <rhezusfactor@yahoo.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: March 10, 2002 2:24 AM
Subject: I think - it's a bug...


> Hello everybody!
>
> Look at this piece of code:
>
> ----------------------------------------------------------------------------
---------------------
>
> WITH ada.text_io,ada.numerics.elementary_functions;
> USE ada.text_io, ada.numerics.elementary_functions;
> PROCEDURE el_stat_fun IS
>    b            : float := 7.5;
>    a:float:=4.0;
>    rr, z : float;
>    r            : float := 4.0;
>    dz           : float := 0.3;
> BEGIN
>    FOR k IN 0..integer(b/dz) LOOP
>       z:=float(k)*dz;
>       put_line (float'image(1.0-(z/b)));
>       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;
>    END LOOP;
> END el_stat_fun;
> ----------------------------------------------------------------------------
------------------------
>
>
>
>
> When compiled using GNAT 3.14 (WinNT sp 6) it raises
> ADA.NUMERICS.ARGUMENT_ERROR in sqrt function when k goes to 25 because
> the argument for sqrt becomes
> negative (like -X.XXXXXE-07 ... And this is a headache No 1).
> However, if one comments out the put_line string - everything works
> fine.
>
> I don't know whether this is a bug or feature, but any kind of help for
> how to avoid the situation when 1.0-1.0/1.0 yields  something different
> from 0.0 will be greatly appreciated.
>
> Thanks in advance,
>
> Anatoly.
>
>
>
>
>
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>





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

* Re: I think - it's a bug...
  2002-03-10  8:24 I think - it's a bug Anatoly Chernyshev
  2002-03-10 12:58 ` David C. Hoos, Sr.
@ 2002-03-11  5:32 ` Jeffrey Carter
  2002-03-11  5:46   ` Anatoly Chernyshev
  2002-03-11  8:19 ` Phil Thornley
  2002-03-11 19:48 ` Anatoly Chernyshev
  3 siblings, 1 reply; 12+ messages in thread
From: Jeffrey Carter @ 2002-03-11  5:32 UTC (permalink / raw)


Anatoly Chernyshev wrote:
> 
> WITH ada.text_io,ada.numerics.elementary_functions;
> USE ada.text_io, ada.numerics.elementary_functions;
> PROCEDURE el_stat_fun IS
>    b            : float := 7.5;
>    a:float:=4.0;
>    rr, z : float;
>    r            : float := 4.0;
>    dz           : float := 0.3;

B, A, R, and Dz are constants. Why not make them named numbers?

> BEGIN
>    FOR k IN 0..integer(b/dz) LOOP
>       z:=float(k)*dz;
>       put_line (float'image(1.0-(z/b)));
>       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;

The parentheses here look funny. Did you perhaps mean

rr:=-a*sqrt((1.0-(z/b))**2)+a+r;

?

>    END LOOP;
> END el_stat_fun;

-- 
Jeff Carter
"English bed-wetting types."
Monty Python & the Holy Grail



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

* Re: I think - it's a bug...
  2002-03-10 12:58 ` David C. Hoos, Sr.
@ 2002-03-11  5:33   ` Anatoly Chernyshev
  2002-03-11 13:43     ` David C. Hoos
  2002-03-11 16:13     ` Stephen Leake
  2002-03-11  5:39   ` Jeffrey Carter
  2002-03-11 14:53   ` Wes Groleau
  2 siblings, 2 replies; 12+ messages in thread
From: Anatoly Chernyshev @ 2002-03-11  5:33 UTC (permalink / raw)




"David C. Hoos, Sr." wrote:

> This is not a bug.  The problem comes about by not being aware of
> the nature of floating point representation in computers.
>
> In your example, the value of dz (0.3) is not exactly representable in
> binary -- it is an infinitely repeating binary fraction. Hence, all values of
> z that you compute are not exactly representable.
>
> Thus, if the value of dz was rounded upward to the next lsb when
> converting from decimal to binary, all values of z will be slightly
> larger than their true value.
>

That's true, but still, why inserting of "put_line (float'image(1.0-(z/b)));"
influences the behaviour of the program so much.
Beyound that, I've got similar things with z=0.1 and 0.25. They were solved
though, by using different optomization levels (-O, -O2...).


>
> The only solution is to test the values of which you are about to take
> the square root, and if the absolute value is less than some very small
> threshold, set the value to 0.0.
>
> Alternatively, if you are sure (given the nature of the problem you
> are solving) that z can never be greater than b, you could replace
> (z/b) by Float'Min (1.0, z/b).
>
> Additionally, you might want to consider the following statement
> from the GNAT User's Guide:
> In particular, if the Ada code will do any floating-point operations,
> then the FPU must be setup in an appropriate manner. For the case
> of the x86, for example, full precision mode is required. The
> procedure GNAT.Float_Control.Reset may be used to ensure that
> the FPU is in the right state.

> Finally you can obtain greater precision by using Long_Float or Long_Long_Float
> instead of Float.

Thanks a lot for those suggestions (but you are omitted what is coming from the
GNAT UG).

>




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

* Re: I think - it's a bug...
  2002-03-10 12:58 ` David C. Hoos, Sr.
  2002-03-11  5:33   ` Anatoly Chernyshev
@ 2002-03-11  5:39   ` Jeffrey Carter
  2002-03-11 14:53   ` Wes Groleau
  2 siblings, 0 replies; 12+ messages in thread
From: Jeffrey Carter @ 2002-03-11  5:39 UTC (permalink / raw)


"David C. Hoos, Sr." wrote:
> 
> Additionally, you might want to consider the following statement
> from the GNAT User's Guide:
> In particular, if the Ada code will do any floating-point operations,
> then the FPU must be setup in an appropriate manner. For the case
> of the x86, for example, full precision mode is required. The
> procedure GNAT.Float_Control.Reset may be used to ensure that
> the FPU is in the right state.

Note that this is in the section "Binding with Non-Ada Main Programs",
which clearly doesn't apply in this case.

-- 
Jeff Carter
"English bed-wetting types."
Monty Python & the Holy Grail



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

* Re: I think - it's a bug...
  2002-03-11  5:32 ` Jeffrey Carter
@ 2002-03-11  5:46   ` Anatoly Chernyshev
  0 siblings, 0 replies; 12+ messages in thread
From: Anatoly Chernyshev @ 2002-03-11  5:46 UTC (permalink / raw)




Jeffrey Carter wrote:

> Anatoly Chernyshev wrote:
> >
> > WITH ada.text_io,ada.numerics.elementary_functions;
> > USE ada.text_io, ada.numerics.elementary_functions;
> > PROCEDURE el_stat_fun IS
> >    b            : float := 7.5;
> >    a:float:=4.0;
> >    rr, z : float;
> >    r            : float := 4.0;
> >    dz           : float := 0.3;
>
> B, A, R, and Dz are constants. Why not make them named numbers?

This was cut from the much bigger program, actually there they are not
constants.

>
> The parentheses here look funny. Did you perhaps mean
>
> rr:=-a*sqrt((1.0-(z/b))**2)+a+r;

This is just a mistyping - I meant what I meant. Anyway, after removing
of extra brackets the problem still persists.






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

* Re: I think - it's a bug...
  2002-03-10  8:24 I think - it's a bug Anatoly Chernyshev
  2002-03-10 12:58 ` David C. Hoos, Sr.
  2002-03-11  5:32 ` Jeffrey Carter
@ 2002-03-11  8:19 ` Phil Thornley
  2002-03-11 19:48 ` Anatoly Chernyshev
  3 siblings, 0 replies; 12+ messages in thread
From: Phil Thornley @ 2002-03-11  8:19 UTC (permalink / raw)


"Anatoly Chernyshev" <rhezusfactor@yahoo.com> wrote in message
news:3C8B184D.49214059@yahoo.com...
> Hello everybody!
>
> Look at this piece of code:
>
> ----------------------------------------------------------------------
---------------------------
>
> WITH ada.text_io,ada.numerics.elementary_functions;
> USE ada.text_io, ada.numerics.elementary_functions;
> PROCEDURE el_stat_fun IS
>    b            : float := 7.5;
>    a:float:=4.0;
>    rr, z : float;
>    r            : float := 4.0;
>    dz           : float := 0.3;
> BEGIN
>    FOR k IN 0..integer(b/dz) LOOP
>       z:=float(k)*dz;
>       put_line (float'image(1.0-(z/b)));
>       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;
>    END LOOP;
> END el_stat_fun;
> ----------------------------------------------------------------------
------------------------------
>
>
>
>
> When compiled using GNAT 3.14 (WinNT sp 6) it raises
> ADA.NUMERICS.ARGUMENT_ERROR in sqrt function when k goes to 25 because
> the argument for sqrt becomes
> negative (like -X.XXXXXE-07 ... And this is a headache No 1).
> However, if one comments out the put_line string - everything works
> fine.
>

You need to look at the generated code. All the variables are local to
the procedure, so if you comment out the Put_Line then the compiler
might be generating no code at all for the procedure.

Alternatively try changing it so that the variable rr is external to the
procedure (and make it volatile as well).

Cheers,

Phil

--
Phil Thornley
Programmes, Engineering
Warton





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

* Re: I think - it's a bug...
  2002-03-11  5:33   ` Anatoly Chernyshev
@ 2002-03-11 13:43     ` David C. Hoos
  2002-03-11 16:13     ` Stephen Leake
  1 sibling, 0 replies; 12+ messages in thread
From: David C. Hoos @ 2002-03-11 13:43 UTC (permalink / raw)


I think what happens when the put_line call is present is that the
C runtime library is called, which on NT can result in the
FPU unit state being changed, hence the desirability (or need) to
call GNAT.Float_Control.Reset, as suggested.

The statement from the UG _was_ included, and is:

In particular, if the Ada code will do any floating-point operations,
then the FPU must be setup in an appropriate manner. For the case
of the x86, for example, full precision mode is required. The
procedure GNAT.Float_Control.Reset may be used to ensure that
the FPU is in the right state.

----- Original Message -----
From: "Anatoly Chernyshev" <rhezusfactor@yahoo.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: Sunday, March 10, 2002 11:33 PM
Subject: Re: I think - it's a bug...


>
>
> "David C. Hoos, Sr." wrote:
>
> > This is not a bug.  The problem comes about by not being aware of
> > the nature of floating point representation in computers.
> >
> > In your example, the value of dz (0.3) is not exactly representable in
> > binary -- it is an infinitely repeating binary fraction. Hence, all
values of
> > z that you compute are not exactly representable.
> >
> > Thus, if the value of dz was rounded upward to the next lsb when
> > converting from decimal to binary, all values of z will be slightly
> > larger than their true value.
> >
>
> That's true, but still, why inserting of "put_line
(float'image(1.0-(z/b)));"
> influences the behaviour of the program so much.
> Beyound that, I've got similar things with z=0.1 and 0.25. They were
solved
> though, by using different optomization levels (-O, -O2...).
>
>
> >
> > The only solution is to test the values of which you are about to take
> > the square root, and if the absolute value is less than some very small
> > threshold, set the value to 0.0.
> >
> > Alternatively, if you are sure (given the nature of the problem you
> > are solving) that z can never be greater than b, you could replace
> > (z/b) by Float'Min (1.0, z/b).
> >
> > Additionally, you might want to consider the following statement
> > from the GNAT User's Guide:
> > In particular, if the Ada code will do any floating-point operations,
> > then the FPU must be setup in an appropriate manner. For the case
> > of the x86, for example, full precision mode is required. The
> > procedure GNAT.Float_Control.Reset may be used to ensure that
> > the FPU is in the right state.
>
> > Finally you can obtain greater precision by using Long_Float or
Long_Long_Float
> > instead of Float.
>
> Thanks a lot for those suggestions (but you are omitted what is coming
from the
> GNAT UG).
>
> >
>
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
>




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

* Re: I think - it's a bug...
  2002-03-10 12:58 ` David C. Hoos, Sr.
  2002-03-11  5:33   ` Anatoly Chernyshev
  2002-03-11  5:39   ` Jeffrey Carter
@ 2002-03-11 14:53   ` Wes Groleau
  2002-03-11 15:15     ` David C. Hoos
  2 siblings, 1 reply; 12+ messages in thread
From: Wes Groleau @ 2002-03-11 14:53 UTC (permalink / raw)



> This is not a bug.  The problem comes about by not being aware of
> the nature of floating point representation in computers.

Unless I misunderstood the original post, there IS a bug.

If commenting out this

> >       put_line (float'image(1.0-(z/b)));

causes this to stop raising an exception

> >       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;

then I think there must be a bug in the optimizer.

But it should be sent to report@gnat.com and not to comp.lang.ada

-- 
Wes Groleau
http://freepages.rootsweb.com/~wgroleau



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

* Re: I think - it's a bug...
  2002-03-11 14:53   ` Wes Groleau
@ 2002-03-11 15:15     ` David C. Hoos
  0 siblings, 0 replies; 12+ messages in thread
From: David C. Hoos @ 2002-03-11 15:15 UTC (permalink / raw)


There are two problems, viz.

   1.  When z is essentially equal to b but (say) 1 lsb greater,
         then z/b is greater than 1.0, causing a negative argument
         to sqrt.

   2.   The problem with commenting out the put_line statement I
         believe to be a documented case where the NT C runtime
         can leave the FPU in a bad state.

----- Original Message ----- 
From: "Wes Groleau" <wesgroleau@despammed.com>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
Sent: Monday, March 11, 2002 8:53 AM
Subject: Re: I think - it's a bug...


> 
> > This is not a bug.  The problem comes about by not being aware of
> > the nature of floating point representation in computers.
> 
> Unless I misunderstood the original post, there IS a bug.
> 
> If commenting out this
> 
> > >       put_line (float'image(1.0-(z/b)));
> 
> causes this to stop raising an exception
> 
> > >       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;
> 
> then I think there must be a bug in the optimizer.
> 
> But it should be sent to report@gnat.com and not to comp.lang.ada
> 
> -- 
> Wes Groleau
> http://freepages.rootsweb.com/~wgroleau
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada.eu.org
> http://ada.eu.org/mailman/listinfo/comp.lang.ada
> 




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

* Re: I think - it's a bug...
  2002-03-11  5:33   ` Anatoly Chernyshev
  2002-03-11 13:43     ` David C. Hoos
@ 2002-03-11 16:13     ` Stephen Leake
  1 sibling, 0 replies; 12+ messages in thread
From: Stephen Leake @ 2002-03-11 16:13 UTC (permalink / raw)


Anatoly Chernyshev <rhezusfactor@yahoo.com> writes:

> That's true, but still, why inserting of "put_line (float'image(1.0-(z/b)));"
> influences the behaviour of the program so much.
> Beyound that, I've got similar things with z=0.1 and 0.25. They were solved
> though, by using different optomization levels (-O, -O2...).

Since that is the _only_ place you have Text_IO, if you leave out the
"put_line", Text_IO is not linked in. Then you don't need the
Microsoft runtime library. The Microsoft runtime library sets the FPU
to the "wrong" mode. If you Use GNAT.Float_Control.Reset, the presence
of "put_line" will no longer matter.

-- 
-- Stephe



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

* Re: I think - it's a bug...
  2002-03-10  8:24 I think - it's a bug Anatoly Chernyshev
                   ` (2 preceding siblings ...)
  2002-03-11  8:19 ` Phil Thornley
@ 2002-03-11 19:48 ` Anatoly Chernyshev
  3 siblings, 0 replies; 12+ messages in thread
From: Anatoly Chernyshev @ 2002-03-11 19:48 UTC (permalink / raw)


Thanks to everyone who tried to answer this post.
Eventually, I've found a solution that always put me on the safe side:

replace
FOR k IN 0..integer(b/dz) LOOP
with
FOR K IN 0..Integer(Float'Truncation(B/Dz)) LOOP

Anatoly Chernyshev wrote:

> Look at this piece of code:
>
> -------------------------------------------------------------------------------------------------
>
> WITH ada.text_io,ada.numerics.elementary_functions;
> USE ada.text_io, ada.numerics.elementary_functions;
> PROCEDURE el_stat_fun IS
>    b            : float := 7.5;
>    a:float:=4.0;
>    rr, z : float;
>    r            : float := 4.0;
>    dz           : float := 0.3;
> BEGIN
>    FOR k IN 0..integer(b/dz) LOOP
>       z:=float(k)*dz;
>       put_line (float'image(1.0-(z/b)));
>       rr:=-a*sqrt((1.0-(z/b)**2))+a+r;
>    END LOOP;
> END el_stat_fun;
> ----------------------------------------------------------------------------------------------------
>
> When compiled using GNAT 3.14 (WinNT sp 6) it raises
> ADA.NUMERICS.ARGUMENT_ERROR in sqrt function when k goes to 25 because
> the argument for sqrt becomes
> negative (like -X.XXXXXE-07 ... And this is a headache No 1).
> However, if one comments out the put_line string - everything works
> fine.
>
> I don't know whether this is a bug or feature, but any kind of help for
> how to avoid the situation when 1.0-1.0/1.0 yields  something different
> from 0.0 will be greatly appreciated.
>
> Thanks in advance,
>
> Anatoly.






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

end of thread, other threads:[~2002-03-11 19:48 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-03-10  8:24 I think - it's a bug Anatoly Chernyshev
2002-03-10 12:58 ` David C. Hoos, Sr.
2002-03-11  5:33   ` Anatoly Chernyshev
2002-03-11 13:43     ` David C. Hoos
2002-03-11 16:13     ` Stephen Leake
2002-03-11  5:39   ` Jeffrey Carter
2002-03-11 14:53   ` Wes Groleau
2002-03-11 15:15     ` David C. Hoos
2002-03-11  5:32 ` Jeffrey Carter
2002-03-11  5:46   ` Anatoly Chernyshev
2002-03-11  8:19 ` Phil Thornley
2002-03-11 19:48 ` Anatoly Chernyshev

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