1 /* mpfr_ai -- Airy function Ai
2
3 Copyright 2010-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
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 3 of the License, or (at your
11 option) any later version.
12
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.
17
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.LESSER. If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
25
26 /* Reminder and notations:
27 -----------------------
28
29 Ai is the solution of:
30 / y'' - x*y = 0
31 { Ai(0) = 1/ ( 9^(1/3)*Gamma(2/3) )
32 \ Ai'(0) = -1/ ( 3^(1/3)*Gamma(1/3) )
33
34 Series development:
35 Ai(x) = sum (a_i*x^i)
36 = sum (t_i)
37
38 Recurrences:
39 a_(i+3) = a_i / ((i+2)*(i+3))
40 t_(i+3) = t_i * x^3 / ((i+2)*(i+3))
41
42 Values:
43 a_0 = Ai(0) ~ 0.355
44 a_1 = Ai'(0) ~ -0.259
45 */
46
47
48 /* Airy function Ai evaluated by the most naive algorithm.
49 Assume that x is a finite number. */
50 static int
mpfr_ai1(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd)51 mpfr_ai1 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
52 {
53 MPFR_ZIV_DECL (loop);
54 MPFR_SAVE_EXPO_DECL (expo);
55 mpfr_prec_t wprec; /* working precision */
56 mpfr_prec_t prec; /* target precision */
57 mpfr_prec_t err; /* used to estimate the evaluation error */
58 mpfr_prec_t correct_bits; /* estimates the number of correct bits*/
59 unsigned long int k;
60 unsigned long int cond; /* condition number of the series */
61 unsigned long int assumed_exponent; /* used as a lowerbound of |EXP(Ai(x))| */
62 int r;
63 mpfr_t s; /* used to store the partial sum */
64 mpfr_t ti, tip1; /* used to store successive values of t_i */
65 mpfr_t x3; /* used to store x^3 */
66 mpfr_t tmp_sp, tmp2_sp; /* small precision variables */
67 unsigned long int x3u; /* used to store ceil(x^3) */
68 mpfr_t temp1, temp2;
69 int test1, test2;
70
71 /* Logging */
72 MPFR_LOG_FUNC (
73 ("x[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd),
74 ("y[%Pd]=%.*Rg", mpfr_get_prec (y), mpfr_log_prec, y) );
75
76 /* Save current exponents range */
77 MPFR_SAVE_EXPO_MARK (expo);
78
79 if (MPFR_UNLIKELY (MPFR_IS_ZERO (x)))
80 {
81 mpfr_t y1, y2;
82 prec = MPFR_ADD_PREC (MPFR_PREC (y), 3);
83 mpfr_init2 (y1, prec);
84 mpfr_init2 (y2, prec);
85 MPFR_ZIV_INIT (loop, prec);
86
87 /* ZIV loop */
88 for (;;)
89 {
90 mpfr_gamma_one_and_two_third (y1, y2, prec); /* y2 = Gamma(2/3)(1 + delta1), |delta1| <= 2^{1-prec}. */
91
92 r = mpfr_set_ui (y1, 9, MPFR_RNDN);
93 MPFR_ASSERTD (r == 0);
94 mpfr_cbrt (y1, y1, MPFR_RNDN); /* y1 = cbrt(9)(1 + delta2), |delta2| <= 2^{-prec}. */
95 mpfr_mul (y1, y1, y2, MPFR_RNDN);
96 mpfr_ui_div (y1, 1, y1, MPFR_RNDN);
97 if (MPFR_LIKELY (MPFR_CAN_ROUND (y1, prec - 3, MPFR_PREC (y), rnd)))
98 break;
99 MPFR_ZIV_NEXT (loop, prec);
100 }
101 r = mpfr_set (y, y1, rnd);
102 MPFR_ZIV_FREE (loop);
103 MPFR_SAVE_EXPO_FREE (expo);
104 mpfr_clear (y1);
105 mpfr_clear (y2);
106 return mpfr_check_range (y, r, rnd);
107 }
108
109 /* now x is not zero */
110 MPFR_ASSERTD(!MPFR_IS_ZERO(x));
111
112 /* FIXME: underflow for large values of |x| ? */
113
114
115 /* Set initial precision */
116 /* If we compute sum(i=0, N-1, t_i), the relative error is bounded by */
117 /* 2*(4N)*2^(1-wprec)*C(|x|)/Ai(x) */
118 /* where C(|x|) = 1 if 0<=x<=1 */
119 /* and C(|x|) = (1/2)*x^(-1/4)*exp(2/3 x^(3/2)) if x >= 1 */
120
121 /* A priori, we do not know N, so we estimate it to ~ prec */
122 /* If 0<=x<=1, we estimate Ai(x) ~ 1/8 */
123 /* if 1<=x, we estimate Ai(x) ~ (1/4)*x^(-1/4)*exp(-2/3 * x^(3/2)) */
124 /* if x<=0, ????? */
125
126 /* We begin with 11 guard bits */
127 prec = MPFR_ADD_PREC (MPFR_PREC (y), 11);
128 MPFR_ZIV_INIT (loop, prec);
129
130 /* The working precision is heuristically chosen in order to obtain */
131 /* approximately prec correct bits in the sum. To sum up: the sum */
132 /* is stopped when the *exact* sum gives ~ prec correct bit. And */
133 /* when it is stopped, the accuracy of the computed sum, with respect*/
134 /* to the exact one should be ~prec bits. */
135 mpfr_init2 (tmp_sp, MPFR_SMALL_PRECISION);
136 mpfr_init2 (tmp2_sp, MPFR_SMALL_PRECISION);
137 mpfr_abs (tmp_sp, x, MPFR_RNDU);
138 mpfr_pow_ui (tmp_sp, tmp_sp, 3, MPFR_RNDU);
139 mpfr_sqrt (tmp_sp, tmp_sp, MPFR_RNDU); /* tmp_sp ~ |x|^(3/2) */
140
141 /* 0.96179669392597567 >~ 2/3 * log2(e). See algorithms.tex */
142 mpfr_set_str (tmp2_sp, "0.96179669392597567", 10, MPFR_RNDU);
143 mpfr_mul (tmp2_sp, tmp_sp, tmp2_sp, MPFR_RNDU);
144
145 /* cond represents the number of lost bits in the evaluation of the sum */
146 if (MPFR_GET_EXP (x) <= 0)
147 cond = 0;
148 else
149 {
150 MPFR_BLOCK_DECL (flags);
151
152 MPFR_BLOCK (flags, cond = mpfr_get_ui (tmp2_sp, MPFR_RNDU));
153 MPFR_ASSERTN (! MPFR_ERANGEFLAG (flags));
154 cond -= (MPFR_GET_EXP (x) - 1) / 4 + 1;
155 }
156
157 /* The variable assumed_exponent is used to store the maximal assumed */
158 /* exponent of Ai(x). More precisely, we assume that |Ai(x)| will be */
159 /* greater than 2^{-assumed_exponent}. */
160 if (MPFR_IS_POS (x))
161 {
162 if (MPFR_GET_EXP (x) <= 0)
163 assumed_exponent = 3;
164 else
165 {
166 unsigned long int t;
167 MPFR_BLOCK_DECL (flags);
168
169 MPFR_BLOCK (flags, t = mpfr_get_ui (tmp2_sp, MPFR_RNDU));
170 MPFR_ASSERTN (! MPFR_ERANGEFLAG (flags));
171 assumed_exponent = t + 2 + (MPFR_GET_EXP (x) / 4 + 1);
172 MPFR_ASSERTN (assumed_exponent > t);
173 }
174 }
175 /* We do not know Ai (x) yet */
176 /* We cover the case when EXP (Ai (x))>=-10 */
177 else
178 assumed_exponent = 10;
179
180 {
181 unsigned long int t, u;
182
183 t = assumed_exponent + cond;
184 MPFR_ASSERTN (t >= cond);
185 u = MPFR_INT_CEIL_LOG2 (prec) + 5;
186 t += u;
187 MPFR_ASSERTN (t >= u);
188 wprec = MPFR_ADD_PREC (prec, t);
189 }
190
191 mpfr_init2 (ti, wprec);
192 mpfr_init2 (tip1, wprec);
193 mpfr_init2 (temp1, wprec);
194 mpfr_init2 (temp2, wprec);
195 mpfr_init2 (x3, wprec);
196 mpfr_init2 (s, wprec);
197
198 /* ZIV loop */
199 for (;;)
200 {
201 MPFR_LOG_MSG (("Working precision: %Pd\n", wprec));
202 mpfr_set_prec (ti, wprec);
203 mpfr_set_prec (tip1, wprec);
204 mpfr_set_prec (x3, wprec);
205 mpfr_set_prec (s, wprec);
206
207 mpfr_sqr (x3, x, MPFR_RNDU);
208 mpfr_mul (x3, x3, x, (MPFR_IS_POS (x)?MPFR_RNDU:MPFR_RNDD)); /* x3=x^3 */
209 if (MPFR_IS_NEG (x))
210 MPFR_CHANGE_SIGN (x3);
211 x3u = mpfr_get_ui (x3, MPFR_RNDU); /* x3u >= ceil(x^3) */
212 if (MPFR_IS_NEG (x))
213 MPFR_CHANGE_SIGN (x3);
214
215 mpfr_gamma_one_and_two_third (temp1, temp2, wprec);
216 mpfr_set_ui (ti, 9, MPFR_RNDN);
217 mpfr_cbrt (ti, ti, MPFR_RNDN);
218 mpfr_mul (ti, ti, temp2, MPFR_RNDN);
219 mpfr_ui_div (ti, 1, ti, MPFR_RNDN); /* ti = 1/( Gamma (2/3)*9^(1/3) ) */
220
221 mpfr_set_ui (tip1, 3, MPFR_RNDN);
222 mpfr_cbrt (tip1, tip1, MPFR_RNDN);
223 mpfr_mul (tip1, tip1, temp1, MPFR_RNDN);
224 mpfr_neg (tip1, tip1, MPFR_RNDN);
225 mpfr_div (tip1, x, tip1, MPFR_RNDN); /* tip1 = -x/(Gamma (1/3)*3^(1/3)) */
226
227 mpfr_add (s, ti, tip1, MPFR_RNDN);
228
229
230 /* Evaluation of the series */
231 k = 2;
232 for (;;)
233 {
234 mpfr_mul (ti, ti, x3, MPFR_RNDN);
235 mpfr_mul (tip1, tip1, x3, MPFR_RNDN);
236
237 mpfr_div_ui2 (ti, ti, k, (k+1), MPFR_RNDN);
238 mpfr_div_ui2 (tip1, tip1, (k+1), (k+2), MPFR_RNDN);
239
240 k += 3;
241 mpfr_add (s, s, ti, MPFR_RNDN);
242 mpfr_add (s, s, tip1, MPFR_RNDN);
243
244 /* FIXME: if s==0 */
245 test1 = MPFR_IS_ZERO (ti)
246 || (MPFR_GET_EXP (ti) + (mpfr_exp_t)prec + 3 <= MPFR_GET_EXP (s));
247 test2 = MPFR_IS_ZERO (tip1)
248 || (MPFR_GET_EXP (tip1) + (mpfr_exp_t)prec + 3 <= MPFR_GET_EXP (s));
249
250 if ( test1 && test2 && (x3u <= k*(k+1)/2) )
251 break; /* FIXME: if k*(k+1) overflows */
252 }
253
254 MPFR_LOG_MSG (("Truncation rank: %lu\n", k));
255
256 err = 4 + MPFR_INT_CEIL_LOG2 (k) + cond - MPFR_GET_EXP (s);
257
258 /* err is the number of bits lost due to the evaluation error */
259 /* wprec-(prec+1): number of bits lost due to the approximation error */
260 MPFR_LOG_MSG (("Roundoff error: %Pd\n", err));
261 MPFR_LOG_MSG (("Approxim error: %Pd\n", wprec-prec-1));
262
263 if (wprec < err + 1)
264 correct_bits = 0;
265 else if (wprec < err + prec +1)
266 correct_bits = wprec - err - 1; /* since wprec > err + 1,
267 correct_bits > 0 */
268 else
269 correct_bits = prec;
270
271 if (MPFR_LIKELY (MPFR_CAN_ROUND (s, correct_bits, MPFR_PREC (y), rnd)))
272 break;
273
274 if (correct_bits == 0)
275 {
276 assumed_exponent *= 2;
277 MPFR_LOG_MSG (("Not a single bit correct (assumed_exponent=%lu)\n",
278 assumed_exponent));
279 wprec = prec + 5 + MPFR_INT_CEIL_LOG2 (prec) + cond +
280 assumed_exponent;
281 }
282 else if (correct_bits < prec)
283 { /* The precision was badly chosen */
284 MPFR_LOG_MSG (("Bad assumption on the exponent of Ai(x)"
285 " (E=%" MPFR_EXP_FSPEC "d)\n",
286 (mpfr_eexp_t) MPFR_GET_EXP (s)));
287 wprec = prec + err + 1;
288 }
289 else
290 { /* We are really in a bad case of the TMD */
291 MPFR_ZIV_NEXT (loop, prec);
292
293 /* We update wprec */
294 /* We assume that K will not be multiplied by more than 4 */
295 wprec = prec + (MPFR_INT_CEIL_LOG2 (k) + 2) + 5 + cond
296 - MPFR_GET_EXP (s);
297 }
298
299 } /* End of ZIV loop */
300
301 MPFR_ZIV_FREE (loop);
302
303 r = mpfr_set (y, s, rnd);
304
305 mpfr_clear (ti);
306 mpfr_clear (tip1);
307 mpfr_clear (temp1);
308 mpfr_clear (temp2);
309 mpfr_clear (x3);
310 mpfr_clear (s);
311 mpfr_clear (tmp_sp);
312 mpfr_clear (tmp2_sp);
313
314 MPFR_SAVE_EXPO_FREE (expo);
315 return mpfr_check_range (y, r, rnd);
316 }
317
318
319 /* Airy function Ai evaluated by Smith algorithm.
320 Assume that x is a finite non-zero number. */
321 static int
mpfr_ai2(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd)322 mpfr_ai2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
323 {
324 MPFR_ZIV_DECL (loop);
325 MPFR_SAVE_EXPO_DECL (expo);
326 mpfr_prec_t wprec; /* working precision */
327 mpfr_prec_t prec; /* target precision */
328 mpfr_prec_t err; /* used to estimate the evaluation error */
329 mpfr_prec_t correctBits; /* estimates the number of correct bits*/
330 unsigned long int i, j, L, t;
331 unsigned long int cond; /* condition number of the series */
332 unsigned long int assumed_exponent; /* used as a lowerbound of |EXP(Ai(x))| */
333 int r; /* returned ternary value */
334 mpfr_t s; /* used to store the partial sum */
335 mpfr_t u0, u1;
336 mpfr_t *z; /* used to store the (x^3j) */
337 mpfr_t result;
338 mpfr_t tmp_sp, tmp2_sp; /* small precision variables */
339 unsigned long int x3u; /* used to store ceil (x^3) */
340 mpfr_t temp1, temp2;
341 int test0, test1;
342
343 /* Logging */
344 MPFR_LOG_FUNC (
345 ("x[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd),
346 ("y[%Pd]=%.*Rg", mpfr_get_prec (y), mpfr_log_prec, y));
347
348 /* Save current exponents range */
349 MPFR_SAVE_EXPO_MARK (expo);
350
351 /* FIXME: underflow for large values of |x| */
352
353 /* Set initial precision */
354 /* See the analysis for the naive evaluation */
355
356 /* We begin with 11 guard bits */
357 prec = MPFR_PREC (y) + 11;
358 MPFR_ZIV_INIT (loop, prec);
359
360 mpfr_init2 (tmp_sp, MPFR_SMALL_PRECISION);
361 mpfr_init2 (tmp2_sp, MPFR_SMALL_PRECISION);
362 mpfr_abs (tmp_sp, x, MPFR_RNDU);
363 mpfr_pow_ui (tmp_sp, tmp_sp, 3, MPFR_RNDU);
364 mpfr_sqrt (tmp_sp, tmp_sp, MPFR_RNDU); /* tmp_sp ~ |x|^(3/2) */
365
366 /* 0.96179669392597567 >~ 2/3 * log2(e). See algorithms.tex */
367 mpfr_set_str (tmp2_sp, "0.96179669392597567", 10, MPFR_RNDU);
368 mpfr_mul (tmp2_sp, tmp_sp, tmp2_sp, MPFR_RNDU);
369
370 /* cond represents the number of lost bits in the evaluation of the sum */
371 if (MPFR_GET_EXP (x) <= 0)
372 cond = 0;
373 else
374 {
375 MPFR_BLOCK_DECL (flags);
376
377 MPFR_BLOCK (flags, cond = mpfr_get_ui (tmp2_sp, MPFR_RNDU));
378 MPFR_ASSERTN (! MPFR_ERANGEFLAG (flags));
379 cond -= (MPFR_GET_EXP (x) - 1) / 4 + 1;
380 }
381
382 /* This variable is used to store the maximal assumed exponent of */
383 /* Ai(x). More precisely, we assume that |Ai(x)| will be greater than */
384 /* 2^{-assumed_exponent}. */
385 if (MPFR_IS_POS (x))
386 {
387 if (MPFR_GET_EXP (x) <= 0)
388 assumed_exponent = 3;
389 else
390 {
391 unsigned long int t;
392 MPFR_BLOCK_DECL (flags);
393
394 MPFR_BLOCK (flags, t = mpfr_get_ui (tmp2_sp, MPFR_RNDU));
395 MPFR_ASSERTN (! MPFR_ERANGEFLAG (flags));
396 assumed_exponent = t + 2 + (MPFR_GET_EXP (x) / 4 + 1);
397 MPFR_ASSERTN (assumed_exponent > t);
398 }
399 }
400 /* We do not know Ai(x) yet */
401 /* We cover the case when EXP(Ai(x))>=-10 */
402 else
403 assumed_exponent = 10;
404
405 {
406 unsigned long int t, u;
407
408 t = assumed_exponent + cond;
409 MPFR_ASSERTN (t >= cond);
410 u = MPFR_INT_CEIL_LOG2 (prec) + 6;
411 t += u;
412 MPFR_ASSERTN (t >= u);
413 wprec = MPFR_ADD_PREC (prec, t);
414 }
415
416 /* We assume that the truncation rank will be ~ prec */
417 L = __gmpfr_isqrt (prec);
418 MPFR_LOG_MSG (("size of blocks L = %lu\n", L));
419
420 z = (mpfr_t *) mpfr_allocate_func ( (L + 1) * sizeof (mpfr_t) );
421 MPFR_ASSERTN (z != NULL);
422 for (j=0; j<=L; j++)
423 mpfr_init2 (z[j], wprec);
424
425 mpfr_init2 (s, wprec);
426 mpfr_init2 (u0, wprec); mpfr_init2 (u1, wprec);
427 mpfr_init2 (result, wprec);
428 mpfr_init2 (temp1, wprec);
429 mpfr_init2 (temp2, wprec);
430
431 /* ZIV loop */
432 for (;;)
433 {
434 MPFR_LOG_MSG (("working precision: %Pd\n", wprec));
435
436 for (j=0; j<=L; j++)
437 mpfr_set_prec (z[j], wprec);
438 mpfr_set_prec (s, wprec);
439 mpfr_set_prec (u0, wprec); mpfr_set_prec (u1, wprec);
440 mpfr_set_prec (result, wprec);
441
442 mpfr_set_ui (u0, 1, MPFR_RNDN);
443 mpfr_set (u1, x, MPFR_RNDN);
444
445 mpfr_set_ui (z[0], 1, MPFR_RNDU);
446 mpfr_sqr (z[1], u1, MPFR_RNDU);
447 mpfr_mul (z[1], z[1], x, (MPFR_IS_POS (x) ? MPFR_RNDU : MPFR_RNDD) );
448
449 if (MPFR_IS_NEG (x))
450 MPFR_CHANGE_SIGN (z[1]);
451 x3u = mpfr_get_ui (z[1], MPFR_RNDU); /* x3u >= ceil (x^3) */
452 if (MPFR_IS_NEG (x))
453 MPFR_CHANGE_SIGN (z[1]);
454
455 for (j=2; j<=L ;j++)
456 {
457 if (j%2 == 0)
458 mpfr_sqr (z[j], z[j/2], MPFR_RNDN);
459 else
460 mpfr_mul (z[j], z[j-1], z[1], MPFR_RNDN);
461 }
462
463 mpfr_gamma_one_and_two_third (temp1, temp2, wprec);
464 mpfr_set_ui (u0, 9, MPFR_RNDN);
465 mpfr_cbrt (u0, u0, MPFR_RNDN);
466 mpfr_mul (u0, u0, temp2, MPFR_RNDN);
467 mpfr_ui_div (u0, 1, u0, MPFR_RNDN); /* u0 = 1/( Gamma (2/3)*9^(1/3) ) */
468
469 mpfr_set_ui (u1, 3, MPFR_RNDN);
470 mpfr_cbrt (u1, u1, MPFR_RNDN);
471 mpfr_mul (u1, u1, temp1, MPFR_RNDN);
472 mpfr_neg (u1, u1, MPFR_RNDN);
473 mpfr_div (u1, x, u1, MPFR_RNDN); /* u1 = -x/(Gamma (1/3)*3^(1/3)) */
474
475 mpfr_set_ui (result, 0, MPFR_RNDN);
476 t = 0;
477
478 /* Evaluation of the series by Smith' method */
479 for (i=0; ; i++)
480 {
481 t += 3 * L;
482
483 /* k = 0 */
484 t -= 3;
485 mpfr_set (s, z[L-1], MPFR_RNDN);
486 for (j=L-2; ; j--)
487 {
488 t -= 3;
489 mpfr_div_ui2 (s, s, (t+2), (t+3), MPFR_RNDN);
490 mpfr_add (s, s, z[j], MPFR_RNDN);
491 if (j==0)
492 break;
493 }
494 mpfr_mul (s, s, u0, MPFR_RNDN);
495 mpfr_add (result, result, s, MPFR_RNDN);
496
497 mpfr_mul (u0, u0, z[L], MPFR_RNDN);
498 for (j=0; j<=L-1; j++)
499 {
500 mpfr_div_ui2 (u0, u0, (t + 2), (t + 3), MPFR_RNDN);
501 t += 3;
502 }
503
504 t++;
505
506 /* k = 1 */
507 t -= 3;
508 mpfr_set (s, z[L-1], MPFR_RNDN);
509 for (j=L-2; ; j--)
510 {
511 t -= 3;
512 mpfr_div_ui2 (s, s, (t + 2), (t + 3), MPFR_RNDN);
513 mpfr_add (s, s, z[j], MPFR_RNDN);
514 if (j==0)
515 break;
516 }
517 mpfr_mul (s, s, u1, MPFR_RNDN);
518 mpfr_add (result, result, s, MPFR_RNDN);
519
520 mpfr_mul (u1, u1, z[L], MPFR_RNDN);
521 for (j=0; j<=L-1; j++)
522 {
523 mpfr_div_ui2 (u1, u1, (t + 2), (t + 3), MPFR_RNDN);
524 t += 3;
525 }
526
527 t++;
528
529 /* k = 2 */
530 t++;
531
532 /* End of the loop over k */
533 t -= 3;
534
535 test0 = MPFR_IS_ZERO (u0) ||
536 MPFR_GET_EXP (u0) + (mpfr_exp_t)prec + 4 <= MPFR_GET_EXP (result);
537 test1 = MPFR_IS_ZERO (u1) ||
538 MPFR_GET_EXP (u1) + (mpfr_exp_t)prec + 4 <= MPFR_GET_EXP (result);
539
540 if ( test0 && test1 && (x3u <= (t + 2) * (t + 3) / 2) )
541 break;
542 }
543
544 MPFR_LOG_MSG (("Truncation rank: %lu\n", t));
545
546 err = (5 + MPFR_INT_CEIL_LOG2 (L+1) + MPFR_INT_CEIL_LOG2 (i+1)
547 + cond - MPFR_GET_EXP (result));
548
549 /* err is the number of bits lost due to the evaluation error */
550 /* wprec-(prec+1): number of bits lost due to the approximation error */
551 MPFR_LOG_MSG (("Roundoff error: %Pd\n", err));
552 MPFR_LOG_MSG (("Approxim error: %Pd\n", wprec - prec - 1));
553
554 if (wprec < err+1)
555 correctBits = 0;
556 else
557 {
558 if (wprec < err+prec+1)
559 correctBits = wprec - err - 1;
560 else
561 correctBits = prec;
562 }
563
564 if (MPFR_LIKELY (MPFR_CAN_ROUND (result, correctBits,
565 MPFR_PREC (y), rnd)))
566 break;
567
568 for (j=0; j<=L; j++)
569 mpfr_clear (z[j]);
570 mpfr_free_func (z, (L + 1) * sizeof (mpfr_t));
571 L = __gmpfr_isqrt (t);
572 MPFR_LOG_MSG (("size of blocks L = %lu\n", L));
573 z = (mpfr_t *) mpfr_allocate_func ( (L + 1) * sizeof (mpfr_t));
574 MPFR_ASSERTN (z != NULL);
575 for (j=0; j<=L; j++)
576 mpfr_init2 (z[j], wprec);
577
578 if (correctBits == 0)
579 {
580 assumed_exponent *= 2;
581 MPFR_LOG_MSG (("Not a single bit correct (assumed_exponent=%lu)\n",
582 assumed_exponent));
583 wprec = prec + 6 + MPFR_INT_CEIL_LOG2 (t) + cond + assumed_exponent;
584 }
585 else
586 {
587 if (correctBits < prec)
588 { /* The precision was badly chosen */
589 MPFR_LOG_MSG (("Bad assumption on the exponent of Ai(x)"
590 " (E=%" MPFR_EXP_FSPEC "d)\n",
591 (mpfr_eexp_t) MPFR_GET_EXP (result)));
592 wprec = prec + err + 1;
593 }
594 else
595 { /* We are really in a bad case of the TMD */
596 MPFR_ZIV_NEXT (loop, prec);
597
598 /* We update wprec */
599 /* We assume that t will not be multiplied by more than 4 */
600 wprec = (prec + (MPFR_INT_CEIL_LOG2 (t) + 2) + 6 + cond
601 - MPFR_GET_EXP (result));
602 }
603 }
604 } /* End of ZIV loop */
605
606 MPFR_ZIV_FREE (loop);
607
608 r = mpfr_set (y, result, rnd);
609
610 mpfr_clear (tmp_sp);
611 mpfr_clear (tmp2_sp);
612 for (j=0; j<=L; j++)
613 mpfr_clear (z[j]);
614 mpfr_free_func (z, (L + 1) * sizeof (mpfr_t));
615
616 mpfr_clear (s);
617 mpfr_clear (u0); mpfr_clear (u1);
618 mpfr_clear (result);
619 mpfr_clear (temp1);
620 mpfr_clear (temp2);
621
622 MPFR_SAVE_EXPO_FREE (expo);
623 return mpfr_check_range (y, r, rnd);
624 }
625
626 /* We consider that the boundary between the area where the naive method
627 should preferably be used and the area where Smith' method should preferably
628 be used has the following form:
629 it is a triangle defined by two lines (one for the negative values of x, and
630 one for the positive values of x) crossing at x=0.
631
632 More precisely,
633
634 * If x<0 and MPFR_AI_THRESHOLD1*x + MPFR_AI_THRESHOLD2*prec > MPFR_AI_SCALE,
635 use Smith' algorithm;
636 * If x>0 and MPFR_AI_THRESHOLD3*x + MPFR_AI_THRESHOLD2*prec > MPFR_AI_SCALE,
637 use Smith' algorithm;
638 * otherwise, use the naive method.
639 */
640
641 #define MPFR_AI_SCALE 1048576
642
643 int
mpfr_ai(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t rnd)644 mpfr_ai (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd)
645 {
646 mpfr_t temp1, temp2;
647 int use_ai2;
648 MPFR_SAVE_EXPO_DECL (expo);
649
650 /* Special cases */
651 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
652 {
653 if (MPFR_IS_NAN (x))
654 {
655 MPFR_SET_NAN (y);
656 MPFR_RET_NAN;
657 }
658 else if (MPFR_IS_INF (x))
659 return mpfr_set_ui (y, 0, rnd);
660 /* the cases x = +0 or -0 will be treated below */
661 }
662
663 /* The exponent range must be large enough for the computation of temp1. */
664 MPFR_SAVE_EXPO_MARK (expo);
665
666 mpfr_init2 (temp1, MPFR_SMALL_PRECISION);
667 mpfr_init2 (temp2, MPFR_SMALL_PRECISION);
668
669 mpfr_set (temp1, x, MPFR_RNDN);
670 mpfr_set_si (temp2, MPFR_AI_THRESHOLD2, MPFR_RNDN);
671 mpfr_mul_ui (temp2, temp2, MPFR_PREC (y) > ULONG_MAX ?
672 ULONG_MAX : (unsigned long) MPFR_PREC (y), MPFR_RNDN);
673
674 if (MPFR_IS_NEG (x))
675 mpfr_mul_si (temp1, temp1, MPFR_AI_THRESHOLD1, MPFR_RNDN);
676 else
677 mpfr_mul_si (temp1, temp1, MPFR_AI_THRESHOLD3, MPFR_RNDN);
678
679 mpfr_add (temp1, temp1, temp2, MPFR_RNDN);
680 mpfr_clear (temp2);
681
682 use_ai2 = mpfr_cmp_si (temp1, MPFR_AI_SCALE) > 0;
683 mpfr_clear (temp1);
684
685 MPFR_SAVE_EXPO_FREE (expo); /* Ignore all previous exceptions. */
686
687 /* we use ai2 if |x|*AI_THRESHOLD1/3 + PREC(y)*AI_THRESHOLD2 > AI_SCALE,
688 which means x cannot be zero in mpfr_ai2 */
689 return use_ai2 ? mpfr_ai2 (y, x, rnd) : mpfr_ai1 (y, x, rnd);
690 }
691