diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 05798cec76a..0f33ba89a70 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2006-10-28 Kaveh R. Ghazi + + PR middle-end/29335 + * builtins.c (do_mpfr_arg2, fold_builtin_hypot): New. + (fold_builtin_pow): Evaluate constant arguments at compile-time + using MPFR. + (fold_builtin_1): Handle BUILT_IN_ATAN2 and BUILT_IN_HYPOT. + (do_mpfr_ckconv): New helper function. + (do_mpfr_arg1): Use do_mpfr_ckconv. + (do_mpfr_arg2): New. + 2006-10-28 Andrew Pinski PR tree-opt/29271 diff --git a/gcc/builtins.c b/gcc/builtins.c index ecd94617699..aedecc9afd0 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -205,6 +205,8 @@ static char target_percent_s[3]; static char target_percent_s_newline[4]; static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, bool); +static tree do_mpfr_arg2 (tree, tree, tree, + int (*)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)); /* Return true if NODE should be considered for inline expansion regardless of the optimization level. This means whenever a function is invoked with @@ -7662,6 +7664,56 @@ fold_builtin_logarithm (tree fndecl, tree arglist, return 0; } +/* Fold a builtin function call to hypot, hypotf, or hypotl. Return + NULL_TREE if no simplification can be made. */ + +static tree +fold_builtin_hypot (tree fndecl, tree arglist, tree type) +{ + tree arg0 = TREE_VALUE (arglist); + tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree res; + + if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + return NULL_TREE; + + /* Calculate the result when the argument is a constant. */ + if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_hypot))) + return res; + + /* If either argument is zero, hypot is fabs of the other. */ + if (real_zerop (arg0)) + return fold_build1 (ABS_EXPR, type, arg1); + else if (real_zerop (arg1)) + return fold_build1 (ABS_EXPR, type, arg0); + + /* hypot(x,x) -> x*sqrt(2). */ + if (operand_equal_p (arg0, arg1, OEP_PURE_SAME)) + { + REAL_VALUE_TYPE sqrt2; + + real_sqrt (&sqrt2, TYPE_MODE (type), &dconst2); + return fold_build2 (MULT_EXPR, type, arg0, + build_real (type, sqrt2)); + } + + /* Transform hypot(-x,y) or hypot(x,-y) or hypot(-x,-y) into + hypot(x,y). */ + if (TREE_CODE (arg0) == NEGATE_EXPR || TREE_CODE (arg1) == NEGATE_EXPR) + { + tree narg0 = (TREE_CODE (arg0) == NEGATE_EXPR) + ? TREE_OPERAND (arg0, 0) : arg0; + tree narg1 = (TREE_CODE (arg1) == NEGATE_EXPR) + ? TREE_OPERAND (arg1, 0) : arg1; + tree narglist = tree_cons (NULL_TREE, narg0, + build_tree_list (NULL_TREE, narg1)); + return build_function_call_expr (fndecl, narglist); + } + + return NULL_TREE; +} + + /* Fold a builtin function call to pow, powf, or powl. Return NULL_TREE if no simplification can be made. */ static tree @@ -7669,10 +7721,15 @@ fold_builtin_pow (tree fndecl, tree arglist, tree type) { tree arg0 = TREE_VALUE (arglist); tree arg1 = TREE_VALUE (TREE_CHAIN (arglist)); + tree res; if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) return NULL_TREE; + /* Calculate the result when the argument is a constant. */ + if ((res = do_mpfr_arg2 (arg0, arg1, type, mpfr_pow))) + return res; + /* Optimize pow(1.0,y) = 1.0. */ if (real_onep (arg0)) return omit_one_operand (type, build_real (type, dconst1), arg1); @@ -9093,6 +9150,16 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) &dconstm1, NULL, false); break; + CASE_FLT_FN (BUILT_IN_ATAN2): + if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE)) + return do_mpfr_arg2 (TREE_VALUE (arglist), + TREE_VALUE (TREE_CHAIN (arglist)), + type, mpfr_atan2); + break; + + CASE_FLT_FN (BUILT_IN_HYPOT): + return fold_builtin_hypot (fndecl, arglist, type); + CASE_FLT_FN (BUILT_IN_POW): return fold_builtin_pow (fndecl, arglist, type); @@ -11303,6 +11370,43 @@ init_target_chars (void) return true; } +/* Helper function for do_mpfr_arg*(). Ensure M is a normal number + and no overflow/underflow occurred. INEXACT is true if M was not + exacly calculated. TYPE is the tree type for the result. This + function assumes that you cleared the MPFR flags and then + calculated M to see if anything subsequently set a flag prior to + entering this function. Return NULL_TREE if any checks fail. */ + +static tree +do_mpfr_ckconv(mpfr_srcptr m, tree type, int inexact) +{ + /* Proceed iff we get a normal number, i.e. not NaN or Inf and no + overflow/underflow occurred. If -frounding-math, proceed iff the + result of calling FUNC was exact. */ + if (mpfr_number_p (m) && !mpfr_overflow_p() && !mpfr_underflow_p() + && (!flag_rounding_math || !inexact)) + { + REAL_VALUE_TYPE rr; + + real_from_mpfr (&rr, m); + /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value, + check for overflow/underflow. If the REAL_VALUE_TYPE is zero + but the mpft_t is not, then we underflowed in the + conversion. */ + if (!real_isnan (&rr) && !real_isinf (&rr) + && (rr.cl == rvc_zero) == (mpfr_zero_p (m) != 0)) + { + REAL_VALUE_TYPE rmode; + + real_convert (&rmode, TYPE_MODE (type), &rr); + /* Proceed iff the specified mode can hold the value. */ + if (real_identical (&rmode, &rr)) + return build_real (type, rmode); + } + } + return NULL_TREE; +} + /* If argument ARG is a REAL_CST, call the one-argument mpfr function FUNC on it and return the resulting value as a tree with type TYPE. If MIN and/or MAX are not NULL, then the supplied ARG must be @@ -11323,46 +11427,65 @@ do_mpfr_arg1 (tree arg, tree type, int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), if (TREE_CODE (arg) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg)) { - REAL_VALUE_TYPE r = TREE_REAL_CST (arg); + const REAL_VALUE_TYPE *const ra = &TREE_REAL_CST (arg); - if (!real_isnan (&r) && !real_isinf (&r) - && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , &r, min)) - && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , &r, max))) + if (!real_isnan (ra) && !real_isinf (ra) + && (!min || real_compare (inclusive ? GE_EXPR: GT_EXPR , ra, min)) + && (!max || real_compare (inclusive ? LE_EXPR: LT_EXPR , ra, max))) { - const enum machine_mode mode = TYPE_MODE (type); - const int prec = REAL_MODE_FORMAT (mode)->p; + const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p; int inexact; mpfr_t m; mpfr_init2 (m, prec); - mpfr_from_real (m, &r); + mpfr_from_real (m, ra); mpfr_clear_flags(); inexact = func (m, m, GMP_RNDN); - - /* Proceed iff we get a normal number, i.e. not NaN or Inf - and no overflow/underflow occurred. If -frounding-math, - proceed iff the result of calling FUNC was exact. */ - if (mpfr_number_p (m) && !mpfr_overflow_p() && !mpfr_underflow_p() - && (!flag_rounding_math || !inexact)) - { - real_from_mpfr (&r, m); - /* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR - value, check for overflow/underflow. If the - REAL_VALUE_TYPE is zero but the mpft_t is not, then - we underflowed in the conversion. */ - if (!real_isnan (&r) && !real_isinf (&r) - && (r.cl == rvc_zero) == (mpfr_zero_p (m) != 0)) - { - REAL_VALUE_TYPE rmode; - real_convert (&rmode, mode, &r); - /* Proceed iff the specified mode can hold the value. */ - if (real_identical (&rmode, &r)) - result = build_real (type, rmode); - } - } + result = do_mpfr_ckconv (m, type, inexact); mpfr_clear (m); } } return result; } + +/* If argument ARG is a REAL_CST, call the two-argument mpfr function + FUNC on it and return the resulting value as a tree with type TYPE. + The mpfr precision is set to the precision of TYPE. We assume that + function FUNC returns zero if the result could be calculated + exactly within the requested precision. */ + +static tree +do_mpfr_arg2 (tree arg1, tree arg2, tree type, + int (*func)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t)) +{ + tree result = NULL_TREE; + + STRIP_NOPS (arg1); + STRIP_NOPS (arg2); + + if (TREE_CODE (arg1) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg1) + && TREE_CODE (arg2) == REAL_CST && ! TREE_CONSTANT_OVERFLOW (arg2)) + { + const REAL_VALUE_TYPE *const ra1 = &TREE_REAL_CST (arg1); + const REAL_VALUE_TYPE *const ra2 = &TREE_REAL_CST (arg2); + + if (!real_isnan (ra1) && !real_isinf (ra1) + && !real_isnan (ra2) && !real_isinf (ra2)) + { + const int prec = REAL_MODE_FORMAT (TYPE_MODE (type))->p; + int inexact; + mpfr_t m1, m2; + + mpfr_inits2 (prec, m1, m2, NULL); + mpfr_from_real (m1, ra1); + mpfr_from_real (m2, ra2); + mpfr_clear_flags(); + inexact = func (m1, m1, m2, GMP_RNDN); + result = do_mpfr_ckconv (m1, type, inexact); + mpfr_clears (m1, m2, NULL); + } + } + + return result; +} diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bec28c524bf..28024ecf579 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2006-10-28 Kaveh R. Ghazi + + * gcc.dg/builtins-20.c: Add tests for hypot. + * gcc.dg/torture/builtin-math-2.c (TESTIT2): New. Add tests for + two-argument builtins. + * gcc.dg/torture/builtin-math-3.c (TESTIT_R): Renamed from + TESTIT2. Update all callers. + (TESTIT2, TESTIT2_R): New helper macros. + Add testcases for pow, hypot and atan2. + 2006-10-28 Andrew Pinski PR C++/29295 diff --git a/gcc/testsuite/gcc.dg/builtins-20.c b/gcc/testsuite/gcc.dg/builtins-20.c index 40a29c4f559..1c8bb9b0cb9 100644 --- a/gcc/testsuite/gcc.dg/builtins-20.c +++ b/gcc/testsuite/gcc.dg/builtins-20.c @@ -15,12 +15,15 @@ extern double cos (double); extern double sin (double); extern double tan (double); +extern double hypot (double, double); extern float cosf (float); extern float sinf (float); extern float tanf (float); +extern float hypotf (float, float); extern long double cosl (long double); extern long double sinl (long double); extern long double tanl (long double); +extern long double hypotl (long double, long double); extern void link_error(void); @@ -55,6 +58,24 @@ void test2(double x, double y) if (-sin(x-y) != sin(y-x)) link_error (); + + if (hypot (x, 0) != __builtin_fabs(x)) + link_error (); + + if (hypot (0, x) != __builtin_fabs(x)) + link_error (); + + if (hypot (x, x) != x * __builtin_sqrt(2)) + link_error (); + + if (hypot (-x, y) != hypot (x, y)) + link_error (); + + if (hypot (x, -y) != hypot (x, y)) + link_error (); + + if (hypot (-x, -y) != hypot (x, y)) + link_error (); } void test1f(float x) @@ -90,6 +111,24 @@ void test2f(float x, float y) if (-sinf(x-y) != sinf(y-x)) link_error (); + + if (hypotf (x, 0) != __builtin_fabsf(x)) + link_error (); + + if (hypotf (0, x) != __builtin_fabsf(x)) + link_error (); + + if (hypotf (x, x) != x * __builtin_sqrtf(2)) + link_error (); + + if (hypotf (-x, y) != hypotf (x, y)) + link_error (); + + if (hypotf (x, -y) != hypotf (x, y)) + link_error (); + + if (hypotf (-x, -y) != hypotf (x, y)) + link_error (); } @@ -126,6 +165,24 @@ void test2l(long double x, long double y) if (-sinl(x-y) != sinl(y-x)) link_error (); + + if (hypotl (x, 0) != __builtin_fabsl(x)) + link_error (); + + if (hypotl (0, x) != __builtin_fabsl(x)) + link_error (); + + if (hypotl (x, x) != x * __builtin_sqrtl(2)) + link_error (); + + if (hypotl (-x, y) != hypotl (x, y)) + link_error (); + + if (hypotl (x, -y) != hypotl (x, y)) + link_error (); + + if (hypotl (-x, -y) != hypotl (x, y)) + link_error (); } int main() diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-2.c b/gcc/testsuite/gcc.dg/torture/builtin-math-2.c index 8545600a195..a2213da2f91 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-2.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-2.c @@ -18,6 +18,12 @@ extern void fool (long double); fool (__builtin_##FUNC##l (ARG##L)); \ } while (0) +#define TESTIT2(FUNC, ARG1, ARG2) do { \ + foof (__builtin_##FUNC##f (ARG1##F, ARG2##F)); \ + foo (__builtin_##FUNC (ARG1, ARG2)); \ + fool (__builtin_##FUNC##l (ARG1##L, ARG2##L)); \ +} while (0) + void bar() { /* An argument of NaN is not evaluated at compile-time. */ @@ -83,6 +89,43 @@ void bar() /* The log1p arg must be [-1 ... Inf] EXclusive. */ TESTIT (log1p, -2.0); TESTIT (log1p, -1.0); + + /* An argument of NaN is not evaluated at compile-time. */ + foof (__builtin_powf (__builtin_nanf(""), 2.5F)); + foo (__builtin_pow (__builtin_nan(""), 2.5)); + fool (__builtin_powl (__builtin_nanl(""), 2.5L)); + foof (__builtin_powf (2.5F, __builtin_nanf(""))); + foo (__builtin_pow (2.5, __builtin_nan(""))); + fool (__builtin_powl (2.5L, __builtin_nanl(""))); + + /* An argument of Inf/-Inf is not evaluated at compile-time. */ + foof (__builtin_powf (__builtin_inff(), 2.5F)); + foo (__builtin_pow (__builtin_inf(), 2.5)); + fool (__builtin_powl (__builtin_infl(), 2.5L)); + foof (__builtin_powf (-__builtin_inff(), 2.5F)); + foo (__builtin_pow (-__builtin_inf(), 2.5)); + fool (__builtin_powl (-__builtin_infl(), 2.5L)); + foof (__builtin_powf (2.5F, __builtin_inff())); + foo (__builtin_pow (2.5, __builtin_inf())); + fool (__builtin_powl (2.5L, __builtin_infl())); + foof (__builtin_powf (2.5F, -__builtin_inff())); + foo (__builtin_pow (2.5, -__builtin_inf())); + fool (__builtin_powl (2.5L, -__builtin_infl())); + + /* Check for Inv/NaN return values. */ + TESTIT2 (pow, -0.0, -4.5); /* Returns Inf */ + TESTIT2 (pow, 0.0, -4.5); /* Returns Inf */ + TESTIT2 (pow, -3.0, -4.5); /* Returns NaN */ + + /* Check for overflow/underflow. */ + foof (__builtin_powf (__FLT_MAX__, 3.5F)); + foo (__builtin_pow (__DBL_MAX__, 3.5)); + fool (__builtin_powl (__LDBL_MAX__, 3.5L)); + TESTIT2 (pow, 2.0, 0x1p50); + foof (__builtin_powf (__FLT_MAX__, -3.5F)); + foo (__builtin_pow (__DBL_MAX__, -3.5)); + fool (__builtin_powl (__LDBL_MAX__, -3.5L)); + TESTIT2 (pow, 2.0, -0x1p50); } /* { dg-final { scan-tree-dump-times "exp2 " 9 "original" } } */ @@ -112,4 +155,7 @@ void bar() /* { dg-final { scan-tree-dump-times "log1p " 2 "original" } } */ /* { dg-final { scan-tree-dump-times "log1pf" 2 "original" } } */ /* { dg-final { scan-tree-dump-times "log1pl" 2 "original" } } */ +/* { dg-final { scan-tree-dump-times "pow " 13 "original" } } */ +/* { dg-final { scan-tree-dump-times "powf" 13 "original" } } */ +/* { dg-final { scan-tree-dump-times "powl" 13 "original" } } */ /* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-3.c b/gcc/testsuite/gcc.dg/torture/builtin-math-3.c index e3c9e98b657..3efe021d8db 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-3.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-3.c @@ -23,8 +23,8 @@ extern void link_error(int); link_error(__LINE__); \ } while (0); -/* Test that (LOW) < FUNC(ARG) < (HI). */ -#define TESTIT2(FUNC,ARG,LOW,HI) do { \ +/* Range test, check that (LOW) < FUNC(ARG) < (HI). */ +#define TESTIT_R(FUNC,ARG,LOW,HI) do { \ if (__builtin_##FUNC##f(ARG) <= (LOW) || __builtin_##FUNC##f(ARG) >= (HI)) \ link_error(__LINE__); \ if (__builtin_##FUNC(ARG) <= (LOW) || __builtin_##FUNC(ARG) >= (HI)) \ @@ -33,70 +33,93 @@ extern void link_error(int); link_error(__LINE__); \ } while (0); +/* Test that FUNC(ARG1, ARG2) == (RES). */ +#define TESTIT2(FUNC,ARG1,ARG2,RES) do { \ + if (__builtin_##FUNC##f(ARG1##F, ARG2##F) != RES##F) \ + link_error(__LINE__); \ + if (__builtin_##FUNC(ARG1, ARG2) != RES) \ + link_error(__LINE__); \ + if (__builtin_##FUNC##l(ARG1##L, ARG2##L) != RES##L) \ + link_error(__LINE__); \ + } while (0); + +/* Range test, check that (LOW) < FUNC(ARG1,ARG2) < (HI). */ +#define TESTIT2_R(FUNC,ARG1,ARG2,LOW,HI) do { \ + if (__builtin_##FUNC##f(ARG1, ARG2) <= (LOW) \ + || __builtin_##FUNC##f(ARG1, ARG2) >= (HI)) \ + link_error(__LINE__); \ + if (__builtin_##FUNC(ARG1, ARG2) <= (LOW) \ + || __builtin_##FUNC(ARG1, ARG2) >= (HI)) \ + link_error(__LINE__); \ + if (__builtin_##FUNC##l(ARG1, ARG2) <= (LOW) \ + || __builtin_##FUNC##l(ARG1, ARG2) >= (HI)) \ + link_error(__LINE__); \ + } while (0); + int main (void) { - TESTIT2 (asin, -1.0, -3.15/2.0, -3.14/2.0); /* asin(-1) == -pi/2 */ + TESTIT_R (asin, -1.0, -3.15/2.0, -3.14/2.0); /* asin(-1) == -pi/2 */ TESTIT (asin, 0.0, 0.0); /* asin(0) == 0 */ TESTIT (asin, -0.0, -0.0); /* asin(-0) == -0 */ - TESTIT2 (asin, 1.0, 3.14/2.0, 3.15/2.0); /* asin(1) == pi/2 */ + TESTIT_R (asin, 1.0, 3.14/2.0, 3.15/2.0); /* asin(1) == pi/2 */ - TESTIT2 (acos, -1.0, 3.14, 3.15); /* acos(-1) == pi */ - TESTIT2 (acos, 0.0, 3.14/2.0, 3.15/2.0); /* acos(0) == pi/2 */ - TESTIT2 (acos, -0.0, 3.14/2.0, 3.15/2.0); /* acos(-0) == pi/2 */ + TESTIT_R (acos, -1.0, 3.14, 3.15); /* acos(-1) == pi */ + TESTIT_R (acos, 0.0, 3.14/2.0, 3.15/2.0); /* acos(0) == pi/2 */ + TESTIT_R (acos, -0.0, 3.14/2.0, 3.15/2.0); /* acos(-0) == pi/2 */ TESTIT (acos, 1.0, 0.0); /* acos(1) == 0 */ - TESTIT2 (atan, -1.0, -3.15/4.0, -3.14/4.0); /* atan(-1) == -pi/4 */ + TESTIT_R (atan, -1.0, -3.15/4.0, -3.14/4.0); /* atan(-1) == -pi/4 */ TESTIT (atan, 0.0, 0.0); /* atan(0) == 0 */ TESTIT (atan, -0.0, -0.0); /* atan(-0) == -0 */ - TESTIT2 (atan, 1.0, 3.14/4.0, 3.15/4.0); /* atan(1) == pi/4 */ + TESTIT_R (atan, 1.0, 3.14/4.0, 3.15/4.0); /* atan(1) == pi/4 */ - TESTIT2 (asinh, -1.0, -0.89, -0.88); /* asinh(-1) == -0.881... */ + TESTIT_R (asinh, -1.0, -0.89, -0.88); /* asinh(-1) == -0.881... */ TESTIT (asinh, 0.0, 0.0); /* asinh(0) == 0 */ TESTIT (asinh, -0.0, -0.0); /* asinh(-0) == -0 */ - TESTIT2 (asinh, 1.0, 0.88, 0.89); /* asinh(1) == 0.881... */ + TESTIT_R (asinh, 1.0, 0.88, 0.89); /* asinh(1) == 0.881... */ TESTIT (acosh, 1.0, 0.0); /* acosh(1) == 0. */ - TESTIT2 (acosh, 2.0, 1.31, 1.32); /* acosh(2) == 1.316... */ + TESTIT_R (acosh, 2.0, 1.31, 1.32); /* acosh(2) == 1.316... */ - TESTIT2 (atanh, -0.5, -0.55, -0.54); /* atanh(-0.5) == -0.549... */ + TESTIT_R (atanh, -0.5, -0.55, -0.54); /* atanh(-0.5) == -0.549... */ TESTIT (atanh, 0.0, 0.0); /* atanh(0) == 0 */ TESTIT (atanh, -0.0, -0.0); /* atanh(-0) == -0 */ - TESTIT2 (atanh, 0.5, 0.54, 0.55); /* atanh(0.5) == 0.549... */ + TESTIT_R (atanh, 0.5, 0.54, 0.55); /* atanh(0.5) == 0.549... */ - TESTIT2 (sin, -1.0, -0.85, -0.84); /* sin(-1) == -0.841... */ + TESTIT_R (sin, -1.0, -0.85, -0.84); /* sin(-1) == -0.841... */ TESTIT (sin, 0.0, 0.0); /* sin(0) == 0 */ TESTIT (sin, -0.0, -0.0); /* sin(-0) == -0 */ - TESTIT2 (sin, 1.0, 0.84, 0.85); /* sin(1) == 0.841... */ + TESTIT_R (sin, 1.0, 0.84, 0.85); /* sin(1) == 0.841... */ - TESTIT2 (cos, -1.0, 0.54, 0.55); /* cos(-1) == 0.5403... */ + TESTIT_R (cos, -1.0, 0.54, 0.55); /* cos(-1) == 0.5403... */ TESTIT (cos, 0.0, 1.0); /* cos(0) == 1 */ TESTIT (cos, -0.0, 1.0); /* cos(-0) == 1 */ - TESTIT2 (cos, 1.0, 0.54, 0.55); /* cos(1) == 0.5403... */ + TESTIT_R (cos, 1.0, 0.54, 0.55); /* cos(1) == 0.5403... */ - TESTIT2 (tan, -1.0, -1.56, 1.55); /* tan(-1) == -1.557... */ + TESTIT_R (tan, -1.0, -1.56, 1.55); /* tan(-1) == -1.557... */ TESTIT (tan, 0.0, 0.0); /* tan(0) == 0 */ TESTIT (tan, -0.0, -0.0); /* tan(-0) == -0 */ - TESTIT2 (tan, 1.0, 1.55, 1.56); /* tan(1) == 1.557... */ + TESTIT_R (tan, 1.0, 1.55, 1.56); /* tan(1) == 1.557... */ - TESTIT2 (sinh, -1.0, -1.18, -1.17); /* sinh(-1) == -1.175... */ + TESTIT_R (sinh, -1.0, -1.18, -1.17); /* sinh(-1) == -1.175... */ TESTIT (sinh, 0.0, 0.0); /* sinh(0) == 0 */ TESTIT (sinh, -0.0, -0.0); /* sinh(-0) == -0 */ - TESTIT2 (sinh, 1.0, 1.17, 1.18); /* sinh(1) == 1.175... */ + TESTIT_R (sinh, 1.0, 1.17, 1.18); /* sinh(1) == 1.175... */ - TESTIT2 (cosh, -1.0, 1.54, 1.55); /* cosh(-1) == 1.543... */ + TESTIT_R (cosh, -1.0, 1.54, 1.55); /* cosh(-1) == 1.543... */ TESTIT (cosh, 0.0, 1.0); /* cosh(0) == 1 */ TESTIT (cosh, -0.0, 1.0); /* cosh(-0) == 1 */ - TESTIT2 (cosh, 1.0, 1.54, 1.55); /* cosh(1) == 1.543... */ + TESTIT_R (cosh, 1.0, 1.54, 1.55); /* cosh(1) == 1.543... */ - TESTIT2 (tanh, -1.0, -0.77, -0.76); /* tanh(-1) == -0.761... */ + TESTIT_R (tanh, -1.0, -0.77, -0.76); /* tanh(-1) == -0.761... */ TESTIT (tanh, -0.0, -0.0); /* tanh(-0) == -0 */ TESTIT (tanh, 0.0, 0.0); /* tanh(0) == 0 */ - TESTIT2 (tanh, 1.0, 0.76, 0.77); /* tanh(1) == 0.761... */ + TESTIT_R (tanh, 1.0, 0.76, 0.77); /* tanh(1) == 0.761... */ - TESTIT2 (exp, -1.0, 0.36, 0.37); /* exp(-1) == 1/e */ + TESTIT_R (exp, -1.0, 0.36, 0.37); /* exp(-1) == 1/e */ TESTIT (exp, -0.0, 1.0); /* exp(-0) == 1 */ TESTIT (exp, 0.0, 1.0); /* exp(0) == 1 */ - TESTIT2 (exp, 1.0, 2.71, 2.72); /* exp(1) == e */ + TESTIT_R (exp, 1.0, 2.71, 2.72); /* exp(1) == e */ TESTIT (exp2, -1.0, 0.5); /* exp2(-1) == 1/2 */ TESTIT (exp2, -0.0, 1.0); /* exp2(-0) == 1 */ @@ -113,14 +136,14 @@ int main (void) TESTIT (pow10, 0.0, 1.0); /* pow10(0) == 1 */ TESTIT (pow10, 1.0, 10.0); /* pow10(1) == 10 */ - TESTIT2 (expm1, -1.0, -0.64, -0.63); /* expm1(-1) == 1/e - 1 */ + TESTIT_R (expm1, -1.0, -0.64, -0.63); /* expm1(-1) == 1/e - 1 */ TESTIT (expm1, -0.0, -0.0); /* expm1(-0) == 0 */ TESTIT (expm1, 0.0, 0.0); /* expm1(0) == 0 */ - TESTIT2 (expm1, 1.0, 1.71, 1.72); /* expm1(1) == e - 1 */ + TESTIT_R (expm1, 1.0, 1.71, 1.72); /* expm1(1) == e - 1 */ TESTIT (log, 1.0, 0.0); /* log(1) == 0 */ - TESTIT2 (log, M_E, 0.99, 1.01); /* log(e) == 1.000... */ - TESTIT2 (log, M_E*M_E, 1.99, 2.01); /* log(e*e) == 2.000... */ + TESTIT_R (log, M_E, 0.99, 1.01); /* log(e) == 1.000... */ + TESTIT_R (log, M_E*M_E, 1.99, 2.01); /* log(e*e) == 2.000... */ TESTIT (log2, 1.0, 0.0); /* log2(1) == 0 */ TESTIT (log2, 2.0, 1.0); /* log2(2) == 1 */ @@ -132,8 +155,8 @@ int main (void) TESTIT (log1p, 0.0, 0.0); /* log1p(0) == 0 */ TESTIT (log1p, -0.0, -0.0); /* log1p(-0) == -0 */ - TESTIT2 (log1p, M_E-1, 0.99, 1.01); /* log1p(e-1) == 1.000... */ - TESTIT2 (log1p, M_E*M_E-1, 1.99, 2.01); /* log1p(e*e-1) == 2.000... */ + TESTIT_R (log1p, M_E-1, 0.99, 1.01); /* log1p(e-1) == 1.000... */ + TESTIT_R (log1p, M_E*M_E-1, 1.99, 2.01); /* log1p(e*e-1) == 2.000... */ TESTIT (cbrt, -0.0, -0.0); /* cbrt(-0) == -0 */ TESTIT (cbrt, 0.0, 0.0); /* cbrt(0) == 0 */ @@ -144,13 +167,41 @@ int main (void) TESTIT (erf, -0.0, -0.0); /* erf(-0) == -0 */ TESTIT (erf, 0.0, 0.0); /* erf(0) == 0 */ - TESTIT2 (erf, 1.0, 0.84, 0.85); /* erf(1) == 0.842... */ - TESTIT2 (erf, -1.0, -0.85, -0.84); /* erf(-1) == -0.842... */ + TESTIT_R (erf, 1.0, 0.84, 0.85); /* erf(1) == 0.842... */ + TESTIT_R (erf, -1.0, -0.85, -0.84); /* erf(-1) == -0.842... */ TESTIT (erfc, -0.0, 1.0); /* erfc(-0) == 1 */ TESTIT (erfc, 0.0, 1.0); /* erfc(0) == 1 */ - TESTIT2 (erfc, 1.0, 0.15, 0.16); /* erfc(1) == 0.157... */ - TESTIT2 (erfc, -1.0, 1.84, 1.85); /* erfc(-1) == 1.842... */ + TESTIT_R (erfc, 1.0, 0.15, 0.16); /* erfc(1) == 0.157... */ + TESTIT_R (erfc, -1.0, 1.84, 1.85); /* erfc(-1) == 1.842... */ + + TESTIT2 (pow, 3.0, 4.0, 81.0); /* pow(3,4) == 81 */ + TESTIT2 (pow, -3.0, 5.0, -243.0); /* pow(-3,5) == -243 */ + TESTIT2 (pow, 16.0, 0.25, 2.0); /* pow(16,1/4) == 2 */ + TESTIT2 (pow, 4.0, -2.0, 0.0625); /* pow(4,-2) == 1/16 */ + TESTIT2 (pow, -2.0, -3.0, -0.125); /* pow(-2,-3) == -1/8 */ + TESTIT2_R (pow, -1.5, -3.0, -0.297, -0.296); /* pow(-1.5,-3) == -1/3.375 */ + + TESTIT2 (hypot, 0.0, 0.0, 0.0); /* hypot(0,0) == 0 */ + TESTIT2 (hypot, -0.0, 0.0, 0.0); /* hypot(-0,0) == 0 */ + TESTIT2 (hypot, 0.0, -0.0, 0.0); /* hypot(0,-0) == 0 */ + TESTIT2 (hypot, -0.0, -0.0, 0.0); /* hypot(-0,-0) == 0 */ + TESTIT2 (hypot, 3.0, 4.0, 5.0); /* hypot(3,4) == 5 */ + TESTIT2 (hypot, -3.0, 4.0, 5.0); /* hypot(-3,4) == 5 */ + TESTIT2 (hypot, 3.0, -4.0, 5.0); /* hypot(3,-4) == 5 */ + TESTIT2 (hypot, -3.0, -4.0, 5.0); /* hypot(-3,-4) == 5 */ + TESTIT2_R (hypot, 4.0, 5.0, 6.40, 6.41); /* hypot(4,5) == 6.403... */ + + TESTIT2 (atan2, 0.0, 0.0, 0.0) /* atan2(0,0) == 0 */ + TESTIT2 (atan2, -0.0, 0.0, -0.0) /* atan2(-0,0) == -0 */ + TESTIT2_R (atan2, 0.0, -0.0, 3.14, 3.15) /* atan2(0,-0) == pi */ + TESTIT2_R (atan2, -0.0, -0.0, -3.15, -3.14) /* atan2(-0,-0) == -pi */ + TESTIT2_R (atan2, 0.0, -1.0, 3.14, 3.15) /* atan2(0,-1) == pi */ + TESTIT2_R (atan2, -0.0, -1.0, -3.15, -3.14) /* atan2(-0,-1) == -pi */ + TESTIT2 (atan2, 0.0, 1.0, 0.0) /* atan2(0,1) == 0 */ + TESTIT2 (atan2, -0.0, 1.0, -0.0) /* atan2(-0,1) == -0 */ + TESTIT2_R (atan2, -1.0, 0.0, -1.58, -1.57) /* atan2(-1,0) == -pi/2 */ + TESTIT2_R (atan2, 1.0, 0.0, 1.57, 1.58) /* atan2(1,0) == pi/2 */ return 0; }