source: trunk/third/gmp/mpz/aors.h @ 18191

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