fixed odd read('*a') behaviour in Windows (A. Kakuto)
[luatex.git] / source / libs / mpfr / mpfr-3.1.2 / src / asin.c
blobe243dcd63ab48c4f7d3487fd08024cdd0a532b54
1 /* mpfr_asin -- arc-sinus of a floating-point number
3 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel 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 3 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.LESSER. If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23 #include "mpfr-impl.h"
25 int
26 mpfr_asin (mpfr_ptr asin, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
28 mpfr_t xp;
29 int compared, inexact;
30 mpfr_prec_t prec;
31 mpfr_exp_t xp_exp;
32 MPFR_SAVE_EXPO_DECL (expo);
33 MPFR_ZIV_DECL (loop);
35 MPFR_LOG_FUNC (
36 ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
37 ("asin[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (asin), mpfr_log_prec, asin,
38 inexact));
40 /* Special cases */
41 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
43 if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
45 MPFR_SET_NAN (asin);
46 MPFR_RET_NAN;
48 else /* x = 0 */
50 MPFR_ASSERTD (MPFR_IS_ZERO (x));
51 MPFR_SET_ZERO (asin);
52 MPFR_SET_SAME_SIGN (asin, x);
53 MPFR_RET (0); /* exact result */
57 /* asin(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
58 MPFR_FAST_COMPUTE_IF_SMALL_INPUT (asin, x, -2 * MPFR_GET_EXP (x), 2, 1,
59 rnd_mode, {});
61 /* Set x_p=|x| (x is a normal number) */
62 mpfr_init2 (xp, MPFR_PREC (x));
63 inexact = mpfr_abs (xp, x, MPFR_RNDN);
64 MPFR_ASSERTD (inexact == 0);
66 compared = mpfr_cmp_ui (xp, 1);
68 MPFR_SAVE_EXPO_MARK (expo);
70 if (MPFR_UNLIKELY (compared >= 0))
72 mpfr_clear (xp);
73 if (compared > 0) /* asin(x) = NaN for |x| > 1 */
75 MPFR_SAVE_EXPO_FREE (expo);
76 MPFR_SET_NAN (asin);
77 MPFR_RET_NAN;
79 else /* x = 1 or x = -1 */
81 if (MPFR_IS_POS (x)) /* asin(+1) = Pi/2 */
82 inexact = mpfr_const_pi (asin, rnd_mode);
83 else /* asin(-1) = -Pi/2 */
85 inexact = -mpfr_const_pi (asin, MPFR_INVERT_RND(rnd_mode));
86 MPFR_CHANGE_SIGN (asin);
88 mpfr_div_2ui (asin, asin, 1, rnd_mode);
91 else
93 /* Compute exponent of 1 - ABS(x) */
94 mpfr_ui_sub (xp, 1, xp, MPFR_RNDD);
95 MPFR_ASSERTD (MPFR_GET_EXP (xp) <= 0);
96 MPFR_ASSERTD (MPFR_GET_EXP (x) <= 0);
97 xp_exp = 2 - MPFR_GET_EXP (xp);
99 /* Set up initial prec */
100 prec = MPFR_PREC (asin) + 10 + xp_exp;
102 /* use asin(x) = atan(x/sqrt(1-x^2)) */
103 MPFR_ZIV_INIT (loop, prec);
104 for (;;)
106 mpfr_set_prec (xp, prec);
107 mpfr_sqr (xp, x, MPFR_RNDN);
108 mpfr_ui_sub (xp, 1, xp, MPFR_RNDN);
109 mpfr_sqrt (xp, xp, MPFR_RNDN);
110 mpfr_div (xp, x, xp, MPFR_RNDN);
111 mpfr_atan (xp, xp, MPFR_RNDN);
112 if (MPFR_LIKELY (MPFR_CAN_ROUND (xp, prec - xp_exp,
113 MPFR_PREC (asin), rnd_mode)))
114 break;
115 MPFR_ZIV_NEXT (loop, prec);
117 MPFR_ZIV_FREE (loop);
118 inexact = mpfr_set (asin, xp, rnd_mode);
120 mpfr_clear (xp);
123 MPFR_SAVE_EXPO_FREE (expo);
124 return mpfr_check_range (asin, inexact, rnd_mode);