1 /* mpfr_atan -- arc-tangent of a floating-point number
3 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
6 This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
26 /* If x = p/2^r, put in y an approximation of atan(x)/x using 2^m terms
27 for the series expansion, with an error of at most 1 ulp.
30 If X=x^2, we want 1 - X/3 + X^2/5 - ... + (-1)^k*X^k/(2k+1) + ...
33 mpfr_atan_aux (mpfr_ptr y
, mpz_ptr p
, long r
, int m
, mpz_t
*tab
)
36 unsigned long n
, i
, k
, j
, l
;
39 mp_prec_t mult
, *accu
, *log2_nb_terms
;
40 mp_prec_t precy
= MPFR_PREC(y
);
42 if (mpz_cmp_ui (p
, 0) == 0)
44 mpfr_set_ui (y
, 1, GMP_RNDN
); /* limit(atan(x)/x, x=0) */
48 accu
= (mp_prec_t
*) (*__gmp_allocate_func
) ((2 * m
+ 2) * sizeof (mp_prec_t
));
49 log2_nb_terms
= accu
+ m
+ 1;
53 ptoj
= S
+ 1*(m
+1); /* p^2^j Precomputed table */
54 Q
= S
+ 2*(m
+1); /* Product of Odd integer table */
56 /* From p to p^2, and r to 2r */
58 MPFR_ASSERTD (2 * r
> r
);
63 mpz_tdiv_q_2exp (p
, p
, n
); /* exact */
66 /* since |p/2^r| < 1, and p is a non-zero integer, necessarily r > 0 */
68 MPFR_ASSERTD (mpz_sgn (p
) > 0);
71 /* check if p=1 (special case) */
74 We compute by binary splitting, with X = x^2 = p/2^r:
75 P(a,b) = p if a+1=b, P(a,c)*P(c,b) otherwise
76 Q(a,b) = (2a+1)*2^r if a+1=b [except Q(0,1)=1], Q(a,c)*Q(c,b) otherwise
77 S(a,b) = p*(2a+1) if a+1=b, Q(c,b)*S(a,c)+Q(a,c)*P(a,c)*S(c,b) otherwise
78 Then atan(x)/x ~ S(0,i)/Q(0,i) for i so that (p/2^r)^i/i is small enough.
79 The factor 2^(r*(b-a)) in Q(a,b) is implicit, thus we have to take it
80 into account when we compute with Q.
82 accu
[0] = 0; /* accu[k] = Mult[0] + ... + Mult[k], where Mult[j] is the
83 number of bits of the corresponding term S[j]/Q[j] */
84 if (mpz_cmp_ui (p
, 1) != 0)
86 /* p <> 1: precompute ptoj table */
88 for (im
= 1 ; im
<= m
; im
++)
89 mpz_mul (ptoj
[im
], ptoj
[im
- 1], ptoj
[im
- 1]);
92 /* the ith term being X^i/(2i+1) with X=p/2^r, we can stop when
93 p^i/2^(r*i) < 2^(-precy), i.e. r*i > precy + log2(p^i) */
94 for (i
= k
= done
= 0; (i
< n
) && (done
== 0); i
+= 2, k
++)
96 /* initialize both S[k],Q[k] and S[k+1],Q[k+1] */
97 mpz_set_ui (Q
[k
+1], 2 * i
+ 3); /* Q(i+1,i+2) */
98 mpz_mul_ui (S
[k
+1], p
, 2 * i
+ 1); /* S(i+1,i+2) */
99 mpz_mul_2exp (S
[k
], Q
[k
+1], r
);
100 mpz_sub (S
[k
], S
[k
], S
[k
+1]); /* S(i,i+2) */
101 mpz_mul_ui (Q
[k
], Q
[k
+1], 2 * i
+ 1); /* Q(i,i+2) */
102 log2_nb_terms
[k
] = 1; /* S[k]/Q[k] corresponds to 2 terms */
103 for (j
= (i
+ 2) >> 1, l
= 1; (j
& 1) == 0; l
++, j
>>= 1, k
--)
105 /* invariant: S[k-1]/Q[k-1] and S[k]/Q[k] correspond
106 to 2^l terms each. We combine them into S[k-1]/Q[k-1] */
107 MPFR_ASSERTD (k
> 0);
108 mpz_mul (S
[k
], S
[k
], Q
[k
-1]);
109 mpz_mul (S
[k
], S
[k
], ptoj
[l
]);
110 mpz_mul (S
[k
-1], S
[k
-1], Q
[k
]);
111 mpz_mul_2exp (S
[k
-1], S
[k
-1], r
<< l
);
112 mpz_add (S
[k
-1], S
[k
-1], S
[k
]);
113 mpz_mul (Q
[k
-1], Q
[k
-1], Q
[k
]);
114 log2_nb_terms
[k
-1] = l
+ 1;
115 /* now S[k-1]/Q[k-1] corresponds to 2^(l+1) terms */
116 MPFR_MPZ_SIZEINBASE2(mult
, ptoj
[l
+1]);
117 /* FIXME: precompute bits(ptoj[l+1]) outside the loop? */
118 mult
= (r
<< (l
+ 1)) - mult
- 1;
119 accu
[k
-1] = (k
== 1) ? mult
: accu
[k
-2] + mult
;
120 if (accu
[k
-1] > precy
)
125 else /* special case p=1: the ith term being X^i/(2i+1) with X=1/2^r,
126 we can stop when r*i > precy i.e. i > precy/r */
129 for (i
= k
= 0; (i
< n
) && (i
<= precy
/ r
); i
+= 2, k
++)
131 mpz_set_ui (Q
[k
+ 1], 2 * i
+ 3);
132 mpz_mul_2exp (S
[k
], Q
[k
+1], r
);
133 mpz_sub_ui (S
[k
], S
[k
], 1 + 2 * i
);
134 mpz_mul_ui (Q
[k
], Q
[k
+ 1], 1 + 2 * i
);
135 log2_nb_terms
[k
] = 1; /* S[k]/Q[k] corresponds to 2 terms */
136 for (j
= (i
+ 2) >> 1, l
= 1; (j
& 1) == 0; l
++, j
>>= 1, k
--)
138 MPFR_ASSERTD (k
> 0);
139 mpz_mul (S
[k
], S
[k
], Q
[k
-1]);
140 mpz_mul (S
[k
-1], S
[k
-1], Q
[k
]);
141 mpz_mul_2exp (S
[k
-1], S
[k
-1], r
<< l
);
142 mpz_add (S
[k
-1], S
[k
-1], S
[k
]);
143 mpz_mul (Q
[k
-1], Q
[k
-1], Q
[k
]);
144 log2_nb_terms
[k
-1] = l
+ 1;
149 /* we need to combine S[0]/Q[0]...S[k-1]/Q[k-1] */
150 l
= 0; /* number of terms accumulated in S[k]/Q[k] */
154 /* combine S[k-1]/Q[k-1] and S[k]/Q[k] */
155 j
= log2_nb_terms
[k
-1];
156 mpz_mul (S
[k
], S
[k
], Q
[k
-1]);
157 if (mpz_cmp_ui (p
, 1) != 0)
158 mpz_mul (S
[k
], S
[k
], ptoj
[j
]);
159 mpz_mul (S
[k
-1], S
[k
-1], Q
[k
]);
160 l
+= 1 << log2_nb_terms
[k
];
161 mpz_mul_2exp (S
[k
-1], S
[k
-1], r
* l
);
162 mpz_add (S
[k
-1], S
[k
-1], S
[k
]);
163 mpz_mul (Q
[k
-1], Q
[k
-1], Q
[k
]);
165 (*__gmp_free_func
) (accu
, (2 * m
+ 2) * sizeof (mp_prec_t
));
167 MPFR_MPZ_SIZEINBASE2 (diff
, S
[0]);
171 mpz_tdiv_q_2exp (S
[0], S
[0], diff
);
173 mpz_mul_2exp (S
[0], S
[0], -diff
);
175 MPFR_MPZ_SIZEINBASE2 (diff
, Q
[0]);
179 mpz_tdiv_q_2exp (Q
[0], Q
[0], diff
);
181 mpz_mul_2exp (Q
[0], Q
[0], -diff
);
183 mpz_tdiv_q (S
[0], S
[0], Q
[0]);
184 mpfr_set_z (y
, S
[0], GMP_RNDD
);
185 MPFR_SET_EXP (y
, MPFR_EXP(y
) + expo
- r
* (i
- 1));
189 mpfr_atan (mpfr_ptr atan
, mpfr_srcptr x
, mp_rnd_t rnd_mode
)
191 mpfr_t xp
, arctgt
, sk
, tmp
, tmp2
;
195 mp_prec_t prec
, realprec
;
196 unsigned long twopoweri
;
197 int comparaison
, inexact
, inexact2
;
199 MPFR_GROUP_DECL (group
);
200 MPFR_SAVE_EXPO_DECL (expo
);
201 MPFR_ZIV_DECL (loop
);
203 MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x
, x
, rnd_mode
),
204 ("atan[%#R]=%R inexact=%d", atan
, atan
, inexact
));
207 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x
)))
214 else if (MPFR_IS_INF (x
))
216 if (MPFR_IS_POS (x
)) /* arctan(+inf) = Pi/2 */
217 inexact
= mpfr_const_pi (atan
, rnd_mode
);
218 else /* arctan(-inf) = -Pi/2 */
220 inexact
= -mpfr_const_pi (atan
,
221 MPFR_INVERT_RND (rnd_mode
));
222 MPFR_CHANGE_SIGN (atan
);
224 inexact2
= mpfr_div_2ui (atan
, atan
, 1, rnd_mode
);
225 if (MPFR_UNLIKELY (inexact2
))
226 inexact
= inexact2
; /* An underflow occurs */
229 else /* x is necessarily 0 */
231 MPFR_ASSERTD (MPFR_IS_ZERO (x
));
232 MPFR_SET_ZERO (atan
);
233 MPFR_SET_SAME_SIGN (atan
, x
);
238 /* atan(x) = x - x^3/3 + x^5/5...
239 so the error is < 2^(3*EXP(x)-1)
240 so `EXP(x)-(3*EXP(x)-1)` = -2*EXP(x)+1 */
241 MPFR_FAST_COMPUTE_IF_SMALL_INPUT (atan
, x
, -2 * MPFR_GET_EXP (x
), 1, 0,
245 MPFR_TMP_INIT_ABS (xp
, x
);
247 /* Other simple case arctan(-+1)=-+pi/4 */
248 comparaison
= mpfr_cmp_ui (xp
, 1);
249 if (MPFR_UNLIKELY (comparaison
== 0))
251 int neg
= MPFR_IS_NEG (x
);
252 inexact
= mpfr_const_pi (atan
, MPFR_IS_POS (x
) ? rnd_mode
253 : MPFR_INVERT_RND (rnd_mode
));
257 MPFR_CHANGE_SIGN (atan
);
259 inexact2
= mpfr_div_2ui (atan
, atan
, 2, rnd_mode
);
260 if (MPFR_UNLIKELY (inexact2
))
261 inexact
= inexact2
; /* an underflow occurs */
265 realprec
= MPFR_PREC (atan
) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (atan
)) + 4;
266 prec
= realprec
+ BITS_PER_MP_LIMB
;
268 MPFR_SAVE_EXPO_MARK (expo
);
272 MPFR_GROUP_INIT_4 (group
, prec
, sk
, tmp
, tmp2
, arctgt
);
276 MPFR_ZIV_INIT (loop
, prec
);
279 /* First, if |x| < 1, we need to have more prec to be able to round (sup)
280 n0 = ceil(log(prec_requested + 2 + 1+ln(2.4)/ln(2))/log(2)) */
284 if (MPFR_GET_EXP (xp
) < 0
285 && (mpfr_uexp_t
) (2-MPFR_GET_EXP (xp
)) > realprec
)
286 sup
= (mpfr_uexp_t
) (2-MPFR_GET_EXP (xp
)) - realprec
;
288 sup
= MPFR_GET_EXP (xp
) < 0 ? 2-MPFR_GET_EXP (xp
) : 1;
290 n0
= MPFR_INT_CEIL_LOG2 ((realprec
+ sup
) + 3);
291 MPFR_ASSERTD (3*n0
> 2);
292 prec
= (realprec
+ sup
) + 1 + MPFR_INT_CEIL_LOG2 (3*n0
-2);
295 MPFR_GROUP_REPREC_4 (group
, prec
, sk
, tmp
, tmp2
, arctgt
);
296 if (MPFR_LIKELY (oldn0
== 0))
299 tabz
= (mpz_t
*) (*__gmp_allocate_func
) (oldn0
*sizeof (mpz_t
));
300 for (i
= 0; i
< oldn0
; i
++)
303 else if (MPFR_UNLIKELY (oldn0
< 3*n0
+1))
305 tabz
= (mpz_t
*) (*__gmp_reallocate_func
)
306 (tabz
, oldn0
*sizeof (mpz_t
), 3*(n0
+1)*sizeof (mpz_t
));
307 for (i
= oldn0
; i
< 3*(n0
+1); i
++)
313 mpfr_ui_div (sk
, 1, xp
, GMP_RNDN
);
315 mpfr_set (sk
, xp
, GMP_RNDN
);
317 /* sk is 1/|x| if |x| > 1, and |x| otherwise, i.e. min(|x|, 1/|x|) */
320 MPFR_SET_ZERO (arctgt
);
322 MPFR_ASSERTD (n0
>= 4);
323 /* FIXME: further reduce the argument so that it is less than
324 1/n where n is the output precision. In such a way, the
325 first calls to mpfr_atan_aux will not be too expensive,
326 since the number of needed terms will be n/log(n), so the
327 factorial contribution will be O(n). */
328 for (i
= 0 ; i
< n0
; i
++)
330 if (MPFR_UNLIKELY (MPFR_IS_ZERO (sk
)))
332 /* Calculation of trunc(tmp) --> mpz */
333 mpfr_mul_2ui (tmp
, sk
, twopoweri
, GMP_RNDN
);
334 mpfr_trunc (tmp
, tmp
);
335 if (!MPFR_IS_ZERO (tmp
))
337 exptol
= mpfr_get_z_exp (ukz
, tmp
);
338 /* since the s_k are decreasing (see algorithms.tex),
339 and s_0 = min(|x|, 1/|x|) < 1, we have sk < 1,
341 MPFR_ASSERTD (exptol
< 0);
342 mpz_tdiv_q_2exp (ukz
, ukz
, (unsigned long int) (-exptol
));
343 /* Calculation of arctan(Ak) */
344 mpfr_set_z (tmp
, ukz
, GMP_RNDN
);
345 mpfr_div_2ui (tmp
, tmp
, twopoweri
, GMP_RNDN
);
346 mpfr_atan_aux (tmp2
, ukz
, twopoweri
, n0
- i
, tabz
);
347 mpfr_mul (tmp2
, tmp2
, tmp
, GMP_RNDN
);
349 mpfr_add (arctgt
, arctgt
, tmp2
, GMP_RNDN
);
351 mpfr_sub (tmp2
, sk
, tmp
, GMP_RNDN
);
352 mpfr_mul (sk
, sk
, tmp
, GMP_RNDN
);
353 mpfr_add_ui (sk
, sk
, 1, GMP_RNDN
);
354 mpfr_div (sk
, tmp2
, sk
, GMP_RNDN
);
358 /* Add last step (Arctan(sk) ~= sk */
359 mpfr_add (arctgt
, arctgt
, sk
, GMP_RNDN
);
362 mpfr_const_pi (tmp
, GMP_RNDN
);
363 mpfr_div_2ui (tmp
, tmp
, 1, GMP_RNDN
);
364 mpfr_sub (arctgt
, tmp
, arctgt
, GMP_RNDN
);
366 MPFR_SET_POS (arctgt
);
368 if (MPFR_LIKELY (MPFR_CAN_ROUND (arctgt
, realprec
, MPFR_PREC (atan
),
371 MPFR_ZIV_NEXT (loop
, realprec
);
373 MPFR_ZIV_FREE (loop
);
375 inexact
= mpfr_set4 (atan
, arctgt
, rnd_mode
, MPFR_SIGN (x
));
377 for (i
= 0 ; i
< oldn0
; i
++)
380 (*__gmp_free_func
) (tabz
, oldn0
*sizeof (mpz_t
));
381 MPFR_GROUP_CLEAR (group
);
383 MPFR_SAVE_EXPO_FREE (expo
);
384 return mpfr_check_range (arctgt
, inexact
, rnd_mode
);