From cf1491f0e56e3d6ad918347fd05a2f953c9eede2 Mon Sep 17 00:00:00 2001 From: "Kaveh R. Ghazi" Date: Wed, 25 Oct 2006 20:44:09 +0000 Subject: [PATCH] re PR middle-end/29335 (transcendental functions with constant arguments should be resolved at compile-time) PR middle-end/29335 * builtins.c (fold_builtin_cbrt, fold_builtin_logarithm): Calculate compile-time constants using MPFR. (fold_builtin_1): Likewise handle BUILT_IN_ERF, BUILT_IN_ERFC, BUILT_IN_EXPM1 and BUILT_IN_LOG1P. testsuite: * gcc.dg/torture/builtin-math-2.c (TESTIT): Use new helper macro. Add checks for log, log2, log10 and log1p. * gcc.dg/torture/builtin-math-3.c: Add checks for -0.0 everywhere we already test 0.0. Add checks for expm1, log, log2, log10, log1p, cbrt, erf and erfc. From-SVN: r118042 --- gcc/ChangeLog | 8 ++ gcc/builtins.c | 83 +++++++++----- gcc/testsuite/ChangeLog | 9 ++ gcc/testsuite/gcc.dg/torture/builtin-math-2.c | 103 +++++++++--------- gcc/testsuite/gcc.dg/torture/builtin-math-3.c | 57 ++++++++++ 5 files changed, 184 insertions(+), 76 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12eca50bb29..c28bd899a01 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2006-10-25 Kaveh R. Ghazi + + PR middle-end/29335 + * builtins.c (fold_builtin_cbrt, fold_builtin_logarithm): + Calculate compile-time constants using MPFR. + (fold_builtin_1): Likewise handle BUILT_IN_ERF, BUILT_IN_ERFC, + BUILT_IN_EXPM1 and BUILT_IN_LOG1P. + 2006-10-25 Bob Wilson * config/xtensa/lib2funcs.S: Use C-style comments. diff --git a/gcc/builtins.c b/gcc/builtins.c index 1dcda03920a..694185d73ad 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -7110,13 +7110,14 @@ fold_builtin_cbrt (tree arglist, tree type) { tree arg = TREE_VALUE (arglist); const enum built_in_function fcode = builtin_mathfn_code (arg); + tree res; if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) return NULL_TREE; - /* Optimize cbrt of constant value. */ - if (real_zerop (arg) || real_onep (arg) || real_minus_onep (arg)) - return arg; + /* Calculate the result when the argument is a constant. */ + if ((res = do_mpfr_arg1 (arg, type, mpfr_cbrt, NULL, NULL, 0))) + return res; if (flag_unsafe_math_optimizations) { @@ -7203,7 +7204,8 @@ fold_builtin_cbrt (tree arglist, tree type) static tree fold_builtin_cos (tree arglist, tree type, tree fndecl) { - tree arg = TREE_VALUE (arglist), res; + tree arg = TREE_VALUE (arglist); + tree res; if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) return NULL_TREE; @@ -7229,7 +7231,8 @@ static tree fold_builtin_tan (tree arglist, tree type) { enum built_in_function fcode; - tree arg = TREE_VALUE (arglist), res; + tree arg = TREE_VALUE (arglist); + tree res; if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) return NULL_TREE; @@ -7552,45 +7555,46 @@ real_dconstp (tree expr, const REAL_VALUE_TYPE *value) } /* A subroutine of fold_builtin to fold the various logarithmic - functions. EXP is the CALL_EXPR of a call to a builtin logN - function. VALUE is the base of the logN function. */ + functions. Return NULL_TREE if no simplification can me made. + FUNC is the corresponding MPFR logarithm function. */ static tree fold_builtin_logarithm (tree fndecl, tree arglist, - const REAL_VALUE_TYPE *value) + int (*func)(mpfr_ptr, mpfr_srcptr, mp_rnd_t)) { if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); tree arg = TREE_VALUE (arglist); + tree res; const enum built_in_function fcode = builtin_mathfn_code (arg); - /* Optimize logN(1.0) = 0.0. */ - if (real_onep (arg)) - return build_real (type, dconst0); - - /* Optimize logN(N) = 1.0. If N can't be truncated to MODE - exactly, then only do this if flag_unsafe_math_optimizations. */ - if (exact_real_truncate (TYPE_MODE (type), value) - || flag_unsafe_math_optimizations) - { - const REAL_VALUE_TYPE value_truncate = - real_value_truncate (TYPE_MODE (type), *value); - if (real_dconstp (arg, &value_truncate)) + /* Optimize log(e) = 1.0. We're never passed an exact 'e', + instead we'll look for 'e' truncated to MODE. So only do + this if flag_unsafe_math_optimizations is set. */ + if (flag_unsafe_math_optimizations && func == mpfr_log) + { + const REAL_VALUE_TYPE e_truncated = + real_value_truncate (TYPE_MODE (type), dconste); + if (real_dconstp (arg, &e_truncated)) return build_real (type, dconst1); } + /* Calculate the result when the argument is a constant. */ + if ((res = do_mpfr_arg1 (arg, type, func, &dconst0, NULL, false))) + return res; + /* Special case, optimize logN(expN(x)) = x. */ if (flag_unsafe_math_optimizations - && ((value == &dconste + && ((func == mpfr_log && (fcode == BUILT_IN_EXP || fcode == BUILT_IN_EXPF || fcode == BUILT_IN_EXPL)) - || (value == &dconst2 + || (func == mpfr_log2 && (fcode == BUILT_IN_EXP2 || fcode == BUILT_IN_EXP2F || fcode == BUILT_IN_EXP2L)) - || (value == &dconst10 && (BUILTIN_EXP10_P (fcode))))) + || (func == mpfr_log10 && (BUILTIN_EXP10_P (fcode))))) return fold_convert (type, TREE_VALUE (TREE_OPERAND (arg, 1))); /* Optimize logN(func()) for various exponential functions. We @@ -7869,7 +7873,8 @@ fold_builtin_exponent (tree fndecl, tree arglist, if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); - tree arg = TREE_VALUE (arglist), res; + tree arg = TREE_VALUE (arglist); + tree res; /* Calculate the result when the argument is a constant. */ if ((res = do_mpfr_arg1 (arg, type, func, NULL, NULL, 0))) @@ -9040,6 +9045,18 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) NULL, NULL, 0); break; + CASE_FLT_FN (BUILT_IN_ERF): + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_erf, + NULL, NULL, 0); + break; + + CASE_FLT_FN (BUILT_IN_ERFC): + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_erfc, + NULL, NULL, 0); + break; + CASE_FLT_FN (BUILT_IN_EXP): return fold_builtin_exponent (fndecl, arglist, mpfr_exp); @@ -9050,14 +9067,26 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) CASE_FLT_FN (BUILT_IN_POW10): return fold_builtin_exponent (fndecl, arglist, mpfr_exp10); + CASE_FLT_FN (BUILT_IN_EXPM1): + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_expm1, + NULL, NULL, 0); + break; + CASE_FLT_FN (BUILT_IN_LOG): - return fold_builtin_logarithm (fndecl, arglist, &dconste); + return fold_builtin_logarithm (fndecl, arglist, mpfr_log); CASE_FLT_FN (BUILT_IN_LOG2): - return fold_builtin_logarithm (fndecl, arglist, &dconst2); + return fold_builtin_logarithm (fndecl, arglist, mpfr_log2); CASE_FLT_FN (BUILT_IN_LOG10): - return fold_builtin_logarithm (fndecl, arglist, &dconst10); + return fold_builtin_logarithm (fndecl, arglist, mpfr_log10); + + CASE_FLT_FN (BUILT_IN_LOG1P): + if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + return do_mpfr_arg1 (TREE_VALUE (arglist), type, mpfr_log1p, + &dconstm1, NULL, false); + break; CASE_FLT_FN (BUILT_IN_POW): return fold_builtin_pow (fndecl, arglist, type); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5284824e850..b90afcc3de2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2006-10-25 Kaveh R. Ghazi + + * gcc.dg/torture/builtin-math-2.c (TESTIT): Use new helper macro. + Add checks for log, log2, log10 and log1p. + + * gcc.dg/torture/builtin-math-3.c: Add checks for -0.0 everywhere + we already test 0.0. Add checks for expm1, log, log2, log10, + log1p, cbrt, erf and erfc. + 2006-10-25 Steve Ellcey * gcc.dg/pthread-init-2.c: Define _POSIX_C_SOURCE on ia64 HP-UX. diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-2.c b/gcc/testsuite/gcc.dg/torture/builtin-math-2.c index fff0e7a8506..8545600a195 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-2.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-2.c @@ -12,6 +12,12 @@ extern void foof (float); extern void foo (double); extern void fool (long double); +#define TESTIT(FUNC, ARG) do { \ + foof (__builtin_##FUNC##f (ARG##F)); \ + foo (__builtin_##FUNC (ARG)); \ + fool (__builtin_##FUNC##l (ARG##L)); \ +} while (0) + void bar() { /* An argument of NaN is not evaluated at compile-time. */ @@ -28,68 +34,55 @@ void bar() fool (__builtin_exp2l (-__builtin_infl())); /* Result overflows MPFR, which in version 2.2.x has 30 exponent bits. */ - foof (__builtin_exp2f (0x1p50F)); - foo (__builtin_exp2 (0x1p50)); - fool (__builtin_exp2l (0x1p50L)); + TESTIT (exp2, 0x1p50); /* Result underflows MPFR, which in version 2.2.x has 30 exponent bits. */ - foof (__builtin_exp2f (-0x1p50F)); - foo (__builtin_exp2 (-0x1p50)); - fool (__builtin_exp2l (-0x1p50L)); + TESTIT (exp2, -0x1p50); /* Result overflows GCC's REAL_VALUE_TYPE, which has 26 exponent bits. */ - foof (__builtin_exp2f (0x1p28F)); - foo (__builtin_exp2 (0x1p28)); - fool (__builtin_exp2l (0x1p28L)); + TESTIT (exp2, 0x1p28); /* Result underflows GCC's REAL_VALUE_TYPE, which has 26 exponent bits. */ - foof (__builtin_exp2f (-0x1p28F)); - foo (__builtin_exp2 (-0x1p28)); - fool (__builtin_exp2l (-0x1p28L)); - + TESTIT (exp2, -0x1p28); + /* Result overflows (even an extended) C double's mode. */ - foof (__builtin_exp2f (0x1p24F)); - foo (__builtin_exp2 (0x1p24)); - fool (__builtin_exp2l (0x1p24L)); + TESTIT (exp2, 0x1p24); /* Result underflows (even an extended) C double's mode. */ - foof (__builtin_exp2f (-0x1p24F)); - foo (__builtin_exp2 (-0x1p24)); - fool (__builtin_exp2l (-0x1p24L)); + TESTIT (exp2, -0x1p24); /* Ensure that normal arguments/results are folded. */ - foof (__builtin_exp2f (1.5F)); - foo (__builtin_exp2 (1.5)); - fool (__builtin_exp2l (1.5L)); - foof (__builtin_exp2f (-1.5F)); - foo (__builtin_exp2 (-1.5)); - fool (__builtin_exp2l (-1.5L)); - + TESTIT (exp2, 1.5); + TESTIT (exp2, -1.5); + /* The asin arg must be [-1 ... 1] inclusive. */ - foof (__builtin_asinf (-1.5F)); - foof (__builtin_asinf (1.5F)); - foo (__builtin_asin (-1.5)); - foo (__builtin_asin (1.5)); - fool (__builtin_asinl (-1.5L)); - fool (__builtin_asinl (1.5L)); + TESTIT (asin, -1.5); + TESTIT (asin, 1.5); /* The acos arg must be [-1 ... 1] inclusive. */ - foof (__builtin_acosf (-1.5F)); - foof (__builtin_acosf (1.5F)); - foo (__builtin_acos (-1.5)); - foo (__builtin_acos (1.5)); - fool (__builtin_acosl (-1.5L)); - fool (__builtin_acosl (1.5L)); - + TESTIT (acos, -1.5); + TESTIT (acos, 1.5); + /* The acosh arg must be [1 ... Inf] inclusive. */ - foof (__builtin_acoshf (0.5F)); - foo (__builtin_acosh (0.5)); - fool (__builtin_acoshl (0.5L)); + TESTIT (acosh, 0.5); - /* The atanh arg must be [-1 ... 1] exclusive. */ - foof (__builtin_atanhf (-1.0F)); - foof (__builtin_atanhf (1.0F)); - foo (__builtin_atanh (-1.0)); - foo (__builtin_atanh (1.0)); - fool (__builtin_atanhl (-1.0L)); - fool (__builtin_atanhl (1.0L)); + /* The atanh arg must be [-1 ... 1] EXclusive. */ + TESTIT (atanh, -1.0); + TESTIT (atanh, 1.0); + + /* The log* arg must be [0 ... Inf] EXclusive. */ + TESTIT (log, -1.0); + TESTIT (log, 0.0); + TESTIT (log, -0.0); + + TESTIT (log2, -1.0); + TESTIT (log2, 0.0); + TESTIT (log2, -0.0); + + TESTIT (log10, -1.0); + TESTIT (log10, 0.0); + TESTIT (log10, -0.0); + + /* The log1p arg must be [-1 ... Inf] EXclusive. */ + TESTIT (log1p, -2.0); + TESTIT (log1p, -1.0); } /* { dg-final { scan-tree-dump-times "exp2 " 9 "original" } } */ @@ -107,4 +100,16 @@ void bar() /* { dg-final { scan-tree-dump-times "atanh " 2 "original" } } */ /* { dg-final { scan-tree-dump-times "atanhf" 2 "original" } } */ /* { dg-final { scan-tree-dump-times "atanhl" 2 "original" } } */ +/* { dg-final { scan-tree-dump-times "log " 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "logf" 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "logl" 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log2 " 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log2f" 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log2l" 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log10 " 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log10f" 3 "original" } } */ +/* { dg-final { scan-tree-dump-times "log10l" 3 "original" } } */ +/* { 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 { 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 d50b227f07c..e3c9e98b657 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-math-3.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-3.c @@ -7,6 +7,9 @@ /* { dg-do link } */ +/* Define "e" with as many bits as found in builtins.c:dconste. */ +#define M_E 2.7182818284590452353602874713526624977572470936999595749669676277241 + /* All references to link_error should go away at compile-time. */ extern void link_error(int); @@ -34,18 +37,22 @@ int main (void) { TESTIT2 (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 */ 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 (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 (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 */ TESTIT2 (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 (acosh, 1.0, 0.0); /* acosh(1) == 0. */ @@ -53,47 +60,97 @@ int main (void) TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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... */ TESTIT2 (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 (exp2, -1.0, 0.5); /* exp2(-1) == 1/2 */ + TESTIT (exp2, -0.0, 1.0); /* exp2(-0) == 1 */ TESTIT (exp2, 0.0, 1.0); /* exp2(0) == 1 */ TESTIT (exp2, 1.0, 2.0); /* exp2(1) == 2 */ TESTIT (exp10, -1.0, 0.1); /* exp10(-1) == 1/10 */ + TESTIT (exp10, -0.0, 1.0); /* exp10(-0) == 1 */ TESTIT (exp10, 0.0, 1.0); /* exp10(0) == 1 */ TESTIT (exp10, 1.0, 10.0); /* exp10(1) == 10 */ TESTIT (pow10, -1.0, 0.1); /* pow10(-1) == 1/10 */ + TESTIT (pow10, -0.0, 1.0); /* pow10(-0) == 1 */ 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 (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 (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 (log2, 1.0, 0.0); /* log2(1) == 0 */ + TESTIT (log2, 2.0, 1.0); /* log2(2) == 1 */ + TESTIT (log2, 4.0, 2.0); /* log2(4) == 2 */ + + TESTIT (log10, 1.0, 0.0); /* log10(1) == 0 */ + TESTIT (log10, 10.0, 1.0); /* log10(10) == 1 */ + TESTIT (log10, 100.0, 2.0); /* log10(100) == 2 */ + + 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 (cbrt, -0.0, -0.0); /* cbrt(-0) == -0 */ + TESTIT (cbrt, 0.0, 0.0); /* cbrt(0) == 0 */ + TESTIT (cbrt, 1.0, 1.0); /* cbrt(1) == 1 */ + TESTIT (cbrt, -1.0, -1.0); /* cbrt(-1) == -1 */ + TESTIT (cbrt, 8.0, 2.0); /* cbrt(8) == 2 */ + TESTIT (cbrt, -8.0, -2.0); /* cbrt(-8) == -2 */ + + 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 (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... */ + return 0; }