1
/* mpfr_mul -- multiply two floating-point numbers
3
Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
5
This file is part of the MPFR Library.
7
The MPFR Library is free software; you can redistribute it and/or modify
8
it under the terms of the GNU Lesser General Public License as published by
9
the Free Software Foundation; either version 2.1 of the License, or (at your
10
option) any later version.
12
The MPFR Library is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
License for more details.
17
You should have received a copy of the GNU Lesser General Public License
18
along with the MPFR Library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20
MA 02111-1307, USA. */
25
#include "mpfr-impl.h"
28
mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mp_rnd_t rnd_mode)
30
int sign_product, cc, inexact, ec, em = 0;
32
mp_limb_t *ap, *bp, *cp, *tmp;
35
mp_size_t an, bn, cn, tn, k;
38
/* deal with NaN and zero */
39
if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
47
sign_product = MPFR_SIGN(b) * MPFR_SIGN(c);
51
if (MPFR_IS_INF(c) || MPFR_NOTZERO(c))
53
if (MPFR_SIGN(a) != sign_product)
56
MPFR_RET(0); /* exact */
64
else if (MPFR_IS_INF(c))
68
if (MPFR_SIGN(a) != sign_product)
71
MPFR_RET(0); /* exact */
80
MPFR_ASSERTN(MPFR_IS_FP(b) && MPFR_IS_FP(c));
81
MPFR_CLEAR_INF(a); /* clear Inf flag */
83
if (MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c))
85
if (MPFR_SIGN(a) != sign_product)
88
MPFR_RET(0); /* 0 * 0 is exact */
93
/* Note: exponent of the result will be bx + cx + ec with ec in {-1,0,1} */
94
if (bx >= 0 && cx > 0)
96
if (__mpfr_emax < 0 ||
97
(mp_exp_unsigned_t) bx + cx > (mp_exp_unsigned_t) __mpfr_emax + 1)
98
return mpfr_set_overflow(a, rnd_mode, sign_product);
100
if ((mp_exp_unsigned_t) bx + cx == (mp_exp_unsigned_t) __mpfr_emax + 1)
103
else if (bx <= 0 && cx < 0)
105
if (__mpfr_emin > 0 ||
106
(mp_exp_unsigned_t) bx + cx < (mp_exp_unsigned_t) __mpfr_emin - 1)
107
return mpfr_set_underflow(a, rnd_mode, sign_product);
109
if ((mp_exp_unsigned_t) bx + cx == (mp_exp_unsigned_t) __mpfr_emin - 1)
113
{ /* bx != 0 and cx doesn't have the same sign */
114
if ((bx + cx) - 1 > __mpfr_emax)
115
return mpfr_set_overflow(a, rnd_mode, sign_product);
117
if ((bx + cx) - 1 == __mpfr_emax)
120
if ((bx + cx) + 1 < __mpfr_emin)
121
return mpfr_set_underflow(a, rnd_mode, sign_product);
123
if ((bx + cx) + 1 == __mpfr_emin)
135
an = (aq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of a */
136
bn = (bq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of b */
137
cn = (cq-1)/BITS_PER_MP_LIMB + 1; /* number of significant limbs of c */
139
MPFR_ASSERTN((mp_size_unsigned_t) bn + cn <= MP_SIZE_T_MAX);
140
k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */
142
MPFR_ASSERTN(bq + cq >= bq); /* no integer overflow */
143
tn = (bq + cq - 1) / BITS_PER_MP_LIMB + 1; /* <= k, thus no int overflow */
145
MPFR_ASSERTN(k <= ((size_t) -1) / BYTES_PER_MP_LIMB);
147
tmp = (mp_limb_t *) TMP_ALLOC((size_t) k * BYTES_PER_MP_LIMB);
149
/* multiplies two mantissa in temporary allocated space */
150
b1 = (bn >= cn) ? mpn_mul (tmp, bp, bn, cp, cn)
151
: mpn_mul (tmp, cp, cn, bp, bn);
153
/* now tmp[0]..tmp[k-1] contains the product of both mantissa,
154
with tmp[k-1]>=2^(BITS_PER_MP_LIMB-2) */
155
b1 >>= BITS_PER_MP_LIMB - 1; /* msb from the product */
159
mpn_lshift (tmp, tmp, tn, 1);
160
cc = mpfr_round_raw (ap, tmp, bq + cq, sign_product < 0, aq,
162
if (cc) /* cc = 1 ==> result is a power of two */
163
ap[an-1] = GMP_LIMB_HIGHBIT;
171
mp_exp_t ax = bx + cx;
173
if (ax == __mpfr_emax && ec > 0)
174
return mpfr_set_overflow(a, rnd_mode, sign_product);
176
if (ax == __mpfr_emin && ec < 0)
177
return mpfr_set_underflow(a, rnd_mode, sign_product);
179
MPFR_EXP(a) = ax + ec;
184
return mpfr_set_overflow(a, rnd_mode, sign_product);
186
MPFR_EXP(a) = __mpfr_emax;
191
return mpfr_set_underflow(a, rnd_mode, sign_product);
193
MPFR_EXP(a) = __mpfr_emin;
196
if (MPFR_SIGN(a) != sign_product)