/* s <- 1 - r/2! + r^2/4! + ... + (-1)^l r^l/(2l)! + ... Assumes |r| < 1. Returns the index l0 of the last term (-1)^l r^l/(2l)!. The absolute error on s is at most 2 * l0 * 2^(-m). */ static int mpfr_cos2_aux (mpfr_ptr s, mpfr_srcptr r) { unsigned int l, b = 2; long int prec_t, m = MPFR_PREC(s); mpfr_t t; MPFR_ASSERTN (MPFR_EXP(r) <= 0); mpfr_init2 (t, m); mpfr_set_ui (t, 1, GMP_RNDN); mpfr_set_ui(s, 1, GMP_RNDN); for (l = 1; MPFR_EXP(t) + m >= 0; l++) { mpfr_mul (t, t, r, GMP_RNDU); /* err <= (3l-1) ulp */ mpfr_div_ui (t, t, (2*l-1)*(2*l), GMP_RNDU); /* err <= 3l ulp */ if (l % 2 == 0) mpfr_add (s, s, t, GMP_RNDD); else mpfr_sub (s, s, t, GMP_RNDD); MPFR_ASSERTN (MPFR_EXP(s) == 0); /* check 1/2 <= s < 1 */ /* err(s) <= l * 2^(-m) */ if (3 * l > (1 << b)) b++; /* now 3l <= 2^b, we want 3l*ulp(t) <= 2^(-m) i.e. b+EXP(t)-PREC(t) <= -m */ prec_t = m + MPFR_EXP(t) + b; if (prec_t >= MPFR_PREC_MIN) mpfr_round_prec (t, GMP_RNDN, prec_t); } mpfr_clear (t); return l; }
// remove trailing zeros (only by limbs) void mpfr_remove_trailing_zeros(mpfr_t x) { unsigned int xn = MPFR_LIMB_SIZE(x); mp_limb_t* xp = MPFR_MANT(x); unsigned int i = 0; while (i < xn && xp[i] == 0) i++; if (i > 0 && i < xn) mpfr_round_prec(x, GMP_RNDN, (xn-i)*BITS_PER_MP_LIMB); }