(root)/
gmp-6.3.0/
mpf/
ui_div.c
       1  /* mpf_ui_div -- Divide an unsigned integer with a float.
       2  
       3  Copyright 1993-1996, 2000-2002, 2004, 2005, 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 <stdio.h>  /* for NULL */
      32  #include "gmp-impl.h"
      33  #include "longlong.h"
      34  
      35  
      36  void
      37  mpf_ui_div (mpf_ptr r, unsigned long int u, mpf_srcptr v)
      38  {
      39    mp_srcptr vp;
      40    mp_ptr rp, tp, remp, new_vp;
      41    mp_size_t vsize;
      42    mp_size_t rsize, prospective_rsize, zeros, tsize, high_zero;
      43    mp_size_t sign_quotient;
      44    mp_size_t prec;
      45    mp_exp_t rexp;
      46    TMP_DECL;
      47  
      48    vsize = v->_mp_size;
      49    sign_quotient = vsize;
      50  
      51    if (UNLIKELY (vsize == 0))
      52      DIVIDE_BY_ZERO;
      53  
      54    if (UNLIKELY (u == 0))
      55      {
      56        r->_mp_size = 0;
      57        r->_mp_exp = 0;
      58        return;
      59      }
      60  
      61    vsize = ABS (vsize);
      62    prec = r->_mp_prec;
      63  
      64    TMP_MARK;
      65    rexp = 1 - v->_mp_exp + 1;
      66  
      67    rp = r->_mp_d;
      68    vp = v->_mp_d;
      69  
      70    prospective_rsize = 1 - vsize + 1;    /* quot from using given u,v sizes */
      71    rsize = prec + 1;                     /* desired quot size */
      72  
      73    zeros = rsize - prospective_rsize;    /* padding u to give rsize */
      74    tsize = 1 + zeros;                    /* u with zeros */
      75  
      76    if (WANT_TMP_DEBUG)
      77      {
      78        /* separate alloc blocks, for malloc debugging */
      79        remp = TMP_ALLOC_LIMBS (vsize);
      80        tp = TMP_ALLOC_LIMBS (tsize);
      81        new_vp = NULL;
      82        if (rp == vp)
      83          new_vp = TMP_ALLOC_LIMBS (vsize);
      84      }
      85    else
      86      {
      87        /* one alloc with calculated size, for efficiency */
      88        mp_size_t size = vsize + tsize + (rp == vp ? vsize : 0);
      89        remp = TMP_ALLOC_LIMBS (size);
      90        tp = remp + vsize;
      91        new_vp = tp + tsize;
      92      }
      93  
      94    /* ensure divisor doesn't overlap quotient */
      95    if (rp == vp)
      96      {
      97        MPN_COPY (new_vp, vp, vsize);
      98        vp = new_vp;
      99      }
     100  
     101    MPN_ZERO (tp, tsize-1);
     102  
     103    tp[tsize - 1] = u & GMP_NUMB_MASK;
     104  #if BITS_PER_ULONG > GMP_NUMB_BITS
     105    if (u > GMP_NUMB_MAX)
     106      {
     107        /* tsize-vsize+1 == rsize, so tsize >= rsize.  rsize == prec+1 >= 2,
     108           so tsize >= 2, hence there's room for 2-limb u with nails */
     109        ASSERT (tsize >= 2);
     110        tp[tsize - 1] = u >> GMP_NUMB_BITS;
     111        tp[tsize - 2] = u & GMP_NUMB_MASK;
     112        rexp++;
     113      }
     114  #endif
     115  
     116    ASSERT (tsize-vsize+1 == rsize);
     117    mpn_tdiv_qr (rp, remp, (mp_size_t) 0, tp, tsize, vp, vsize);
     118  
     119    /* strip possible zero high limb */
     120    high_zero = (rp[rsize-1] == 0);
     121    rsize -= high_zero;
     122    rexp -= high_zero;
     123  
     124    r->_mp_size = sign_quotient >= 0 ? rsize : -rsize;
     125    r->_mp_exp = rexp;
     126    TMP_FREE;
     127  }