kernel - Reenable acpi sleep states
[dragonfly.git] / contrib / mpfr / pow_ui.c
blob67894da0e0f8ec96b10fc443ea514be67e640f3e
1 /* mpfr_pow_ui-- compute the power of a floating-point
2 by a machine integer
4 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
5 Contributed by the Arenaire and Cacao projects, INRIA.
7 This file is part of the GNU MPFR Library.
9 The GNU MPFR Library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or (at your
12 option) any later version.
14 The GNU MPFR Library is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with the GNU MPFR Library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
22 MA 02110-1301, USA. */
24 #define MPFR_NEED_LONGLONG_H
25 #include "mpfr-impl.h"
27 /* sets y to x^n, and return 0 if exact, non-zero otherwise */
28 int
29 mpfr_pow_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mp_rnd_t rnd)
31 unsigned long m;
32 mpfr_t res;
33 mp_prec_t prec, err;
34 int inexact;
35 mp_rnd_t rnd1;
36 MPFR_SAVE_EXPO_DECL (expo);
37 MPFR_ZIV_DECL (loop);
38 MPFR_BLOCK_DECL (flags);
40 MPFR_LOG_FUNC (("x[%#R]=%R n=%lu rnd=%d", x, x, n, rnd),
41 ("y[%#R]=%R inexact=%d", y, y, inexact));
43 /* x^0 = 1 for any x, even a NaN */
44 if (MPFR_UNLIKELY (n == 0))
45 return mpfr_set_ui (y, 1, rnd);
47 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
49 if (MPFR_IS_NAN (x))
51 MPFR_SET_NAN (y);
52 MPFR_RET_NAN;
54 else if (MPFR_IS_INF (x))
56 /* Inf^n = Inf, (-Inf)^n = Inf for n even, -Inf for n odd */
57 if (MPFR_IS_NEG (x) && (n & 1) == 1)
58 MPFR_SET_NEG (y);
59 else
60 MPFR_SET_POS (y);
61 MPFR_SET_INF (y);
62 MPFR_RET (0);
64 else /* x is zero */
66 MPFR_ASSERTD (MPFR_IS_ZERO (x));
67 /* 0^n = 0 for any n */
68 MPFR_SET_ZERO (y);
69 if (MPFR_IS_POS (x) || (n & 1) == 0)
70 MPFR_SET_POS (y);
71 else
72 MPFR_SET_NEG (y);
73 MPFR_RET (0);
76 else if (MPFR_UNLIKELY (n <= 2))
78 if (n < 2)
79 /* x^1 = x */
80 return mpfr_set (y, x, rnd);
81 else
82 /* x^2 = sqr(x) */
83 return mpfr_sqr (y, x, rnd);
86 /* Augment exponent range */
87 MPFR_SAVE_EXPO_MARK (expo);
89 /* setup initial precision */
90 prec = MPFR_PREC (y) + 3 + BITS_PER_MP_LIMB
91 + MPFR_INT_CEIL_LOG2 (MPFR_PREC (y));
92 mpfr_init2 (res, prec);
94 rnd1 = MPFR_IS_POS (x) ? GMP_RNDU : GMP_RNDD; /* away */
96 MPFR_ZIV_INIT (loop, prec);
97 for (;;)
99 int i;
101 for (m = n, i = 0; m; i++, m >>= 1)
103 /* now 2^(i-1) <= n < 2^i */
104 MPFR_ASSERTD (prec > (mpfr_prec_t) i);
105 err = prec - 1 - (mpfr_prec_t) i;
106 /* First step: compute square from x */
107 MPFR_BLOCK (flags,
108 inexact = mpfr_mul (res, x, x, GMP_RNDU);
109 MPFR_ASSERTD (i >= 2);
110 if (n & (1UL << (i-2)))
111 inexact |= mpfr_mul (res, res, x, rnd1);
112 for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--)
114 inexact |= mpfr_mul (res, res, res, GMP_RNDU);
115 if (n & (1UL << i))
116 inexact |= mpfr_mul (res, res, x, rnd1);
118 /* let r(n) be the number of roundings: we have r(2)=1, r(3)=2,
119 and r(2n)=2r(n)+1, r(2n+1)=2r(n)+2, thus r(n)=n-1.
120 Using Higham's method, to each rounding corresponds a factor
121 (1-theta) with 0 <= theta <= 2^(1-p), thus at the end the
122 absolute error is bounded by (n-1)*2^(1-p)*res <= 2*(n-1)*ulp(res)
123 since 2^(-p)*x <= ulp(x). Since n < 2^i, this gives a maximal
124 error of 2^(1+i)*ulp(res).
126 if (MPFR_LIKELY (inexact == 0
127 || MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags)
128 || MPFR_CAN_ROUND (res, err, MPFR_PREC (y), rnd)))
129 break;
130 /* Actualisation of the precision */
131 MPFR_ZIV_NEXT (loop, prec);
132 mpfr_set_prec (res, prec);
134 MPFR_ZIV_FREE (loop);
136 if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags) || MPFR_UNDERFLOW (flags)))
138 mpz_t z;
140 /* Internal overflow or underflow. However the approximation error has
141 * not been taken into account. So, let's solve this problem by using
142 * mpfr_pow_z, which can handle it. This case could be improved in the
143 * future, without having to use mpfr_pow_z.
145 MPFR_LOG_MSG (("Internal overflow or underflow,"
146 " let's use mpfr_pow_z.\n", 0));
147 mpfr_clear (res);
148 MPFR_SAVE_EXPO_FREE (expo);
149 mpz_init (z);
150 mpz_set_ui (z, n);
151 inexact = mpfr_pow_z (y, x, z, rnd);
152 mpz_clear (z);
153 return inexact;
156 inexact = mpfr_set (y, res, rnd);
157 mpfr_clear (res);
159 MPFR_SAVE_EXPO_FREE (expo);
160 return mpfr_check_range (y, inexact, rnd);