blob: 1fd038a87073d6bc2d6f39886818c1de1d1e3ec1 [file] [log] [blame]
/* Excess precision tests. Test excess precision is removed when
necessary. */
/* { dg-do run } */
/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } */
#include <float.h>
#include <stdarg.h>
extern void abort (void);
extern void exit (int);
volatile float f1 = 1.0f;
volatile float f2 = 0x1.0p-30f;
volatile float f3 = 0x1.0p-60f;
volatile double d1 = 1.0;
volatile double d2 = 0x1.0p-30;
volatile double d3 = 0x1.0p-60;
volatile double d3d = 0x1.0p-52;
volatile float fadd1 = 1.0f + 0x1.0p-30f;
volatile double dadd2 = 1.0 + 0x1.0p-30 + 0x1.0p-60;
volatile double dh = 0x1.0p-24;
volatile float fha = 1.0f + 0x1.0p-23f;
void
test_assign (void)
{
float f;
double d;
f = f1 + f2;
if (f != fadd1)
abort ();
d = f1 + f2;
if (d != dadd2)
abort ();
d = d1 + d2 + d3;
if (d != dadd2)
abort ();
/* Verify rounding direct to float without double rounding. */
if (sizeof(long double) > sizeof(double) ) {
f = d1 + dh + d3;
if (f != fha)
abort ();
} else {
f = d1 + dh + d3d;
if (f != fha)
abort ();
}
}
void
test_init (void)
{
float f = f1 + f2;
double d = d1 + d2 + d3;
if (f != fadd1)
abort ();
if (d != dadd2)
abort ();
}
volatile int i1 = 0x40000001;
volatile unsigned int u1 = 0x80000001u;
volatile long long ll1 = 0x4000000000000001ll;
volatile unsigned long long ull1 = 0x8000000000000001ull;
void
test_cast (void)
{
if ((float)(f1 + f2) != fadd1)
abort ();
if ((double)(d1 + d2 + d3) != dadd2)
abort ();
if ((double)(f1 + f2 + f3) != dadd2)
abort ();
if ((float)i1 != 0x1.0p30f)
abort ();
if ((float)u1 != 0x1.0p31f)
abort ();
if ((float)ll1 != 0x1.0p62f)
abort ();
if ((float)ull1 != 0x1.0p63f)
abort ();
if ((double)ll1 != 0x1.0p62)
abort ();
if ((double)ull1 != 0x1.0p63)
abort ();
}
static inline void
check_float (float f)
{
if (f != fadd1)
abort ();
}
static inline void
check_double (double d)
{
if (d != dadd2)
abort ();
}
static inline void
check_float_nonproto (f)
float f;
{
if (f != fadd1)
abort ();
}
static inline void
check_double_nonproto (d)
double d;
{
if (d != dadd2)
abort ();
}
static void
check_double_va (int i, ...)
{
va_list ap;
va_start (ap, i);
if (va_arg (ap, double) != dadd2)
abort ();
va_end (ap);
}
void
test_call (void)
{
check_float (f1 + f2);
check_double (d1 + d2 + d3);
check_double (f1 + f2 + f3);
check_float_nonproto (f1 + f2);
check_double_nonproto (d1 + d2 + d3);
check_double_nonproto (f1 + f2 + f3);
check_double_va (0, d1 + d2 + d3);
check_double_va (0, f1 + f2 + f3);
}
static inline float
return_float (void)
{
return f1 + f2;
}
static inline double
return_double1 (void)
{
return d1 + d2 + d3;
}
static inline double
return_double2 (void)
{
return f1 + f2 + f3;
}
void
test_return (void)
{
if (return_float () != fadd1)
abort ();
if (return_double1 () != dadd2)
abort ();
if (return_double2 () != dadd2)
abort ();
}
volatile float flt_min = FLT_MIN;
volatile double dbl_min = DBL_MIN;
volatile float flt_max = FLT_MAX;
volatile double dbl_max = DBL_MAX;
void
test_builtin (void)
{
/* Classification macros convert to the semantic type. signbit and
comparison macros do not. */
if (!__builtin_isinf (flt_max * flt_max))
abort ();
if (!__builtin_isinf (dbl_max * dbl_max))
abort ();
if (__builtin_isnormal (flt_max * flt_max))
abort ();
if (__builtin_isnormal (dbl_max * dbl_max))
abort ();
if (__builtin_isfinite (flt_max * flt_max))
abort ();
if (__builtin_isfinite (dbl_max * dbl_max))
abort ();
if (!__builtin_isgreater (flt_min * flt_min, 0.0f))
abort ();
if (!__builtin_isgreaterequal (flt_min * flt_min, 0.0f))
abort ();
if (!__builtin_isless (0.0f, flt_min * flt_min))
abort ();
if (__builtin_islessequal (flt_min * flt_min, 0.0f))
abort ();
if (!__builtin_islessgreater (flt_min * flt_min, 0.0f))
abort ();
if (!__builtin_isgreaterequal (dbl_min * dbl_min, 0.0))
abort ();
if (sizeof(long double) > sizeof(double) ) {
if (!__builtin_isgreater (dbl_min * dbl_min, 0.0))
abort ();
if (!__builtin_isless (0.0, dbl_min * dbl_min))
abort ();
if (__builtin_islessequal (dbl_min * dbl_min, 0.0))
abort ();
if (!__builtin_islessgreater (dbl_min * dbl_min, 0.0))
abort ();
}
else {
if (__builtin_isgreater (dbl_min * dbl_min, 0.0))
abort ();
if (__builtin_isless (0.0, dbl_min * dbl_min))
abort ();
if (!__builtin_islessequal (dbl_min * dbl_min, 0.0))
abort ();
if (__builtin_islessgreater (dbl_min * dbl_min, 0.0))
abort ();
}
}
int
main (void)
{
test_assign ();
test_init ();
test_cast ();
test_call ();
test_return ();
test_builtin ();
exit (0);
}