Home | History | Annotate | Line # | Download | only in mpz
mul.c revision 1.1.1.3
      1      1.1  mrg /* mpz_mul -- Multiply two integers.
      2      1.1  mrg 
      3  1.1.1.2  mrg Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2005, 2009, 2011, 2012 Free
      4      1.1  mrg Software Foundation, Inc.
      5      1.1  mrg 
      6      1.1  mrg This file is part of the GNU MP Library.
      7      1.1  mrg 
      8      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
      9  1.1.1.3  mrg it under the terms of either:
     10  1.1.1.3  mrg 
     11  1.1.1.3  mrg   * the GNU Lesser General Public License as published by the Free
     12  1.1.1.3  mrg     Software Foundation; either version 3 of the License, or (at your
     13  1.1.1.3  mrg     option) any later version.
     14  1.1.1.3  mrg 
     15  1.1.1.3  mrg or
     16  1.1.1.3  mrg 
     17  1.1.1.3  mrg   * the GNU General Public License as published by the Free Software
     18  1.1.1.3  mrg     Foundation; either version 2 of the License, or (at your option) any
     19  1.1.1.3  mrg     later version.
     20  1.1.1.3  mrg 
     21  1.1.1.3  mrg or both in parallel, as here.
     22      1.1  mrg 
     23      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     24      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     25  1.1.1.3  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     26  1.1.1.3  mrg for more details.
     27      1.1  mrg 
     28  1.1.1.3  mrg You should have received copies of the GNU General Public License and the
     29  1.1.1.3  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     30  1.1.1.3  mrg see https://www.gnu.org/licenses/.  */
     31      1.1  mrg 
     32      1.1  mrg #include <stdio.h> /* for NULL */
     33      1.1  mrg #include "gmp.h"
     34      1.1  mrg #include "gmp-impl.h"
     35      1.1  mrg 
     36      1.1  mrg 
     37      1.1  mrg void
     38      1.1  mrg mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
     39      1.1  mrg {
     40      1.1  mrg   mp_size_t usize;
     41      1.1  mrg   mp_size_t vsize;
     42      1.1  mrg   mp_size_t wsize;
     43      1.1  mrg   mp_size_t sign_product;
     44      1.1  mrg   mp_ptr up, vp;
     45      1.1  mrg   mp_ptr wp;
     46      1.1  mrg   mp_ptr free_me;
     47      1.1  mrg   size_t free_me_size;
     48      1.1  mrg   mp_limb_t cy_limb;
     49      1.1  mrg   TMP_DECL;
     50      1.1  mrg 
     51      1.1  mrg   usize = SIZ (u);
     52      1.1  mrg   vsize = SIZ (v);
     53      1.1  mrg   sign_product = usize ^ vsize;
     54      1.1  mrg   usize = ABS (usize);
     55      1.1  mrg   vsize = ABS (vsize);
     56      1.1  mrg 
     57      1.1  mrg   if (usize < vsize)
     58      1.1  mrg     {
     59      1.1  mrg       MPZ_SRCPTR_SWAP (u, v);
     60      1.1  mrg       MP_SIZE_T_SWAP (usize, vsize);
     61      1.1  mrg     }
     62      1.1  mrg 
     63      1.1  mrg   if (vsize == 0)
     64      1.1  mrg     {
     65  1.1.1.2  mrg       SIZ (w) = 0;
     66      1.1  mrg       return;
     67      1.1  mrg     }
     68      1.1  mrg 
     69      1.1  mrg #if HAVE_NATIVE_mpn_mul_2
     70      1.1  mrg   if (vsize <= 2)
     71      1.1  mrg     {
     72  1.1.1.2  mrg       wp = MPZ_REALLOC (w, usize+vsize);
     73      1.1  mrg       if (vsize == 1)
     74  1.1.1.2  mrg 	cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
     75      1.1  mrg       else
     76  1.1.1.2  mrg 	{
     77  1.1.1.2  mrg 	  cy_limb = mpn_mul_2 (wp, PTR (u), usize, PTR (v));
     78  1.1.1.2  mrg 	  usize++;
     79  1.1.1.2  mrg 	}
     80      1.1  mrg       wp[usize] = cy_limb;
     81      1.1  mrg       usize += (cy_limb != 0);
     82  1.1.1.2  mrg       SIZ (w) = (sign_product >= 0 ? usize : -usize);
     83      1.1  mrg       return;
     84      1.1  mrg     }
     85      1.1  mrg #else
     86      1.1  mrg   if (vsize == 1)
     87      1.1  mrg     {
     88  1.1.1.2  mrg       wp = MPZ_REALLOC (w, usize+1);
     89  1.1.1.2  mrg       cy_limb = mpn_mul_1 (wp, PTR (u), usize, PTR (v)[0]);
     90      1.1  mrg       wp[usize] = cy_limb;
     91      1.1  mrg       usize += (cy_limb != 0);
     92  1.1.1.2  mrg       SIZ (w) = (sign_product >= 0 ? usize : -usize);
     93      1.1  mrg       return;
     94      1.1  mrg     }
     95      1.1  mrg #endif
     96      1.1  mrg 
     97      1.1  mrg   TMP_MARK;
     98      1.1  mrg   free_me = NULL;
     99  1.1.1.2  mrg   up = PTR (u);
    100  1.1.1.2  mrg   vp = PTR (v);
    101  1.1.1.2  mrg   wp = PTR (w);
    102      1.1  mrg 
    103      1.1  mrg   /* Ensure W has space enough to store the result.  */
    104      1.1  mrg   wsize = usize + vsize;
    105  1.1.1.2  mrg   if (ALLOC (w) < wsize)
    106      1.1  mrg     {
    107      1.1  mrg       if (wp == up || wp == vp)
    108      1.1  mrg 	{
    109      1.1  mrg 	  free_me = wp;
    110  1.1.1.2  mrg 	  free_me_size = ALLOC (w);
    111      1.1  mrg 	}
    112      1.1  mrg       else
    113  1.1.1.3  mrg 	(*__gmp_free_func) (wp, (size_t) ALLOC (w) * GMP_LIMB_BYTES);
    114      1.1  mrg 
    115  1.1.1.2  mrg       ALLOC (w) = wsize;
    116  1.1.1.3  mrg       wp = __GMP_ALLOCATE_FUNC_LIMBS (wsize);
    117  1.1.1.2  mrg       PTR (w) = wp;
    118      1.1  mrg     }
    119      1.1  mrg   else
    120      1.1  mrg     {
    121      1.1  mrg       /* Make U and V not overlap with W.  */
    122      1.1  mrg       if (wp == up)
    123      1.1  mrg 	{
    124      1.1  mrg 	  /* W and U are identical.  Allocate temporary space for U.  */
    125      1.1  mrg 	  up = TMP_ALLOC_LIMBS (usize);
    126      1.1  mrg 	  /* Is V identical too?  Keep it identical with U.  */
    127      1.1  mrg 	  if (wp == vp)
    128      1.1  mrg 	    vp = up;
    129      1.1  mrg 	  /* Copy to the temporary space.  */
    130      1.1  mrg 	  MPN_COPY (up, wp, usize);
    131      1.1  mrg 	}
    132      1.1  mrg       else if (wp == vp)
    133      1.1  mrg 	{
    134      1.1  mrg 	  /* W and V are identical.  Allocate temporary space for V.  */
    135      1.1  mrg 	  vp = TMP_ALLOC_LIMBS (vsize);
    136      1.1  mrg 	  /* Copy to the temporary space.  */
    137      1.1  mrg 	  MPN_COPY (vp, wp, vsize);
    138      1.1  mrg 	}
    139      1.1  mrg     }
    140      1.1  mrg 
    141      1.1  mrg   if (up == vp)
    142      1.1  mrg     {
    143      1.1  mrg       mpn_sqr (wp, up, usize);
    144      1.1  mrg       cy_limb = wp[wsize - 1];
    145      1.1  mrg     }
    146      1.1  mrg   else
    147      1.1  mrg     {
    148      1.1  mrg       cy_limb = mpn_mul (wp, up, usize, vp, vsize);
    149      1.1  mrg     }
    150      1.1  mrg 
    151      1.1  mrg   wsize -= cy_limb == 0;
    152      1.1  mrg 
    153  1.1.1.2  mrg   SIZ (w) = sign_product < 0 ? -wsize : wsize;
    154      1.1  mrg   if (free_me != NULL)
    155  1.1.1.3  mrg     (*__gmp_free_func) (free_me, free_me_size * GMP_LIMB_BYTES);
    156      1.1  mrg   TMP_FREE;
    157      1.1  mrg }
    158