Patchwork [Fortran,committed] Add libquadmath testcase gfortran.dg/quad_2.f90

login
register
mail settings
Submitter Tobias Burnus
Date Nov. 5, 2011, 8:51 p.m.
Message ID <4EB5A1C2.7090606@net-b.de>
Download mbox | patch
Permalink /patch/123890/
State New
Headers show

Comments

Tobias Burnus - Nov. 5, 2011, 8:51 p.m.
Motivated by the report at  
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/6373a2dfe64f0b83

There is currently no run-test check that libquadmath actually works. 
The attached and committed (Rev. 181015) adds one which tests for 
libquadmath that I/O read/write works. Additionally, it checks that the 
result for sqrt(2.0) is OK.

The test uses the largest available floating-point number - be it 8, 10 
or 16 - and tests for that. The checks should be thus OK for any system.

Regarding the issue mentioned in the linked report: Kai could reproduce 
the issue - he also gets "0.0" under MinGW64 with the current trunk. 
(The report was for MinGW32 4.7.0 and allegedly it worked for 4.6.2.)

Tobias
Eric Botcazou - Nov. 7, 2011, 8:55 p.m.
> The test uses the largest available floating-point number - be it 8, 10
> or 16 - and tests for that. The checks should be thus OK for any system.

It fails with a link failure on SPARC Solaris 8 and 9:

FAIL: gfortran.dg/quad_2.f90  -O0  (test for excess errors)
Excess errors:
Undefined                       first referenced
 symbol                             in file
sqrtl                               /var/tmp//ccU7N9qc.o
ld: fatal: Symbol referencing errors. No output written to ./quad_2.exe
Steve Kargl - Nov. 7, 2011, 9 p.m.
On Mon, Nov 07, 2011 at 09:55:48PM +0100, Eric Botcazou wrote:
> > The test uses the largest available floating-point number - be it 8, 10
> > or 16 - and tests for that. The checks should be thus OK for any system.
> 
> It fails with a link failure on SPARC Solaris 8 and 9:
> 
> FAIL: gfortran.dg/quad_2.f90  -O0  (test for excess errors)
> Excess errors:
> Undefined                       first referenced
>  symbol                             in file
> sqrtl                               /var/tmp//ccU7N9qc.o
> ld: fatal: Symbol referencing errors. No output written to ./quad_2.exe

I suppose the obvious question is 'does libm on sparc solaris 8/9
contain a long double sqrtl() function?'  If the answer is no,
then xfail the testcase.
Rainer Orth - Nov. 8, 2011, 10:14 a.m.
Steve Kargl <sgk@troutmask.apl.washington.edu> writes:

> On Mon, Nov 07, 2011 at 09:55:48PM +0100, Eric Botcazou wrote:
>> > The test uses the largest available floating-point number - be it 8, 10
>> > or 16 - and tests for that. The checks should be thus OK for any system.
>> 
>> It fails with a link failure on SPARC Solaris 8 and 9:
>> 
>> FAIL: gfortran.dg/quad_2.f90  -O0  (test for excess errors)
>> Excess errors:
>> Undefined                       first referenced
>>  symbol                             in file
>> sqrtl                               /var/tmp//ccU7N9qc.o
>> ld: fatal: Symbol referencing errors. No output written to ./quad_2.exe
>
> I suppose the obvious question is 'does libm on sparc solaris 8/9
> contain a long double sqrtl() function?'  If the answer is no,
> then xfail the testcase.

Please no: sqrtl is a C99 addition, and we don't want lists of non-C99
targets in tests that require them.

	Rainer
Steve Kargl - Nov. 8, 2011, 3:24 p.m.
On Tue, Nov 08, 2011 at 11:14:52AM +0100, Rainer Orth wrote:
> Steve Kargl <sgk@troutmask.apl.washington.edu> writes:
> 
> > On Mon, Nov 07, 2011 at 09:55:48PM +0100, Eric Botcazou wrote:
> >> > The test uses the largest available floating-point number - be it 8, 10
> >> > or 16 - and tests for that. The checks should be thus OK for any system.
> >> 
> >> It fails with a link failure on SPARC Solaris 8 and 9:
> >> 
> >> FAIL: gfortran.dg/quad_2.f90  -O0  (test for excess errors)
> >> Excess errors:
> >> Undefined                       first referenced
> >>  symbol                             in file
> >> sqrtl                               /var/tmp//ccU7N9qc.o
> >> ld: fatal: Symbol referencing errors. No output written to ./quad_2.exe
> >
> > I suppose the obvious question is 'does libm on sparc solaris 8/9
> > contain a long double sqrtl() function?'  If the answer is no,
> > then xfail the testcase.
> 
> Please no: sqrtl is a C99 addition, and we don't want lists of non-C99
> targets in tests that require them.
> 

OK, so, then we simply accept that running a regression test
on these targets will always FAIL?  If the answer is 'yes',
then please close this PR because I doubt anyone will implement
sqrtl().
Rainer Orth - Nov. 8, 2011, 3:41 p.m.
Steve Kargl <sgk@troutmask.apl.washington.edu> writes:

>> Please no: sqrtl is a C99 addition, and we don't want lists of non-C99
>> targets in tests that require them.
>> 
>
> OK, so, then we simply accept that running a regression test
> on these targets will always FAIL?  If the answer is 'yes',
> then please close this PR because I doubt anyone will implement
> sqrtl().

No.  AFAICS so far C99 functions have been implemented in
intrinsics/c99_functions.c for the benefit of platforms that aren't
C99.  Has this policy changed recently?  

I don't think it's a good idea for libgfortran to contain references to
nonexistant functions (or for gfortran to emit references to C99
functions on non-C99 platforms, if that's the case).  At least that's
not what any other GCC language frontend does.

	Rainer
Janne Blomqvist - Nov. 8, 2011, 4:10 p.m.
On Tue, Nov 8, 2011 at 17:41, Rainer Orth <ro@cebitec.uni-bielefeld.de> wrote:
> Steve Kargl <sgk@troutmask.apl.washington.edu> writes:
>
>>> Please no: sqrtl is a C99 addition, and we don't want lists of non-C99
>>> targets in tests that require them.
>>>
>>
>> OK, so, then we simply accept that running a regression test
>> on these targets will always FAIL?  If the answer is 'yes',
>> then please close this PR because I doubt anyone will implement
>> sqrtl().
>
> No.  AFAICS so far C99 functions have been implemented in
> intrinsics/c99_functions.c for the benefit of platforms that aren't
> C99.  Has this policy changed recently?

I don't think there has ever been a such a hard policy. Yes,
c99_functions.c provides _some_ C99 functions when they can be
implemented in terms of other available functions. E.g. sqrtf() is
provided by

#ifndef HAVE_SQRTF
#define HAVE_SQRTF 1
float sqrtf (float x);

float
sqrtf (float x)
{
  return (float) sqrt (x);
}
#endif

Obviously, sqrtl() could be provided in the same way using the C89
sqrt(), but I'm sure we all agree that would be a pretty crappy
implementation. I think it's better to leave it out than to give users
a false impression that they have a functioning sqrtl.

> I don't think it's a good idea for libgfortran to contain references to
> nonexistant functions (or for gfortran to emit references to C99
> functions on non-C99 platforms, if that's the case).  At least that's
> not what any other GCC language frontend does.

So what would be a good solution then, assuming Santa doesn't suddenly
provide us with a target-independent C99 math library? One solution, I
suppose, would be to not support real(kind=10) (C long double) on
non-C99 targets. Do we have some mechanism for determining this when
building the frontend?
Steve Kargl - Nov. 8, 2011, 4:11 p.m.
On Tue, Nov 08, 2011 at 04:41:32PM +0100, Rainer Orth wrote:
> Steve Kargl <sgk@troutmask.apl.washington.edu> writes:
> 
> >> Please no: sqrtl is a C99 addition, and we don't want lists of non-C99
> >> targets in tests that require them.
> >> 
> >
> > OK, so, then we simply accept that running a regression test
> > on these targets will always FAIL?  If the answer is 'yes',
> > then please close this PR because I doubt anyone will implement
> > sqrtl().
> 
> No.  AFAICS so far C99 functions have been implemented in
> intrinsics/c99_functions.c for the benefit of platforms that aren't
> C99.  Has this policy changed recently?  

The policy has not changed.  However, it took me >3 years to
get an implementation of sqrtl() into FreeBSD's libm.  On the
surface, sqrtl() looks almost trivial to implement, but the
IEEE 754 requirement of correct rounding in all rounding modes
can be a nightmare to get right.  Adopting FreeBSD sqrtl() has
some issues.

> I don't think it's a good idea for libgfortran to contain references to
> nonexistant functions (or for gfortran to emit references to C99
> functions on non-C99 platforms, if that's the case).  At least that's
> not what any other GCC language frontend does.

AFAIK, gfortran has always assumed that it is being built/run on
a system with C99 functions.  If one does not care about correct
rounding, then one can do

#include <math.h>

long double
sqrtl(long double x)
{

  if (x == 0) return x;

  if (x < 0) return ((x - x) / (x - x));

  if (isfinite(x)) 
    {
       reduce x to 2*f*2**n.
       check if x is subnormal and adjust f and n.
       if (n is odd)
         {
            f = 2*f;
			n--;
         }
       use Newtow's iteration to compute sqrtl(f) with a
       starting value of xn = sqrt(f)

       now combine everything return (xn*2**(n/2))
    }
  else
    return (x * x + x);
 
}

Patch

Index: gcc/testsuite/gfortran.dg/quad_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/quad_2.f90        (Revision 0)
+++ gcc/testsuite/gfortran.dg/quad_2.f90        (Revision 0)
@@ -0,0 +1,63 @@ 
+! { dg-do run }
+!
+! This test checks whether the largest possible
+! floating-point number works.
+!
+! This is a run-time check. Depending on the architecture,
+! this tests REAL(8), REAL(10) or REAL(16) and REAL(16)
+! might be a hardware or libquadmath 128bit number.
+!
+program test_qp
+   use iso_fortran_env, only: real_kinds
+   implicit none
+   integer, parameter :: QP = real_kinds(ubound(real_kinds,dim=1))
+   real(qp) :: fp1, fp2, fp3, fp4
+   character(len=80) :: str1, str2, str3, str4
+   fp1 = 1
+   fp2 = sqrt (2.0_qp)
+   write (str1,*) fp1
+   write (str2,'(g0)') fp1
+   write (str3,*) fp2
+   write (str4,'(g0)') fp2
+
+!   print '(3a)', '>',trim(str1),'<'
+!   print '(3a)', '>',trim(str2),'<'
+!   print '(3a)', '>',trim(str3),'<'
+!   print '(3a)', '>',trim(str4),'<'
+
+   read (str1, *) fp3
+   if (fp1 /= fp3) call abort()
+   read (str2, *) fp3
+   if (fp1 /= fp3) call abort()
+   read (str3, *) fp4
+   if (fp2 /= fp4) call abort()
+   read (str4, *) fp4
+   if (fp2 /= fp4) call abort()
+
+   select case (qp)
+     case (8)
+       if (str1 /= "   1.0000000000000000") call abort()
+       if (str2 /= "1.0000000000000000") call abort()
+       if (str3 /= "   1.4142135623730951") call abort()
+       if (str4 /= "1.4142135623730951") call abort()
+     case (10)
+       if (str1 /= "   1.00000000000000000000") call abort()
+       if (str2 /= "1.00000000000000000000") call abort()
+       if (str3 /= "   1.41421356237309504876") call abort()
+       if (str4 /= "1.41421356237309504876") call abort()
+     case (16)
+       if (str1 /= "   1.00000000000000000000000000000000000") call abort()
+       if (str2 /= "1.00000000000000000000000000000000000") call abort()
+       if (str3 /= "   1.41421356237309504880168872420969798") call abort()
+       if (str4 /= "1.41421356237309504880168872420969798") call abort()
+       block
+         real(qp), volatile :: fp2a
+         fp2a = 2.0_qp
+         fp2a = sqrt (fp2a)
+         if (abs (fp2a - fp2) > sqrt(2.0_qp)-nearest(sqrt(2.0_qp),-1.0_qp)) call abort()
+       end block
+     case default
+       call abort()
+   end select
+
+end program test_qp
Index: gcc/testsuite/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog     (Revision 181014)
+++ gcc/testsuite/ChangeLog     (Arbeitskopie)
@@ -1,3 +1,7 @@ 
+2011-11-05  Tobias Burnus  <burnus@net-b.de>
+
+	* gfortran.dg/quad_2.f90: New.
+
 2011-11-05  Eric Botcazou  <ebotcazou@adacore.com>
 
	* gcc.dg/strlenopt-22g.c: New wrapper around...
@@ -26,10 +30,10 @@ 
 
 2011-10-09  Magnus Fromreide  <magfr@lysator.liu.se>
 
-        * g++.dg/cpp0x/enum21a.C: Test that enum x { y, } does
-        generate a pedwarn in c++98-mode.
-        * g++.dg/cpp0x/enum21b.C: Test that enum x { y, }
-        don't generate a pedwarn in c++0x-mode.
+	* g++.dg/cpp0x/enum21a.C: Test that enum x { y, } does
+	generate a pedwarn in c++98-mode.
+	* g++.dg/cpp0x/enum21b.C: Test that enum x { y, }
+	don't generate a pedwarn in c++0x-mode.
 
 2011-11-04  Olivier Goffart  <olivier@woboq.com>