TEST(math, nextafterl) {
  ASSERT_DOUBLE_EQ(0.0L, nextafterl(0.0L, 0.0L));
  // Use a runtime value to accomodate the case when
  // sizeof(double) == sizeof(long double)
  long double smallest_positive = ldexpl(1.0L, LDBL_MIN_EXP - LDBL_MANT_DIG);
  ASSERT_DOUBLE_EQ(smallest_positive, nextafterl(0.0L, 1.0L));
  ASSERT_DOUBLE_EQ(-smallest_positive, nextafterl(0.0L, -1.0L));
}
GFC_REAL_16
nearest_r16 (GFC_REAL_16 s, GFC_REAL_16 dir)
{
  dir = copysignl (__builtin_infl (), dir);
  if (FLT_EVAL_METHOD != 0)
    {
      /* ??? Work around glibc bug on x86.  */
      volatile GFC_REAL_16 r = nextafterl (s, dir);
      return r;
    }
  else
    return nextafterl (s, dir);
}
Exemple #3
0
/*
 * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
 * that the result will be subnormal, and care is taken to ensure that
 * double rounding does not occur.
 */
static inline long double
add_and_denormalize(long double a, long double b, int scale)
{
	struct dd sum;
	int bits_lost;
	union IEEEl2bits u;

	sum = dd_add(a, b);

	/*
	 * If we are losing at least two bits of accuracy to denormalization,
	 * then the first lost bit becomes a round bit, and we adjust the
	 * lowest bit of sum.hi to make it a sticky bit summarizing all the
	 * bits in sum.lo. With the sticky bit adjusted, the hardware will
	 * break any ties in the correct direction.
	 *
	 * If we are losing only one bit to denormalization, however, we must
	 * break the ties manually.
	 */
	if (sum.lo != 0) {
		u.e = sum.hi;
		bits_lost = -u.bits.exp - scale + 1;
		if ((bits_lost != 1) ^ (int)(u.bits.manl & 1))
			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
	}
	return (ldexp(sum.hi, scale));
}
Exemple #4
0
void test_nextafter()
{
    static_assert((std::is_same<decltype(nextafter((double)0, (double)0)), double>::value), "");
    static_assert((std::is_same<decltype(nextafterf(0,0)), float>::value), "");
    static_assert((std::is_same<decltype(nextafterl(0,0)), long double>::value), "");
    assert(nextafter(0,1) == hexfloat<double>(0x1, 0, -1074));
}
Exemple #5
0
/*
 * Compute a+b, with a small tweak:  The least significant bit of the
 * result is adjusted into a sticky bit summarizing all the bits that
 * were lost to rounding.  This adjustment negates the effects of double
 * rounding when the result is added to another number with a higher
 * exponent.  For an explanation of round and sticky bits, see any reference
 * on FPU design, e.g.,
 *
 *     J. Coonen.  An Implementation Guide to a Proposed Standard for
 *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
 */
static inline long double add_adjusted(long double a, long double b)
{
	struct dd sum;
	union ldshape u;

	sum = dd_add(a, b);
	if (sum.lo != 0) {
		u.f = sum.hi;
		if (!LASTBIT(u))
			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
	}
	return (sum.hi);
}
Exemple #6
0
/*
 * Compute a+b, with a small tweak:  The least significant bit of the
 * result is adjusted into a sticky bit summarizing all the bits that
 * were lost to rounding.  This adjustment negates the effects of double
 * rounding when the result is added to another number with a higher
 * exponent.  For an explanation of round and sticky bits, see any reference
 * on FPU design, e.g.,
 *
 *     J. Coonen.  An Implementation Guide to a Proposed Standard for
 *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
 */
static inline long double
add_adjusted(long double a, long double b)
{
	struct dd sum;
	union IEEEl2bits u;

	sum = dd_add(a, b);
	if (sum.lo != 0) {
		u.e = sum.hi;
		if ((u.bits.manl & 1) == 0)
			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
	}
	return (sum.hi);
}
Exemple #7
0
/*
 * Compute a+b, with a small tweak:  The least significant bit of the
 * result is adjusted into a sticky bit summarizing all the bits that
 * were lost to rounding.  This adjustment negates the effects of double
 * rounding when the result is added to another number with a higher
 * exponent.  For an explanation of round and sticky bits, see any reference
 * on FPU design, e.g.,
 *
 *     J. Coonen.  An Implementation Guide to a Proposed Standard for
 *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
 */
static inline long double
add_adjusted(long double a, long double b)
{
	struct dd sum;
	union ieee_ext_u u;

	sum = dd_add(a, b);
	if (sum.lo != 0) {
		u.extu_ld = sum.hi;
		if ((u.extu_ext.ext_fracl & 1) == 0)
			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
	}
	return (sum.hi);
}
Exemple #8
0
int main(int argc, char *argv[])
{
	int i;
	float f;
	double d;
	long double ld;
	char *eptr;

	for (i = 1; i < argc; i++) {
		errno = 0;
		f = strtof(argv[i], &eptr);
		f = nextafterf(f, INFINITY);
		printf("%a  (*eptr:%d errno:%d)\n", f, *eptr, errno);
		errno = 0;
		d = strtod(argv[i], &eptr);
		d = nextafter(d, INFINITY);
		printf("%a  (*eptr:%d errno:%d)\n", d, *eptr, errno);
		errno = 0;
		ld = strtold(argv[i], &eptr);
		ld = nextafterl(ld, INFINITY);
		printf("%La  (*eptr:%d errno:%d)\n", ld, *eptr, errno);
	}
	return 0;
}
Exemple #9
0
_f_real16
_NEAREST_16(_f_real16 a, _f_real16 s)
{
	_f_real16	d;
	_f_real16	result;
	if ( a == 0 || s == 0 ) {
		if ( s < 0 ) {
			result	= -_SPACING_16(a);
		} else {
			result	= _SPACING_16(a);
		}
	} else {
		if (a < 0) {
			d	= a * (-2);
		} else {
			d	= a * 2;
		}
		if (s < 0)
			d	= -d;
		/* use nextafterl routine in libc prototyped in math.h */
		result	= nextafterl(a,d);
	}
	return result;
}
int
main(int argc, char *argv[])
{
    assert(test(nextafter(0.0, 0.0), 0.0));
    assert(test(nextafter(-0.0, 0.0), 0.0));
    assert(test(nextafter(0.0, -0.0), -0.0));
    assert(test(nextafter(-0.0, -0.0), -0.0));

    assert(test(nextafterf(0.0F, 0.0F), 0.0F));
    assert(test(nextafterf(-0.0F, 0.0F), 0.0F));
    assert(test(nextafterf(0.0F, -0.0F), -0.0F));
    assert(test(nextafterf(-0.0F, -0.0F), -0.0F));

    assert(test(nextafterl(0.0L, 0.0L), 0.0L));
    assert(test(nextafterl(-0.0L, 0.0L), 0.0L));
    assert(test(nextafterl(0.0L, -0.0L), -0.0L));
    assert(test(nextafterf(-0.0L, -0.0L), -0.0L));

    assert(test(nextafter(NAN, 1.0), NAN));
    assert(test(nextafter(1.0, NAN), NAN));
    assert(test(nextafter(NAN, NAN), NAN));

    assert(test(nextafterf(NAN, 1.0F), NAN));
    assert(test(nextafterf(1.0F, NAN), NAN));
    assert(test(nextafterf(NAN, NAN), NAN));

    assert(test(nextafterl(NAN, 1.0L), NAN));
    assert(test(nextafterl(1.0L, NAN), NAN));
    assert(test(nextafterl(NAN, NAN), NAN));

    assert(test(nextafter(0x1.fffffffffffffp+0, INFINITY), 0x1p1));
    assert(test(nextafter(0x1p1, -INFINITY), 0x1.fffffffffffffp+0));

    assert(test(nextafterf(0x1.fffffep+0f, INFINITY), 0x1p1f));
    assert(test(nextafterf(0x1p1f, -INFINITY), 0x1.fffffep+0f));

    return (0);
}
Exemple #11
0
static int
do_test (void)
{
  int result = 0;

#ifndef NO_LONG_DOUBLE
  {
    long double x = 0x100000001ll + (long double) 0.5;
    long double q;
    long double r;

    r = modfl (x, &q);
    if (q != (long double) 0x100000001ll || r != 0.5)
      {
	printf ("modfl (%Lg, ...) failed\n", x);
	result = 1;
      }
  }

  {
    long double x;
    long double m;
    long double r;
    int e;
    int i;

# if LDBL_MANT_DIG == 64
    m = 0xf.fffffffffffffffp-4L;
# elif LDBL_MANT_DIG == 106
    /* This has to match the mantissa of LDBL_MAX which actually does have a
       missing bit in the middle.  */
    m = 0x1.fffffffffffff7ffffffffffff8p-1L;
# elif LDBL_MANT_DIG == 113
    m = 0x1.ffffffffffffffffffffffffffffp-1L;
# else
#  error "Please adjust"
# endif

    for (i = LDBL_MAX_EXP, x = LDBL_MAX; i >= LDBL_MIN_EXP; --i, x /= 2.0L)
      {
	printf ("2^%d: ", i);

	r = frexpl (x, &e);
	if (r != m)
	  {
	    printf ("mantissa incorrect: %.20La\n", r);
	    result = 1;
	    continue;
	  }
	if (e != i)
	  {
	    printf ("exponent wrong %d (%.20Lg)\n", e, x);
	    result = 1;
	    continue;
	  }
	puts ("ok");
      }

    for (i = LDBL_MIN_EXP, x = LDBL_MIN; i >= LDBL_MIN_EXP - LDBL_MANT_DIG + 1;
	 --i, x /= 2.0L)
      {
        printf ("2^%d: ", i);

        r = frexpl (x, &e);
        if (r != 0.5L)
          {
            printf ("mantissa incorrect: %.20La\n", r);
            result = 1;
            continue;
          }
        if (e != i)
          {
            printf ("exponent wrong %d (%.20Lg)\n", e, x);
            result = 1;
            continue;
          }
        puts ("ok");
      }

  }

# if 0
  {
    int e;
    long double r = frexpl (LDBL_MIN * LDBL_EPSILON, &e);

    if (r != 0.5)
      {
	printf ("frexpl (LDBL_MIN * LDBL_EPSILON, ...): mantissa wrong: %Lg\n",
		r);
	result = 1;
      }
    else if (e != -16444)
      {
	printf ("frexpl (LDBL_MIN * LDBL_EPSILON, ...): exponent wrong: %d\n",
		e);
	result = 1;
      }
  }
# endif
#endif

  {
    double x = 0x100000001ll + (double) 0.5;
    double q;
    double r;

    r = modf (x, &q);
    if (q != (double) 0x100000001ll || r != 0.5)
      {
	printf ("modf (%g, ...) failed\n", x);
	result = 1;
      }
  }

  {
    union ieee754_float v1;
    union ieee754_float v2;
    float f;

    v1.f = f = FLT_MIN;
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (FLT_MIN) failed: %d\n", fpclassify (f));
	result = 1;
      }
    f = nextafterf (f, FLT_MIN / 2.0f);
    if (fpclassify (f) != FP_SUBNORMAL)
      {
	printf ("fpclassify (FLT_MIN-epsilon) failed: %d\n", fpclassify (f));
	result = 1;
      }
    v2.f = f = nextafterf (f, FLT_MIN);
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (FLT_MIN-epsilon+epsilon) failed: %d\n",
		fpclassify (f));
	result = 1;
      }

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("FLT_MIN: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("FLT_MIN: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("FLT_MIN: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.f = f = -FLT_MIN;
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (-FLT_MIN) failed: %d\n", fpclassify (f));
	result = 1;
      }
    f = nextafterf (f, -FLT_MIN / 2.0f);
    if (fpclassify (f) != FP_SUBNORMAL)
      {
	printf ("fpclassify (-FLT_MIN-epsilon) failed: %d\n", fpclassify (f));
	result = 1;
      }
    v2.f = f = nextafterf (f, -FLT_MIN);
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (-FLT_MIN-epsilon+epsilon) failed: %d\n",
		fpclassify (f));
	result = 1;
      }

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("-FLT_MIN: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-FLT_MIN: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-FLT_MIN: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    f = FLT_MAX;
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (FLT_MAX) failed: %d\n", fpclassify (f));
	result = 1;
      }
    f = nextafterf (f, INFINITY);
    if (fpclassify (f) != FP_INFINITE)
      {
	printf ("fpclassify (FLT_MAX+epsilon) failed: %d\n", fpclassify (f));
	result = 1;
      }

    f = -FLT_MAX;
    if (fpclassify (f) != FP_NORMAL)
      {
	printf ("fpclassify (-FLT_MAX) failed: %d\n", fpclassify (f));
	result = 1;
      }
    f = nextafterf (f, -INFINITY);
    if (fpclassify (f) != FP_INFINITE)
      {
	printf ("fpclassify (-FLT_MAX-epsilon) failed: %d\n", fpclassify (f));
	result = 1;
      }

    v1.f = f = 0.0625;
    f = nextafterf (f, 0.0);
    v2.f = f = nextafterf (f, 1.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("0.0625f down: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0625f down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("0.0625f down: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.f = f = 0.0625;
    f = nextafterf (f, 1.0);
    v2.f = f = nextafterf (f, 0.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("0.0625f up: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0625f up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("0.0625f up: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.f = f = -0.0625;
    f = nextafterf (f, 0.0);
    v2.f = f = nextafterf (f, -1.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("-0.0625f up: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-0.0625f up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-0.0625f up: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.f = f = -0.0625;
    f = nextafterf (f, -1.0);
    v2.f = f = nextafterf (f, 0.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("-0.0625f down: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-0.0625f down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-0.0625f down: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.f = f = 0.0f;
    f = nextafterf (f, 1.0);
    v2.f = nextafterf (f, -1.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("0.0f up: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0f up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (0 != v2.ieee.negative)
      {
	printf ("0.0f up: negative differs: 0 vs %d\n",
		v2.ieee.negative);
	result = 1;
      }

    v1.f = f = 0.0f;
    f = nextafterf (f, -1.0);
    v2.f = nextafterf (f, 1.0);

    if (v1.ieee.mantissa != v2.ieee.mantissa)
      {
	printf ("0.0f down: mantissa differs: %8x vs %8x\n",
		v1.ieee.mantissa, v2.ieee.mantissa);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0f down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (1 != v2.ieee.negative)
      {
	printf ("0.0f down: negative differs: 1 vs %d\n",
		v2.ieee.negative);
	result = 1;
      }

    if (nextafterf (0.0f, INFINITY) != nextafterf (0.0f, 1.0f)
        || nextafterf (-0.0f, INFINITY) != nextafterf (-0.0f, 1.0f)
        || nextafterf (0.0f, -INFINITY) != nextafterf (0.0f, -1.0f)
        || nextafterf (-0.0f, -INFINITY) != nextafterf (-0.0f, -1.0f))
      {
	printf ("nextafterf (+-0, +-Inf) != nextafterf (+-0, +-1)\n");
	result = 1;
      }

    if (nexttowardf (0.0f, INFINITY) != nexttowardf (0.0f, 1.0f)
        || nexttowardf (-0.0f, INFINITY) != nexttowardf (-0.0f, 1.0f)
        || nexttowardf (0.0f, -INFINITY) != nexttowardf (0.0f, -1.0f)
        || nexttowardf (-0.0f, -INFINITY) != nexttowardf (-0.0f, -1.0f))
      {
	printf ("nexttowardf (+-0, +-Inf) != nexttowardf (+-0, +-1)\n");
	result = 1;
      }
  }

  {
    union ieee754_double v1;
    union ieee754_double v2;
    double d;

    v1.d = d = DBL_MIN;
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (DBL_MIN) failed: %d\n", fpclassify (d));
	result = 1;
      }
    d = nextafter (d, DBL_MIN / 2.0);
    if (fpclassify (d) != FP_SUBNORMAL)
      {
	printf ("fpclassify (DBL_MIN-epsilon) failed: %d\n", fpclassify (d));
	result = 1;
      }
    v2.d = d = nextafter (d, DBL_MIN);
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (DBL_MIN-epsilon+epsilon) failed: %d\n",
		fpclassify (d));
	result = 1;
      }

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("DBL_MIN: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("DBL_MIN: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("DBL_MIN: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("DBL_MIN: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.d = d = -DBL_MIN;
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (-DBL_MIN) failed: %d\n", fpclassify (d));
	result = 1;
      }
    d = nextafter (d, -DBL_MIN / 2.0);
    if (fpclassify (d) != FP_SUBNORMAL)
      {
	printf ("fpclassify (-DBL_MIN-epsilon) failed: %d\n", fpclassify (d));
	result = 1;
      }
    v2.d = d = nextafter (d, -DBL_MIN);
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (-DBL_MIN-epsilon+epsilon) failed: %d\n",
		fpclassify (d));
	result = 1;
      }

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("-DBL_MIN: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("-DBL_MIN: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-DBL_MIN: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-DBL_MIN: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    d = DBL_MAX;
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (DBL_MAX) failed: %d\n", fpclassify (d));
	result = 1;
      }
    d = nextafter (d, INFINITY);
    if (fpclassify (d) != FP_INFINITE)
      {
	printf ("fpclassify (DBL_MAX+epsilon) failed: %d\n", fpclassify (d));
	result = 1;
      }

    d = -DBL_MAX;
    if (fpclassify (d) != FP_NORMAL)
      {
	printf ("fpclassify (-DBL_MAX) failed: %d\n", fpclassify (d));
	result = 1;
      }
    d = nextafter (d, -INFINITY);
    if (fpclassify (d) != FP_INFINITE)
      {
	printf ("fpclassify (-DBL_MAX-epsilon) failed: %d\n", fpclassify (d));
	result = 1;
      }

    v1.d = d = 0.0625;
    d = nextafter (d, 0.0);
    v2.d = d = nextafter (d, 1.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("0.0625 down: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("0.0625 down: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0625 down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("0.0625 down: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.d = d = 0.0625;
    d = nextafter (d, 1.0);
    v2.d = d = nextafter (d, 0.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("0.0625 up: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("0.0625 up: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0625 up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("0.0625 up: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.d = d = -0.0625;
    d = nextafter (d, 0.0);
    v2.d = d = nextafter (d, -1.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("-0.0625 up: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("-0.0625 up: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-0.0625 up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-0.0625 up: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.d = d = -0.0625;
    d = nextafter (d, -1.0);
    v2.d = d = nextafter (d, 0.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("-0.0625 down: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("-0.0625 down: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("-0.0625 down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (v1.ieee.negative != v2.ieee.negative)
      {
	printf ("-0.0625 down: negative differs: %d vs %d\n",
		v1.ieee.negative, v2.ieee.negative);
	result = 1;
      }

    v1.d = d = 0.0;
    d = nextafter (d, 1.0);
    v2.d = nextafter (d, -1.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("0.0 up: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("0.0 up: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0 up: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (0 != v2.ieee.negative)
      {
	printf ("0.0 up: negative differs: 0 vs %d\n",
		v2.ieee.negative);
	result = 1;
      }

    v1.d = d = 0.0;
    d = nextafter (d, -1.0);
    v2.d = nextafter (d, 1.0);

    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
      {
	printf ("0.0 down: mantissa0 differs: %8x vs %8x\n",
		v1.ieee.mantissa0, v2.ieee.mantissa0);
	result = 1;
      }
    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
      {
	printf ("0.0 down: mantissa1 differs: %8x vs %8x\n",
		v1.ieee.mantissa1, v2.ieee.mantissa1);
	result = 1;
      }
    if (v1.ieee.exponent != v2.ieee.exponent)
      {
	printf ("0.0 down: exponent differs: %4x vs %4x\n",
		v1.ieee.exponent, v2.ieee.exponent);
	result = 1;
      }
    if (1 != v2.ieee.negative)
      {
	printf ("0.0 down: negative differs: 1 vs %d\n",
		v2.ieee.negative);
	result = 1;
      }

    if (nextafter (0.0, INFINITY) != nextafter (0.0, 1.0)
        || nextafter (-0.0, INFINITY) != nextafter (-0.0, 1.0)
        || nextafter (0.0, -INFINITY) != nextafter (0.0, -1.0)
        || nextafter (-0.0, -INFINITY) != nextafter (-0.0, -1.0))
      {
	printf ("nextafter (+-0, +-Inf) != nextafter (+-0, +-1)\n");
	result = 1;
      }

    if (nexttoward (0.0, INFINITY) != nexttoward (0.0, 1.0)
        || nexttoward (-0.0, INFINITY) != nexttoward (-0.0, 1.0)
        || nexttoward (0.0, -INFINITY) != nexttoward (0.0, -1.0)
        || nexttoward (-0.0, -INFINITY) != nexttoward (-0.0, -1.0))
      {
	printf ("nexttoward (+-0, +-Inf) != nexttoward (+-0, +-1)\n");
	result = 1;
      }
  }

#ifndef NO_LONG_DOUBLE
  {
    long double v1, v2;

    v1 = LDBL_MIN;
    if (fpclassify (v1) != FP_NORMAL)
      {
	printf ("fpclassify (LDBL_MIN) failed: %d (%La)\n",
		fpclassify (v1), v1);
	result = 1;
      }
    v2 = nextafterl (v1, LDBL_MIN / 2.0);
    if (fpclassify (v2) != FP_SUBNORMAL)
      {
	printf ("fpclassify (LDBL_MIN-epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }
    v2 = nextafterl (v2, LDBL_MIN);
    if (fpclassify (v2) != FP_NORMAL)
      {
	printf ("fpclassify (LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }

    if (v1 != v2)
      {
	printf ("LDBL_MIN-epsilon+epsilon != LDBL_MIN: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = -LDBL_MIN;
    if (fpclassify (v1) != FP_NORMAL)
      {
	printf ("fpclassify (-LDBL_MIN) failed: %d (%La)\n",
		fpclassify (v1), v1);
	result = 1;
      }
    v2 = nextafterl (v1, -LDBL_MIN / 2.0);
    if (fpclassify (v2) != FP_SUBNORMAL)
      {
	printf ("fpclassify (-LDBL_MIN-epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }
    v2 = nextafterl (v2, -LDBL_MIN);
    if (fpclassify (v2) != FP_NORMAL)
      {
	printf ("fpclassify (-LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }

    if (v1 != v2)
      {
	printf ("-LDBL_MIN-epsilon+epsilon != -LDBL_MIN: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = LDBL_MAX;
    if (fpclassify (v1) != FP_NORMAL)
      {
	printf ("fpclassify (LDBL_MAX) failed: %d (%La)\n",
		fpclassify (v1), v1);
	result = 1;
      }
    v2 = nextafterl (v1, INFINITY);
    if (fpclassify (v2) != FP_INFINITE)
      {
	printf ("fpclassify (LDBL_MAX+epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }

    v1 = -LDBL_MAX;
    if (fpclassify (v1) != FP_NORMAL)
      {
	printf ("fpclassify (-LDBL_MAX) failed: %d (%La)\n",
		fpclassify (v1), v1);
	result = 1;
      }
    v2 = nextafterl (v1, -INFINITY);
    if (fpclassify (v2) != FP_INFINITE)
      {
	printf ("fpclassify (-LDBL_MAX-epsilon) failed: %d (%La)\n",
		fpclassify (v2), v2);
	result = 1;
      }

    v1 = 0.0625;
    v2 = nextafterl (v1, 0.0);
    v2 = nextafterl (v2, 1.0);

    if (v1 != v2)
      {
	printf ("0.0625L-epsilon+epsilon != 0.0625L: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = 0.0625;
    v2 = nextafterl (v1, 1.0);
    v2 = nextafterl (v2, 0.0);

    if (v1 != v2)
      {
	printf ("0.0625L+epsilon-epsilon != 0.0625L: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = -0.0625;
    v2 = nextafterl (v1, 0.0);
    v2 = nextafterl (v2, -1.0);

    if (v1 != v2)
      {
	printf ("-0.0625L+epsilon-epsilon != -0.0625L: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = -0.0625;
    v2 = nextafterl (v1, -1.0);
    v2 = nextafterl (v2, 0.0);

    if (v1 != v2)
      {
	printf ("-0.0625L-epsilon+epsilon != -0.0625L: %La vs %La\n", v2, v1);
	result = 1;
      }

    v1 = 0.0;
    v2 = nextafterl (v1, 1.0);
    v2 = nextafterl (v2, -1.0);

    if (v1 != v2)
      {
	printf ("0.0+epsilon-epsilon != 0.0L: %La vs %La\n", v2, v1);
	result = 1;
      }
    if (signbit (v2))
      {
	printf ("0.0+epsilon-epsilon is negative\n");
	result = 1;
      }

    v1 = 0.0;
    v2 = nextafterl (v1, -1.0);
    v2 = nextafterl (v2, 1.0);

    if (v1 != v2)
      {
	printf ("0.0-epsilon+epsilon != 0.0L: %La vs %La\n", v2, v1);
	result = 1;
      }
    if (!signbit (v2))
      {
	printf ("0.0-epsilon+epsilon is positive\n");
	result = 1;
      }

    if (nextafterl (0.0, INFINITY) != nextafterl (0.0, 1.0)
        || nextafterl (-0.0, INFINITY) != nextafterl (-0.0, 1.0)
        || nextafterl (0.0, -INFINITY) != nextafterl (0.0, -1.0)
        || nextafterl (-0.0, -INFINITY) != nextafterl (-0.0, -1.0))
      {
	printf ("nextafterl (+-0, +-Inf) != nextafterl (+-0, +-1)\n");
	result = 1;
      }

    if (nexttowardl (0.0L, INFINITY) != nexttowardl (0.0L, 1.0L)
        || nexttowardl (-0.0L, INFINITY) != nexttowardl (-0.0L, 1.0L)
        || nexttowardl (0.0L, -INFINITY) != nexttowardl (0.0L, -1.0L)
        || nexttowardl (-0.0L, -INFINITY) != nexttowardl (-0.0L, -1.0L))
      {
	printf ("nexttowardl (+-0, +-Inf) != nexttowardl (+-0, +-1)\n");
	result = 1;
      }
  }
#endif

  if (! isnormal (FLT_MIN))
    {
      puts ("isnormal (FLT_MIN) failed");
      result = 1;
    }
  if (! isnormal (DBL_MIN))
    {
      puts ("isnormal (DBL_MIN) failed");
      result = 1;
    }
#ifndef NO_LONG_DOUBLE
  if (! isnormal (LDBL_MIN))
    {
      puts ("isnormal (LDBL_MIN) failed");
      result = 1;
    }
#endif

#if defined (__i386__) || defined (__x86_64__)
  /* This is a test for the strange long doubles in x86 FPUs.  */
  {
    union
    {
      char b[10];
      long double d;
    } u =
      { .b = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0 } };

    if (fpclassify (u.d) != FP_NORMAL)
      {
	printf ("fpclassify (0x00008000000000000000) failed: %d (%Lg)\n",
		fpclassify (u.d), u.d);
	result = 1;
      }
  }

  /* Special qNaNs in x86 long double.  Test for scalbl.  */
  {
    union
    {
      char b[10];
      long double d;
    } u =
      { .b = { 0, 1, 0, 0, 0, 0, 0, 0xc0, 0xff, 0x7f } };
    long double r;

    r = scalbl (u.d, 0.0);
    if (!isnan (r))
      {
	puts ("scalbl (qNaN, 0) does not return NaN");
	result = 1;
      }
    else if (memcmp (&r, &u.d, sizeof (double)) != 0)
      {
	puts ("scalbl (qNaN, 0) does not return the same NaN");
	result = 1;
      }
  }
#endif

#ifndef NO_LONG_DOUBLE
  {
    long double r;

    feclearexcept (FE_ALL_EXCEPT);
    r = scalbl (LDBL_MIN, 2147483647);
    if (! isinf (r))
      {
	puts ("scalbl (LDBL_MIN, 2147483647) does not return Inf");
	result = 1;
      }
    else if (signbit (r) != 0)
      {
	puts ("scalbl (LDBL_MIN, 2147483647) returns -Inf");
	result = 1;
      }
    else if (fetestexcept (FE_UNDERFLOW))
      {
	puts ("scalbl (LDBL_MIN, 2147483647) raises underflow exception");
	result = 1;
      }

    feclearexcept (FE_ALL_EXCEPT);
    r = scalbl (LDBL_MAX, -2147483647);
    if (r != 0.0)
      {
	puts ("scalbl (LDBL_MAX, -2147483647) does not return 0");
	result = 1;
      }
    else if (signbit (r) != 0)
      {
	puts ("scalbl (LDBL_MAX, -2147483647) returns -Inf");
	result = 1;
      }
    else if (fetestexcept (FE_OVERFLOW))
      {
	puts ("scalbl (LDBL_MAX, -2147483647) raises overflow exception");
	result = 1;
      }
  }
#endif

  /* The tests here are very similar to tests earlier in this file,
     the important difference is just that there are no intervening
     union variables that cause some GCC versions to hide possible
     bugs in nextafter* implementation.  */
  if (nextafterf (nextafterf (FLT_MIN, FLT_MIN / 2.0), FLT_MIN) != FLT_MIN)
    {
      puts ("nextafterf FLT_MIN test failed");
      result = 1;
    }
  if (nextafterf (nextafterf (-FLT_MIN, -FLT_MIN / 2.0), -FLT_MIN)
      != -FLT_MIN)
    {
      puts ("nextafterf -FLT_MIN test failed");
      result = 1;
    }
  if (nextafter (nextafter (DBL_MIN, DBL_MIN / 2.0), DBL_MIN) != DBL_MIN)
    {
      puts ("nextafter DBL_MIN test failed");
      result = 1;
    }
  if (nextafter (nextafter (-DBL_MIN, -DBL_MIN / 2.0), -DBL_MIN) != -DBL_MIN)
    {
      puts ("nextafter -DBL_MIN test failed");
      result = 1;
    }
#ifndef NO_LONG_DOUBLE
  if (nextafterl (nextafterl (LDBL_MIN, LDBL_MIN / 2.0), LDBL_MIN)
      != LDBL_MIN)
    {
      puts ("nextafterl LDBL_MIN test failed");
      result = 1;
    }
  if (nextafterl (nextafterl (-LDBL_MIN, -LDBL_MIN / 2.0), -LDBL_MIN)
      != -LDBL_MIN)
    {
      puts ("nextafterl -LDBL_MIN test failed");
      result = 1;
    }
#endif

  volatile float f1 = FLT_MAX;
  volatile float f2 = FLT_MAX / 2;
  (void) &f1;
  (void) &f2;
  feclearexcept (FE_ALL_EXCEPT);
  f2 += f1;
#if defined(FE_OVERFLOW) && defined(FE_INEXACT)
  int fe = fetestexcept (FE_ALL_EXCEPT);
  if (EXCEPTION_TESTS (float) && fe != (FE_OVERFLOW | FE_INEXACT))
    {
      printf ("float overflow test failed: %x\n", fe);
      result = 1;
    }
#endif

  volatile double d1 = DBL_MAX;
  volatile double d2 = DBL_MAX / 2;
  (void) &d1;
  (void) &d2;
  feclearexcept (FE_ALL_EXCEPT);
  d2 += d1;
#if defined(FE_OVERFLOW) && defined(FE_INEXACT)
  fe = fetestexcept (FE_ALL_EXCEPT);
  if (EXCEPTION_TESTS (double) && fe != (FE_OVERFLOW | FE_INEXACT))
    {
      printf ("double overflow test failed: %x\n", fe);
      result = 1;
    }
#endif

#ifndef NO_LONG_DOUBLE
  volatile long double ld1 = LDBL_MAX;
  volatile long double ld2 = LDBL_MAX / 2;
  (void) &ld1;
  (void) &ld2;
  feclearexcept (FE_ALL_EXCEPT);
  ld2 += ld1;
# if defined(FE_OVERFLOW) && defined(FE_INEXACT)
  fe = fetestexcept (FE_ALL_EXCEPT);
  if (EXCEPTION_TESTS (long double) && fe != (FE_OVERFLOW | FE_INEXACT))
    {
      printf ("long double overflow test failed: %x\n", fe);
      result = 1;
    }
# endif
#endif

#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG == 113
  volatile long double ld3 = 0x1.0000000000010000000100000001p+1;
  volatile long double ld4 = 0x1.0000000000000000000000000001p+1;
  (void) &ld3;
  (void) &ld4;
  ld3 -= ld4;
  if (ld3 != 0x1.0p-47)
    {
      printf ("long double subtraction test failed %.28La\n", ld3);
      result = 1;
    }
#endif

/* Skip testing IBM long double format, for 2 reasons:
   1) it only supports FE_TONEAREST
   2) nextafter (0.0, 1.0) == nextafterl (0.0L, 1.0L), so
      nextafter (0.0, 1.0) / 16.0L will be 0.0L.  */
#if !defined NO_LONG_DOUBLE && LDBL_MANT_DIG >= DBL_MANT_DIG + 4 \
    && LDBL_MANT_DIG != 106
  int oldmode = fegetround ();
  int j;
  for (j = 0; j < 4; j++)
    {
      int mode;
      int i;
      int k = 0;
      const char *mstr;
      switch (j)
	{
#ifdef FE_TONEAREST
	case 0:
	  mode = FE_TONEAREST;
	  mstr = "nearest";
	  k = 8;
	  break;
#endif
#ifdef FE_DOWNWARD
	case 1:
	  mode = FE_DOWNWARD;
	  mstr = "-inf";
	  break;
#endif
#ifdef FE_UPWARD
	case 2:
	  mode = FE_UPWARD;
	  mstr = "+inf";
	  k = 15;
	  break;
#endif
#ifdef FE_TOWARDZERO
	case 3:
	  mode = FE_TOWARDZERO;
	  mstr = "0";
	  break;
#endif
	default:
	  continue;
	}

      volatile long double ld5 = nextafter (0.0, 1.0) / 16.0L;
      volatile double d5;
      (void) &ld5;
      for (i = 0; i <= 32; i++)
	{
	  if (fesetround (mode))
	    {
	      printf ("failed to set rounding mode to %s\n", mstr);
	      if (ROUNDING_TESTS (long double, mode)
		  && ROUNDING_TESTS (double, mode))
		result = 1;
	      else
		puts ("ignoring this failure");
	      break;
	    }
	  d5 = ld5 * i;
	  (void) &d5;
	  fesetround (oldmode);
	  if (d5 != ((j == 0 && i == 8) ? 0 : (i + k) / 16)
		    * nextafter (0.0, 1.0))
	    {
	      printf ("%La incorrectly rounded to %s as %a\n",
		      ld5 * i, mstr, d5);
	      if (ROUNDING_TESTS (long double, mode)
		  && ROUNDING_TESTS (double, mode))
		result = 1;
	      else
		puts ("ignoring this failure");
	    }
Exemple #12
0
int
main (void)
{
  int result = 0;

  float i = INFINITY;
  float m = FLT_MAX;
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterf (m, i) != i)
    {
      puts ("nextafterf+ failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafterf+ did not overflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterf (-m, -i) != -i)
    {
      puts ("nextafterf- failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafterf- did not overflow");
      ++result;
    }

  i = 0;
  m = FLT_MIN;
  feclearexcept (FE_ALL_EXCEPT);
  i = nextafterf (m, i);
  if (i < 0 || i >= FLT_MIN)
    {
      puts ("nextafterf+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf+ did not underflow");
      ++result;
    }
  i = 0;
  feclearexcept (FE_ALL_EXCEPT);
  i = nextafterf (-m, -i);
  if (i > 0 || i <= -FLT_MIN)
    {
      puts ("nextafterf- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf- did not underflow");
      ++result;
    }
  i = -INFINITY;
  feclearexcept (FE_ALL_EXCEPT);
  m = nextafterf (zero, inf);
  if (m < 0.0 || m >= FLT_MIN)
    {
      puts ("nextafterf+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterf (m, i) != 0.0)
    {
      puts ("nextafterf+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  m = nextafterf (copysignf (zero, -1.0), -inf);
  if (m > 0.0 || m <= -FLT_MIN)
    {
      puts ("nextafterf- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf- did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterf (m, -i) != 0.0)
    {
      puts ("nextafterf- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterf- did not underflow");
      ++result;
    }

  double di = INFINITY;
  double dm = DBL_MAX;
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafter (dm, di) != di)
    {
      puts ("nextafter+ failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafter+ did not overflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafter (-dm, -di) != -di)
    {
      puts ("nextafter failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafter- did not overflow");
      ++result;
    }

  di = 0;
  dm = DBL_MIN;
  feclearexcept (FE_ALL_EXCEPT);
  di = nextafter (dm, di);
  if (di < 0 || di >= DBL_MIN)
    {
      puts ("nextafter+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter+ did not underflow");
      ++result;
    }
  di = 0;
  feclearexcept (FE_ALL_EXCEPT);
  di = nextafter (-dm, -di);
  if (di > 0 || di <= -DBL_MIN)
    {
      puts ("nextafter- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter- did not underflow");
      ++result;
    }
  di = -INFINITY;
  feclearexcept (FE_ALL_EXCEPT);
  dm = nextafter (zero, inf);
  if (dm < 0.0 || dm >= DBL_MIN)
    {
      puts ("nextafter+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafter (dm, di) != 0.0)
    {
      puts ("nextafter+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  dm = nextafter (copysign (zero, -1.0), -inf);
  if (dm > 0.0 || dm <= -DBL_MIN)
    {
      puts ("nextafter- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter- did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafter (dm, -di) != 0.0)
    {
      puts ("nextafter- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafter- did not underflow");
      ++result;
    }

#ifndef NO_LONG_DOUBLE
  long double li = INFINITY;
  long double lm = LDBL_MAX;
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterl (lm, li) != li)
    {
      puts ("nextafterl+ failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafterl+ did not overflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterl (-lm, -li) != -li)
    {
      puts ("nextafterl failed");
      ++result;
    }
  if (fetestexcept (FE_OVERFLOW) == 0)
    {
      puts ("nextafterl- did not overflow");
      ++result;
    }

  li = 0;
  lm = LDBL_MIN;
  feclearexcept (FE_ALL_EXCEPT);
  li = nextafterl (lm, li);
  if (li < 0 || li >= LDBL_MIN)
    {
      puts ("nextafterl+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl+ did not underflow");
      ++result;
    }
  li = 0;
  feclearexcept (FE_ALL_EXCEPT);
  li = nextafterl (-lm, -li);
  if (li > 0 || li <= -LDBL_MIN)
    {
      puts ("nextafterl- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl- did not underflow");
      ++result;
    }
  li = -INFINITY;
  feclearexcept (FE_ALL_EXCEPT);
  lm = nextafterl (zero, inf);
  if (lm < 0.0 || lm >= LDBL_MIN)
    {
      puts ("nextafterl+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterl (lm, li) != 0.0)
    {
      puts ("nextafterl+ failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl+ did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  lm = nextafterl (copysign (zero, -1.0), -inf);
  if (lm > 0.0 || lm <= -LDBL_MIN)
    {
      puts ("nextafterl- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl- did not underflow");
      ++result;
    }
  feclearexcept (FE_ALL_EXCEPT);
  if (nextafterl (lm, -li) != 0.0)
    {
      puts ("nextafterl- failed");
      ++result;
    }
  if (fetestexcept (FE_UNDERFLOW) == 0)
    {
      puts ("nextafterl- did not underflow");
      ++result;
    }
#endif

  return result;
}
Exemple #13
0
void
domathl (void)
{
#ifndef NO_LONG_DOUBLE
  long double f1;
  long double f2;

  int i1;

  f1 = acosl(0.0);
  fprintf( stdout, "acosl          : %Lf\n", f1);

  f1 = acoshl(0.0);
  fprintf( stdout, "acoshl         : %Lf\n", f1);

  f1 = asinl(1.0);
  fprintf( stdout, "asinl          : %Lf\n", f1);

  f1 = asinhl(1.0);
  fprintf( stdout, "asinhl         : %Lf\n", f1);

  f1 = atanl(M_PI_4);
  fprintf( stdout, "atanl          : %Lf\n", f1);

  f1 = atan2l(2.3, 2.3);
  fprintf( stdout, "atan2l         : %Lf\n", f1);

  f1 = atanhl(1.0);
  fprintf( stdout, "atanhl         : %Lf\n", f1);

  f1 = cbrtl(27.0);
  fprintf( stdout, "cbrtl          : %Lf\n", f1);

  f1 = ceill(3.5);
  fprintf( stdout, "ceill          : %Lf\n", f1);

  f1 = copysignl(3.5, -2.5);
  fprintf( stdout, "copysignl      : %Lf\n", f1);

  f1 = cosl(M_PI_2);
  fprintf( stdout, "cosl           : %Lf\n", f1);

  f1 = coshl(M_PI_2);
  fprintf( stdout, "coshl          : %Lf\n", f1);

  f1 = erfl(42.0);
  fprintf( stdout, "erfl           : %Lf\n", f1);

  f1 = erfcl(42.0);
  fprintf( stdout, "erfcl          : %Lf\n", f1);

  f1 = expl(0.42);
  fprintf( stdout, "expl           : %Lf\n", f1);

  f1 = exp2l(0.42);
  fprintf( stdout, "exp2l          : %Lf\n", f1);

  f1 = expm1l(0.00042);
  fprintf( stdout, "expm1l         : %Lf\n", f1);

  f1 = fabsl(-1.123);
  fprintf( stdout, "fabsl          : %Lf\n", f1);

  f1 = fdiml(1.123, 2.123);
  fprintf( stdout, "fdiml          : %Lf\n", f1);

  f1 = floorl(0.5);
  fprintf( stdout, "floorl         : %Lf\n", f1);
  f1 = floorl(-0.5);
  fprintf( stdout, "floorl         : %Lf\n", f1);

  f1 = fmal(2.1, 2.2, 3.01);
  fprintf( stdout, "fmal           : %Lf\n", f1);

  f1 = fmaxl(-0.42, 0.42);
  fprintf( stdout, "fmaxl          : %Lf\n", f1);

  f1 = fminl(-0.42, 0.42);
  fprintf( stdout, "fminl          : %Lf\n", f1);

  f1 = fmodl(42.0, 3.0);
  fprintf( stdout, "fmodl          : %Lf\n", f1);

  /* no type-specific variant */
  i1 = fpclassify(1.0);
  fprintf( stdout, "fpclassify     : %d\n", i1);

  f1 = frexpl(42.0, &i1);
  fprintf( stdout, "frexpl         : %Lf\n", f1);

  f1 = hypotl(42.0, 42.0);
  fprintf( stdout, "hypotl         : %Lf\n", f1);

  i1 = ilogbl(42.0);
  fprintf( stdout, "ilogbl         : %d\n", i1);

  /* no type-specific variant */
  i1 = isfinite(3.0);
  fprintf( stdout, "isfinite       : %d\n", i1);

  /* no type-specific variant */
  i1 = isgreater(3.0, 3.1);
  fprintf( stdout, "isgreater      : %d\n", i1);

  /* no type-specific variant */
  i1 = isgreaterequal(3.0, 3.1);
  fprintf( stdout, "isgreaterequal : %d\n", i1);

  /* no type-specific variant */
  i1 = isinf(3.0);
  fprintf( stdout, "isinf          : %d\n", i1);

  /* no type-specific variant */
  i1 = isless(3.0, 3.1);
  fprintf( stdout, "isless         : %d\n", i1);

  /* no type-specific variant */
  i1 = islessequal(3.0, 3.1);
  fprintf( stdout, "islessequal    : %d\n", i1);

  /* no type-specific variant */
  i1 = islessgreater(3.0, 3.1);
  fprintf( stdout, "islessgreater  : %d\n", i1);

  /* no type-specific variant */
  i1 = isnan(0.0);
  fprintf( stdout, "isnan          : %d\n", i1);

  /* no type-specific variant */
  i1 = isnormal(3.0);
  fprintf( stdout, "isnormal       : %d\n", i1);

  /* no type-specific variant */
  f1 = isunordered(1.0, 2.0);
  fprintf( stdout, "isunordered    : %d\n", i1);

  f1 = j0l(1.2);
  fprintf( stdout, "j0l            : %Lf\n", f1);

  f1 = j1l(1.2);
  fprintf( stdout, "j1l            : %Lf\n", f1);

  f1 = jnl(2,1.2);
  fprintf( stdout, "jnl            : %Lf\n", f1);

  f1 = ldexpl(1.2,3);
  fprintf( stdout, "ldexpl         : %Lf\n", f1);

  f1 = lgammal(42.0);
  fprintf( stdout, "lgammal        : %Lf\n", f1);

  f1 = llrintl(-0.5);
  fprintf( stdout, "llrintl        : %Lf\n", f1);
  f1 = llrintl(0.5);
  fprintf( stdout, "llrintl        : %Lf\n", f1);

  f1 = llroundl(-0.5);
  fprintf( stdout, "lroundl        : %Lf\n", f1);
  f1 = llroundl(0.5);
  fprintf( stdout, "lroundl        : %Lf\n", f1);

  f1 = logl(42.0);
  fprintf( stdout, "logl           : %Lf\n", f1);

  f1 = log10l(42.0);
  fprintf( stdout, "log10l         : %Lf\n", f1);

  f1 = log1pl(42.0);
  fprintf( stdout, "log1pl         : %Lf\n", f1);

  f1 = log2l(42.0);
  fprintf( stdout, "log2l          : %Lf\n", f1);

  f1 = logbl(42.0);
  fprintf( stdout, "logbl          : %Lf\n", f1);

  f1 = lrintl(-0.5);
  fprintf( stdout, "lrintl         : %Lf\n", f1);
  f1 = lrintl(0.5);
  fprintf( stdout, "lrintl         : %Lf\n", f1);

  f1 = lroundl(-0.5);
  fprintf( stdout, "lroundl        : %Lf\n", f1);
  f1 = lroundl(0.5);
  fprintf( stdout, "lroundl        : %Lf\n", f1);

  f1 = modfl(42.0,&f2);
  fprintf( stdout, "lmodfl         : %Lf\n", f1);

  f1 = nanl("");
  fprintf( stdout, "nanl           : %Lf\n", f1);

  f1 = nearbyintl(1.5);
  fprintf( stdout, "nearbyintl     : %Lf\n", f1);

  f1 = nextafterl(1.5,2.0);
  fprintf( stdout, "nextafterl     : %Lf\n", f1);

  f1 = powl(3.01, 2.0);
  fprintf( stdout, "powl           : %Lf\n", f1);

  f1 = remainderl(3.01,2.0);
  fprintf( stdout, "remainderl     : %Lf\n", f1);

  f1 = remquol(29.0,3.0,&i1);
  fprintf( stdout, "remquol        : %Lf\n", f1);

  f1 = rintl(0.5);
  fprintf( stdout, "rintl          : %Lf\n", f1);
  f1 = rintl(-0.5);
  fprintf( stdout, "rintl          : %Lf\n", f1);

  f1 = roundl(0.5);
  fprintf( stdout, "roundl         : %Lf\n", f1);
  f1 = roundl(-0.5);
  fprintf( stdout, "roundl         : %Lf\n", f1);

  f1 = scalblnl(1.2,3);
  fprintf( stdout, "scalblnl       : %Lf\n", f1);

  f1 = scalbnl(1.2,3);
  fprintf( stdout, "scalbnl        : %Lf\n", f1);

  /* no type-specific variant */
  i1 = signbit(1.0);
  fprintf( stdout, "signbit        : %i\n", i1);

  f1 = sinl(M_PI_4);
  fprintf( stdout, "sinl           : %Lf\n", f1);

  f1 = sinhl(M_PI_4);
  fprintf( stdout, "sinhl          : %Lf\n", f1);

  f1 = sqrtl(9.0);
  fprintf( stdout, "sqrtl          : %Lf\n", f1);

  f1 = tanl(M_PI_4);
  fprintf( stdout, "tanl           : %Lf\n", f1);

  f1 = tanhl(M_PI_4);
  fprintf( stdout, "tanhl          : %Lf\n", f1);

  f1 = tgammal(2.1);
  fprintf( stdout, "tgammal        : %Lf\n", f1);

  f1 = truncl(3.5);
  fprintf( stdout, "truncl         : %Lf\n", f1);

  f1 = y0l(1.2);
  fprintf( stdout, "y0l            : %Lf\n", f1);

  f1 = y1l(1.2);
  fprintf( stdout, "y1l            : %Lf\n", f1);

  f1 = ynl(3,1.2);
  fprintf( stdout, "ynl            : %Lf\n", f1);
#endif
}
Exemple #14
0
static int testl(long double long_double_x, int int_x, long long_x)
{
int r = 0;
r += __finitel(long_double_x);
r += __fpclassifyl(long_double_x);
r += __isinfl(long_double_x);
r += __isnanl(long_double_x);
r += __signbitl(long_double_x);
r += acoshl(long_double_x);
r += acosl(long_double_x);
r += asinhl(long_double_x);
r += asinl(long_double_x);
r += atan2l(long_double_x, long_double_x);
r += atanhl(long_double_x);
r += atanl(long_double_x);
r += cbrtl(long_double_x);
r += ceill(long_double_x);
r += copysignl(long_double_x, long_double_x);
r += coshl(long_double_x);
r += cosl(long_double_x);
r += erfcl(long_double_x);
r += erfl(long_double_x);
r += exp2l(long_double_x);
r += expl(long_double_x);
r += expm1l(long_double_x);
r += fabsl(long_double_x);
r += fdiml(long_double_x, long_double_x);
r += floorl(long_double_x);
r += fmal(long_double_x, long_double_x, long_double_x);
r += fmaxl(long_double_x, long_double_x);
r += fminl(long_double_x, long_double_x);
r += fmodl(long_double_x, long_double_x);
r += frexpl(long_double_x, &int_x);
r += hypotl(long_double_x, long_double_x);
r += ilogbl(long_double_x);
r += ldexpl(long_double_x, int_x);
r += lgammal(long_double_x);
r += llrintl(long_double_x);
r += llroundl(long_double_x);
r += log10l(long_double_x);
r += log1pl(long_double_x);
r += log2l(long_double_x);
r += logbl(long_double_x);
r += logl(long_double_x);
r += lrintl(long_double_x);
r += lroundl(long_double_x);
r += modfl(long_double_x, &long_double_x);
r += nearbyintl(long_double_x);
r += nextafterl(long_double_x, long_double_x);
r += nexttowardl(long_double_x, long_double_x);
r += powl(long_double_x, long_double_x);
r += remainderl(long_double_x, long_double_x);
r += remquol(long_double_x, long_double_x, &int_x);
r += rintl(long_double_x);
r += roundl(long_double_x);
r += scalblnl(long_double_x, long_x);
r += scalbnl(long_double_x, int_x);
r += sinhl(long_double_x);
r += sinl(long_double_x);
r += sqrtl(long_double_x);
r += tanhl(long_double_x);
r += tanl(long_double_x);
r += tgammal(long_double_x);
r += truncl(long_double_x);
return r;
}
TEST(math, nextafterl) {
  ASSERT_FLOAT_EQ(0.0, nextafterl(0.0, 0.0));
  ASSERT_FLOAT_EQ(1.4012985e-45, nextafterl(0.0, 1.0));
  ASSERT_FLOAT_EQ(0.0, nextafterl(0.0, -1.0));
}
Exemple #16
0
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *	Dekker, T.  A Floating-Point Technique for Extending the
 *	Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double
fmal(long double x, long double y, long double z)
{
	long double xs, ys, zs, adj;
	struct dd xy, r;
	int oround;
	int ex, ey, ez;
	int spread;

	/*
	 * Handle special cases. The order of operations and the particular
	 * return values here are crucial in handling special cases involving
	 * infinities, NaNs, overflows, and signed zeroes correctly.
	 */
	if (x == 0.0 || y == 0.0)
		return (x * y + z);
	if (z == 0.0)
		return (x * y);
	if (!isfinite(x) || !isfinite(y))
		return (x * y + z);
	if (!isfinite(z))
		return (z);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread < -LDBL_MANT_DIG) {
		feraiseexcept(FE_INEXACT);
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
		switch (oround) {
		case FE_TONEAREST:
			return (z);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
		default:	/* FE_UPWARD */
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
		}
	}
	if (spread <= LDBL_MANT_DIG * 2)
		zs = ldexpl(zs, -spread);
	else
		zs = copysignl(LDBL_MIN, zs);

	fesetround(FE_TONEAREST);
	/* work around clang bug 8100 */
	volatile long double vxs = xs;

	/*
	 * Basic approach for round-to-nearest:
	 *
	 *     (xy.hi, xy.lo) = x * y		(exact)
	 *     (r.hi, r.lo)   = xy.hi + z	(exact)
	 *     adj = xy.lo + r.lo		(inexact; low bit is sticky)
	 *     result = r.hi + adj		(correctly rounded)
	 */
	xy = dd_mul(vxs, ys);
	r = dd_add(xy.hi, zs);

	spread = ex + ey;

	if (r.hi == 0.0) {
		/*
		 * When the addends cancel to 0, ensure that the result has
		 * the correct sign.
		 */
		fesetround(oround);
		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
		return (xy.hi + vzs + ldexpl(xy.lo, spread));
	}

	if (oround != FE_TONEAREST) {
		/*
		 * There is no need to worry about double rounding in directed
		 * rounding modes.
		 */
		fesetround(oround);
		/* work around clang bug 8100 */
		volatile long double vrlo = r.lo;
		adj = vrlo + xy.lo;
		return (ldexpl(r.hi + adj, spread));
	}

	adj = add_adjusted(r.lo, xy.lo);
	if (spread + ilogbl(r.hi) > -16383)
		return (ldexpl(r.hi + adj, spread));
	else
		return (add_and_denormalize(r.hi, adj, spread));
}
Exemple #17
0
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *	Dekker, T.  A Floating-Point Technique for Extending the
 *	Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double
fmal(long double x, long double y, long double z)
{
#if LDBL_MANT_DIG == 64
	static const long double split = 0x1p32L + 1.0;
#elif LDBL_MANT_DIG == 113
	static const long double split = 0x1p57L + 1.0;
#endif
	long double xs, ys, zs;
	long double c, cc, hx, hy, p, q, tx, ty;
	long double r, rr, s;
	int oround;
	int ex, ey, ez;
	int spread;

	if (z == 0.0)
		return (x * y);
	if (x == 0.0 || y == 0.0)
		return (x * y + z);

	/* Results of frexp() are undefined for these cases. */
	if (!isfinite(x) || !isfinite(y) || !isfinite(z))
		return (x * y + z);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread > LDBL_MANT_DIG * 2) {
		fenv_t env;
		feraiseexcept(FE_INEXACT);
		switch(oround) {
		case FE_TONEAREST:
			return (x * y);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, 0);
			feupdateenv(&env);
			return (r);
		case FE_DOWNWARD:
			if (z > 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, -INFINITY);
			feupdateenv(&env);
			return (r);
		default:	/* FE_UPWARD */
			if (z < 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, INFINITY);
			feupdateenv(&env);
			return (r);
		}
	}
	if (spread < -LDBL_MANT_DIG) {
		feraiseexcept(FE_INEXACT);
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
		switch (oround) {
		case FE_TONEAREST:
			return (z);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
		default:	/* FE_UPWARD */
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
		}
	}

	/*
	 * Use Dekker's algorithm to perform the multiplication and
	 * subsequent addition in twice the machine precision.
	 * Arrange so that x * y = c + cc, and x * y + z = r + rr.
	 */
	fesetround(FE_TONEAREST);

	p = xs * split;
	hx = xs - p;
	hx += p;
	tx = xs - hx;

	p = ys * split;
	hy = ys - p;
	hy += p;
	ty = ys - hy;

	p = hx * hy;
	q = hx * ty + tx * hy;
	c = p + q;
	cc = p - c + q + tx * ty;

	zs = ldexpl(zs, -spread);
	r = c + zs;
	s = r - c;
	rr = (c - (r - s)) + (zs - s) + cc;

	spread = ex + ey;
	if (spread + ilogbl(r) > -16383) {
		fesetround(oround);
		r = r + rr;
	} else {
		/*
		 * The result is subnormal, so we round before scaling to
		 * avoid double rounding.
		 */
		p = ldexpl(copysignl(0x1p-16382L, r), -spread);
		c = r + p;
		s = c - r;
		cc = (r - (c - s)) + (p - s) + rr;
		fesetround(oround);
		r = (c + cc) - p;
	}
	return (ldexpl(r, spread));
}
npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y)
{
    return nextafterl(x, y);
}
TEST(math, nextafterl_OpenBSD_bug) {
  // OpenBSD/x86's libm had a bug here.
  ASSERT_TRUE(nextafter(1.0, 0.0) - 1.0 < 0.0);
  ASSERT_TRUE(nextafterf(1.0f, 0.0f) - 1.0f < 0.0f);
  ASSERT_TRUE(nextafterl(1.0L, 0.0L) - 1.0L < 0.0L);
}
Exemple #20
0
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *      Dekker, T.  A Floating-Point Technique for Extending the
 *      Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double fmal(long double x, long double y, long double z)
{
	#pragma STDC FENV_ACCESS ON
	long double xs, ys, zs, adj;
	struct dd xy, r;
	int oround;
	int ex, ey, ez;
	int spread;

	/*
	 * Handle special cases. The order of operations and the particular
	 * return values here are crucial in handling special cases involving
	 * infinities, NaNs, overflows, and signed zeroes correctly.
	 */
	if (!isfinite(x) || !isfinite(y))
		return (x * y + z);
	if (!isfinite(z))
		return (z);
	if (x == 0.0 || y == 0.0)
		return (x * y + z);
	if (z == 0.0)
		return (x * y);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread < -LDBL_MANT_DIG) {
#ifdef FE_INEXACT
		feraiseexcept(FE_INEXACT);
#endif
#ifdef FE_UNDERFLOW
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
#endif
		switch (oround) {
		default: /* FE_TONEAREST */
			return (z);
#ifdef FE_TOWARDZERO
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
#endif
#ifdef FE_DOWNWARD
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
#endif
#ifdef FE_UPWARD
		case FE_UPWARD:
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
#endif
		}
	}
	if (spread <= LDBL_MANT_DIG * 2)
		zs = scalbnl(zs, -spread);
	else
		zs = copysignl(LDBL_MIN, zs);

	fesetround(FE_TONEAREST);

	/*
	 * Basic approach for round-to-nearest:
	 *
	 *     (xy.hi, xy.lo) = x * y           (exact)
	 *     (r.hi, r.lo)   = xy.hi + z       (exact)
	 *     adj = xy.lo + r.lo               (inexact; low bit is sticky)
	 *     result = r.hi + adj              (correctly rounded)
	 */
	xy = dd_mul(xs, ys);
	r = dd_add(xy.hi, zs);

	spread = ex + ey;

	if (r.hi == 0.0) {
		/*
		 * When the addends cancel to 0, ensure that the result has
		 * the correct sign.
		 */
		fesetround(oround);
		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
		return xy.hi + vzs + scalbnl(xy.lo, spread);
	}

	if (oround != FE_TONEAREST) {
		/*
		 * There is no need to worry about double rounding in directed
		 * rounding modes.
		 * But underflow may not be raised correctly, example in downward rounding:
		 * fmal(0x1.0000000001p-16000L, 0x1.0000000001p-400L, -0x1p-16440L)
		 */
		long double ret;
#if defined(FE_INEXACT) && defined(FE_UNDERFLOW)
		int e = fetestexcept(FE_INEXACT);
		feclearexcept(FE_INEXACT);
#endif
		fesetround(oround);
		adj = r.lo + xy.lo;
		ret = scalbnl(r.hi + adj, spread);
#if defined(FE_INEXACT) && defined(FE_UNDERFLOW)
		if (ilogbl(ret) < -16382 && fetestexcept(FE_INEXACT))
			feraiseexcept(FE_UNDERFLOW);
		else if (e)
			feraiseexcept(FE_INEXACT);
#endif
		return ret;
	}

	adj = add_adjusted(r.lo, xy.lo);
	if (spread + ilogbl(r.hi) > -16383)
		return scalbnl(r.hi + adj, spread);
	else
		return add_and_denormalize(r.hi, adj, spread);
}
Exemple #21
0
void test_rounding()
{
    // The first several blocks of tests use values with no more than
    // six significant decimal digits, six being a natural value for
    //   std::numeric_limits<float>::digits10
    // on an IEC 60559 machine.

    // Test rounding in (-1.0, 1.0).

    test_various_float_types(-0.999999L, -1.0L);
    test_various_float_types(-0.500001L, -1.0L);
    test_various_float_types(-0.500000L, -1.0L); // Away from zero.
    test_various_float_types(-0.499999L, -0.0L);
    test_various_float_types(-0.000001L, -0.0L);
    test_various_float_types(-0.000000L, -0.0L);
    test_various_float_types( 0.000000L,  0.0L);
    test_various_float_types( 0.000001L,  0.0L);
    test_various_float_types( 0.499999L,  0.0L);
    test_various_float_types( 0.500000L,  1.0L); // Away from zero.
    test_various_float_types( 0.500001L,  1.0L);
    test_various_float_types( 0.999999L,  1.0L);

    // Rounding to nearest: make sure halfway cases are rounded away
    // from zero.

    test_various_float_types(-4.5L, -5.0L);
    test_various_float_types(-3.5L, -4.0L);
    test_various_float_types(-2.5L, -3.0L);
    test_various_float_types(-1.5L, -2.0L);
    test_various_float_types(-0.5L, -1.0L);
    test_various_float_types( 0.5L,  1.0L);
    test_various_float_types( 1.5L,  2.0L);
    test_various_float_types( 2.5L,  3.0L);
    test_various_float_types( 3.5L,  4.0L);
    test_various_float_types( 4.5L,  5.0L);

    // The next block of tests uses values in the open interval
    //   (-1E29, +1E29)
    // which is well within the range of a float on an IEC 60559 machine
    // that uses the natural implementation such that
    //   std::numeric_limits<float>::max_exponent10
    // is 38.

    // Rounding an already-rounded integral value shouldn't change its
    // representation. Note however that some of these integers are
    // deliberately outside the range that can be exactly represented,
    // at least on a machine where
    //   std::numeric_limits<some-float-type)::digits10
    // is less than twenty-eight.

    test_various_float_types(-1234567890123456789012345678.0L, -1234567890123456789012345678.0L);
    test_various_float_types(-9876543200000000000000000000.0L, -9876543200000000000000000000.0L);
    test_various_float_types(-1000000000000000000000000000.0L, -1000000000000000000000000000.0L);
    test_various_float_types(-100001.0L, -100001.0L);
    test_various_float_types(-2.0L, -2.0L);
    test_various_float_types(-1.0L, -1.0L);
    test_various_float_types(-0.0L, -0.0L);
    test_various_float_types( 0.0L,  0.0L);
    test_various_float_types( 1.0L,  1.0L);
    test_various_float_types( 2.0L,  2.0L);
    test_various_float_types( 100001.0L,  100001.0L);
    test_various_float_types( 1000000000000000000000000000.0L,  1000000000000000000000000000.0L);
    test_various_float_types( 9876543200000000000000000000.0L,  9876543200000000000000000000.0L);
    test_various_float_types( 1234567890123456789012345678.0L,  1234567890123456789012345678.0L);

    // Test some numbers that are representable in all IEEE formats,
    // but not necessarily as exact integers because they have
    // FLT_DIG or DBL_DIG significant digits (and mantissae chosen
    // so that no more digits are accurately representable).
    test_various_float_types(987654.321L, 987654.0L);
    test_various_float_types(987654321098765.375L,  987654321098765.0L);
    test_various_float_types(987654321098765.500L,  987654321098766.0L);

    // Note: This test
//  test_various_float_types(987654321098765.4321L,  987654321098765.0L);
    // produces a 'failure' with type double on an intel machine using
    // ISO 60559 64-bit doubles (53-bit significand) when the rounding
    // direction is toward positive infinity. This is not a failure of
    // the algorithm, but rather an inherent limitation on precision.
    // The number to be rounded is not exactly representable as a double.
    // It is between 987654321098765.375 and 987654321098765.500, which
    // are exactly representable. The latter representation is chosen
    // only when the rounding direction is upward, and rounding it to
    // nearest correctly maps it to the next higher integer.
    //
    // Thus, the uncertainty due to [2.13.3/1] in the least significant
    // decimal digit of a number that is not exactly representable can
    // exceed four times epsilon. SOMEDAY !! It remains to establish
    // rigorous bounds, both overall and for each step.

    // The fifty-third Mersenne number was identified by the gnu octave
    // maintainers as a difficult case. See:
    //   http://article.gmane.org/gmane.comp.gnu.mingw.user/26299
    //     [2008-04-25T00:31:26Z from Tatsuro MATSUOKA]

    long double const M53 = 6361.0L * 69431.0L * 20394401.0L;

    test_various_float_types(      M53,  9007199254740991.0L);
    test_various_float_types(     -M53, -9007199254740991.0L);

    test_various_float_types( 1 +  M53,  9007199254740992.0L);
    test_various_float_types( 1 + -M53, -9007199254740990.0L);

    test_various_float_types(-1 +  M53,  9007199254740990.0L);
    test_various_float_types(-1 + -M53, -9007199254740992.0L);

    // Here is a similar testcase from François-Xavier Coudert,
    // who refers to:
    //   http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00917.html
    // | 0.499999999999999944488848768742172978818416595458984375
    // | 4503599627370497.0
    // |
    // | They should be rounded to 0.0 and 4503599627370497.0, but
    // | simply adding 0.5 and truncating will round to 1.0 and
    // | 4503599627370498.
    //
    // The number above that's very close to one-half is in fact
    //   nextafter(0.5, 0.0)
    // both of which are ffffffffffffdf3f / 3fdfffffffffffff internally.

    test_various_float_types(4503599627370497.0L, 4503599627370497.0L);

    // This test:
//    test_various_float_types(nextafter(0.5L, 0.0L), 0.0L);
    // mustn't be run as such because, e.g., the value
    //   static_cast<float>(nextafter(0.5L, 0.0L))
    // need not be distinct from 0.0F.

    BOOST_TEST((test_one_case(nextafterf(0.5F, 0.0F), 0.0F)));
    BOOST_TEST((test_one_case(nextafter (0.5 , 0.0 ), 0.0 )));
    BOOST_TEST((test_one_case(nextafterl(0.5L, 0.0L), 0.0L)));
}
Exemple #22
0
int main(int argc, char *argv[])
{
  long double x;
  x = nextafterl((long double) argc, (long double) argc);
  return 0;
}