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