This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [Solaris] Catch FP exceptions


>   i386 only, might be related
> 
> ,.,. CXG2021 ACATS 2.5 13-05-27 17:47:57
> ---- CXG2021 Check the accuracy of the complex SIN and COS functions.
>    * CXG2021 Identity_2_Test  3 0: Cos(( 1.60300E+01,  1.60000E+01))
>                 imaginary part actual:  1.40623E+06 expected:
>                 1.40622E+06 difference:  4.00000E+00 max err:
>                 3.68797E+00 efactor: 1.40623E+06.
> **** CXG2021 FAILED ****************************.

The test fails because the difference (4.00000E+00) is larger than the max err 
(3.68797E+00).  I've reduced the testcase to p.adb, which reads in part:

   package Complex_Type is new Ada.Numerics.Generic_Complex_Types (Float);
   use Complex_Type;

   package CEF is
     new Ada.Numerics.Generic_Complex_Elementary_Functions (Complex_Type);

   function Sin (X : Complex) return Complex renames CEF.Sin;
   function Cos (X : Complex) return Complex renames CEF.Cos;

   Z : Complex;
   W : constant Complex := (0.0625, 0.0625);
   ZmW : Complex;
   Sin_ZmW, Cos_ZmW : Complex;
   A1, A2 : Complex;
   Sin_W : constant Complex := (6.2581348413276935585E-2,
                                6.2418588008436587236E-2);
   Cos_W_m_1 : constant Complex := (-2.5431314180235545803E-6,
                                    -3.9062493377261771826E-3);
begin

   for I in 2 .. 3 loop
      Z := (16.0 + Float (I) / Float (100), 16.0);
      ZmW := Z - W;
      Cos_ZmW := Cos (ZmW);

and most of the 4.00000E+00 difference for I = 3 in the final result comes 
from Im (Cos_ZmW), which in turn comes from Re (ZmW).  We have at -O1:

(gdb) x/f ($esp)
0xffffce60:     16.0300007
(gdb) x/f ($esp + 8)
0xffffce68:     0.0625
(gdb) nexti
0x0804a2e6      2791          zmw := p__complex_type__Osubtract__2 (z, w);
(gdb) p/f $eax
$1 = 15.9675007        <========= Re (ZmW)

and we have at -O2:

(gdb) info reg st0
st0            0.0625   (raw 0x3ffb8000000000000000)
(gdb) info reg st1
st1            16.030000000000000000624500451351651     (raw 
0x4003803d70a3d70a3d71)
(gdb) nexti
0x0804a231      520                 re => left.re - right.re,
(gdb) info reg st0
st0            15.967500000000000000624500451351651     (raw 
0x4002ff7ae147ae147ae2)
(gdb) nexti
(gdb) x/f ($ebp - 0x44)
0xffffce94:     15.9674997    <========= Re (ZmW)

with Im (Zmw) the same (15.9375) in both cases.  At a result, Im (Cos_ZmW) is 
1071153.38 at -O1 and 1071149.5 at -O2, the difference (3.88) being already 
larger than the max err.

IOW most of the difference only comes from:

  16.0 + Float (I) / Float (100) - 0.0625

where we truncate to 32-bit at -O1 before doing the subtraction, whereas we 
keep the Extended Precision at -O2, and then goes through the exponentation,
leading to the final 3.88 difference.

Fixed thusly, tested on i686-suse-linux, applied on the mainline.


2013-05-31  Eric Botcazou  <ebotcazou@adacore.com>

	* ada/acats/floatstore.lst: New.
	* ada/acats/run_all.sh: Process it.


-- 
Eric Botcazou
with Text_IO; use Text_IO;
with Ada.Numerics.Generic_Complex_Types;
with Ada.Numerics.Generic_Complex_Elementary_Functions;

procedure P is

   package Complex_Type is new Ada.Numerics.Generic_Complex_Types (Float);
   use Complex_Type;

   package CEF is
     new Ada.Numerics.Generic_Complex_Elementary_Functions (Complex_Type);

   function Sin (X : Complex) return Complex renames CEF.Sin;
   function Cos (X : Complex) return Complex renames CEF.Cos;

   Z : Complex;
   W : constant Complex := (0.0625, 0.0625);
   ZmW : Complex;
   Sin_ZmW, Cos_ZmW : Complex;
   A1, A2 : Complex;
   Sin_W : constant Complex := (6.2581348413276935585E-2,
                                6.2418588008436587236E-2);
   Cos_W_m_1 : constant Complex := (-2.5431314180235545803E-6,
                                    -3.9062493377261771826E-3);
begin

   for I in 2 .. 3 loop
      Z := (16.0 + Float (I) / Float (100), 16.0);
      ZmW := Z - W;
      Sin_ZmW := Sin (ZmW);
      Cos_ZmW := Cos (ZmW);
      A1 := Cos (Z);
      A2 := Cos_ZmW + (Cos_ZmW * Cos_W_m_1 - Sin_ZmW * Sin_W);
      Put_Line (" actual: " & A1.Im'Img & " | expected: " & A2.Im'Img);
   end loop;

end;
Index: ada/acats/run_all.sh
===================================================================
--- ada/acats/run_all.sh	(revision 199343)
+++ ada/acats/run_all.sh	(working copy)
@@ -225,6 +225,10 @@ for chapter in $chapters; do
       if [ $? -eq 0 ]; then
          extraflags="$extraflags -gnatE"
       fi
+      grep $i $testdir/floatstore.lst > /dev/null 2>&1
+      if [ $? -eq 0 ]; then
+         extraflags="$extraflags -ffloat-store"
+      fi
       grep $i $testdir/stackcheck.lst > /dev/null 2>&1
       if [ $? -eq 0 ]; then
          extraflags="$extraflags -fstack-check"
Index: ada/acats/floatstore.lst
===================================================================
--- ada/acats/floatstore.lst	(revision 0)
+++ ada/acats/floatstore.lst	(revision 0)
@@ -0,0 +1 @@
+cxg2021

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]