1 /* mpz_mul -- Multiply two integers.
3 Copyright 1991, 1993, 1994, 1996, 2000, 2001, 2005, 2009, 2011 Free
4 Software Foundation, Inc.
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 */
39 mp_size_t sign_product
;
49 sign_product
= usize
^ vsize
;
55 MPZ_SRCPTR_SWAP (u
, v
);
56 MP_SIZE_T_SWAP (usize
, vsize
);
65 #if HAVE_NATIVE_mpn_mul_2
68 MPZ_REALLOC (w
, usize
+vsize
);
71 cy_limb
= mpn_mul_1 (wp
, PTR(u
), usize
, PTR(v
)[0]);
74 cy_limb
= mpn_mul_2 (wp
, PTR(u
), usize
, PTR(v
));
78 usize
+= (cy_limb
!= 0);
79 SIZ(w
) = (sign_product
>= 0 ? usize
: -usize
);
85 MPZ_REALLOC (w
, usize
+1);
87 cy_limb
= mpn_mul_1 (wp
, PTR(u
), usize
, PTR(v
)[0]);
89 usize
+= (cy_limb
!= 0);
90 SIZ(w
) = (sign_product
>= 0 ? usize
: -usize
);
101 /* Ensure W has space enough to store the result. */
102 wsize
= usize
+ vsize
;
103 if (ALLOC(w
) < wsize
)
105 if (wp
== up
|| wp
== vp
)
108 free_me_size
= ALLOC(w
);
111 (*__gmp_free_func
) (wp
, ALLOC(w
) * BYTES_PER_MP_LIMB
);
114 wp
= (mp_ptr
) (*__gmp_allocate_func
) (wsize
* BYTES_PER_MP_LIMB
);
119 /* Make U and V not overlap with W. */
122 /* W and U are identical. Allocate temporary space for U. */
123 up
= TMP_ALLOC_LIMBS (usize
);
124 /* Is V identical too? Keep it identical with U. */
127 /* Copy to the temporary space. */
128 MPN_COPY (up
, wp
, usize
);
132 /* W and V are identical. Allocate temporary space for V. */
133 vp
= TMP_ALLOC_LIMBS (vsize
);
134 /* Copy to the temporary space. */
135 MPN_COPY (vp
, wp
, vsize
);
141 mpn_sqr (wp
, up
, usize
);
142 cy_limb
= wp
[wsize
- 1];
146 cy_limb
= mpn_mul (wp
, up
, usize
, vp
, vsize
);
149 wsize
-= cy_limb
== 0;
151 SIZ(w
) = sign_product
< 0 ? -wsize
: wsize
;
153 (*__gmp_free_func
) (free_me
, free_me_size
* BYTES_PER_MP_LIMB
);