本文整理汇总了C++中MPFR_INT_CEIL_LOG2函数的典型用法代码示例。如果您正苦于以下问题:C++ MPFR_INT_CEIL_LOG2函数的具体用法?C++ MPFR_INT_CEIL_LOG2怎么用?C++ MPFR_INT_CEIL_LOG2使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了MPFR_INT_CEIL_LOG2函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: mpfr_const_euler_internal
int
mpfr_const_euler_internal (mpfr_t x, mpfr_rnd_t rnd)
{
mpfr_prec_t prec = MPFR_PREC(x), m, log2m;
mpfr_t y, z;
unsigned long n;
int inexact;
MPFR_ZIV_DECL (loop);
log2m = MPFR_INT_CEIL_LOG2 (prec);
m = prec + 2 * log2m + 23;
mpfr_init2 (y, m);
mpfr_init2 (z, m);
MPFR_ZIV_INIT (loop, m);
for (;;)
{
mpfr_exp_t exp_S, err;
/* since prec >= 1, we have m >= 24 here, which ensures n >= 9 below */
n = 1 + (unsigned long) ((double) m * LOG2 / 2.0);
MPFR_ASSERTD (n >= 9);
mpfr_const_euler_S2 (y, n); /* error <= 3 ulps */
exp_S = MPFR_EXP(y);
mpfr_set_ui (z, n, MPFR_RNDN);
mpfr_log (z, z, MPFR_RNDD); /* error <= 1 ulp */
mpfr_sub (y, y, z, MPFR_RNDN); /* S'(n) - log(n) */
/* the error is less than 1/2 + 3*2^(exp_S-EXP(y)) + 2^(EXP(z)-EXP(y))
<= 1/2 + 2^(exp_S+2-EXP(y)) + 2^(EXP(z)-EXP(y))
<= 1/2 + 2^(1+MAX(exp_S+2,EXP(z))-EXP(y)) */
err = 1 + MAX(exp_S + 2, MPFR_EXP(z)) - MPFR_EXP(y);
err = (err >= -1) ? err + 1 : 0; /* error <= 2^err ulp(y) */
exp_S = MPFR_EXP(y);
mpfr_const_euler_R (z, n); /* err <= ulp(1/2) = 2^(-m) */
mpfr_sub (y, y, z, MPFR_RNDN);
/* err <= 1/2 ulp(y) + 2^(-m) + 2^(err + exp_S - EXP(y)) ulp(y).
Since the result is between 0.5 and 1, ulp(y) = 2^(-m).
So we get 3/2*ulp(y) + 2^(err + exp_S - EXP(y)) ulp(y).
3/2 + 2^e <= 2^(e+1) for e>=1, and <= 2^2 otherwise */
err = err + exp_S - MPFR_EXP(y);
err = (err >= 1) ? err + 1 : 2;
if (MPFR_LIKELY (MPFR_CAN_ROUND (y, m - err, prec, rnd)))
break;
MPFR_ZIV_NEXT (loop, m);
mpfr_set_prec (y, m);
mpfr_set_prec (z, m);
}
MPFR_ZIV_FREE (loop);
inexact = mpfr_set (x, y, rnd);
mpfr_clear (y);
mpfr_clear (z);
return inexact; /* always inexact */
}
示例2: test_int_ceil_log2
static void
test_int_ceil_log2 (void)
{
int i;
int val[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
for (i = 1; i < 17; i++)
{
if (MPFR_INT_CEIL_LOG2 (i) != val[i-1])
{
printf ("Error 1 in test_int_ceil_log2 for i = %d\n", i);
exit (1);
}
if (MPFR_INT_CEIL_LOG2 (i) != __gmpfr_int_ceil_log2 (i))
{
printf ("Error 2 in test_int_ceil_log2 for i = %d\n", i);
exit (1);
}
}
}
示例3: Gamma
//.........这里部分代码省略.........
{
mpfr_sub (tmp, tmp, tmp2, MPFR_RNDZ); /* low bnd on |sin(Pi*(2-x))| */
mpfr_ui_div (tmp, 12, tmp, MPFR_RNDU); /* upper bound */
mpfr_log2 (tmp, tmp, MPFR_RNDU);
mpfr_add (xp, tmp, xp, MPFR_RNDU);
/* The assert below checks that expo.saved_emin - 2 always
fits in a long. FIXME if we want to allow mpfr_exp_t to
be a long long, for instance. */
MPFR_ASSERTN (MPFR_EMIN_MIN - 2 >= LONG_MIN);
underflow = mpfr_cmp_si (xp, expo.saved_emin - 2) <= 0;
}
mpfr_clear (xp);
mpfr_clear (tmp);
mpfr_clear (tmp2);
if (underflow) /* the sign is the opposite of that of sin(Pi*(2-x)) */
{
MPFR_SAVE_EXPO_FREE (expo);
return mpfr_underflow (gamma, (rnd_mode == MPFR_RNDN) ? MPFR_RNDZ : rnd_mode, -sgn);
}
}
realprec = MPFR_PREC (gamma);
/* we want both 1-x and 2-x to be exact */
{
mpfr_prec_t w;
w = mpfr_gamma_1_minus_x_exact (x);
if (realprec < w)
realprec = w;
w = mpfr_gamma_2_minus_x_exact (x);
if (realprec < w)
realprec = w;
}
realprec = realprec + MPFR_INT_CEIL_LOG2 (realprec) + 20;
MPFR_ASSERTD(realprec >= 5);
MPFR_GROUP_INIT_4 (group, realprec + MPFR_INT_CEIL_LOG2 (realprec) + 20,
xp, tmp, tmp2, GammaTrial);
mpz_init (fact);
MPFR_ZIV_INIT (loop, realprec);
for (;;)
{
mpfr_exp_t err_g;
int ck;
MPFR_GROUP_REPREC_4 (group, realprec, xp, tmp, tmp2, GammaTrial);
/* reflection formula: gamma(x) = Pi*(x-1)/sin(Pi*(2-x))/gamma(2-x) */
ck = mpfr_ui_sub (xp, 2, x, MPFR_RNDN); /* 2-x, exact */
MPFR_ASSERTD(ck == 0); (void) ck; /* use ck to avoid a warning */
mpfr_gamma (tmp, xp, MPFR_RNDN); /* gamma(2-x), error (1+u) */
mpfr_const_pi (tmp2, MPFR_RNDN); /* Pi, error (1+u) */
mpfr_mul (GammaTrial, tmp2, xp, MPFR_RNDN); /* Pi*(2-x), error (1+u)^2 */
err_g = MPFR_GET_EXP(GammaTrial);
mpfr_sin (GammaTrial, GammaTrial, MPFR_RNDN); /* sin(Pi*(2-x)) */
/* If tmp is +Inf, we compute exp(lngamma(x)). */
if (mpfr_inf_p (tmp))
{
inex = mpfr_explgamma (gamma, x, &expo, tmp, tmp2, rnd_mode);
if (inex)
goto end;
else
goto ziv_next;
}
err_g = err_g + 1 - MPFR_GET_EXP(GammaTrial);
/* let g0 the true value of Pi*(2-x), g the computed value.
示例4: mpfr_agm
/* agm(x,y) is between x and y, so we don't need to save exponent range */
int
mpfr_agm (mpfr_ptr r, mpfr_srcptr op2, mpfr_srcptr op1, mp_rnd_t rnd_mode)
{
int compare, inexact;
mp_size_t s;
mp_prec_t p, q;
mp_limb_t *up, *vp, *tmpp;
mpfr_t u, v, tmp;
unsigned long n; /* number of iterations */
unsigned long err = 0;
MPFR_ZIV_DECL (loop);
MPFR_TMP_DECL(marker);
MPFR_LOG_FUNC (("op2[%#R]=%R op1[%#R]=%R rnd=%d", op2,op2,op1,op1,rnd_mode),
("r[%#R]=%R inexact=%d", r, r, inexact));
/* Deal with special values */
if (MPFR_ARE_SINGULAR (op1, op2))
{
/* If a or b is NaN, the result is NaN */
if (MPFR_IS_NAN(op1) || MPFR_IS_NAN(op2))
{
MPFR_SET_NAN(r);
MPFR_RET_NAN;
}
/* now one of a or b is Inf or 0 */
/* If a and b is +Inf, the result is +Inf.
Otherwise if a or b is -Inf or 0, the result is NaN */
else if (MPFR_IS_INF(op1) || MPFR_IS_INF(op2))
{
if (MPFR_IS_STRICTPOS(op1) && MPFR_IS_STRICTPOS(op2))
{
MPFR_SET_INF(r);
MPFR_SET_SAME_SIGN(r, op1);
MPFR_RET(0); /* exact */
}
else
{
MPFR_SET_NAN(r);
MPFR_RET_NAN;
}
}
else /* a and b are neither NaN nor Inf, and one is zero */
{ /* If a or b is 0, the result is +0 since a sqrt is positive */
MPFR_ASSERTD (MPFR_IS_ZERO (op1) || MPFR_IS_ZERO (op2));
MPFR_SET_POS (r);
MPFR_SET_ZERO (r);
MPFR_RET (0); /* exact */
}
}
MPFR_CLEAR_FLAGS (r);
/* If a or b is negative (excluding -Infinity), the result is NaN */
if (MPFR_UNLIKELY(MPFR_IS_NEG(op1) || MPFR_IS_NEG(op2)))
{
MPFR_SET_NAN(r);
MPFR_RET_NAN;
}
/* Precision of the following calculus */
q = MPFR_PREC(r);
p = q + MPFR_INT_CEIL_LOG2(q) + 15;
MPFR_ASSERTD (p >= 7); /* see algorithms.tex */
s = (p - 1) / BITS_PER_MP_LIMB + 1;
/* b (op2) and a (op1) are the 2 operands but we want b >= a */
compare = mpfr_cmp (op1, op2);
if (MPFR_UNLIKELY( compare == 0 ))
{
mpfr_set (r, op1, rnd_mode);
MPFR_RET (0); /* exact */
}
else if (compare > 0)
{
mpfr_srcptr t = op1;
op1 = op2;
op2 = t;
}
/* Now b(=op2) >= a (=op1) */
MPFR_TMP_MARK(marker);
/* Main loop */
MPFR_ZIV_INIT (loop, p);
for (;;)
{
mp_prec_t eq;
/* Init temporary vars */
MPFR_TMP_INIT (up, u, p, s);
MPFR_TMP_INIT (vp, v, p, s);
MPFR_TMP_INIT (tmpp, tmp, p, s);
/* Calculus of un and vn */
mpfr_mul (u, op1, op2, GMP_RNDN); /* Faster since PREC(op) < PREC(u) */
mpfr_sqrt (u, u, GMP_RNDN);
mpfr_add (v, op1, op2, GMP_RNDN); /* add with !=prec is still good*/
mpfr_div_2ui (v, v, 1, GMP_RNDN);
n = 1;
//.........这里部分代码省略.........
示例5: mpfr_mul_ui
int
mpfr_mul_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode)
{
mp_limb_t *yp;
mp_size_t xn;
int cnt, inexact;
MPFR_TMP_DECL (marker);
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
{
if (MPFR_IS_NAN (x))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else if (MPFR_IS_INF (x))
{
if (u != 0)
{
MPFR_SET_INF (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0); /* infinity is exact */
}
else /* 0 * infinity */
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
}
else /* x is zero */
{
MPFR_ASSERTD (MPFR_IS_ZERO (x));
MPFR_SET_ZERO (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0); /* zero is exact */
}
}
else if (MPFR_UNLIKELY (u <= 1))
{
if (u < 1)
{
MPFR_SET_ZERO (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0); /* zero is exact */
}
else
return mpfr_set (y, x, rnd_mode);
}
else if (MPFR_UNLIKELY (IS_POW2 (u)))
return mpfr_mul_2si (y, x, MPFR_INT_CEIL_LOG2 (u), rnd_mode);
yp = MPFR_MANT (y);
xn = MPFR_LIMB_SIZE (x);
MPFR_ASSERTD (xn < MP_SIZE_T_MAX);
MPFR_TMP_MARK(marker);
yp = MPFR_TMP_LIMBS_ALLOC (xn + 1);
MPFR_ASSERTN (u == (mp_limb_t) u);
yp[xn] = mpn_mul_1 (yp, MPFR_MANT (x), xn, u);
/* x * u is stored in yp[xn], ..., yp[0] */
/* since the case u=1 was treated above, we have u >= 2, thus
yp[xn] >= 1 since x was msb-normalized */
MPFR_ASSERTD (yp[xn] != 0);
if (MPFR_LIKELY (MPFR_LIMB_MSB (yp[xn]) == 0))
{
count_leading_zeros (cnt, yp[xn]);
mpn_lshift (yp, yp, xn + 1, cnt);
}
else
{
cnt = 0;
}
/* now yp[xn], ..., yp[0] is msb-normalized too, and has at most
PREC(x) + (GMP_NUMB_BITS - cnt) non-zero bits */
MPFR_RNDRAW (inexact, y, yp, (mpfr_prec_t) (xn + 1) * GMP_NUMB_BITS,
rnd_mode, MPFR_SIGN (x), cnt -- );
MPFR_TMP_FREE (marker);
cnt = GMP_NUMB_BITS - cnt;
if (MPFR_UNLIKELY (__gmpfr_emax < MPFR_EMAX_MIN + cnt
|| MPFR_GET_EXP (x) > __gmpfr_emax - cnt))
return mpfr_overflow (y, rnd_mode, MPFR_SIGN(x));
MPFR_SET_EXP (y, MPFR_GET_EXP (x) + cnt);
MPFR_SET_SAME_SIGN (y, x);
return inexact;
}
示例6: mpfr_fac_ui
int
mpfr_fac_ui (mpfr_ptr y, unsigned long int x, mpfr_rnd_t rnd_mode)
{
mpfr_t t; /* Variable of Intermediary Calculation*/
unsigned long i;
int round, inexact;
mpfr_prec_t Ny; /* Precision of output variable */
mpfr_prec_t Nt; /* Precision of Intermediary Calculation variable */
mpfr_prec_t err; /* Precision of error */
mpfr_rnd_t rnd;
MPFR_SAVE_EXPO_DECL (expo);
MPFR_ZIV_DECL (loop);
/***** test x = 0 and x == 1******/
if (MPFR_UNLIKELY (x <= 1))
return mpfr_set_ui (y, 1, rnd_mode); /* 0! = 1 and 1! = 1 */
MPFR_SAVE_EXPO_MARK (expo);
/* Initialisation of the Precision */
Ny = MPFR_PREC (y);
/* compute the size of intermediary variable */
Nt = Ny + 2 * MPFR_INT_CEIL_LOG2 (x) + 7;
mpfr_init2 (t, Nt); /* initialise of intermediary variable */
rnd = MPFR_RNDZ;
MPFR_ZIV_INIT (loop, Nt);
for (;;)
{
/* compute factorial */
inexact = mpfr_set_ui (t, 1, rnd);
for (i = 2 ; i <= x ; i++)
{
round = mpfr_mul_ui (t, t, i, rnd);
/* assume the first inexact product gives the sign
of difference: is that always correct? */
if (inexact == 0)
inexact = round;
}
err = Nt - 1 - MPFR_INT_CEIL_LOG2 (Nt);
round = !inexact || mpfr_can_round (t, err, rnd, MPFR_RNDZ,
Ny + (rnd_mode == MPFR_RNDN));
if (MPFR_LIKELY (round))
{
/* If inexact = 0, then t is exactly x!, so round is the
correct inexact flag.
Otherwise, t != x! since we rounded to zero or away. */
round = mpfr_set (y, t, rnd_mode);
if (inexact == 0)
{
inexact = round;
break;
}
else if ((inexact < 0 && round <= 0)
|| (inexact > 0 && round >= 0))
break;
else /* inexact and round have opposite signs: we cannot
compute the inexact flag. Restart using the
symmetric rounding. */
rnd = (rnd == MPFR_RNDZ) ? MPFR_RNDU : MPFR_RNDZ;
}
MPFR_ZIV_NEXT (loop, Nt);
mpfr_set_prec (t, Nt);
}
MPFR_ZIV_FREE (loop);
mpfr_clear (t);
MPFR_SAVE_EXPO_FREE (expo);
return mpfr_check_range (y, inexact, rnd_mode);
}
示例7: log
/* Implements asymptotic expansion for jn or yn (formulae 9.2.5 and 9.2.6
from Abramowitz & Stegun).
Assumes |z| > p log(2)/2, where p is the target precision
(z can be negative only for jn).
Return 0 if the expansion does not converge enough (the value 0 as inexact
flag should not happen for normal input).
*/
static int
FUNCTION (mpfr_ptr res, long n, mpfr_srcptr z, mpfr_rnd_t r)
{
mpfr_t s, c, P, Q, t, iz, err_t, err_s, err_u;
mpfr_prec_t w;
long k;
int inex, stop, diverge = 0;
mpfr_exp_t err2, err;
MPFR_ZIV_DECL (loop);
mpfr_init (c);
w = MPFR_PREC(res) + MPFR_INT_CEIL_LOG2(MPFR_PREC(res)) + 4;
MPFR_ZIV_INIT (loop, w);
for (;;)
{
mpfr_set_prec (c, w);
mpfr_init2 (s, w);
mpfr_init2 (P, w);
mpfr_init2 (Q, w);
mpfr_init2 (t, w);
mpfr_init2 (iz, w);
mpfr_init2 (err_t, 31);
mpfr_init2 (err_s, 31);
mpfr_init2 (err_u, 31);
/* Approximate sin(z) and cos(z). In the following, err <= k means that
the approximate value y and the true value x are related by
y = x * (1 + u)^k with |u| <= 2^(-w), following Higham's method. */
mpfr_sin_cos (s, c, z, MPFR_RNDN);
if (MPFR_IS_NEG(z))
mpfr_neg (s, s, MPFR_RNDN); /* compute jn/yn(|z|), fix sign later */
/* The absolute error on s/c is bounded by 1/2 ulp(1/2) <= 2^(-w-1). */
mpfr_add (t, s, c, MPFR_RNDN);
mpfr_sub (c, s, c, MPFR_RNDN);
mpfr_swap (s, t);
/* now s approximates sin(z)+cos(z), and c approximates sin(z)-cos(z),
with total absolute error bounded by 2^(1-w). */
/* precompute 1/(8|z|) */
mpfr_si_div (iz, MPFR_IS_POS(z) ? 1 : -1, z, MPFR_RNDN); /* err <= 1 */
mpfr_div_2ui (iz, iz, 3, MPFR_RNDN);
/* compute P and Q */
mpfr_set_ui (P, 1, MPFR_RNDN);
mpfr_set_ui (Q, 0, MPFR_RNDN);
mpfr_set_ui (t, 1, MPFR_RNDN); /* current term */
mpfr_set_ui (err_t, 0, MPFR_RNDN); /* error on t */
mpfr_set_ui (err_s, 0, MPFR_RNDN); /* error on P and Q (sum of errors) */
for (k = 1, stop = 0; stop < 4; k++)
{
/* compute next term: t(k)/t(k-1) = (2n+2k-1)(2n-2k+1)/(8kz) */
mpfr_mul_si (t, t, 2 * (n + k) - 1, MPFR_RNDN); /* err <= err_k + 1 */
mpfr_mul_si (t, t, 2 * (n - k) + 1, MPFR_RNDN); /* err <= err_k + 2 */
mpfr_div_ui (t, t, k, MPFR_RNDN); /* err <= err_k + 3 */
mpfr_mul (t, t, iz, MPFR_RNDN); /* err <= err_k + 5 */
/* the relative error on t is bounded by (1+u)^(5k)-1, which is
bounded by 6ku for 6ku <= 0.02: first |5 log(1+u)| <= |5.5u|
for |u| <= 0.15, then |exp(5.5u)-1| <= 6u for |u| <= 0.02. */
mpfr_mul_ui (err_t, t, 6 * k, MPFR_IS_POS(t) ? MPFR_RNDU : MPFR_RNDD);
mpfr_abs (err_t, err_t, MPFR_RNDN); /* exact */
/* the absolute error on t is bounded by err_t * 2^(-w) */
mpfr_abs (err_u, t, MPFR_RNDU);
mpfr_mul_2ui (err_u, err_u, w, MPFR_RNDU); /* t * 2^w */
mpfr_add (err_u, err_u, err_t, MPFR_RNDU); /* max|t| * 2^w */
if (stop >= 2)
{
/* take into account the neglected terms: t * 2^w */
mpfr_div_2ui (err_s, err_s, w, MPFR_RNDU);
if (MPFR_IS_POS(t))
mpfr_add (err_s, err_s, t, MPFR_RNDU);
else
mpfr_sub (err_s, err_s, t, MPFR_RNDU);
mpfr_mul_2ui (err_s, err_s, w, MPFR_RNDU);
stop ++;
}
/* if k is odd, add to Q, otherwise to P */
else if (k & 1)
{
/* if k = 1 mod 4, add, otherwise subtract */
if ((k & 2) == 0)
mpfr_add (Q, Q, t, MPFR_RNDN);
else
mpfr_sub (Q, Q, t, MPFR_RNDN);
/* check if the next term is smaller than ulp(Q): if EXP(err_u)
<= EXP(Q), since the current term is bounded by
err_u * 2^(-w), it is bounded by ulp(Q) */
if (MPFR_EXP(err_u) <= MPFR_EXP(Q))
stop ++;
else
stop = 0;
}
//.........这里部分代码省略.........
示例8: mpfr_sinh
int
mpfr_sinh (mpfr_ptr y, mpfr_srcptr xt, mp_rnd_t rnd_mode)
{
mpfr_t x;
int inexact;
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", xt, xt, rnd_mode),
("y[%#R]=%R inexact=%d", y, y, inexact));
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt)))
{
if (MPFR_IS_NAN (xt))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else if (MPFR_IS_INF (xt))
{
MPFR_SET_INF (y);
MPFR_SET_SAME_SIGN (y, xt);
MPFR_RET (0);
}
else /* xt is zero */
{
MPFR_ASSERTD (MPFR_IS_ZERO (xt));
MPFR_SET_ZERO (y); /* sinh(0) = 0 */
MPFR_SET_SAME_SIGN (y, xt);
MPFR_RET (0);
}
}
/* sinh(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP(xt), 2, 1,
rnd_mode, {});
MPFR_TMP_INIT_ABS (x, xt);
{
mpfr_t t, ti;
mp_exp_t d;
mp_prec_t Nt; /* Precision of the intermediary variable */
long int err; /* Precision of error */
MPFR_ZIV_DECL (loop);
MPFR_SAVE_EXPO_DECL (expo);
MPFR_GROUP_DECL (group);
MPFR_SAVE_EXPO_MARK (expo);
/* compute the precision of intermediary variable */
Nt = MAX (MPFR_PREC (x), MPFR_PREC (y));
/* the optimal number of bits : see algorithms.ps */
Nt = Nt + MPFR_INT_CEIL_LOG2 (Nt) + 4;
/* If x is near 0, exp(x) - 1/exp(x) = 2*x+x^3/3+O(x^5) */
if (MPFR_GET_EXP (x) < 0)
Nt -= 2*MPFR_GET_EXP (x);
/* initialise of intermediary variables */
MPFR_GROUP_INIT_2 (group, Nt, t, ti);
/* First computation of sinh */
MPFR_ZIV_INIT (loop, Nt);
for (;;) {
/* compute sinh */
mpfr_clear_flags ();
mpfr_exp (t, x, GMP_RNDD); /* exp(x) */
/* exp(x) can overflow! */
/* BUG/TODO/FIXME: exp can overflow but sinh may be representable! */
if (MPFR_UNLIKELY (mpfr_overflow_p ())) {
inexact = mpfr_overflow (y, rnd_mode, MPFR_SIGN (xt));
MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, MPFR_FLAGS_OVERFLOW);
break;
}
d = MPFR_GET_EXP (t);
mpfr_ui_div (ti, 1, t, GMP_RNDU); /* 1/exp(x) */
mpfr_sub (t, t, ti, GMP_RNDN); /* exp(x) - 1/exp(x) */
mpfr_div_2ui (t, t, 1, GMP_RNDN); /* 1/2(exp(x) - 1/exp(x)) */
/* it may be that t is zero (in fact, it can only occur when te=1,
and thus ti=1 too) */
if (MPFR_IS_ZERO (t))
err = Nt; /* double the precision */
else
{
/* calculation of the error */
d = d - MPFR_GET_EXP (t) + 2;
/* error estimate: err = Nt-(__gmpfr_ceil_log2(1+pow(2,d)));*/
err = Nt - (MAX (d, 0) + 1);
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, MPFR_PREC (y), rnd_mode)))
{
inexact = mpfr_set4 (y, t, rnd_mode, MPFR_SIGN (xt));
break;
}
}
/* actualisation of the precision */
Nt += err;
MPFR_ZIV_NEXT (loop, Nt);
MPFR_GROUP_REPREC_2 (group, Nt, t, ti);
}
MPFR_ZIV_FREE (loop);
MPFR_GROUP_CLEAR (group);
//.........这里部分代码省略.........
示例9: mpfr_cos
int
mpfr_cos (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
mpfr_prec_t K0, K, precy, m, k, l;
int inexact, reduce = 0;
mpfr_t r, s, xr, c;
mpfr_exp_t exps, cancel = 0, expx;
MPFR_ZIV_DECL (loop);
MPFR_SAVE_EXPO_DECL (expo);
MPFR_GROUP_DECL (group);
MPFR_LOG_FUNC (
("x[%Pu]=%*.Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
("y[%Pu]=%*.Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y,
inexact));
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
{
if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else
{
MPFR_ASSERTD (MPFR_IS_ZERO (x));
return mpfr_set_ui (y, 1, rnd_mode);
}
}
MPFR_SAVE_EXPO_MARK (expo);
/* cos(x) = 1-x^2/2 + ..., so error < 2^(2*EXP(x)-1) */
expx = MPFR_GET_EXP (x);
MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, -2 * expx,
1, 0, rnd_mode, expo, {});
/* Compute initial precision */
precy = MPFR_PREC (y);
if (precy >= MPFR_SINCOS_THRESHOLD)
{
MPFR_SAVE_EXPO_FREE (expo);
return mpfr_cos_fast (y, x, rnd_mode);
}
K0 = __gmpfr_isqrt (precy / 3);
m = precy + 2 * MPFR_INT_CEIL_LOG2 (precy) + 2 * K0;
if (expx >= 3)
{
reduce = 1;
/* As expx + m - 1 will silently be converted into mpfr_prec_t
in the mpfr_init2 call, the assert below may be useful to
avoid undefined behavior. */
MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX);
mpfr_init2 (c, expx + m - 1);
mpfr_init2 (xr, m);
}
MPFR_GROUP_INIT_2 (group, m, r, s);
MPFR_ZIV_INIT (loop, m);
for (;;)
{
/* If |x| >= 4, first reduce x cmod (2*Pi) into xr, using mpfr_remainder:
let e = EXP(x) >= 3, and m the target precision:
(1) c <- 2*Pi [precision e+m-1, nearest]
(2) xr <- remainder (x, c) [precision m, nearest]
We have |c - 2*Pi| <= 1/2ulp(c) = 2^(3-e-m)
|xr - x - k c| <= 1/2ulp(xr) <= 2^(1-m)
|k| <= |x|/(2*Pi) <= 2^(e-2)
Thus |xr - x - 2kPi| <= |k| |c - 2Pi| + 2^(1-m) <= 2^(2-m).
It follows |cos(xr) - cos(x)| <= 2^(2-m). */
if (reduce)
{
mpfr_const_pi (c, MPFR_RNDN);
mpfr_mul_2ui (c, c, 1, MPFR_RNDN); /* 2Pi */
mpfr_remainder (xr, x, c, MPFR_RNDN);
if (MPFR_IS_ZERO(xr))
goto ziv_next;
/* now |xr| <= 4, thus r <= 16 below */
mpfr_mul (r, xr, xr, MPFR_RNDU); /* err <= 1 ulp */
}
else
mpfr_mul (r, x, x, MPFR_RNDU); /* err <= 1 ulp */
/* now |x| < 4 (or xr if reduce = 1), thus |r| <= 16 */
/* we need |r| < 1/2 for mpfr_cos2_aux, i.e., EXP(r) - 2K <= -1 */
K = K0 + 1 + MAX(0, MPFR_GET_EXP(r)) / 2;
/* since K0 >= 0, if EXP(r) < 0, then K >= 1, thus EXP(r) - 2K <= -3;
otherwise if EXP(r) >= 0, then K >= 1/2 + EXP(r)/2, thus
EXP(r) - 2K <= -1 */
MPFR_SET_EXP (r, MPFR_GET_EXP (r) - 2 * K); /* Can't overflow! */
/* s <- 1 - r/2! + ... + (-1)^l r^l/(2l)! */
l = mpfr_cos2_aux (s, r);
/* l is the error bound in ulps on s */
MPFR_SET_ONE (r);
//.........这里部分代码省略.........
示例10: mpfr_pow_si
//.........这里部分代码省略.........
* cc: Sun C 5.8 2005/10/13
* cc: Sun C 5.8 Patch 121016-02 2006/03/31
* cc: Sun C 5.8 Patch 121016-04 2006/10/18
*/
expy =
n != -1 && expx > 0 && expx > (__gmpfr_emin - 1) / n ?
MPFR_EMIN_MIN - 2 /* Underflow */ :
n != -1 && expx < 0 && expx < (__gmpfr_emax - 1) / n ?
MPFR_EMAX_MAX /* Overflow */ : n * expx;
return mpfr_set_si_2exp (y, n % 2 ? MPFR_INT_SIGN (x) : 1,
expy, rnd);
}
/* General case */
{
/* Declaration of the intermediary variable */
mpfr_t t;
/* Declaration of the size variable */
mpfr_prec_t Ny; /* target precision */
mpfr_prec_t Nt; /* working precision */
mpfr_rnd_t rnd1;
int size_n;
int inexact;
unsigned long abs_n;
MPFR_SAVE_EXPO_DECL (expo);
MPFR_ZIV_DECL (loop);
abs_n = - (unsigned long) n;
count_leading_zeros (size_n, (mp_limb_t) abs_n);
size_n = GMP_NUMB_BITS - size_n;
/* initial working precision */
Ny = MPFR_PREC (y);
Nt = Ny + size_n + 3 + MPFR_INT_CEIL_LOG2 (Ny);
MPFR_SAVE_EXPO_MARK (expo);
/* initialise of intermediary variable */
mpfr_init2 (t, Nt);
/* We will compute rnd(rnd1(1/x) ^ |n|), where rnd1 is the rounding
toward sign(x), to avoid spurious overflow or underflow, as in
mpfr_pow_z. */
rnd1 = MPFR_EXP (x) < 1 ? MPFR_RNDZ :
(MPFR_SIGN (x) > 0 ? MPFR_RNDU : MPFR_RNDD);
MPFR_ZIV_INIT (loop, Nt);
for (;;)
{
MPFR_BLOCK_DECL (flags);
/* compute (1/x)^|n| */
MPFR_BLOCK (flags, mpfr_ui_div (t, 1, x, rnd1));
MPFR_ASSERTD (! MPFR_UNDERFLOW (flags));
/* t = (1/x)*(1+theta) where |theta| <= 2^(-Nt) */
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
goto overflow;
MPFR_BLOCK (flags, mpfr_pow_ui (t, t, abs_n, rnd));
/* t = (1/x)^|n|*(1+theta')^(|n|+1) where |theta'| <= 2^(-Nt).
If (|n|+1)*2^(-Nt) <= 1/2, which is satisfied as soon as
Nt >= bits(n)+2, then we can use Lemma \ref{lemma_graillat}
from algorithms.tex, which yields x^n*(1+theta) with
|theta| <= 2(|n|+1)*2^(-Nt), thus the error is bounded by
2(|n|+1) ulps <= 2^(bits(n)+2) ulps. */
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
{
示例11: mpfr_sin
int
mpfr_sin (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
mpfr_t c, xr;
mpfr_srcptr xx;
mpfr_exp_t expx, err;
mpfr_prec_t precy, m;
int inexact, sign, reduce;
MPFR_ZIV_DECL (loop);
MPFR_SAVE_EXPO_DECL (expo);
MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
("y[%#R]=%R inexact=%d", y, y, inexact));
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
{
if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else /* x is zero */
{
MPFR_ASSERTD (MPFR_IS_ZERO (x));
MPFR_SET_ZERO (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0);
}
}
/* sin(x) = x - x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, x, -2 * MPFR_GET_EXP (x), 2, 0,
rnd_mode, {});
MPFR_SAVE_EXPO_MARK (expo);
/* Compute initial precision */
precy = MPFR_PREC (y);
if (precy >= MPFR_SINCOS_THRESHOLD)
return mpfr_sin_fast (y, x, rnd_mode);
m = precy + MPFR_INT_CEIL_LOG2 (precy) + 13;
expx = MPFR_GET_EXP (x);
mpfr_init (c);
mpfr_init (xr);
MPFR_ZIV_INIT (loop, m);
for (;;)
{
/* first perform argument reduction modulo 2*Pi (if needed),
also helps to determine the sign of sin(x) */
if (expx >= 2) /* If Pi < x < 4, we need to reduce too, to determine
the sign of sin(x). For 2 <= |x| < Pi, we could avoid
the reduction. */
{
reduce = 1;
/* As expx + m - 1 will silently be converted into mpfr_prec_t
in the mpfr_set_prec call, the assert below may be useful to
avoid undefined behavior. */
MPFR_ASSERTN (expx + m - 1 <= MPFR_PREC_MAX);
mpfr_set_prec (c, expx + m - 1);
mpfr_set_prec (xr, m);
mpfr_const_pi (c, MPFR_RNDN);
mpfr_mul_2ui (c, c, 1, MPFR_RNDN);
mpfr_remainder (xr, x, c, MPFR_RNDN);
/* The analysis is similar to that of cos.c:
|xr - x - 2kPi| <= 2^(2-m). Thus we can decide the sign
of sin(x) if xr is at distance at least 2^(2-m) of both
0 and +/-Pi. */
mpfr_div_2ui (c, c, 1, MPFR_RNDN);
/* Since c approximates Pi with an error <= 2^(2-expx-m) <= 2^(-m),
it suffices to check that c - |xr| >= 2^(2-m). */
if (MPFR_SIGN (xr) > 0)
mpfr_sub (c, c, xr, MPFR_RNDZ);
else
mpfr_add (c, c, xr, MPFR_RNDZ);
if (MPFR_IS_ZERO(xr)
|| MPFR_EXP(xr) < (mpfr_exp_t) 3 - (mpfr_exp_t) m
|| MPFR_EXP(c) < (mpfr_exp_t) 3 - (mpfr_exp_t) m)
goto ziv_next;
/* |xr - x - 2kPi| <= 2^(2-m), thus |sin(xr) - sin(x)| <= 2^(2-m) */
xx = xr;
}
else /* the input argument is already reduced */
{
reduce = 0;
xx = x;
}
sign = MPFR_SIGN(xx);
/* now that the argument is reduced, precision m is enough */
mpfr_set_prec (c, m);
mpfr_cos (c, xx, MPFR_RNDZ); /* can't be exact */
mpfr_nexttoinf (c); /* now c = cos(x) rounded away */
mpfr_mul (c, c, c, MPFR_RNDU); /* away */
mpfr_ui_sub (c, 1, c, MPFR_RNDZ);
//.........这里部分代码省略.........
示例12: mpfr_log
int
mpfr_log (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode)
{
int inexact;
mpfr_prec_t p, q;
mpfr_t tmp1, tmp2;
MPFR_SAVE_EXPO_DECL (expo);
MPFR_ZIV_DECL (loop);
MPFR_GROUP_DECL(group);
MPFR_LOG_FUNC
(("a[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (a), mpfr_log_prec, a, rnd_mode),
("r[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (r), mpfr_log_prec, r,
inexact));
/* Special cases */
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a)))
{
/* If a is NaN, the result is NaN */
if (MPFR_IS_NAN (a))
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
/* check for infinity before zero */
else if (MPFR_IS_INF (a))
{
if (MPFR_IS_NEG (a))
/* log(-Inf) = NaN */
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
else /* log(+Inf) = +Inf */
{
MPFR_SET_INF (r);
MPFR_SET_POS (r);
MPFR_RET (0);
}
}
else /* a is zero */
{
MPFR_ASSERTD (MPFR_IS_ZERO (a));
MPFR_SET_INF (r);
MPFR_SET_NEG (r);
mpfr_set_divby0 ();
MPFR_RET (0); /* log(0) is an exact -infinity */
}
}
/* If a is negative, the result is NaN */
else if (MPFR_UNLIKELY (MPFR_IS_NEG (a)))
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
/* If a is 1, the result is 0 */
else if (MPFR_UNLIKELY (MPFR_GET_EXP (a) == 1 && mpfr_cmp_ui (a, 1) == 0))
{
MPFR_SET_ZERO (r);
MPFR_SET_POS (r);
MPFR_RET (0); /* only "normal" case where the result is exact */
}
q = MPFR_PREC (r);
/* use initial precision about q+lg(q)+5 */
p = q + 5 + 2 * MPFR_INT_CEIL_LOG2 (q);
/* % ~(mpfr_prec_t)GMP_NUMB_BITS ;
m=q; while (m) { p++; m >>= 1; } */
/* if (MPFR_LIKELY(p % GMP_NUMB_BITS != 0))
p += GMP_NUMB_BITS - (p%GMP_NUMB_BITS); */
MPFR_SAVE_EXPO_MARK (expo);
MPFR_GROUP_INIT_2 (group, p, tmp1, tmp2);
MPFR_ZIV_INIT (loop, p);
for (;;)
{
long m;
mpfr_exp_t cancel;
/* Calculus of m (depends on p) */
m = (p + 1) / 2 - MPFR_GET_EXP (a) + 1;
mpfr_mul_2si (tmp2, a, m, MPFR_RNDN); /* s=a*2^m, err<=1 ulp */
mpfr_div (tmp1, __gmpfr_four, tmp2, MPFR_RNDN);/* 4/s, err<=2 ulps */
mpfr_agm (tmp2, __gmpfr_one, tmp1, MPFR_RNDN); /* AG(1,4/s),err<=3 ulps */
mpfr_mul_2ui (tmp2, tmp2, 1, MPFR_RNDN); /* 2*AG(1,4/s), err<=3 ulps */
mpfr_const_pi (tmp1, MPFR_RNDN); /* compute pi, err<=1ulp */
mpfr_div (tmp2, tmp1, tmp2, MPFR_RNDN); /* pi/2*AG(1,4/s), err<=5ulps */
mpfr_const_log2 (tmp1, MPFR_RNDN); /* compute log(2), err<=1ulp */
mpfr_mul_si (tmp1, tmp1, m, MPFR_RNDN); /* compute m*log(2),err<=2ulps */
mpfr_sub (tmp1, tmp2, tmp1, MPFR_RNDN); /* log(a), err<=7ulps+cancel */
if (MPFR_LIKELY (MPFR_IS_PURE_FP (tmp1) && MPFR_IS_PURE_FP (tmp2)))
{
cancel = MPFR_GET_EXP (tmp2) - MPFR_GET_EXP (tmp1);
MPFR_LOG_MSG (("canceled bits=%ld\n", (long) cancel));
MPFR_LOG_VAR (tmp1);
if (MPFR_UNLIKELY (cancel < 0))
//.........这里部分代码省略.........
示例13: mpfr_log10
int
mpfr_log10 (mpfr_ptr r, mpfr_srcptr a, mpfr_rnd_t rnd_mode)
{
int inexact;
MPFR_SAVE_EXPO_DECL (expo);
/* If a is NaN, the result is NaN */
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a)))
{
if (MPFR_IS_NAN (a))
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
/* check for infinity before zero */
else if (MPFR_IS_INF (a))
{
if (MPFR_IS_NEG (a))
/* log10(-Inf) = NaN */
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
else /* log10(+Inf) = +Inf */
{
MPFR_SET_INF (r);
MPFR_SET_POS (r);
MPFR_RET (0); /* exact */
}
}
else /* a = 0 */
{
MPFR_ASSERTD (MPFR_IS_ZERO (a));
MPFR_SET_INF (r);
MPFR_SET_NEG (r);
MPFR_RET (0); /* log10(0) is an exact -infinity */
}
}
/* If a is negative, the result is NaN */
if (MPFR_UNLIKELY (MPFR_IS_NEG (a)))
{
MPFR_SET_NAN (r);
MPFR_RET_NAN;
}
/* If a is 1, the result is 0 */
if (mpfr_cmp_ui (a, 1) == 0)
{
MPFR_SET_ZERO (r);
MPFR_SET_POS (r);
MPFR_RET (0); /* result is exact */
}
MPFR_SAVE_EXPO_MARK (expo);
/* General case */
{
/* Declaration of the intermediary variable */
mpfr_t t, tt;
MPFR_ZIV_DECL (loop);
/* Declaration of the size variable */
mpfr_prec_t Ny = MPFR_PREC(r); /* Precision of output variable */
mpfr_prec_t Nt; /* Precision of the intermediary variable */
mpfr_exp_t err; /* Precision of error */
/* compute the precision of intermediary variable */
/* the optimal number of bits : see algorithms.tex */
Nt = Ny + 4 + MPFR_INT_CEIL_LOG2 (Ny);
/* initialise of intermediary variables */
mpfr_init2 (t, Nt);
mpfr_init2 (tt, Nt);
/* First computation of log10 */
MPFR_ZIV_INIT (loop, Nt);
for (;;)
{
/* compute log10 */
mpfr_set_ui (t, 10, MPFR_RNDN); /* 10 */
mpfr_log (t, t, MPFR_RNDD); /* log(10) */
mpfr_log (tt, a, MPFR_RNDN); /* log(a) */
mpfr_div (t, tt, t, MPFR_RNDN); /* log(a)/log(10) */
/* estimation of the error */
err = Nt - 4;
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, Ny, rnd_mode)))
break;
/* log10(10^n) is exact:
FIXME: Can we have 10^n exactly representable as a mpfr_t
but n can't fit an unsigned long? */
if (MPFR_IS_POS (t)
&& mpfr_integer_p (t) && mpfr_fits_ulong_p (t, MPFR_RNDN)
&& !mpfr_ui_pow_ui (tt, 10, mpfr_get_ui (t, MPFR_RNDN), MPFR_RNDN)
&& mpfr_cmp (a, tt) == 0)
break;
/* actualisation of the precision */
MPFR_ZIV_NEXT (loop, Nt);
//.........这里部分代码省略.........
示例14: mpfr_div_ui
/* returns 0 if result exact, non-zero otherwise */
int
mpfr_div_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode)
{
long i;
int sh;
mp_size_t xn, yn, dif;
mp_limb_t *xp, *yp, *tmp, c, d;
mpfr_exp_t exp;
int inexact, middle = 1, nexttoinf;
MPFR_TMP_DECL(marker);
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
{
if (MPFR_IS_NAN (x))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else if (MPFR_IS_INF (x))
{
MPFR_SET_INF (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0);
}
else
{
MPFR_ASSERTD (MPFR_IS_ZERO(x));
if (u == 0) /* 0/0 is NaN */
{
MPFR_SET_NAN(y);
MPFR_RET_NAN;
}
else
{
MPFR_SET_ZERO(y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET(0);
}
}
}
else if (MPFR_UNLIKELY (u <= 1))
{
if (u < 1)
{
/* x/0 is Inf since x != 0*/
MPFR_SET_INF (y);
MPFR_SET_SAME_SIGN (y, x);
MPFR_RET (0);
}
else /* y = x/1 = x */
return mpfr_set (y, x, rnd_mode);
}
else if (MPFR_UNLIKELY (IS_POW2 (u)))
return mpfr_div_2si (y, x, MPFR_INT_CEIL_LOG2 (u), rnd_mode);
MPFR_SET_SAME_SIGN (y, x);
MPFR_TMP_MARK (marker);
xn = MPFR_LIMB_SIZE (x);
yn = MPFR_LIMB_SIZE (y);
xp = MPFR_MANT (x);
yp = MPFR_MANT (y);
exp = MPFR_GET_EXP (x);
dif = yn + 1 - xn;
/* we need to store yn+1 = xn + dif limbs of the quotient */
/* don't use tmp=yp since the mpn_lshift call below requires yp >= tmp+1 */
tmp = (mp_limb_t*) MPFR_TMP_ALLOC ((yn + 1) * BYTES_PER_MP_LIMB);
c = (mp_limb_t) u;
MPFR_ASSERTN (u == c);
if (dif >= 0)
c = mpn_divrem_1 (tmp, dif, xp, xn, c); /* used all the dividend */
else /* dif < 0 i.e. xn > yn, don't use the (-dif) low limbs from x */
c = mpn_divrem_1 (tmp, 0, xp - dif, yn + 1, c);
inexact = (c != 0);
/* First pass in estimating next bit of the quotient, in case of RNDN *
* In case we just have the right number of bits (postpone this ?), *
* we need to check whether the remainder is more or less than half *
* the divisor. The test must be performed with a subtraction, so as *
* to prevent carries. */
if (MPFR_LIKELY (rnd_mode == MPFR_RNDN))
{
if (c < (mp_limb_t) u - c) /* We have u > c */
middle = -1;
else if (c > (mp_limb_t) u - c)
middle = 1;
else
middle = 0; /* exactly in the middle */
}
/* If we believe that we are right in the middle or exact, we should check
that we did not neglect any word of x (division large / 1 -> small). */
//.........这里部分代码省略.........
示例15: mpfr_tanh
int
mpfr_tanh (mpfr_ptr y, mpfr_srcptr xt , mpfr_rnd_t rnd_mode)
{
/****** Declaration ******/
mpfr_t x;
int inexact;
MPFR_SAVE_EXPO_DECL (expo);
MPFR_LOG_FUNC
(("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (xt), mpfr_log_prec, xt, rnd_mode),
("y[%Pu]=%.*Rg inexact=%d",
mpfr_get_prec (y), mpfr_log_prec, y, inexact));
/* Special value checking */
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (xt)))
{
if (MPFR_IS_NAN (xt))
{
MPFR_SET_NAN (y);
MPFR_RET_NAN;
}
else if (MPFR_IS_INF (xt))
{
/* tanh(inf) = 1 && tanh(-inf) = -1 */
return mpfr_set_si (y, MPFR_INT_SIGN (xt), rnd_mode);
}
else /* tanh (0) = 0 and xt is zero */
{
MPFR_ASSERTD (MPFR_IS_ZERO(xt));
MPFR_SET_ZERO (y);
MPFR_SET_SAME_SIGN (y, xt);
MPFR_RET (0);
}
}
/* tanh(x) = x - x^3/3 + ... so the error is < 2^(3*EXP(x)-1) */
MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP (xt), 1, 0,
rnd_mode, {});
MPFR_TMP_INIT_ABS (x, xt);
MPFR_SAVE_EXPO_MARK (expo);
/* General case */
{
/* Declaration of the intermediary variable */
mpfr_t t, te;
mpfr_exp_t d;
/* Declaration of the size variable */
mpfr_prec_t Ny = MPFR_PREC(y); /* target precision */
mpfr_prec_t Nt; /* working precision */
long int err; /* error */
int sign = MPFR_SIGN (xt);
MPFR_ZIV_DECL (loop);
MPFR_GROUP_DECL (group);
/* First check for BIG overflow of exp(2*x):
For x > 0, exp(2*x) > 2^(2*x)
If 2 ^(2*x) > 2^emax or x>emax/2, there is an overflow */
if (MPFR_UNLIKELY (mpfr_cmp_si (x, __gmpfr_emax/2) >= 0)) {
/* initialise of intermediary variables
since 'set_one' label assumes the variables have been
initialize */
MPFR_GROUP_INIT_2 (group, MPFR_PREC_MIN, t, te);
goto set_one;
}
/* Compute the precision of intermediary variable */
/* The optimal number of bits: see algorithms.tex */
Nt = Ny + MPFR_INT_CEIL_LOG2 (Ny) + 4;
/* if x is small, there will be a cancellation in exp(2x)-1 */
if (MPFR_GET_EXP (x) < 0)
Nt += -MPFR_GET_EXP (x);
/* initialise of intermediary variable */
MPFR_GROUP_INIT_2 (group, Nt, t, te);
MPFR_ZIV_INIT (loop, Nt);
for (;;) {
/* tanh = (exp(2x)-1)/(exp(2x)+1) */
mpfr_mul_2ui (te, x, 1, MPFR_RNDN); /* 2x */
/* since x > 0, we can only have an overflow */
mpfr_exp (te, te, MPFR_RNDN); /* exp(2x) */
if (MPFR_UNLIKELY (MPFR_IS_INF (te))) {
set_one:
inexact = MPFR_FROM_SIGN_TO_INT (sign);
mpfr_set4 (y, __gmpfr_one, MPFR_RNDN, sign);
if (MPFR_IS_LIKE_RNDZ (rnd_mode, MPFR_IS_NEG_SIGN (sign)))
{
inexact = -inexact;
mpfr_nexttozero (y);
}
break;
}
d = MPFR_GET_EXP (te); /* For Error calculation */
mpfr_add_ui (t, te, 1, MPFR_RNDD); /* exp(2x) + 1*/
mpfr_sub_ui (te, te, 1, MPFR_RNDU); /* exp(2x) - 1*/
d = d - MPFR_GET_EXP (te);
mpfr_div (t, te, t, MPFR_RNDN); /* (exp(2x)-1)/(exp(2x)+1)*/
//.........这里部分代码省略.........