Add APIC_ID to extract apic id from local apic id field
[dragonfly.git] / contrib / mpfr / asin.c
1 /* mpfr_asin -- arc-sinus of a floating-point number
2
3 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 Contributed by the Arenaire and Cacao projects, INRIA.
5
6 This file is part of the GNU MPFR Library, and was contributed by Mathieu Dutour.
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 2.1 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.LIB.  If not, write to
20 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #include "mpfr-impl.h"
24
25 int
26 mpfr_asin (mpfr_ptr asin, mpfr_srcptr x, mp_rnd_t rnd_mode)
27 {
28   mpfr_t xp;
29   int compared, inexact;
30   mp_prec_t prec;
31   mp_exp_t xp_exp;
32   MPFR_SAVE_EXPO_DECL (expo);
33   MPFR_ZIV_DECL (loop);
34
35   MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
36                  ("asin[%#R]=%R inexact=%d", asin, asin, inexact));
37
38   /* Special cases */
39   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
40     {
41       if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
42         {
43           MPFR_SET_NAN (asin);
44           MPFR_RET_NAN;
45         }
46       else /* x = 0 */
47         {
48           MPFR_ASSERTD (MPFR_IS_ZERO (x));
49           MPFR_SET_ZERO (asin);
50           MPFR_SET_SAME_SIGN (asin, x);
51           MPFR_RET (0); /* exact result */
52         }
53     }
54
55   /* asin(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
56   MPFR_FAST_COMPUTE_IF_SMALL_INPUT (asin, x, -2 * MPFR_GET_EXP (x), 2, 1,
57                                     rnd_mode, {});
58
59   /* Set x_p=|x| (x is a normal number) */
60   mpfr_init2 (xp, MPFR_PREC (x));
61   inexact = mpfr_abs (xp, x, GMP_RNDN);
62   MPFR_ASSERTD (inexact == 0);
63
64   compared = mpfr_cmp_ui (xp, 1);
65
66   if (MPFR_UNLIKELY (compared >= 0))
67     {
68       mpfr_clear (xp);
69       if (compared > 0)                  /* asin(x) = NaN for |x| > 1 */
70         {
71           MPFR_SET_NAN (asin);
72           MPFR_RET_NAN;
73         }
74       else                              /* x = 1 or x = -1 */
75         {
76           if (MPFR_IS_POS (x)) /* asin(+1) = Pi/2 */
77             inexact = mpfr_const_pi (asin, rnd_mode);
78           else /* asin(-1) = -Pi/2 */
79             {
80               inexact = -mpfr_const_pi (asin, MPFR_INVERT_RND(rnd_mode));
81               MPFR_CHANGE_SIGN (asin);
82             }
83           mpfr_div_2ui (asin, asin, 1, rnd_mode); /* May underflow */
84           return inexact;
85         }
86     }
87
88   MPFR_SAVE_EXPO_MARK (expo);
89
90   /* Compute exponent of 1 - ABS(x) */
91   mpfr_ui_sub (xp, 1, xp, GMP_RNDD);
92   MPFR_ASSERTD (MPFR_GET_EXP (xp) <= 0);
93   MPFR_ASSERTD (MPFR_GET_EXP (x) <= 0);
94   xp_exp = 2 - MPFR_GET_EXP (xp);
95
96   /* Set up initial prec */
97   prec = MPFR_PREC (asin) + 10 + xp_exp;
98
99   /* use asin(x) = atan(x/sqrt(1-x^2)) */
100   MPFR_ZIV_INIT (loop, prec);
101   for (;;)
102     {
103       mpfr_set_prec (xp, prec);
104       mpfr_sqr (xp, x, GMP_RNDN);
105       mpfr_ui_sub (xp, 1, xp, GMP_RNDN);
106       mpfr_sqrt (xp, xp, GMP_RNDN);
107       mpfr_div (xp, x, xp, GMP_RNDN);
108       mpfr_atan (xp, xp, GMP_RNDN);
109       if (MPFR_LIKELY (MPFR_CAN_ROUND (xp, prec - xp_exp,
110                                        MPFR_PREC (asin), rnd_mode)))
111         break;
112       MPFR_ZIV_NEXT (loop, prec);
113     }
114   MPFR_ZIV_FREE (loop);
115   inexact = mpfr_set (asin, xp, rnd_mode);
116
117   mpfr_clear (xp);
118
119   MPFR_SAVE_EXPO_FREE (expo);
120   return mpfr_check_range (asin, inexact, rnd_mode);
121 }