Upgrade MPFR from 2.4.1 to 2.4.2-p3 on the vendor branch.
[dragonfly.git] / contrib / mpfr / sqr.c
1 /* mpfr_sqr -- Floating square
2
3 Copyright 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.
7
8 The GNU MPFR Library is free software; you can redistribute
9 it and/or modify it under the terms of the GNU Lesser
10 General Public License as published by the Free Software
11 Foundation; either version 2.1 of the License, or (at your
12 option) any later version.
13
14 The GNU MPFR Library is distributed in the hope that it will
15 be useful, but WITHOUT ANY WARRANTY; without even the
16 implied warranty of MERCHANTABILITY or FITNESS FOR A
17 PARTICULAR PURPOSE.  See the GNU Lesser General Public
18 License for more details.
19
20 You should have received a copy of the GNU Lesser
21 General Public License along with the GNU MPFR Library; see
22 the file COPYING.LIB.  If not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
24 MA 02110-1301, USA. */
25
26 #include "mpfr-impl.h"
27
28 int
29 mpfr_sqr (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode)
30 {
31   int cc, inexact;
32   mp_exp_t  ax;
33   mp_limb_t *tmp;
34   mp_limb_t b1;
35   mp_prec_t bq;
36   mp_size_t bn, tn;
37   MPFR_TMP_DECL(marker);
38
39   MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", b, b, rnd_mode),
40                  ("y[%#R]=%R inexact=%d", a, a, inexact));
41
42   /* deal with special cases */
43   if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(b)))
44     {
45       if (MPFR_IS_NAN(b))
46         {
47           MPFR_SET_NAN(a);
48           MPFR_RET_NAN;
49         }
50       MPFR_SET_POS (a);
51       if (MPFR_IS_INF(b))
52         MPFR_SET_INF(a);
53       else
54         ( MPFR_ASSERTD(MPFR_IS_ZERO(b)), MPFR_SET_ZERO(a) );
55       MPFR_RET(0);
56     }
57   MPFR_CLEAR_FLAGS(a);
58   ax = 2 * MPFR_GET_EXP (b);
59   bq = MPFR_PREC(b);
60
61   MPFR_ASSERTD (2 * bq > bq); /* PREC_MAX is /2 so no integer overflow */
62
63   bn = MPFR_LIMB_SIZE(b); /* number of limbs of b */
64   tn = 1 + (2 * bq - 1) / BITS_PER_MP_LIMB; /* number of limbs of square,
65                                                2*bn or 2*bn-1 */
66
67   MPFR_TMP_MARK(marker);
68   tmp = (mp_limb_t *) MPFR_TMP_ALLOC((size_t) 2 * bn * BYTES_PER_MP_LIMB);
69
70   /* Multiplies the mantissa in temporary allocated space */
71   mpn_sqr_n (tmp, MPFR_MANT(b), bn);
72   b1 = tmp[2 * bn - 1];
73
74   /* now tmp[0]..tmp[2*bn-1] contains the product of both mantissa,
75      with tmp[2*bn-1]>=2^(BITS_PER_MP_LIMB-2) */
76   b1 >>= BITS_PER_MP_LIMB - 1; /* msb from the product */
77
78   /* if the mantissas of b and c are uniformly distributed in ]1/2, 1],
79      then their product is in ]1/4, 1/2] with probability 2*ln(2)-1 ~ 0.386
80      and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */
81   tmp += 2 * bn - tn; /* +0 or +1 */
82   if (MPFR_UNLIKELY(b1 == 0))
83     mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */
84
85   cc = mpfr_round_raw (MPFR_MANT (a), tmp, 2 * bq, 0,
86                        MPFR_PREC (a), rnd_mode, &inexact);
87   /* cc = 1 ==> result is a power of two */
88   if (MPFR_UNLIKELY(cc))
89     MPFR_MANT(a)[MPFR_LIMB_SIZE(a)-1] = MPFR_LIMB_HIGHBIT;
90
91   MPFR_TMP_FREE(marker);
92   {
93     mp_exp_t ax2 = ax + (mp_exp_t) (b1 - 1 + cc);
94     if (MPFR_UNLIKELY( ax2 > __gmpfr_emax))
95       return mpfr_overflow (a, rnd_mode, MPFR_SIGN_POS);
96     if (MPFR_UNLIKELY( ax2 < __gmpfr_emin))
97       {
98         /* In the rounding to the nearest mode, if the exponent of the exact
99            result (i.e. before rounding, i.e. without taking cc into account)
100            is < __gmpfr_emin - 1 or the exact result is a power of 2 (i.e. if
101            both arguments are powers of 2), then round to zero. */
102         if (rnd_mode == GMP_RNDN &&
103             (ax + (mp_exp_t) b1 < __gmpfr_emin || mpfr_powerof2_raw (b)))
104           rnd_mode = GMP_RNDZ;
105         return mpfr_underflow (a, rnd_mode, MPFR_SIGN_POS);
106       }
107     MPFR_SET_EXP (a, ax2);
108     MPFR_SET_POS (a);
109   }
110   MPFR_RET (inexact);
111 }