This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: PR29335 use MPFR for two-argument math builtins (pow, atan2, hypot)


This patch hooks up the two-argument builtins to MPFR, namely pow, atan2
and hypot.  I added a two-argument do_mpfr_arg2() function and split out
the common parts from the one-argument version into a helper.  I also took
the opportunity to add some other hypot transformations, namely:

hypot(x,0) -> fabs(x)
hypot(0,y) -> fabs(y)
hypot(x,x) -> x*sqrt(2)
hypot(-x,y) -> hypot(x,y)
hypot(x,-y) -> hypot(x,y)
hypot(-x,-y) -> hypot(x,y)

(Some of these are similar to what we already do for cabs.)


Tested on sparc-sun-solaris2.10, no regressions.  All the new testcases
pass.  I also tested pow against the transcendental accuracy testsuite.
It has two testcases, and both got "perfect" results.  (It has no hypot or
atan2 tests).  All the previously converted functions still also get
"perfect" results so I'm relatively confident I haven't broken anything
(that previously worked) with the helper function split out.

Okay for mainline?

		Thanks,
		--Kaveh


2006-10-27  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

	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.

testsuite:
	* 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.

diff -rup orig/egcc-SVN20061025/gcc/builtins.c egcc-SVN20061025/gcc/builtins.c
--- orig/egcc-SVN20061025/gcc/builtins.c	2006-10-25 16:45:49.000000000 -0400
+++ egcc-SVN20061025/gcc/builtins.c	2006-10-27 18:35:36.940877412 -0400
@@ -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
@@ -7657,6 +7659,54 @@ fold_builtin_logarithm (tree fndecl, tre
   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
@@ -7664,10 +7714,15 @@ fold_builtin_pow (tree fndecl, tree argl
 {
   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);
@@ -9088,6 +9143,16 @@ fold_builtin_1 (tree fndecl, tree arglis
 			     &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);

@@ -11298,6 +11363,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
@@ -11318,46 +11420,65 @@ do_mpfr_arg1 (tree arg, tree type, int (

   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 -rup orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/builtins-20.c egcc-SVN20061025/gcc/testsuite/gcc.dg/builtins-20.c
--- orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/builtins-20.c	2006-03-21 20:01:23.000000000 -0500
+++ egcc-SVN20061025/gcc/testsuite/gcc.dg/builtins-20.c	2006-10-27 18:43:35.390013675 -0400
@@ -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 -rup orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-2.c egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-2.c
--- orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-2.c	2006-10-25 16:45:36.000000000 -0400
+++ egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-2.c	2006-10-27 18:17:03.886171304 -0400
@@ -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 -rup orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-3.c egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-3.c
--- orig/egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-3.c	2006-10-25 16:45:36.000000000 -0400
+++ egcc-SVN20061025/gcc/testsuite/gcc.dg/torture/builtin-math-3.c	2006-10-27 18:56:18.166826300 -0400
@@ -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;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]