[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#463478: gcc-4.3: generates wrong code on i386 with -O3



Package: gcc-4.3
Version: 4.3-20080127-1
Severity: important

The attached code, coming from the GNU libc (test-ifloat.c and 
s_cacoshf.c) gives wrong results when compiled with gcc-4.3 and -O3. The
results are correct with gcc-4.3 and lower optimisation or with gcc-4.2.


-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386

Kernel: Linux 2.6.18-5-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages gcc-4.3 depends on:
ii  binutils            2.18.1~cvs20080103-1 The GNU assembler, linker and bina
ii  cpp-4.3             4.3-20080127-1       The GNU C preprocessor
ii  gcc-4.3-base        4.3-20080127-1       The GNU Compiler Collection (base 
ii  libc6               2.7-6                GNU C Library: Shared libraries
ii  libgcc1             1:4.3-20080127-1     GCC support library
ii  libgmp3c2           2:4.2.2+dfsg-1       Multiprecision arithmetic library
ii  libgomp1            4.3-20080127-1       GCC OpenMP (GOMP) support library
ii  libmpfr1ldbl        2.3.0.dfsg.1-2       multiple precision floating-point 

Versions of packages gcc-4.3 recommends:
ii  libc6-dev                     2.7-6      GNU C Library: Development Librari

-- no debconf information
/* gcc-4.3 -Wall -std=gnu99 -O3 -o test-cacoshf test-cacoshf.c */

#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif

#include <complex.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>

__complex__ float
mycacoshf (__complex__ float x)
{
  __complex__ float res;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
    {
      if (icls == FP_INFINITE)
	{
	  __real__ res = HUGE_VALF;

	  if (rcls == FP_NAN)
	    __imag__ res = nanf ("");
	  else
	    __imag__ res = copysignf ((rcls == FP_INFINITE
					 ? (__real__ x < 0.0
					    ? M_PI - M_PI_4 : M_PI_4)
					 : M_PI_2), __imag__ x);
	}
      else if (rcls == FP_INFINITE)
	{
	  __real__ res = HUGE_VALF;

	  if (icls >= FP_ZERO)
	    __imag__ res = copysignf (signbit (__real__ x) ? M_PI : 0.0,
					__imag__ x);
	  else
	    __imag__ res = nanf ("");
	}
      else
	{
	  __real__ res = nanf ("");
	  __imag__ res = nanf ("");
	}
    }
  else if (rcls == FP_ZERO && icls == FP_ZERO)
    {
      __real__ res = 0.0;
      __imag__ res = copysignf (M_PI_2, __imag__ x);
    }
  else
    {
      __complex__ float y;

      __real__ y = (__real__ x - __imag__ x) * (__real__ x + __imag__ x) - 1.0;
      __imag__ y = 2.0 * __real__ x * __imag__ x;

      y = csqrtf (y);

      if (__real__ x < 0.0)
	y = -y;

      __real__ y += __real__ x;
      __imag__ y += __imag__ x;

      res = clogf (y);

      /* We have to use the positive branch.  */
      if (__real__ res < 0.0)
	res = -res;
    }
  return res;
}


/* Various constants (we must supply them precalculated for accuracy).  */
#define M_PI_34l		(M_PIl - M_PI_4l)		/* 3*pi/4 */

static float minus_zero, plus_zero, nan_value;

#define BUILD_COMPLEX(real, imag) \
  ({ __complex__ float __retval;					      \
     __real__ __retval = (real);					      \
     __imag__ __retval = (imag);					      \
     __retval; })

#define MANT_DIG (FLT_MANT_DIG-1) 

static void
check_float_internal (const char *test_name, float computed, float expected,
		      float max_ulp, int xfail)
{
  int ok = 0;
  float diff = 0;
  float ulp = 0;

  if (isnan (computed) && isnan (expected))
    ok = 1;
  else if (isinf (computed) && isinf (expected))
    {
      /* Test for sign of infinities.  */
      if (signbit (computed) != signbit (expected))
	{
	  ok = 0;
	  printf ("infinity has wrong sign.\n");
	}
      else
	ok = 1;
    }
  /* Don't calc ulp for NaNs or infinities.  */
  else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected))
    ok = 0;
  else
    {
      diff = fabsf (computed - expected);
      /* ilogb (0) isn't allowed.  */
      if (expected == 0.0)
	ulp = diff / ldexpf (1.0, - MANT_DIG);
      else
	ulp = diff / ldexpf (1.0, ilogbf (expected) - MANT_DIG);
      if (computed == 0.0 && expected == 0.0
	  && signbit(computed) != signbit (expected))
	ok = 0;
      else if (ulp <= 0.5 || (ulp <= max_ulp))
	ok = 1;
      else
        ok = 0;

    }
  if (ok == xfail)
    {
      if (!ok)
	printf ("Failure: ");
      printf ("Test: %s\n", test_name);
      printf ("Result:\n");
      printf (" is:         % .20e  % .20a\n",
	      computed, computed);
      printf (" should be:  % .20e  % .20a\n",
	      expected, expected);
    }
}


static void
check_complex (const char *test_name, __complex__ float computed,
	       __complex__ float expected,
	       __complex__ float max_ulp, __complex__ int xfail)
{
  float part_comp, part_exp, part_max_ulp;
  int part_xfail;
  char str[200];

  sprintf (str, "Real part of: %s", test_name);
  part_comp = __real__ computed;
  part_exp = __real__ expected;
  part_max_ulp = __real__ max_ulp;
  part_xfail = __real__ xfail;

  check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail);

  sprintf (str, "Imaginary part of: %s", test_name);
  part_comp = __imag__ computed;
  part_exp = __imag__ expected;
  part_max_ulp = __imag__ max_ulp;
  part_xfail = __imag__ xfail;
  check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail);
}

int main (int argc, char **argv)
{
  plus_zero = 0.0;
  nan_value = plus_zero / plus_zero;
  minus_zero = copysignf (0.0, -1.0);

  check_complex ("cacosh (0 + 0 i) == 0.0 + pi/2 i", mycacoshf (BUILD_COMPLEX (0, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0);
  check_complex ("cacosh (-0 + 0 i) == 0.0 + pi/2 i", mycacoshf (BUILD_COMPLEX (minus_zero, 0)), BUILD_COMPLEX (0.0, M_PI_2l), 0, 0);
  check_complex ("cacosh (0 - 0 i) == 0.0 - pi/2 i", mycacoshf (BUILD_COMPLEX (0, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0);
  check_complex ("cacosh (-0 - 0 i) == 0.0 - pi/2 i", mycacoshf (BUILD_COMPLEX (minus_zero, minus_zero)), BUILD_COMPLEX (0.0, -M_PI_2l), 0, 0);
  check_complex ("cacosh (-inf + inf i) == inf + 3/4 pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_34l), 0, 0);
  check_complex ("cacosh (-inf - inf i) == inf - 3/4 pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_34l), 0, 0);

  check_complex ("cacosh (inf + inf i) == inf + pi/4 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_4l), 0, 0);
  check_complex ("cacosh (inf - inf i) == inf - pi/4 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_4l), 0, 0);

  check_complex ("cacosh (-10.0 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (-10.0, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
  check_complex ("cacosh (-10.0 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (-10.0, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);
  check_complex ("cacosh (0 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (0, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
  check_complex ("cacosh (0 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (0, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);
  check_complex ("cacosh (0.1 + inf i) == inf + pi/2 i", mycacoshf (BUILD_COMPLEX (0.1L, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, M_PI_2l), 0, 0);
  check_complex ("cacosh (0.1 - inf i) == inf - pi/2 i", mycacoshf (BUILD_COMPLEX (0.1L, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, -M_PI_2l), 0, 0);

  check_complex ("cacosh (-inf + 0 i) == inf + pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, 0)), BUILD_COMPLEX (HUGE_VALF, M_PIl), 0, 0);
  check_complex ("cacosh (-inf - 0 i) == inf - pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, minus_zero)), BUILD_COMPLEX (HUGE_VALF, -M_PIl), 0, 0);
  check_complex ("cacosh (-inf + 100 i) == inf + pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, 100)), BUILD_COMPLEX (HUGE_VALF, M_PIl), 0, 0);
  check_complex ("cacosh (-inf - 100 i) == inf - pi i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, -100)), BUILD_COMPLEX (HUGE_VALF, -M_PIl), 0, 0);

  check_complex ("cacosh (inf + 0 i) == inf + 0.0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, 0)), BUILD_COMPLEX (HUGE_VALF, 0.0), 0, 0);
  check_complex ("cacosh (inf - 0 i) == inf - 0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, minus_zero)), BUILD_COMPLEX (HUGE_VALF, minus_zero), 0, 0);
  check_complex ("cacosh (inf + 0.5 i) == inf + 0.0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, 0.5)), BUILD_COMPLEX (HUGE_VALF, 0.0), 0, 0);
  check_complex ("cacosh (inf - 0.5 i) == inf - 0 i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, -0.5)), BUILD_COMPLEX (HUGE_VALF, minus_zero), 0, 0);

  check_complex ("cacosh (inf + NaN i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (HUGE_VALF, nan_value)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
  check_complex ("cacosh (-inf + NaN i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (-HUGE_VALF, nan_value)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);

  check_complex ("cacosh (0 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (0, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
  check_complex ("cacosh (-0 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (minus_zero, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);

  check_complex ("cacosh (NaN + inf i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);
  check_complex ("cacosh (NaN - inf i) == inf + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, -HUGE_VALF)), BUILD_COMPLEX (HUGE_VALF, nan_value), 0, 0);

  check_complex ("cacosh (10.5 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
  check_complex ("cacosh (-10.5 + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (-10.5, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);

  check_complex ("cacosh (NaN + 0.75 i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, 0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);
  check_complex ("cacosh (NaN - 0.75 i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, -0.75)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);

  check_complex ("cacosh (NaN + NaN i) == NaN + NaN i", mycacoshf (BUILD_COMPLEX (nan_value, nan_value)), BUILD_COMPLEX (nan_value, nan_value), 0, 0);

  return 0;
}



Reply to: