xref: /dragonfly/contrib/mpfr/src/mul.c (revision ab6d115f)
14a238c70SJohn Marino /* mpfr_mul -- multiply two floating-point numbers
24a238c70SJohn Marino 
3*ab6d115fSJohn Marino Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
54a238c70SJohn Marino 
64a238c70SJohn Marino This file is part of the GNU MPFR Library.
74a238c70SJohn Marino 
84a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
94a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
104a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
114a238c70SJohn Marino option) any later version.
124a238c70SJohn Marino 
134a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
144a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
154a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
164a238c70SJohn Marino License for more details.
174a238c70SJohn Marino 
184a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
194a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
204a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
214a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
224a238c70SJohn Marino 
234a238c70SJohn Marino #define MPFR_NEED_LONGLONG_H
244a238c70SJohn Marino #include "mpfr-impl.h"
254a238c70SJohn Marino 
264a238c70SJohn Marino 
274a238c70SJohn Marino /********* BEGINNING CHECK *************/
284a238c70SJohn Marino 
294a238c70SJohn Marino /* Check if we have to check the result of mpfr_mul.
304a238c70SJohn Marino    TODO: Find a better (and faster?) check than using old implementation */
314a238c70SJohn Marino #ifdef WANT_ASSERT
324a238c70SJohn Marino # if WANT_ASSERT >= 3
334a238c70SJohn Marino 
344a238c70SJohn Marino int mpfr_mul2 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode);
354a238c70SJohn Marino static int
mpfr_mul3(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t rnd_mode)364a238c70SJohn Marino mpfr_mul3 (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
374a238c70SJohn Marino {
384a238c70SJohn Marino   /* Old implementation */
394a238c70SJohn Marino   int sign_product, cc, inexact;
404a238c70SJohn Marino   mpfr_exp_t ax;
414a238c70SJohn Marino   mp_limb_t *tmp;
424a238c70SJohn Marino   mp_limb_t b1;
434a238c70SJohn Marino   mpfr_prec_t bq, cq;
444a238c70SJohn Marino   mp_size_t bn, cn, tn, k;
454a238c70SJohn Marino   MPFR_TMP_DECL(marker);
464a238c70SJohn Marino 
474a238c70SJohn Marino   /* deal with special cases */
484a238c70SJohn Marino   if (MPFR_ARE_SINGULAR(b,c))
494a238c70SJohn Marino     {
504a238c70SJohn Marino       if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
514a238c70SJohn Marino         {
524a238c70SJohn Marino           MPFR_SET_NAN(a);
534a238c70SJohn Marino           MPFR_RET_NAN;
544a238c70SJohn Marino         }
554a238c70SJohn Marino       sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) );
564a238c70SJohn Marino       if (MPFR_IS_INF(b))
574a238c70SJohn Marino         {
584a238c70SJohn Marino           if (MPFR_IS_INF(c) || MPFR_NOTZERO(c))
594a238c70SJohn Marino             {
604a238c70SJohn Marino               MPFR_SET_SIGN(a,sign_product);
614a238c70SJohn Marino               MPFR_SET_INF(a);
624a238c70SJohn Marino               MPFR_RET(0); /* exact */
634a238c70SJohn Marino             }
644a238c70SJohn Marino           else
654a238c70SJohn Marino             {
664a238c70SJohn Marino               MPFR_SET_NAN(a);
674a238c70SJohn Marino               MPFR_RET_NAN;
684a238c70SJohn Marino             }
694a238c70SJohn Marino         }
704a238c70SJohn Marino       else if (MPFR_IS_INF(c))
714a238c70SJohn Marino         {
724a238c70SJohn Marino           if (MPFR_NOTZERO(b))
734a238c70SJohn Marino             {
744a238c70SJohn Marino               MPFR_SET_SIGN(a, sign_product);
754a238c70SJohn Marino               MPFR_SET_INF(a);
764a238c70SJohn Marino               MPFR_RET(0); /* exact */
774a238c70SJohn Marino             }
784a238c70SJohn Marino           else
794a238c70SJohn Marino             {
804a238c70SJohn Marino               MPFR_SET_NAN(a);
814a238c70SJohn Marino               MPFR_RET_NAN;
824a238c70SJohn Marino             }
834a238c70SJohn Marino         }
844a238c70SJohn Marino       else
854a238c70SJohn Marino         {
864a238c70SJohn Marino           MPFR_ASSERTD(MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c));
874a238c70SJohn Marino           MPFR_SET_SIGN(a, sign_product);
884a238c70SJohn Marino           MPFR_SET_ZERO(a);
894a238c70SJohn Marino           MPFR_RET(0); /* 0 * 0 is exact */
904a238c70SJohn Marino         }
914a238c70SJohn Marino     }
924a238c70SJohn Marino   sign_product = MPFR_MULT_SIGN( MPFR_SIGN(b) , MPFR_SIGN(c) );
934a238c70SJohn Marino 
944a238c70SJohn Marino   ax = MPFR_GET_EXP (b) + MPFR_GET_EXP (c);
954a238c70SJohn Marino 
964a238c70SJohn Marino   bq = MPFR_PREC (b);
974a238c70SJohn Marino   cq = MPFR_PREC (c);
984a238c70SJohn Marino 
99*ab6d115fSJohn Marino   MPFR_ASSERTN ((mpfr_uprec_t) bq + cq <= MPFR_PREC_MAX);
1004a238c70SJohn Marino 
101*ab6d115fSJohn Marino   bn = MPFR_PREC2LIMBS (bq); /* number of limbs of b */
102*ab6d115fSJohn Marino   cn = MPFR_PREC2LIMBS (cq); /* number of limbs of c */
1034a238c70SJohn Marino   k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */
104*ab6d115fSJohn Marino   tn = MPFR_PREC2LIMBS (bq + cq);
1054a238c70SJohn Marino   /* <= k, thus no int overflow */
1064a238c70SJohn Marino   MPFR_ASSERTD(tn <= k);
1074a238c70SJohn Marino 
1084a238c70SJohn Marino   /* Check for no size_t overflow*/
1094a238c70SJohn Marino   MPFR_ASSERTD((size_t) k <= ((size_t) -1) / BYTES_PER_MP_LIMB);
1104a238c70SJohn Marino   MPFR_TMP_MARK(marker);
1114a238c70SJohn Marino   tmp = MPFR_TMP_LIMBS_ALLOC (k);
1124a238c70SJohn Marino 
1134a238c70SJohn Marino   /* multiplies two mantissa in temporary allocated space */
1144a238c70SJohn Marino   b1 = (MPFR_LIKELY(bn >= cn)) ?
1154a238c70SJohn Marino     mpn_mul (tmp, MPFR_MANT(b), bn, MPFR_MANT(c), cn)
1164a238c70SJohn Marino     : mpn_mul (tmp, MPFR_MANT(c), cn, MPFR_MANT(b), bn);
1174a238c70SJohn Marino 
1184a238c70SJohn Marino   /* now tmp[0]..tmp[k-1] contains the product of both mantissa,
1194a238c70SJohn Marino      with tmp[k-1]>=2^(GMP_NUMB_BITS-2) */
1204a238c70SJohn Marino   b1 >>= GMP_NUMB_BITS - 1; /* msb from the product */
1214a238c70SJohn Marino 
1224a238c70SJohn Marino   /* if the mantissas of b and c are uniformly distributed in ]1/2, 1],
1234a238c70SJohn Marino      then their product is in ]1/4, 1/2] with probability 2*ln(2)-1 ~ 0.386
1244a238c70SJohn Marino      and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */
1254a238c70SJohn Marino   tmp += k - tn;
1264a238c70SJohn Marino   if (MPFR_UNLIKELY(b1 == 0))
1274a238c70SJohn Marino     mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */
1284a238c70SJohn Marino   cc = mpfr_round_raw (MPFR_MANT (a), tmp, bq + cq,
1294a238c70SJohn Marino                        MPFR_IS_NEG_SIGN(sign_product),
1304a238c70SJohn Marino                        MPFR_PREC (a), rnd_mode, &inexact);
1314a238c70SJohn Marino 
1324a238c70SJohn Marino   /* cc = 1 ==> result is a power of two */
1334a238c70SJohn Marino   if (MPFR_UNLIKELY(cc))
1344a238c70SJohn Marino     MPFR_MANT(a)[MPFR_LIMB_SIZE(a)-1] = MPFR_LIMB_HIGHBIT;
1354a238c70SJohn Marino 
1364a238c70SJohn Marino   MPFR_TMP_FREE(marker);
1374a238c70SJohn Marino 
1384a238c70SJohn Marino   {
1394a238c70SJohn Marino     mpfr_exp_t ax2 = ax + (mpfr_exp_t) (b1 - 1 + cc);
1404a238c70SJohn Marino     if (MPFR_UNLIKELY( ax2 > __gmpfr_emax))
1414a238c70SJohn Marino       return mpfr_overflow (a, rnd_mode, sign_product);
1424a238c70SJohn Marino     if (MPFR_UNLIKELY( ax2 < __gmpfr_emin))
1434a238c70SJohn Marino       {
1444a238c70SJohn Marino         /* In the rounding to the nearest mode, if the exponent of the exact
1454a238c70SJohn Marino            result (i.e. before rounding, i.e. without taking cc into account)
1464a238c70SJohn Marino            is < __gmpfr_emin - 1 or the exact result is a power of 2 (i.e. if
1474a238c70SJohn Marino            both arguments are powers of 2) in absolute value, then round to
1484a238c70SJohn Marino            zero. */
1494a238c70SJohn Marino         if (rnd_mode == MPFR_RNDN &&
1504a238c70SJohn Marino             (ax + (mpfr_exp_t) b1 < __gmpfr_emin ||
1514a238c70SJohn Marino              (mpfr_powerof2_raw (b) && mpfr_powerof2_raw (c))))
1524a238c70SJohn Marino           rnd_mode = MPFR_RNDZ;
1534a238c70SJohn Marino         return mpfr_underflow (a, rnd_mode, sign_product);
1544a238c70SJohn Marino       }
1554a238c70SJohn Marino     MPFR_SET_EXP (a, ax2);
1564a238c70SJohn Marino     MPFR_SET_SIGN(a, sign_product);
1574a238c70SJohn Marino   }
1584a238c70SJohn Marino   MPFR_RET (inexact);
1594a238c70SJohn Marino }
1604a238c70SJohn Marino 
1614a238c70SJohn Marino int
mpfr_mul(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t rnd_mode)1624a238c70SJohn Marino mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
1634a238c70SJohn Marino {
1644a238c70SJohn Marino   mpfr_t ta, tb, tc;
1654a238c70SJohn Marino   int inexact1, inexact2;
1664a238c70SJohn Marino 
1674a238c70SJohn Marino   mpfr_init2 (ta, MPFR_PREC (a));
1684a238c70SJohn Marino   mpfr_init2 (tb, MPFR_PREC (b));
1694a238c70SJohn Marino   mpfr_init2 (tc, MPFR_PREC (c));
1704a238c70SJohn Marino   MPFR_ASSERTN (mpfr_set (tb, b, MPFR_RNDN) == 0);
1714a238c70SJohn Marino   MPFR_ASSERTN (mpfr_set (tc, c, MPFR_RNDN) == 0);
1724a238c70SJohn Marino 
1734a238c70SJohn Marino   inexact2 = mpfr_mul3 (ta, tb, tc, rnd_mode);
1744a238c70SJohn Marino   inexact1  = mpfr_mul2 (a, b, c, rnd_mode);
1754a238c70SJohn Marino   if (mpfr_cmp (ta, a) || inexact1*inexact2 < 0
1764a238c70SJohn Marino       || (inexact1*inexact2 == 0 && (inexact1|inexact2) != 0))
1774a238c70SJohn Marino     {
1784a238c70SJohn Marino       fprintf (stderr, "mpfr_mul return different values for %s\n"
1794a238c70SJohn Marino                "Prec_a = %lu, Prec_b = %lu, Prec_c = %lu\nB = ",
1804a238c70SJohn Marino                mpfr_print_rnd_mode (rnd_mode),
1814a238c70SJohn Marino                MPFR_PREC (a), MPFR_PREC (b), MPFR_PREC (c));
1824a238c70SJohn Marino       mpfr_out_str (stderr, 16, 0, tb, MPFR_RNDN);
1834a238c70SJohn Marino       fprintf (stderr, "\nC = ");
1844a238c70SJohn Marino       mpfr_out_str (stderr, 16, 0, tc, MPFR_RNDN);
1854a238c70SJohn Marino       fprintf (stderr, "\nOldMul: ");
1864a238c70SJohn Marino       mpfr_out_str (stderr, 16, 0, ta, MPFR_RNDN);
1874a238c70SJohn Marino       fprintf (stderr, "\nNewMul: ");
1884a238c70SJohn Marino       mpfr_out_str (stderr, 16, 0, a, MPFR_RNDN);
1894a238c70SJohn Marino       fprintf (stderr, "\nNewInexact = %d | OldInexact = %d\n",
1904a238c70SJohn Marino                inexact1, inexact2);
1914a238c70SJohn Marino       MPFR_ASSERTN(0);
1924a238c70SJohn Marino     }
1934a238c70SJohn Marino 
1944a238c70SJohn Marino   mpfr_clears (ta, tb, tc, (mpfr_ptr) 0);
1954a238c70SJohn Marino   return inexact1;
1964a238c70SJohn Marino }
1974a238c70SJohn Marino 
1984a238c70SJohn Marino # define mpfr_mul mpfr_mul2
1994a238c70SJohn Marino # endif
2004a238c70SJohn Marino #endif
2014a238c70SJohn Marino 
2024a238c70SJohn Marino /****** END OF CHECK *******/
2034a238c70SJohn Marino 
2044a238c70SJohn Marino /* Multiply 2 mpfr_t */
2054a238c70SJohn Marino 
2064a238c70SJohn Marino /* Note: mpfr_sqr will call mpfr_mul if bn > MPFR_SQR_THRESHOLD,
2074a238c70SJohn Marino    in order to use Mulders' mulhigh, which is handled only here
2084a238c70SJohn Marino    to avoid partial code duplication. There is some overhead due
2094a238c70SJohn Marino    to the additional tests, but slowdown should not be noticeable
2104a238c70SJohn Marino    as this code is not executed in very small precisions. */
2114a238c70SJohn Marino 
2124a238c70SJohn Marino int
mpfr_mul(mpfr_ptr a,mpfr_srcptr b,mpfr_srcptr c,mpfr_rnd_t rnd_mode)2134a238c70SJohn Marino mpfr_mul (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
2144a238c70SJohn Marino {
2154a238c70SJohn Marino   int sign, inexact;
2164a238c70SJohn Marino   mpfr_exp_t ax, ax2;
2174a238c70SJohn Marino   mp_limb_t *tmp;
2184a238c70SJohn Marino   mp_limb_t b1;
2194a238c70SJohn Marino   mpfr_prec_t bq, cq;
2204a238c70SJohn Marino   mp_size_t bn, cn, tn, k, threshold;
2214a238c70SJohn Marino   MPFR_TMP_DECL (marker);
2224a238c70SJohn Marino 
2234a238c70SJohn Marino   MPFR_LOG_FUNC
2244a238c70SJohn Marino     (("b[%Pu]=%.*Rg c[%Pu]=%.*Rg rnd=%d",
2254a238c70SJohn Marino       mpfr_get_prec (b), mpfr_log_prec, b,
2264a238c70SJohn Marino       mpfr_get_prec (c), mpfr_log_prec, c, rnd_mode),
2274a238c70SJohn Marino      ("a[%Pu]=%.*Rg inexact=%d",
2284a238c70SJohn Marino       mpfr_get_prec (a), mpfr_log_prec, a, inexact));
2294a238c70SJohn Marino 
2304a238c70SJohn Marino   /* deal with special cases */
2314a238c70SJohn Marino   if (MPFR_ARE_SINGULAR (b, c))
2324a238c70SJohn Marino     {
2334a238c70SJohn Marino       if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
2344a238c70SJohn Marino         {
2354a238c70SJohn Marino           MPFR_SET_NAN (a);
2364a238c70SJohn Marino           MPFR_RET_NAN;
2374a238c70SJohn Marino         }
2384a238c70SJohn Marino       sign = MPFR_MULT_SIGN (MPFR_SIGN (b), MPFR_SIGN (c));
2394a238c70SJohn Marino       if (MPFR_IS_INF (b))
2404a238c70SJohn Marino         {
2414a238c70SJohn Marino           if (!MPFR_IS_ZERO (c))
2424a238c70SJohn Marino             {
2434a238c70SJohn Marino               MPFR_SET_SIGN (a, sign);
2444a238c70SJohn Marino               MPFR_SET_INF (a);
2454a238c70SJohn Marino               MPFR_RET (0);
2464a238c70SJohn Marino             }
2474a238c70SJohn Marino           else
2484a238c70SJohn Marino             {
2494a238c70SJohn Marino               MPFR_SET_NAN (a);
2504a238c70SJohn Marino               MPFR_RET_NAN;
2514a238c70SJohn Marino             }
2524a238c70SJohn Marino         }
2534a238c70SJohn Marino       else if (MPFR_IS_INF (c))
2544a238c70SJohn Marino         {
2554a238c70SJohn Marino           if (!MPFR_IS_ZERO (b))
2564a238c70SJohn Marino             {
2574a238c70SJohn Marino               MPFR_SET_SIGN (a, sign);
2584a238c70SJohn Marino               MPFR_SET_INF (a);
2594a238c70SJohn Marino               MPFR_RET(0);
2604a238c70SJohn Marino             }
2614a238c70SJohn Marino           else
2624a238c70SJohn Marino             {
2634a238c70SJohn Marino               MPFR_SET_NAN (a);
2644a238c70SJohn Marino               MPFR_RET_NAN;
2654a238c70SJohn Marino             }
2664a238c70SJohn Marino         }
2674a238c70SJohn Marino       else
2684a238c70SJohn Marino         {
2694a238c70SJohn Marino           MPFR_ASSERTD (MPFR_IS_ZERO(b) || MPFR_IS_ZERO(c));
2704a238c70SJohn Marino           MPFR_SET_SIGN (a, sign);
2714a238c70SJohn Marino           MPFR_SET_ZERO (a);
2724a238c70SJohn Marino           MPFR_RET (0);
2734a238c70SJohn Marino         }
2744a238c70SJohn Marino     }
2754a238c70SJohn Marino   sign = MPFR_MULT_SIGN (MPFR_SIGN (b), MPFR_SIGN (c));
2764a238c70SJohn Marino 
2774a238c70SJohn Marino   ax = MPFR_GET_EXP (b) + MPFR_GET_EXP (c);
2784a238c70SJohn Marino   /* Note: the exponent of the exact result will be e = bx + cx + ec with
2794a238c70SJohn Marino      ec in {-1,0,1} and the following assumes that e is representable. */
2804a238c70SJohn Marino 
2814a238c70SJohn Marino   /* FIXME: Useful since we do an exponent check after ?
2824a238c70SJohn Marino    * It is useful iff the precision is big, there is an overflow
2834a238c70SJohn Marino    * and we are doing further mults...*/
2844a238c70SJohn Marino #ifdef HUGE
2854a238c70SJohn Marino   if (MPFR_UNLIKELY (ax > __gmpfr_emax + 1))
2864a238c70SJohn Marino     return mpfr_overflow (a, rnd_mode, sign);
2874a238c70SJohn Marino   if (MPFR_UNLIKELY (ax < __gmpfr_emin - 2))
2884a238c70SJohn Marino     return mpfr_underflow (a, rnd_mode == MPFR_RNDN ? MPFR_RNDZ : rnd_mode,
2894a238c70SJohn Marino                            sign);
2904a238c70SJohn Marino #endif
2914a238c70SJohn Marino 
2924a238c70SJohn Marino   bq = MPFR_PREC (b);
2934a238c70SJohn Marino   cq = MPFR_PREC (c);
2944a238c70SJohn Marino 
295*ab6d115fSJohn Marino   MPFR_ASSERTN ((mpfr_uprec_t) bq + cq <= MPFR_PREC_MAX);
2964a238c70SJohn Marino 
297*ab6d115fSJohn Marino   bn = MPFR_PREC2LIMBS (bq); /* number of limbs of b */
298*ab6d115fSJohn Marino   cn = MPFR_PREC2LIMBS (cq); /* number of limbs of c */
2994a238c70SJohn Marino   k = bn + cn; /* effective nb of limbs used by b*c (= tn or tn+1) below */
300*ab6d115fSJohn Marino   tn = MPFR_PREC2LIMBS (bq + cq);
3014a238c70SJohn Marino   MPFR_ASSERTD (tn <= k); /* tn <= k, thus no int overflow */
3024a238c70SJohn Marino 
3034a238c70SJohn Marino   /* Check for no size_t overflow*/
3044a238c70SJohn Marino   MPFR_ASSERTD ((size_t) k <= ((size_t) -1) / BYTES_PER_MP_LIMB);
3054a238c70SJohn Marino   MPFR_TMP_MARK (marker);
3064a238c70SJohn Marino   tmp = MPFR_TMP_LIMBS_ALLOC (k);
3074a238c70SJohn Marino 
3084a238c70SJohn Marino   /* multiplies two mantissa in temporary allocated space */
3094a238c70SJohn Marino   if (MPFR_UNLIKELY (bn < cn))
3104a238c70SJohn Marino     {
3114a238c70SJohn Marino       mpfr_srcptr z = b;
3124a238c70SJohn Marino       mp_size_t zn  = bn;
3134a238c70SJohn Marino       b = c;
3144a238c70SJohn Marino       bn = cn;
3154a238c70SJohn Marino       c = z;
3164a238c70SJohn Marino       cn = zn;
3174a238c70SJohn Marino     }
3184a238c70SJohn Marino   MPFR_ASSERTD (bn >= cn);
3194a238c70SJohn Marino   if (MPFR_LIKELY (bn <= 2))
3204a238c70SJohn Marino     {
3214a238c70SJohn Marino       if (bn == 1)
3224a238c70SJohn Marino         {
3234a238c70SJohn Marino           /* 1 limb * 1 limb */
3244a238c70SJohn Marino           umul_ppmm (tmp[1], tmp[0], MPFR_MANT (b)[0], MPFR_MANT (c)[0]);
3254a238c70SJohn Marino           b1 = tmp[1];
3264a238c70SJohn Marino         }
3274a238c70SJohn Marino       else if (MPFR_UNLIKELY (cn == 1))
3284a238c70SJohn Marino         {
3294a238c70SJohn Marino           /* 2 limbs * 1 limb */
3304a238c70SJohn Marino           mp_limb_t t;
3314a238c70SJohn Marino           umul_ppmm (tmp[1], tmp[0], MPFR_MANT (b)[0], MPFR_MANT (c)[0]);
3324a238c70SJohn Marino           umul_ppmm (tmp[2], t, MPFR_MANT (b)[1], MPFR_MANT (c)[0]);
3334a238c70SJohn Marino           add_ssaaaa (tmp[2], tmp[1], tmp[2], tmp[1], 0, t);
3344a238c70SJohn Marino           b1 = tmp[2];
3354a238c70SJohn Marino         }
3364a238c70SJohn Marino       else
3374a238c70SJohn Marino         {
3384a238c70SJohn Marino           /* 2 limbs * 2 limbs */
3394a238c70SJohn Marino           mp_limb_t t1, t2, t3;
3404a238c70SJohn Marino           /* First 2 limbs * 1 limb */
3414a238c70SJohn Marino           umul_ppmm (tmp[1], tmp[0], MPFR_MANT (b)[0], MPFR_MANT (c)[0]);
3424a238c70SJohn Marino           umul_ppmm (tmp[2], t1, MPFR_MANT (b)[1], MPFR_MANT (c)[0]);
3434a238c70SJohn Marino           add_ssaaaa (tmp[2], tmp[1], tmp[2], tmp[1], 0, t1);
3444a238c70SJohn Marino           /* Second, the other 2 limbs * 1 limb product */
3454a238c70SJohn Marino           umul_ppmm (t1, t2, MPFR_MANT (b)[0], MPFR_MANT (c)[1]);
3464a238c70SJohn Marino           umul_ppmm (tmp[3], t3, MPFR_MANT (b)[1], MPFR_MANT (c)[1]);
3474a238c70SJohn Marino           add_ssaaaa (tmp[3], t1, tmp[3], t1, 0, t3);
3484a238c70SJohn Marino           /* Sum those two partial products */
3494a238c70SJohn Marino           add_ssaaaa (tmp[2], tmp[1], tmp[2], tmp[1], t1, t2);
3504a238c70SJohn Marino           tmp[3] += (tmp[2] < t1);
3514a238c70SJohn Marino           b1 = tmp[3];
3524a238c70SJohn Marino         }
3534a238c70SJohn Marino       b1 >>= (GMP_NUMB_BITS - 1);
3544a238c70SJohn Marino       tmp += k - tn;
3554a238c70SJohn Marino       if (MPFR_UNLIKELY (b1 == 0))
3564a238c70SJohn Marino         mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */
3574a238c70SJohn Marino     }
3584a238c70SJohn Marino   else
3594a238c70SJohn Marino     /* Mulders' mulhigh. This code can also be used via mpfr_sqr,
3604a238c70SJohn Marino        hence the tests b != c. */
3614a238c70SJohn Marino     if (MPFR_UNLIKELY (bn > (threshold = b != c ?
3624a238c70SJohn Marino                              MPFR_MUL_THRESHOLD : MPFR_SQR_THRESHOLD)))
3634a238c70SJohn Marino       {
3644a238c70SJohn Marino         mp_limb_t *bp, *cp;
3654a238c70SJohn Marino         mp_size_t n;
3664a238c70SJohn Marino         mpfr_prec_t p;
3674a238c70SJohn Marino 
3684a238c70SJohn Marino         /* First check if we can reduce the precision of b or c:
3694a238c70SJohn Marino            exact values are a nightmare for the short product trick */
3704a238c70SJohn Marino         bp = MPFR_MANT (b);
3714a238c70SJohn Marino         cp = MPFR_MANT (c);
3724a238c70SJohn Marino         MPFR_ASSERTN (threshold >= 1);
3734a238c70SJohn Marino         if (MPFR_UNLIKELY ((bp[0] == 0 && bp[1] == 0) ||
3744a238c70SJohn Marino                            (cp[0] == 0 && cp[1] == 0)))
3754a238c70SJohn Marino           {
3764a238c70SJohn Marino             mpfr_t b_tmp, c_tmp;
3774a238c70SJohn Marino 
3784a238c70SJohn Marino             MPFR_TMP_FREE (marker);
3794a238c70SJohn Marino             /* Check for b */
3804a238c70SJohn Marino             while (*bp == 0)
3814a238c70SJohn Marino               {
3824a238c70SJohn Marino                 bp++;
3834a238c70SJohn Marino                 bn--;
3844a238c70SJohn Marino                 MPFR_ASSERTD (bn > 0);
3854a238c70SJohn Marino               } /* This must end since the most significant limb is != 0 */
3864a238c70SJohn Marino 
3874a238c70SJohn Marino             /* Check for c too: if b ==c, will do nothing */
3884a238c70SJohn Marino             while (*cp == 0)
3894a238c70SJohn Marino               {
3904a238c70SJohn Marino                 cp++;
3914a238c70SJohn Marino                 cn--;
3924a238c70SJohn Marino                 MPFR_ASSERTD (cn > 0);
3934a238c70SJohn Marino               } /* This must end since the most significant limb is != 0 */
3944a238c70SJohn Marino 
3954a238c70SJohn Marino             /* It is not the faster way, but it is safer */
3964a238c70SJohn Marino             MPFR_SET_SAME_SIGN (b_tmp, b);
3974a238c70SJohn Marino             MPFR_SET_EXP (b_tmp, MPFR_GET_EXP (b));
3984a238c70SJohn Marino             MPFR_PREC (b_tmp) = bn * GMP_NUMB_BITS;
3994a238c70SJohn Marino             MPFR_MANT (b_tmp) = bp;
4004a238c70SJohn Marino 
4014a238c70SJohn Marino             if (b != c)
4024a238c70SJohn Marino               {
4034a238c70SJohn Marino                 MPFR_SET_SAME_SIGN (c_tmp, c);
4044a238c70SJohn Marino                 MPFR_SET_EXP (c_tmp, MPFR_GET_EXP (c));
4054a238c70SJohn Marino                 MPFR_PREC (c_tmp) = cn * GMP_NUMB_BITS;
4064a238c70SJohn Marino                 MPFR_MANT (c_tmp) = cp;
4074a238c70SJohn Marino 
4084a238c70SJohn Marino                 /* Call again mpfr_mul with the fixed arguments */
4094a238c70SJohn Marino                 return mpfr_mul (a, b_tmp, c_tmp, rnd_mode);
4104a238c70SJohn Marino               }
4114a238c70SJohn Marino             else
4124a238c70SJohn Marino               /* Call mpfr_mul instead of mpfr_sqr as the precision
4134a238c70SJohn Marino                  is probably still high enough. */
4144a238c70SJohn Marino               return mpfr_mul (a, b_tmp, b_tmp, rnd_mode);
4154a238c70SJohn Marino           }
4164a238c70SJohn Marino 
4174a238c70SJohn Marino         /* Compute estimated precision of mulhigh.
4184a238c70SJohn Marino            We could use `+ (n < cn) + (n < bn)' instead of `+ 2',
4194a238c70SJohn Marino            but does it worth it? */
4204a238c70SJohn Marino         n = MPFR_LIMB_SIZE (a) + 1;
4214a238c70SJohn Marino         n = MIN (n, cn);
4224a238c70SJohn Marino         MPFR_ASSERTD (n >= 1 && 2*n <= k && n <= cn && n <= bn);
4234a238c70SJohn Marino         p = n * GMP_NUMB_BITS - MPFR_INT_CEIL_LOG2 (n + 2);
4244a238c70SJohn Marino         bp += bn - n;
4254a238c70SJohn Marino         cp += cn - n;
4264a238c70SJohn Marino 
4274a238c70SJohn Marino         /* Check if MulHigh can produce a roundable result.
4284a238c70SJohn Marino            We may lose 1 bit due to RNDN, 1 due to final shift. */
4294a238c70SJohn Marino         if (MPFR_UNLIKELY (MPFR_PREC (a) > p - 5))
4304a238c70SJohn Marino           {
4314a238c70SJohn Marino             if (MPFR_UNLIKELY (MPFR_PREC (a) > p - 5 + GMP_NUMB_BITS
4324a238c70SJohn Marino                                || bn <= threshold + 1))
4334a238c70SJohn Marino               {
4344a238c70SJohn Marino                 /* MulHigh can't produce a roundable result. */
4354a238c70SJohn Marino                 MPFR_LOG_MSG (("mpfr_mulhigh can't be used (%lu VS %lu)\n",
4364a238c70SJohn Marino                                MPFR_PREC (a), p));
4374a238c70SJohn Marino                 goto full_multiply;
4384a238c70SJohn Marino               }
4394a238c70SJohn Marino             /* Add one extra limb to mantissa of b and c. */
4404a238c70SJohn Marino             if (bn > n)
4414a238c70SJohn Marino               bp --;
4424a238c70SJohn Marino             else
4434a238c70SJohn Marino               {
4444a238c70SJohn Marino                 bp = MPFR_TMP_LIMBS_ALLOC (n + 1);
4454a238c70SJohn Marino                 bp[0] = 0;
4464a238c70SJohn Marino                 MPN_COPY (bp + 1, MPFR_MANT (b) + bn - n, n);
4474a238c70SJohn Marino               }
4484a238c70SJohn Marino             if (b != c)
4494a238c70SJohn Marino               {
4504a238c70SJohn Marino                 if (cn > n)
4514a238c70SJohn Marino                   cp --; /* FIXME: Could this happen? */
4524a238c70SJohn Marino                 else
4534a238c70SJohn Marino                   {
4544a238c70SJohn Marino                     cp = MPFR_TMP_LIMBS_ALLOC (n + 1);
4554a238c70SJohn Marino                     cp[0] = 0;
4564a238c70SJohn Marino                     MPN_COPY (cp + 1, MPFR_MANT (c) + cn - n, n);
4574a238c70SJohn Marino                   }
4584a238c70SJohn Marino               }
4594a238c70SJohn Marino             /* We will compute with one extra limb */
4604a238c70SJohn Marino             n++;
4614a238c70SJohn Marino             /* ceil(log2(n+2)) takes into account the lost bits due to
4624a238c70SJohn Marino                Mulders' short product */
4634a238c70SJohn Marino             p = n * GMP_NUMB_BITS - MPFR_INT_CEIL_LOG2 (n + 2);
4644a238c70SJohn Marino             /* Due to some nasty reasons we can have only 4 bits */
4654a238c70SJohn Marino             MPFR_ASSERTD (MPFR_PREC (a) <= p - 4);
4664a238c70SJohn Marino 
4674a238c70SJohn Marino             if (MPFR_LIKELY (k < 2*n))
4684a238c70SJohn Marino               {
4694a238c70SJohn Marino                 tmp = MPFR_TMP_LIMBS_ALLOC (2 * n);
4704a238c70SJohn Marino                 tmp += 2*n-k; /* `tmp' still points to an area of `k' limbs */
4714a238c70SJohn Marino               }
4724a238c70SJohn Marino           }
4734a238c70SJohn Marino         MPFR_LOG_MSG (("Use mpfr_mulhigh (%lu VS %lu)\n", MPFR_PREC (a), p));
4744a238c70SJohn Marino         /* Compute an approximation of the product of b and c */
4754a238c70SJohn Marino         if (b != c)
4764a238c70SJohn Marino           mpfr_mulhigh_n (tmp + k - 2 * n, bp, cp, n);
4774a238c70SJohn Marino         else
4784a238c70SJohn Marino           mpfr_sqrhigh_n (tmp + k - 2 * n, bp, n);
4794a238c70SJohn Marino         /* now tmp[0]..tmp[k-1] contains the product of both mantissa,
4804a238c70SJohn Marino            with tmp[k-1]>=2^(GMP_NUMB_BITS-2) */
4814a238c70SJohn Marino         /* [VL] FIXME: This cannot be true: mpfr_mulhigh_n only
4824a238c70SJohn Marino            depends on pointers and n. As k can be arbitrarily larger,
4834a238c70SJohn Marino            the result cannot depend on k. And indeed, with GMP compiled
4844a238c70SJohn Marino            with --enable-alloca=debug, valgrind was complaining, at
4854a238c70SJohn Marino            least because MPFR_RNDRAW at the end tried to compute the
4864a238c70SJohn Marino            sticky bit even when not necessary; this problem is fixed,
4874a238c70SJohn Marino            but there's at least something wrong with the comment above. */
4884a238c70SJohn Marino         b1 = tmp[k-1] >> (GMP_NUMB_BITS - 1); /* msb from the product */
4894a238c70SJohn Marino 
4904a238c70SJohn Marino         /* If the mantissas of b and c are uniformly distributed in (1/2, 1],
4914a238c70SJohn Marino            then their product is in (1/4, 1/2] with probability 2*ln(2)-1
4924a238c70SJohn Marino            ~ 0.386 and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */
4934a238c70SJohn Marino         if (MPFR_UNLIKELY (b1 == 0))
4944a238c70SJohn Marino           /* Warning: the mpfr_mulhigh_n call above only surely affects
4954a238c70SJohn Marino              tmp[k-n-1..k-1], thus we shift only those limbs */
4964a238c70SJohn Marino           mpn_lshift (tmp + k - n - 1, tmp + k - n - 1, n + 1, 1);
4974a238c70SJohn Marino         tmp += k - tn;
4984a238c70SJohn Marino         MPFR_ASSERTD (MPFR_LIMB_MSB (tmp[tn-1]) != 0);
4994a238c70SJohn Marino 
5004a238c70SJohn Marino         /* if the most significant bit b1 is zero, we have only p-1 correct
5014a238c70SJohn Marino            bits */
5024a238c70SJohn Marino         if (MPFR_UNLIKELY (!mpfr_round_p (tmp, tn, p + b1 - 1, MPFR_PREC(a)
5034a238c70SJohn Marino                                           + (rnd_mode == MPFR_RNDN))))
5044a238c70SJohn Marino           {
5054a238c70SJohn Marino             tmp -= k - tn; /* tmp may have changed, FIX IT!!!!! */
5064a238c70SJohn Marino             goto full_multiply;
5074a238c70SJohn Marino           }
5084a238c70SJohn Marino       }
5094a238c70SJohn Marino     else
5104a238c70SJohn Marino       {
5114a238c70SJohn Marino       full_multiply:
5124a238c70SJohn Marino         MPFR_LOG_MSG (("Use mpn_mul\n", 0));
5134a238c70SJohn Marino         b1 = mpn_mul (tmp, MPFR_MANT (b), bn, MPFR_MANT (c), cn);
5144a238c70SJohn Marino 
5154a238c70SJohn Marino         /* now tmp[0]..tmp[k-1] contains the product of both mantissa,
5164a238c70SJohn Marino            with tmp[k-1]>=2^(GMP_NUMB_BITS-2) */
5174a238c70SJohn Marino         b1 >>= GMP_NUMB_BITS - 1; /* msb from the product */
5184a238c70SJohn Marino 
5194a238c70SJohn Marino         /* if the mantissas of b and c are uniformly distributed in (1/2, 1],
5204a238c70SJohn Marino            then their product is in (1/4, 1/2] with probability 2*ln(2)-1
5214a238c70SJohn Marino            ~ 0.386 and in [1/2, 1] with probability 2-2*ln(2) ~ 0.614 */
5224a238c70SJohn Marino         tmp += k - tn;
5234a238c70SJohn Marino         if (MPFR_UNLIKELY (b1 == 0))
5244a238c70SJohn Marino           mpn_lshift (tmp, tmp, tn, 1); /* tn <= k, so no stack corruption */
5254a238c70SJohn Marino       }
5264a238c70SJohn Marino 
5274a238c70SJohn Marino   ax2 = ax + (mpfr_exp_t) (b1 - 1);
5284a238c70SJohn Marino   MPFR_RNDRAW (inexact, a, tmp, bq+cq, rnd_mode, sign, ax2++);
5294a238c70SJohn Marino   MPFR_TMP_FREE (marker);
5304a238c70SJohn Marino   MPFR_EXP  (a) = ax2; /* Can't use MPFR_SET_EXP: Expo may be out of range */
5314a238c70SJohn Marino   MPFR_SET_SIGN (a, sign);
5324a238c70SJohn Marino   if (MPFR_UNLIKELY (ax2 > __gmpfr_emax))
5334a238c70SJohn Marino     return mpfr_overflow (a, rnd_mode, sign);
5344a238c70SJohn Marino   if (MPFR_UNLIKELY (ax2 < __gmpfr_emin))
5354a238c70SJohn Marino     {
5364a238c70SJohn Marino       /* In the rounding to the nearest mode, if the exponent of the exact
5374a238c70SJohn Marino          result (i.e. before rounding, i.e. without taking cc into account)
5384a238c70SJohn Marino          is < __gmpfr_emin - 1 or the exact result is a power of 2 (i.e. if
5394a238c70SJohn Marino          both arguments are powers of 2), then round to zero. */
5404a238c70SJohn Marino       if (rnd_mode == MPFR_RNDN
5414a238c70SJohn Marino           && (ax + (mpfr_exp_t) b1 < __gmpfr_emin
5424a238c70SJohn Marino               || (mpfr_powerof2_raw (b) && mpfr_powerof2_raw (c))))
5434a238c70SJohn Marino         rnd_mode = MPFR_RNDZ;
5444a238c70SJohn Marino       return mpfr_underflow (a, rnd_mode, sign);
5454a238c70SJohn Marino     }
5464a238c70SJohn Marino   MPFR_RET (inexact);
5474a238c70SJohn Marino }
548