1 /* mpz_addmul, mpz_submul -- add or subtract multiple.
3 Copyright 2001, 2004, 2005 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
12 The GNU MP Library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
24 /* expecting x and y both with non-zero high limbs */
25 #define mpn_cmp_twosizes_lt(xp,xsize, yp,ysize) \
27 || ((xsize) == (ysize) && mpn_cmp (xp, yp, xsize) < 0))
30 /* sub>=0 means an addmul w += x*y, sub<0 means a submul w -= x*y.
32 The signs of w, x and y are fully accounted for by each flipping "sub".
34 The sign of w is retained for the result, unless the absolute value
35 submul underflows, in which case it flips. */
37 static void __gmpz_aorsmul __GMP_PROTO ((REGPARM_3_1 (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub))) REGPARM_ATTR (1);
38 #define mpz_aorsmul(w,x,y,sub) __gmpz_aorsmul (REGPARM_3_1 (w, x, y, sub))
40 REGPARM_ATTR (1) static void
41 mpz_aorsmul (mpz_ptr w, mpz_srcptr x, mpz_srcptr y, mp_size_t sub)
43 mp_size_t xsize, ysize, tsize, wsize, wsize_signed;
48 /* w unaffected if x==0 or y==0 */
51 if (xsize == 0 || ysize == 0)
54 /* make x the bigger of the two */
55 if (ABS(ysize) > ABS(xsize))
57 MPZ_SRCPTR_SWAP (x, y);
58 MP_SIZE_T_SWAP (xsize, ysize);
64 /* use mpn_addmul_1/mpn_submul_1 if possible */
67 mpz_aorsmul_1 (w, x, PTR(y)[0], sub);
74 wsize_signed = SIZ(w);
76 wsize = ABS(wsize_signed);
78 tsize = xsize + ysize;
79 MPZ_REALLOC (w, MAX (wsize, tsize) + 1);
82 if (wsize_signed == 0)
84 /* Nothing to add to, just set w=x*y. No w==x or w==y overlap here,
85 since we know x,y!=0 but w==0. */
86 high = mpn_mul (wp, PTR(x),xsize, PTR(y),ysize);
88 SIZ(w) = (sub >= 0 ? tsize : -tsize);
93 tp = TMP_ALLOC_LIMBS (tsize);
95 high = mpn_mul (tp, PTR(x),xsize, PTR(y),ysize);
97 ASSERT (tp[tsize-1] != 0);
101 mp_size_t usize = wsize;
113 c = mpn_add (wp, up,usize, tp,tsize);
120 mp_size_t usize = wsize;
122 if (mpn_cmp_twosizes_lt (up,usize, tp,tsize))
130 wsize_signed = -wsize_signed;
133 ASSERT_NOCARRY (mpn_sub (wp, up,usize, tp,tsize));
135 MPN_NORMALIZE (wp, wsize);
138 SIZ(w) = (wsize_signed >= 0 ? wsize : -wsize);
145 mpz_addmul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
147 mpz_aorsmul (w, u, v, (mp_size_t) 0);
151 mpz_submul (mpz_ptr w, mpz_srcptr u, mpz_srcptr v)
153 mpz_aorsmul (w, u, v, (mp_size_t) -1);