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
This commit is contained in:
Kaveh R. Ghazi 2006-10-29 02:02:10 +00:00 committed by Kaveh Ghazi
parent 5c9ab0a6ee
commit 4413d881d0
6 changed files with 365 additions and 67 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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()

View File

@ -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" } } */

View File

@ -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;
}