develooper Front page | perl.perl5.porters | Postings from June 2001

Re: [20010118.017] op/int.t failure

Thread Previous | Thread Next
From:
Hugo
Date:
June 5, 2001 06:40
Subject:
Re: [20010118.017] op/int.t failure
Message ID:
200106051243.NAA15525@crypt.compulink.co.uk
In <200106040119.CAA10769@crypt.compulink.co.uk>, Hugo writes:
:Nicholas Clark wrote:
::Not sure where to proceed from here - I think it's a gcc or libc issue,
::but as I couldn't make that test fail on long doubles I couldn't track it
::further.
:
:It is a clear bug in glibc modfl:
:
:crypt% cat t0
:#include <math.h>
:#include <stdio.h>
:
:int main(int argc, char** argv) {
:    long double nv = 4294967303.15;
:    long double v, w;
:    v = modfl(nv, &w);
:    printf("z = <%Lf> v = <%Lf> w = <%Lf>\n", nv, v, w);
:    return 0;
:}
:
:crypt% gcc -o t0 t0.c
:crypt% ./t0
:z = <4294967303.150000> v = <1.150000> w = <4294967302.000000>
:crypt% 
:
:(Note that modf() does not exhibit this bug.)
:
:I'll report this, if I can work out where to.

The glibc team report only that it is fixed in the latest version.

:I can't see any easy way for us to work around this.

Here is an easy way for us to work around this. Ideally we'd have
configure support for MODFL_POW32_BUG, but setting it manually
(with Configure -Accflags=-DMODFL_POW32_BUG) allows all tests to
pass here with small ints, long doubles.

For details, see http://bugs.gnu.org/cgi-bin/gnatsweb.pl and look
at bug ids 1548 and 2309.

Hugo
--- pp.c.old	Mon Jun  4 00:46:14 2001
+++ pp.c	Tue Jun  5 13:16:18 2001
@@ -2598,7 +2598,16 @@
 		  SETu(U_V(value));
 	      } else {
 #if defined(HAS_MODFL) || defined(LONG_DOUBLE_EQUALS_DOUBLE)
+#  if MODFL_POW32_BUG
+/* some versions of glibc split (i + d) into (i-1, d+1) for 2^32 <= i < 2^64 */
+		  {
+		      NV offset = Perl_modf(value, &value);
+		      (void)Perl_modf(offset, &offset);
+		      value += offset;
+		  }
+#  else
 		  (void)Perl_modf(value, &value);
+#  endif
 #else
 		  double tmp = (double)value;
 		  (void)Perl_modf(tmp, &tmp);
@@ -2612,7 +2621,16 @@
 		  SETi(I_V(value));
 	      } else {
 #if defined(HAS_MODFL) || defined(LONG_DOUBLE_EQUALS_DOUBLE)
+#  if MODFL_POW32_BUG
+/* some versions of glibc split (i + d) into (i-1, d+1) for 2^32 <= i < 2^64 */
+		  {
+		      NV offset = Perl_modf(-value, &value);
+		      (void)Perl_modf(offset, &offset);
+		      value += offset;
+		  }
+#  else
 		  (void)Perl_modf(-value, &value);
+#  endif
 		  value = -value;
 #else
 		  double tmp = (double)value;

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About