Actually hook powernow.4 into the build.
[dragonfly.git] / contrib / mpfr / erfc.c
blob9fea237a2f5a7a6d5c530d9f68586f80a0a10a02
1 /* mpfr_erfc -- The Complementary Error Function of a floating-point number
3 Copyright 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.
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 /* erfc(x) = 1 - erf(x) */
28 /* Put in y an approximation of erfc(x) for large x, using formulae 7.1.23 and
29 7.1.24 from Abramowitz and Stegun.
30 Returns e such that the error is bounded by 2^e ulp(y),
31 or returns 0 in case of underflow.
33 static mp_exp_t
34 mpfr_erfc_asympt (mpfr_ptr y, mpfr_srcptr x)
36 mpfr_t t, xx, err;
37 unsigned long k;
38 mp_prec_t prec = MPFR_PREC(y);
39 mp_exp_t exp_err;
41 mpfr_init2 (t, prec);
42 mpfr_init2 (xx, prec);
43 mpfr_init2 (err, 31);
44 /* let u = 2^(1-p), and let us represent the error as (1+u)^err
45 with a bound for err */
46 mpfr_mul (xx, x, x, GMP_RNDD); /* err <= 1 */
47 mpfr_ui_div (xx, 1, xx, GMP_RNDU); /* upper bound for 1/(2x^2), err <= 2 */
48 mpfr_div_2ui (xx, xx, 1, GMP_RNDU); /* exact */
49 mpfr_set_ui (t, 1, GMP_RNDN); /* current term, exact */
50 mpfr_set (y, t, GMP_RNDN); /* current sum */
51 mpfr_set_ui (err, 0, GMP_RNDN);
52 for (k = 1; ; k++)
54 mpfr_mul_ui (t, t, 2 * k - 1, GMP_RNDU); /* err <= 4k-3 */
55 mpfr_mul (t, t, xx, GMP_RNDU); /* err <= 4k */
56 /* for -1 < x < 1, and |nx| < 1, we have |(1+x)^n| <= 1+7/4|nx|.
57 Indeed, for x>=0: log((1+x)^n) = n*log(1+x) <= n*x. Let y=n*x < 1,
58 then exp(y) <= 1+7/4*y.
59 For x<=0, let x=-x, we can prove by induction that (1-x)^n >= 1-n*x.*/
60 mpfr_mul_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), GMP_RNDU);
61 mpfr_add_ui (err, err, 14 * k, GMP_RNDU); /* 2^(1-p) * t <= 2 ulp(t) */
62 mpfr_div_2si (err, err, MPFR_GET_EXP (y) - MPFR_GET_EXP (t), GMP_RNDU);
63 if (MPFR_GET_EXP (t) + (mp_exp_t) prec <= MPFR_GET_EXP (y))
65 /* the truncation error is bounded by |t| < ulp(y) */
66 mpfr_add_ui (err, err, 1, GMP_RNDU);
67 break;
69 if (k & 1)
70 mpfr_sub (y, y, t, GMP_RNDN);
71 else
72 mpfr_add (y, y, t, GMP_RNDN);
74 /* the error on y is bounded by err*ulp(y) */
75 mpfr_mul (t, x, x, GMP_RNDU); /* rel. err <= 2^(1-p) */
76 mpfr_div_2ui (err, err, 3, GMP_RNDU); /* err/8 */
77 mpfr_add (err, err, t, GMP_RNDU); /* err/8 + xx */
78 mpfr_mul_2ui (err, err, 3, GMP_RNDU); /* err + 8*xx */
79 mpfr_exp (t, t, GMP_RNDU); /* err <= 1/2*ulp(t) + err(x*x)*t
80 <= 1/2*ulp(t)+2*|x*x|*ulp(t)
81 <= (2*|x*x|+1/2)*ulp(t) */
82 mpfr_mul (t, t, x, GMP_RNDN); /* err <= 1/2*ulp(t) + (4*|x*x|+1)*ulp(t)
83 <= (4*|x*x|+3/2)*ulp(t) */
84 mpfr_const_pi (xx, GMP_RNDZ); /* err <= ulp(Pi) */
85 mpfr_sqrt (xx, xx, GMP_RNDN); /* err <= 1/2*ulp(xx) + ulp(Pi)/2/sqrt(Pi)
86 <= 3/2*ulp(xx) */
87 mpfr_mul (t, t, xx, GMP_RNDN); /* err <= (8 |xx| + 13/2) * ulp(t) */
88 mpfr_div (y, y, t, GMP_RNDN); /* the relative error on input y is bounded
89 by (1+u)^err with u = 2^(1-p), that on
90 t is bounded by (1+u)^(8 |xx| + 13/2),
91 thus that on output y is bounded by
92 8 |xx| + 7 + err. */
94 if (MPFR_IS_ZERO(y))
96 /* If y is zero, most probably we have underflow. We check it directly
97 using the fact that erfc(x) <= exp(-x^2)/sqrt(Pi)/x for x >= 0.
98 We compute an upper approximation of exp(-x^2)/sqrt(Pi)/x.
100 mpfr_mul (t, x, x, GMP_RNDD); /* t <= x^2 */
101 mpfr_neg (t, t, GMP_RNDU); /* -x^2 <= t */
102 mpfr_exp (t, t, GMP_RNDU); /* exp(-x^2) <= t */
103 mpfr_const_pi (xx, GMP_RNDD); /* xx <= sqrt(Pi), cached */
104 mpfr_mul (xx, xx, x, GMP_RNDD); /* xx <= sqrt(Pi)*x */
105 mpfr_div (y, t, xx, GMP_RNDN); /* if y is zero, this means that the upper
106 approximation of exp(-x^2)/sqrt(Pi)/x
107 is nearer from 0 than from 2^(-emin-1),
108 thus we have underflow. */
109 exp_err = 0;
111 else
113 mpfr_add_ui (err, err, 7, GMP_RNDU);
114 exp_err = MPFR_GET_EXP (err);
117 mpfr_clear (t);
118 mpfr_clear (xx);
119 mpfr_clear (err);
120 return exp_err;
124 mpfr_erfc (mpfr_ptr y, mpfr_srcptr x, mp_rnd_t rnd)
126 int inex;
127 mpfr_t tmp;
128 mp_exp_t te, err;
129 mp_prec_t prec;
130 MPFR_SAVE_EXPO_DECL (expo);
131 MPFR_ZIV_DECL (loop);
133 MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd),
134 ("y[%#R]=%R inexact=%d", y, y, inex));
136 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
138 if (MPFR_IS_NAN (x))
140 MPFR_SET_NAN (y);
141 MPFR_RET_NAN;
143 /* erfc(+inf) = 0+, erfc(-inf) = 2 erfc (0) = 1 */
144 else if (MPFR_IS_INF (x))
145 return mpfr_set_ui (y, MPFR_IS_POS (x) ? 0 : 2, rnd);
146 else
147 return mpfr_set_ui (y, 1, rnd);
150 if (MPFR_SIGN (x) > 0)
152 /* for x >= 27282, erfc(x) < 2^(-2^30-1) */
153 if (mpfr_cmp_ui (x, 27282) >= 0)
154 return mpfr_underflow (y, (rnd == GMP_RNDN) ? GMP_RNDZ : rnd, 1);
157 if (MPFR_SIGN (x) < 0)
159 mp_exp_t e = MPFR_EXP(x);
160 /* For x < 0 going to -infinity, erfc(x) tends to 2 by below.
161 More precisely, we have 2 + 1/sqrt(Pi)/x/exp(x^2) < erfc(x) < 2.
162 Thus log2 |2 - erfc(x)| <= -log2|x| - x^2 / log(2).
163 If |2 - erfc(x)| < 2^(-PREC(y)) then the result is either 2 or
164 nextbelow(2).
165 For x <= -27282, -log2|x| - x^2 / log(2) <= -2^30.
167 if ((MPFR_PREC(y) <= 7 && e >= 2) || /* x <= -2 */
168 (MPFR_PREC(y) <= 25 && e >= 3) || /* x <= -4 */
169 (MPFR_PREC(y) <= 120 && mpfr_cmp_si (x, -9) <= 0) ||
170 mpfr_cmp_si (x, -27282) <= 0)
172 near_two:
173 mpfr_set_ui (y, 2, GMP_RNDN);
174 mpfr_set_inexflag ();
175 if (rnd == GMP_RNDZ || rnd == GMP_RNDD)
177 mpfr_nextbelow (y);
178 return -1;
180 else
181 return 1;
183 else if (e >= 3) /* more accurate test */
185 mpfr_t t, u;
186 int near_2;
187 mpfr_init2 (t, 32);
188 mpfr_init2 (u, 32);
189 /* the following is 1/log(2) rounded to zero on 32 bits */
190 mpfr_set_str_binary (t, "1.0111000101010100011101100101001");
191 mpfr_sqr (u, x, GMP_RNDZ);
192 mpfr_mul (t, t, u, GMP_RNDZ); /* t <= x^2/log(2) */
193 mpfr_neg (u, x, GMP_RNDZ); /* 0 <= u <= |x| */
194 mpfr_log2 (u, u, GMP_RNDZ); /* u <= log2(|x|) */
195 mpfr_add (t, t, u, GMP_RNDZ); /* t <= log2|x| + x^2 / log(2) */
196 near_2 = mpfr_cmp_ui (t, MPFR_PREC(y)) >= 0;
197 mpfr_clear (t);
198 mpfr_clear (u);
199 if (near_2)
200 goto near_two;
204 /* Init stuff */
205 MPFR_SAVE_EXPO_MARK (expo);
207 /* erfc(x) ~ 1, with error < 2^(EXP(x)+1) */
208 MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, __gmpfr_one, - MPFR_GET_EXP (x) - 1,
209 0, MPFR_SIGN(x) < 0,
210 rnd, inex = _inexact; goto end);
212 prec = MPFR_PREC (y) + MPFR_INT_CEIL_LOG2 (MPFR_PREC (y)) + 3;
213 if (MPFR_GET_EXP (x) > 0)
214 prec += 2 * MPFR_GET_EXP(x);
216 mpfr_init2 (tmp, prec);
218 MPFR_ZIV_INIT (loop, prec); /* Initialize the ZivLoop controler */
219 for (;;) /* Infinite loop */
221 /* use asymptotic formula only whenever x^2 >= p*log(2),
222 otherwise it will not converge */
223 if (MPFR_SIGN (x) > 0 &&
224 2 * MPFR_GET_EXP (x) - 2 >= MPFR_INT_CEIL_LOG2 (prec))
225 /* we have x^2 >= p in that case */
227 err = mpfr_erfc_asympt (tmp, x);
228 if (err == 0) /* underflow case */
230 mpfr_clear (tmp);
231 MPFR_SAVE_EXPO_FREE (expo);
232 return mpfr_underflow (y, (rnd == GMP_RNDN) ? GMP_RNDZ : rnd, 1);
235 else
237 mpfr_erf (tmp, x, GMP_RNDN);
238 MPFR_ASSERTD (!MPFR_IS_SINGULAR (tmp)); /* FIXME: 0 only for x=0 ? */
239 te = MPFR_GET_EXP (tmp);
240 mpfr_ui_sub (tmp, 1, tmp, GMP_RNDN);
241 /* See error analysis in algorithms.tex for details */
242 if (MPFR_IS_ZERO (tmp))
244 prec *= 2;
245 err = prec; /* ensures MPFR_CAN_ROUND fails */
247 else
248 err = MAX (te - MPFR_GET_EXP (tmp), 0) + 1;
250 if (MPFR_LIKELY (MPFR_CAN_ROUND (tmp, prec - err, MPFR_PREC (y), rnd)))
251 break;
252 MPFR_ZIV_NEXT (loop, prec); /* Increase used precision */
253 mpfr_set_prec (tmp, prec);
255 MPFR_ZIV_FREE (loop); /* Free the ZivLoop Controler */
257 inex = mpfr_set (y, tmp, rnd); /* Set y to the computed value */
258 mpfr_clear (tmp);
260 end:
261 MPFR_SAVE_EXPO_FREE (expo);
262 return mpfr_check_range (y, inex, rnd);