1 /* mpz_mul -- Multiply two integers.
3 Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2005 Free Software Foundation,
6 This file is part of the GNU MP Library.
8 The GNU MP Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MP Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 #include <stdio.h> /* for NULL */
31 mpz_mul (mpz_ptr w
, mpz_srcptr u
, mpz_srcptr v
)
32 #else /* BERKELEY_MP */
33 mult (mpz_srcptr u
, mpz_srcptr v
, mpz_ptr w
)
34 #endif /* BERKELEY_MP */
36 mp_size_t usize
= u
->_mp_size
;
37 mp_size_t vsize
= v
->_mp_size
;
39 mp_size_t sign_product
;
47 sign_product
= usize
^ vsize
;
53 MPZ_SRCPTR_SWAP (u
, v
);
54 MP_SIZE_T_SWAP (usize
, vsize
);
63 #if HAVE_NATIVE_mpn_mul_2
66 MPZ_REALLOC (w
, usize
+vsize
);
69 cy_limb
= mpn_mul_1 (wp
, PTR(u
), usize
, PTR(v
)[0]);
72 cy_limb
= mpn_mul_2 (wp
, PTR(u
), usize
, PTR(v
));
76 usize
+= (cy_limb
!= 0);
77 SIZ(w
) = (sign_product
>= 0 ? usize
: -usize
);
83 MPZ_REALLOC (w
, usize
+1);
85 cy_limb
= mpn_mul_1 (wp
, PTR(u
), usize
, PTR(v
)[0]);
87 usize
+= (cy_limb
!= 0);
88 SIZ(w
) = (sign_product
>= 0 ? usize
: -usize
);
99 /* Ensure W has space enough to store the result. */
100 wsize
= usize
+ vsize
;
101 if (w
->_mp_alloc
< wsize
)
103 if (wp
== up
|| wp
== vp
)
106 free_me_size
= w
->_mp_alloc
;
109 (*__gmp_free_func
) (wp
, w
->_mp_alloc
* BYTES_PER_MP_LIMB
);
111 w
->_mp_alloc
= wsize
;
112 wp
= (mp_ptr
) (*__gmp_allocate_func
) (wsize
* BYTES_PER_MP_LIMB
);
117 /* Make U and V not overlap with W. */
120 /* W and U are identical. Allocate temporary space for U. */
121 up
= (mp_ptr
) TMP_ALLOC (usize
* BYTES_PER_MP_LIMB
);
122 /* Is V identical too? Keep it identical with U. */
125 /* Copy to the temporary space. */
126 MPN_COPY (up
, wp
, usize
);
130 /* W and V are identical. Allocate temporary space for V. */
131 vp
= (mp_ptr
) TMP_ALLOC (vsize
* BYTES_PER_MP_LIMB
);
132 /* Copy to the temporary space. */
133 MPN_COPY (vp
, wp
, vsize
);
137 cy_limb
= mpn_mul (wp
, up
, usize
, vp
, vsize
);
138 wsize
= usize
+ vsize
;
139 wsize
-= cy_limb
== 0;
141 w
->_mp_size
= sign_product
< 0 ? -wsize
: wsize
;
143 (*__gmp_free_func
) (free_me
, free_me_size
* BYTES_PER_MP_LIMB
);