xref: /dragonfly/contrib/gmp/mpz/aors.h (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /* mpz_add, mpz_sub -- add or subtract integers.
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino Copyright 1991, 1993, 1994, 1996, 2000, 2001 Free Software Foundation, Inc.
4*86d7f5d3SJohn Marino 
5*86d7f5d3SJohn Marino This file is part of the GNU MP Library.
6*86d7f5d3SJohn Marino 
7*86d7f5d3SJohn Marino The GNU MP Library is free software; you can redistribute it and/or modify
8*86d7f5d3SJohn Marino it under the terms of the GNU Lesser General Public License as published by
9*86d7f5d3SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
10*86d7f5d3SJohn Marino option) any later version.
11*86d7f5d3SJohn Marino 
12*86d7f5d3SJohn Marino The GNU MP Library is distributed in the hope that it will be useful, but
13*86d7f5d3SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*86d7f5d3SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15*86d7f5d3SJohn Marino License for more details.
16*86d7f5d3SJohn Marino 
17*86d7f5d3SJohn Marino You should have received a copy of the GNU Lesser General Public License
18*86d7f5d3SJohn Marino along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19*86d7f5d3SJohn Marino 
20*86d7f5d3SJohn Marino #include "gmp.h"
21*86d7f5d3SJohn Marino #include "gmp-impl.h"
22*86d7f5d3SJohn Marino 
23*86d7f5d3SJohn Marino 
24*86d7f5d3SJohn Marino #ifdef BERKELEY_MP
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino #include "mp.h"
27*86d7f5d3SJohn Marino #ifdef OPERATION_add
28*86d7f5d3SJohn Marino #define FUNCTION     madd
29*86d7f5d3SJohn Marino #define VARIATION
30*86d7f5d3SJohn Marino #endif
31*86d7f5d3SJohn Marino #ifdef OPERATION_sub
32*86d7f5d3SJohn Marino #define FUNCTION     msub
33*86d7f5d3SJohn Marino #define VARIATION    -
34*86d7f5d3SJohn Marino #endif
35*86d7f5d3SJohn Marino #define ARGUMENTS    mpz_srcptr u, mpz_srcptr v, mpz_ptr w
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino #else /* normal GMP */
38*86d7f5d3SJohn Marino 
39*86d7f5d3SJohn Marino #ifdef OPERATION_add
40*86d7f5d3SJohn Marino #define FUNCTION     mpz_add
41*86d7f5d3SJohn Marino #define VARIATION
42*86d7f5d3SJohn Marino #endif
43*86d7f5d3SJohn Marino #ifdef OPERATION_sub
44*86d7f5d3SJohn Marino #define FUNCTION     mpz_sub
45*86d7f5d3SJohn Marino #define VARIATION    -
46*86d7f5d3SJohn Marino #endif
47*86d7f5d3SJohn Marino #define ARGUMENTS    mpz_ptr w, mpz_srcptr u, mpz_srcptr v
48*86d7f5d3SJohn Marino 
49*86d7f5d3SJohn Marino #endif
50*86d7f5d3SJohn Marino 
51*86d7f5d3SJohn Marino #ifndef FUNCTION
52*86d7f5d3SJohn Marino Error, need OPERATION_add or OPERATION_sub
53*86d7f5d3SJohn Marino #endif
54*86d7f5d3SJohn Marino 
55*86d7f5d3SJohn Marino 
56*86d7f5d3SJohn Marino void
57*86d7f5d3SJohn Marino FUNCTION (ARGUMENTS)
58*86d7f5d3SJohn Marino {
59*86d7f5d3SJohn Marino   mp_srcptr up, vp;
60*86d7f5d3SJohn Marino   mp_ptr wp;
61*86d7f5d3SJohn Marino   mp_size_t usize, vsize, wsize;
62*86d7f5d3SJohn Marino   mp_size_t abs_usize;
63*86d7f5d3SJohn Marino   mp_size_t abs_vsize;
64*86d7f5d3SJohn Marino 
65*86d7f5d3SJohn Marino   usize = u->_mp_size;
66*86d7f5d3SJohn Marino   vsize = VARIATION v->_mp_size;
67*86d7f5d3SJohn Marino   abs_usize = ABS (usize);
68*86d7f5d3SJohn Marino   abs_vsize = ABS (vsize);
69*86d7f5d3SJohn Marino 
70*86d7f5d3SJohn Marino   if (abs_usize < abs_vsize)
71*86d7f5d3SJohn Marino     {
72*86d7f5d3SJohn Marino       /* Swap U and V. */
73*86d7f5d3SJohn Marino       MPZ_SRCPTR_SWAP (u, v);
74*86d7f5d3SJohn Marino       MP_SIZE_T_SWAP (usize, vsize);
75*86d7f5d3SJohn Marino       MP_SIZE_T_SWAP (abs_usize, abs_vsize);
76*86d7f5d3SJohn Marino     }
77*86d7f5d3SJohn Marino 
78*86d7f5d3SJohn Marino   /* True: ABS_USIZE >= ABS_VSIZE.  */
79*86d7f5d3SJohn Marino 
80*86d7f5d3SJohn Marino   /* If not space for w (and possible carry), increase space.  */
81*86d7f5d3SJohn Marino   wsize = abs_usize + 1;
82*86d7f5d3SJohn Marino   if (w->_mp_alloc < wsize)
83*86d7f5d3SJohn Marino     _mpz_realloc (w, wsize);
84*86d7f5d3SJohn Marino 
85*86d7f5d3SJohn Marino   /* These must be after realloc (u or v may be the same as w).  */
86*86d7f5d3SJohn Marino   up = u->_mp_d;
87*86d7f5d3SJohn Marino   vp = v->_mp_d;
88*86d7f5d3SJohn Marino   wp = w->_mp_d;
89*86d7f5d3SJohn Marino 
90*86d7f5d3SJohn Marino   if ((usize ^ vsize) < 0)
91*86d7f5d3SJohn Marino     {
92*86d7f5d3SJohn Marino       /* U and V have different sign.  Need to compare them to determine
93*86d7f5d3SJohn Marino 	 which operand to subtract from which.  */
94*86d7f5d3SJohn Marino 
95*86d7f5d3SJohn Marino       /* This test is right since ABS_USIZE >= ABS_VSIZE.  */
96*86d7f5d3SJohn Marino       if (abs_usize != abs_vsize)
97*86d7f5d3SJohn Marino 	{
98*86d7f5d3SJohn Marino 	  mpn_sub (wp, up, abs_usize, vp, abs_vsize);
99*86d7f5d3SJohn Marino 	  wsize = abs_usize;
100*86d7f5d3SJohn Marino 	  MPN_NORMALIZE (wp, wsize);
101*86d7f5d3SJohn Marino 	  if (usize < 0)
102*86d7f5d3SJohn Marino 	    wsize = -wsize;
103*86d7f5d3SJohn Marino 	}
104*86d7f5d3SJohn Marino       else if (mpn_cmp (up, vp, abs_usize) < 0)
105*86d7f5d3SJohn Marino 	{
106*86d7f5d3SJohn Marino 	  mpn_sub_n (wp, vp, up, abs_usize);
107*86d7f5d3SJohn Marino 	  wsize = abs_usize;
108*86d7f5d3SJohn Marino 	  MPN_NORMALIZE (wp, wsize);
109*86d7f5d3SJohn Marino 	  if (usize >= 0)
110*86d7f5d3SJohn Marino 	    wsize = -wsize;
111*86d7f5d3SJohn Marino 	}
112*86d7f5d3SJohn Marino       else
113*86d7f5d3SJohn Marino 	{
114*86d7f5d3SJohn Marino 	  mpn_sub_n (wp, up, vp, abs_usize);
115*86d7f5d3SJohn Marino 	  wsize = abs_usize;
116*86d7f5d3SJohn Marino 	  MPN_NORMALIZE (wp, wsize);
117*86d7f5d3SJohn Marino 	  if (usize < 0)
118*86d7f5d3SJohn Marino 	    wsize = -wsize;
119*86d7f5d3SJohn Marino 	}
120*86d7f5d3SJohn Marino     }
121*86d7f5d3SJohn Marino   else
122*86d7f5d3SJohn Marino     {
123*86d7f5d3SJohn Marino       /* U and V have same sign.  Add them.  */
124*86d7f5d3SJohn Marino       mp_limb_t cy_limb = mpn_add (wp, up, abs_usize, vp, abs_vsize);
125*86d7f5d3SJohn Marino       wp[abs_usize] = cy_limb;
126*86d7f5d3SJohn Marino       wsize = abs_usize + cy_limb;
127*86d7f5d3SJohn Marino       if (usize < 0)
128*86d7f5d3SJohn Marino 	wsize = -wsize;
129*86d7f5d3SJohn Marino     }
130*86d7f5d3SJohn Marino 
131*86d7f5d3SJohn Marino   w->_mp_size = wsize;
132*86d7f5d3SJohn Marino }
133