OSDN Git Service

PR middle-end/29335
authorghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Oct 2006 20:44:09 +0000 (20:44 +0000)
committerghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Oct 2006 20:44:09 +0000 (20:44 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@118042 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/builtin-math-2.c
gcc/testsuite/gcc.dg/torture/builtin-math-3.c

index 12eca50..c28bd89 100644 (file)
@@ -1,3 +1,11 @@
+2006-10-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       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  <bob.wilson@acm.org>
 
        * config/xtensa/lib2funcs.S: Use C-style comments.
index 1dcda03..694185d 100644 (file)
@@ -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);
index 5284824..b90afcc 100644 (file)
@@ -1,3 +1,12 @@
+2006-10-25  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * 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  <sje@cup.hp.com>
 
        * gcc.dg/pthread-init-2.c: Define _POSIX_C_SOURCE on ia64 HP-UX.
index fff0e7a..8545600 100644 (file)
@@ -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.  */
+  TESTIT (atanh, -1.0);
+  TESTIT (atanh, 1.0);
 
-  /* 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 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" } } */
index d50b227..e3c9e98 100644 (file)
@@ -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;
 }