github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/generic/udiv_w_sdiv.c (about)

     1  /* mpn_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed
     2     division.
     3  
     4     Contributed by Peter L. Montgomery.
     5  
     6     THIS IS AN INTERNAL FUNCTION WITH A MUTABLE INTERFACE.  IT IS ONLY SAFE
     7     TO REACH THIS FUNCTION THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS
     8     ALMOST GUARANTEED THAT THIS FUNCTION WILL CHANGE OR DISAPPEAR IN A FUTURE
     9     GNU MP RELEASE.
    10  
    11  
    12  Copyright 1992, 1994, 1996, 2000, 2011, 2012 Free Software Foundation, Inc.
    13  
    14  This file is part of the GNU MP Library.
    15  
    16  The GNU MP Library is free software; you can redistribute it and/or modify
    17  it under the terms of either:
    18  
    19    * the GNU Lesser General Public License as published by the Free
    20      Software Foundation; either version 3 of the License, or (at your
    21      option) any later version.
    22  
    23  or
    24  
    25    * the GNU General Public License as published by the Free Software
    26      Foundation; either version 2 of the License, or (at your option) any
    27      later version.
    28  
    29  or both in parallel, as here.
    30  
    31  The GNU MP Library is distributed in the hope that it will be useful, but
    32  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    33  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    34  for more details.
    35  
    36  You should have received copies of the GNU General Public License and the
    37  GNU Lesser General Public License along with the GNU MP Library.  If not,
    38  see https://www.gnu.org/licenses/.  */
    39  
    40  #include "gmp.h"
    41  #include "gmp-impl.h"
    42  #include "longlong.h"
    43  
    44  mp_limb_t
    45  mpn_udiv_w_sdiv (mp_limb_t *rp, mp_limb_t a1, mp_limb_t a0, mp_limb_t d)
    46  {
    47    mp_limb_t q, r;
    48    mp_limb_t c0, c1, b1;
    49  
    50    ASSERT (d != 0);
    51    ASSERT (a1 < d);
    52  
    53    if ((mp_limb_signed_t) d >= 0)
    54      {
    55        if (a1 < d - a1 - (a0 >> (GMP_LIMB_BITS - 1)))
    56  	{
    57  	  /* dividend, divisor, and quotient are nonnegative */
    58  	  sdiv_qrnnd (q, r, a1, a0, d);
    59  	}
    60        else
    61  	{
    62  	  /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
    63  	  sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (GMP_LIMB_BITS - 1));
    64  	  /* Divide (c1*2^32 + c0) by d */
    65  	  sdiv_qrnnd (q, r, c1, c0, d);
    66  	  /* Add 2^31 to quotient */
    67  	  q += (mp_limb_t) 1 << (GMP_LIMB_BITS - 1);
    68  	}
    69      }
    70    else
    71      {
    72        b1 = d >> 1;			/* d/2, between 2^30 and 2^31 - 1 */
    73        c1 = a1 >> 1;			/* A/2 */
    74        c0 = (a1 << (GMP_LIMB_BITS - 1)) + (a0 >> 1);
    75  
    76        if (a1 < b1)			/* A < 2^32*b1, so A/2 < 2^31*b1 */
    77  	{
    78  	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
    79  
    80  	  r = 2*r + (a0 & 1);		/* Remainder from A/(2*b1) */
    81  	  if ((d & 1) != 0)
    82  	    {
    83  	      if (r >= q)
    84  		r = r - q;
    85  	      else if (q - r <= d)
    86  		{
    87  		  r = r - q + d;
    88  		  q--;
    89  		}
    90  	      else
    91  		{
    92  		  r = r - q + 2*d;
    93  		  q -= 2;
    94  		}
    95  	    }
    96  	}
    97        else if (c1 < b1)			/* So 2^31 <= (A/2)/b1 < 2^32 */
    98  	{
    99  	  c1 = (b1 - 1) - c1;
   100  	  c0 = ~c0;			/* logical NOT */
   101  
   102  	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
   103  
   104  	  q = ~q;			/* (A/2)/b1 */
   105  	  r = (b1 - 1) - r;
   106  
   107  	  r = 2*r + (a0 & 1);		/* A/(2*b1) */
   108  
   109  	  if ((d & 1) != 0)
   110  	    {
   111  	      if (r >= q)
   112  		r = r - q;
   113  	      else if (q - r <= d)
   114  		{
   115  		  r = r - q + d;
   116  		  q--;
   117  		}
   118  	      else
   119  		{
   120  		  r = r - q + 2*d;
   121  		  q -= 2;
   122  		}
   123  	    }
   124  	}
   125        else				/* Implies c1 = b1 */
   126  	{				/* Hence a1 = d - 1 = 2*b1 - 1 */
   127  	  if (a0 >= -d)
   128  	    {
   129  	      q = -CNST_LIMB(1);
   130  	      r = a0 + d;
   131  	    }
   132  	  else
   133  	    {
   134  	      q = -CNST_LIMB(2);
   135  	      r = a0 + 2*d;
   136  	    }
   137  	}
   138      }
   139  
   140    *rp = r;
   141    return q;
   142  }