Actually hook powernow.4 into the build.
[dragonfly.git] / contrib / mpfr / acos.c
blob69e560f7eafd62b73c546c71f4da5df7a75ed780
1 /* mpfr_acos -- arc-cosinus 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 #include "mpfr-impl.h"
25 int
26 mpfr_acos (mpfr_ptr acos, mpfr_srcptr x, mp_rnd_t rnd_mode)
28 mpfr_t xp, arcc, tmp;
29 mp_exp_t supplement;
30 mp_prec_t prec;
31 int sign, compared, inexact;
32 MPFR_SAVE_EXPO_DECL (expo);
33 MPFR_ZIV_DECL (loop);
35 MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
36 ("acos[%#R]=%R inexact=%d", acos, acos, inexact));
38 /* Singular cases */
39 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
41 if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
43 MPFR_SET_NAN (acos);
44 MPFR_RET_NAN;
46 else /* necessarily x=0 */
48 MPFR_ASSERTD(MPFR_IS_ZERO(x));
49 /* acos(0)=Pi/2 */
50 inexact = mpfr_const_pi (acos, rnd_mode);
51 mpfr_div_2ui (acos, acos, 1, rnd_mode); /* exact */
52 MPFR_RET (inexact);
56 /* Set x_p=|x| */
57 sign = MPFR_SIGN (x);
58 mpfr_init2 (xp, MPFR_PREC (x));
59 mpfr_abs (xp, x, GMP_RNDN); /* Exact */
61 compared = mpfr_cmp_ui (xp, 1);
63 if (MPFR_UNLIKELY (compared >= 0))
65 mpfr_clear (xp);
66 if (compared > 0) /* acos(x) = NaN for x > 1 */
68 MPFR_SET_NAN(acos);
69 MPFR_RET_NAN;
71 else
73 if (MPFR_IS_POS_SIGN (sign)) /* acos(+1) = 0 */
74 return mpfr_set_ui (acos, 0, rnd_mode);
75 else /* acos(-1) = Pi */
76 return mpfr_const_pi (acos, rnd_mode);
80 MPFR_SAVE_EXPO_MARK (expo);
82 /* Compute the supplement */
83 mpfr_ui_sub (xp, 1, xp, GMP_RNDD);
84 if (MPFR_IS_POS_SIGN (sign))
85 supplement = 2 - 2 * MPFR_GET_EXP (xp);
86 else
87 supplement = 2 - MPFR_GET_EXP (xp);
88 mpfr_clear (xp);
90 prec = MPFR_PREC (acos) + 10 + supplement;
92 /* VL: The following change concerning prec comes from r3145
93 "Optimize mpfr_acos by choosing a better initial precision."
94 but it doesn't seem to be correct and leads to problems (assertion
95 failure or very important inefficiency) with tiny arguments.
96 Therefore, I've disabled it. */
97 /* If x ~ 2^-N, acos(x) ~ PI/2 - x - x^3/6
98 If Prec < 2*N, we can't round since x^3/6 won't be counted. */
99 #if 0
100 if (MPFR_PREC (acos) >= MPFR_PREC (x) && MPFR_GET_EXP (x) < 0)
102 mpfr_uexp_t pmin = (mpfr_uexp_t) (-2 * MPFR_GET_EXP (x)) + 5;
103 MPFR_ASSERTN (pmin <= MPFR_PREC_MAX);
104 if (prec < pmin)
105 prec = pmin;
107 #endif
109 mpfr_init2 (tmp, prec);
110 mpfr_init2 (arcc, prec);
112 MPFR_ZIV_INIT (loop, prec);
113 for (;;)
115 /* acos(x) = Pi/2 - asin(x) = Pi/2 - atan(x/sqrt(1-x^2)) */
116 mpfr_sqr (tmp, x, GMP_RNDN);
117 mpfr_ui_sub (tmp, 1, tmp, GMP_RNDN);
118 mpfr_sqrt (tmp, tmp, GMP_RNDN);
119 mpfr_div (tmp, x, tmp, GMP_RNDN);
120 mpfr_atan (arcc, tmp, GMP_RNDN);
121 mpfr_const_pi (tmp, GMP_RNDN);
122 mpfr_div_2ui (tmp, tmp, 1, GMP_RNDN);
123 mpfr_sub (arcc, tmp, arcc, GMP_RNDN);
125 if (MPFR_LIKELY (MPFR_CAN_ROUND (arcc, prec-supplement,
126 MPFR_PREC (acos), rnd_mode)))
127 break;
128 MPFR_ZIV_NEXT (loop, prec);
129 mpfr_set_prec (tmp, prec);
130 mpfr_set_prec (arcc, prec);
132 MPFR_ZIV_FREE (loop);
134 inexact = mpfr_set (acos, arcc, rnd_mode);
135 mpfr_clear (tmp);
136 mpfr_clear (arcc);
138 MPFR_SAVE_EXPO_FREE (expo);
139 return mpfr_check_range (acos, inexact, rnd_mode);