(root)/
gmp-6.3.0/
mpz/
cfdiv_r_2exp.c
       1  /* mpz_cdiv_r_2exp, mpz_fdiv_r_2exp -- remainder from mpz divided by 2^n.
       2  
       3  Copyright 2001, 2002, 2004, 2012 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library.
       6  
       7  The GNU MP Library is free software; you can redistribute it and/or modify
       8  it under the terms of either:
       9  
      10    * the GNU Lesser General Public License as published by the Free
      11      Software Foundation; either version 3 of the License, or (at your
      12      option) any later version.
      13  
      14  or
      15  
      16    * the GNU General Public License as published by the Free Software
      17      Foundation; either version 2 of the License, or (at your option) any
      18      later version.
      19  
      20  or both in parallel, as here.
      21  
      22  The GNU MP Library is distributed in the hope that it will be useful, but
      23  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      24  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      25  for more details.
      26  
      27  You should have received copies of the GNU General Public License and the
      28  GNU Lesser General Public License along with the GNU MP Library.  If not,
      29  see https://www.gnu.org/licenses/.  */
      30  
      31  #include "gmp-impl.h"
      32  
      33  
      34  /* Bit mask of "n" least significant bits of a limb. */
      35  #define LOW_MASK(n)   ((CNST_LIMB(1) << (n)) - 1)
      36  
      37  
      38  /* dir==1 for ceil, dir==-1 for floor */
      39  
      40  static void __gmpz_cfdiv_r_2exp (REGPARM_3_1 (mpz_ptr, mpz_srcptr, mp_bitcnt_t, int)) REGPARM_ATTR (1);
      41  #define cfdiv_r_2exp(w,u,cnt,dir)  __gmpz_cfdiv_r_2exp (REGPARM_3_1 (w, u, cnt, dir))
      42  
      43  REGPARM_ATTR (1) static void
      44  cfdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt, int dir)
      45  {
      46    mp_size_t  usize, abs_usize, limb_cnt, i;
      47    mp_srcptr  up;
      48    mp_ptr     wp;
      49    mp_limb_t  high;
      50  
      51    usize = SIZ(u);
      52    if (usize == 0)
      53      {
      54        SIZ(w) = 0;
      55        return;
      56      }
      57  
      58    limb_cnt = cnt / GMP_NUMB_BITS;
      59    cnt %= GMP_NUMB_BITS;
      60    abs_usize = ABS (usize);
      61  
      62    /* MPZ_REALLOC(w) below is only when w!=u, so we can fetch PTR(u) here
      63       nice and early */
      64    up = PTR(u);
      65  
      66    if ((usize ^ dir) < 0)
      67      {
      68        /* Round towards zero, means just truncate */
      69  
      70        if (w == u)
      71  	{
      72  	  /* if already smaller than limb_cnt then do nothing */
      73  	  if (abs_usize <= limb_cnt)
      74  	    return;
      75  	  wp = (mp_ptr) up;
      76  	}
      77        else
      78  	{
      79  	  i = MIN (abs_usize, limb_cnt+1);
      80  	  wp = MPZ_NEWALLOC (w, i);
      81  	  MPN_COPY (wp, up, i);
      82  
      83  	  /* if smaller than limb_cnt then only the copy is needed */
      84  	  if (abs_usize <= limb_cnt)
      85  	    {
      86  	      SIZ(w) = usize;
      87  	      return;
      88  	    }
      89  	}
      90      }
      91    else
      92      {
      93        /* Round away from zero, means twos complement if non-zero */
      94  
      95        /* if u!=0 and smaller than divisor, then must negate */
      96        if (abs_usize <= limb_cnt)
      97  	goto negate;
      98  
      99        /* if non-zero low limb, then must negate */
     100        for (i = 0; i < limb_cnt; i++)
     101  	if (up[i] != 0)
     102  	  goto negate;
     103  
     104        /* if non-zero partial limb, then must negate */
     105        if ((up[limb_cnt] & LOW_MASK (cnt)) != 0)
     106  	goto negate;
     107  
     108        /* otherwise low bits of u are zero, so that's the result */
     109        SIZ(w) = 0;
     110        return;
     111  
     112      negate:
     113        /* twos complement negation to get 2**cnt-u */
     114  
     115        wp = MPZ_REALLOC (w, limb_cnt+1);
     116        up = PTR(u);
     117  
     118        /* Ones complement */
     119        i = MIN (abs_usize, limb_cnt+1);
     120        ASSERT_CARRY (mpn_neg (wp, up, i));
     121        for ( ; i <= limb_cnt; i++)
     122  	wp[i] = GMP_NUMB_MAX;
     123  
     124        usize = -usize;
     125      }
     126  
     127    /* Mask the high limb */
     128    high = wp[limb_cnt];
     129    high &= LOW_MASK (cnt);
     130    wp[limb_cnt] = high;
     131  
     132    /* Strip any consequent high zeros */
     133    while (high == 0)
     134      {
     135        limb_cnt--;
     136        if (limb_cnt < 0)
     137  	{
     138  	  SIZ(w) = 0;
     139  	  return;
     140  	}
     141        high = wp[limb_cnt];
     142      }
     143  
     144    limb_cnt++;
     145    SIZ(w) = (usize >= 0 ? limb_cnt : -limb_cnt);
     146  }
     147  
     148  
     149  void
     150  mpz_cdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
     151  {
     152    cfdiv_r_2exp (w, u, cnt, 1);
     153  }
     154  
     155  void
     156  mpz_fdiv_r_2exp (mpz_ptr w, mpz_srcptr u, mp_bitcnt_t cnt)
     157  {
     158    cfdiv_r_2exp (w, u, cnt, -1);
     159  }