version 1.1.1.2, 2000/09/09 14:12:55 |
version 1.1.1.3, 2003/08/25 16:06:33 |
|
|
/* mpz_mul -- Multiply two integers. |
/* mpz_mul -- Multiply two integers. |
|
|
Copyright (C) 1991, 1993, 1994, 1996, 2000 Free Software Foundation, Inc. |
Copyright 1991, 1993, 1994, 1996, 2000, 2001 Free Software Foundation, Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
|
|
Line 26 MA 02111-1307, USA. */ |
|
Line 26 MA 02111-1307, USA. */ |
|
#include "mp.h" |
#include "mp.h" |
#endif |
#endif |
|
|
#ifndef BERKELEY_MP |
|
void |
void |
#if __STDC__ |
#ifndef BERKELEY_MP |
mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v) |
mpz_mul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v) |
#else |
|
mpz_mul (w, u, v) |
|
mpz_ptr w; |
|
mpz_srcptr u; |
|
mpz_srcptr v; |
|
#endif |
|
#else /* BERKELEY_MP */ |
#else /* BERKELEY_MP */ |
void |
|
#if __STDC__ |
|
mult (mpz_srcptr u, mpz_srcptr v, mpz_ptr w) |
mult (mpz_srcptr u, mpz_srcptr v, mpz_ptr w) |
#else |
|
mult (u, v, w) |
|
mpz_srcptr u; |
|
mpz_srcptr v; |
|
mpz_ptr w; |
|
#endif |
|
#endif /* BERKELEY_MP */ |
#endif /* BERKELEY_MP */ |
{ |
{ |
mp_size_t usize = u->_mp_size; |
mp_size_t usize = u->_mp_size; |
|
|
mp_size_t sign_product; |
mp_size_t sign_product; |
mp_ptr up, vp; |
mp_ptr up, vp; |
mp_ptr wp; |
mp_ptr wp; |
mp_ptr free_me = NULL; |
mp_ptr free_me; |
size_t free_me_size; |
size_t free_me_size; |
mp_limb_t cy_limb; |
mp_limb_t cy_limb; |
TMP_DECL (marker); |
TMP_DECL (marker); |
|
|
TMP_MARK (marker); |
|
sign_product = usize ^ vsize; |
sign_product = usize ^ vsize; |
usize = ABS (usize); |
usize = ABS (usize); |
vsize = ABS (vsize); |
vsize = ABS (vsize); |
|
|
if (usize < vsize) |
if (usize < vsize) |
{ |
{ |
/* Swap U and V. */ |
MPZ_SRCPTR_SWAP (u, v); |
{const __mpz_struct *t = u; u = v; v = t;} |
MP_SIZE_T_SWAP (usize, vsize); |
{mp_size_t t = usize; usize = vsize; vsize = t;} |
|
} |
} |
|
|
|
if (vsize == 0) |
|
{ |
|
SIZ(w) = 0; |
|
return; |
|
} |
|
|
|
#if HAVE_NATIVE_mpn_mul_2 |
|
if (vsize <= 2) |
|
{ |
|
MPZ_REALLOC (w, usize+vsize); |
|
wp = PTR(w); |
|
if (vsize == 1) |
|
cy_limb = mpn_mul_1 (wp, PTR(u), usize, PTR(v)[0]); |
|
else |
|
{ |
|
cy_limb = mpn_mul_2 (wp, PTR(u), usize, PTR(v)); |
|
usize++; |
|
} |
|
wp[usize] = cy_limb; |
|
usize += (cy_limb != 0); |
|
SIZ(w) = (sign_product >= 0 ? usize : -usize); |
|
return; |
|
} |
|
#else |
|
if (vsize == 1) |
|
{ |
|
MPZ_REALLOC (w, usize+1); |
|
wp = PTR(w); |
|
cy_limb = mpn_mul_1 (wp, PTR(u), usize, PTR(v)[0]); |
|
wp[usize] = cy_limb; |
|
usize += (cy_limb != 0); |
|
SIZ(w) = (sign_product >= 0 ? usize : -usize); |
|
return; |
|
} |
|
#endif |
|
|
|
TMP_MARK (marker); |
|
free_me = NULL; |
up = u->_mp_d; |
up = u->_mp_d; |
vp = v->_mp_d; |
vp = v->_mp_d; |
wp = w->_mp_d; |
wp = w->_mp_d; |
|
|
free_me_size = w->_mp_alloc; |
free_me_size = w->_mp_alloc; |
} |
} |
else |
else |
(*_mp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB); |
(*__gmp_free_func) (wp, w->_mp_alloc * BYTES_PER_MP_LIMB); |
|
|
w->_mp_alloc = wsize; |
w->_mp_alloc = wsize; |
wp = (mp_ptr) (*_mp_allocate_func) (wsize * BYTES_PER_MP_LIMB); |
wp = (mp_ptr) (*__gmp_allocate_func) (wsize * BYTES_PER_MP_LIMB); |
w->_mp_d = wp; |
w->_mp_d = wp; |
} |
} |
else |
else |
|
|
} |
} |
} |
} |
|
|
if (vsize == 0) |
cy_limb = mpn_mul (wp, up, usize, vp, vsize); |
{ |
wsize = usize + vsize; |
wsize = 0; |
wsize -= cy_limb == 0; |
} |
|
else |
|
{ |
|
cy_limb = mpn_mul (wp, up, usize, vp, vsize); |
|
wsize = usize + vsize; |
|
wsize -= cy_limb == 0; |
|
} |
|
|
|
w->_mp_size = sign_product < 0 ? -wsize : wsize; |
w->_mp_size = sign_product < 0 ? -wsize : wsize; |
if (free_me != NULL) |
if (free_me != NULL) |
(*_mp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); |
(*__gmp_free_func) (free_me, free_me_size * BYTES_PER_MP_LIMB); |
TMP_FREE (marker); |
TMP_FREE (marker); |
} |
} |