aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKaveh R. Ghazi <ghazi@caip.rutgers.edu>2006-10-29 02:02:10 +0000
committerKaveh Ghazi <ghazi@gcc.gnu.org>2006-10-29 02:02:10 +0000
commit4413d881d03be475aab1891d66081ed54e042b73 (patch)
treecab82ea78089af1aeb39e45b02ea963d4f45a7e8 /gcc
parent5c9ab0a6eec9628575740a3640cf3d12e0d70132 (diff)
downloadgcc-4413d881d03be475aab1891d66081ed54e042b73.zip
gcc-4413d881d03be475aab1891d66081ed54e042b73.tar.gz
gcc-4413d881d03be475aab1891d66081ed54e042b73.tar.bz2
re PR middle-end/29335 (transcendental functions with constant arguments should be resolved at compile-time)
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. From-SVN: r118129
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/builtins.c181
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/builtins-20.c57
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-math-2.c46
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-math-3.c127
6 files changed, 365 insertions, 67 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 05798ce..0f33ba8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2006-10-28 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.
+
2006-10-28 Andrew Pinski <andrew_pinski@playstation.sony.com>
PR tree-opt/29271
diff --git a/gcc/builtins.c b/gcc/builtins.c
index ecd9461..aedecc9 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 bec28c5..28024ec 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2006-10-28 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * 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 <andrew_pinski@playstation.sony.com>
PR C++/29295
diff --git a/gcc/testsuite/gcc.dg/builtins-20.c b/gcc/testsuite/gcc.dg/builtins-20.c
index 40a29c4..1c8bb9b 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 8545600..a2213da 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 e3c9e98..3efe021 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;
}