1/* mpf_ui_div -- Divide an unsigned integer with a float. 2 3Copyright 1993, 1994, 1995, 1996, 2000, 2001, 2002, 2004, 2005 Free Software 4Foundation, Inc. 5 6This file is part of the GNU MP Library. 7 8The GNU MP Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MP Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 20 21#include <stdio.h> /* for NULL */ 22#include "gmp.h" 23#include "gmp-impl.h" 24#include "longlong.h" 25 26 27void 28mpf_ui_div (mpf_ptr r, unsigned long int u, mpf_srcptr v) 29{ 30 mp_srcptr vp; 31 mp_ptr rp, tp, remp, new_vp; 32 mp_size_t vsize; 33 mp_size_t rsize, prospective_rsize, zeros, tsize, high_zero; 34 mp_size_t sign_quotient; 35 mp_size_t prec; 36 mp_exp_t rexp; 37 TMP_DECL; 38 39 vsize = v->_mp_size; 40 sign_quotient = vsize; 41 vsize = ABS (vsize); 42 prec = r->_mp_prec; 43 44 if (UNLIKELY (vsize == 0)) 45 DIVIDE_BY_ZERO; 46 47 if (UNLIKELY (u == 0)) 48 { 49 r->_mp_size = 0; 50 r->_mp_exp = 0; 51 return; 52 } 53 54 TMP_MARK; 55 rexp = 1 - v->_mp_exp + 1; 56 57 rp = r->_mp_d; 58 vp = v->_mp_d; 59 60 prospective_rsize = 1 - vsize + 1; /* quot from using given u,v sizes */ 61 rsize = prec + 1; /* desired quot size */ 62 63 zeros = rsize - prospective_rsize; /* padding u to give rsize */ 64 tsize = 1 + zeros; /* u with zeros */ 65 66 if (WANT_TMP_DEBUG) 67 { 68 /* separate alloc blocks, for malloc debugging */ 69 remp = TMP_ALLOC_LIMBS (vsize); 70 tp = TMP_ALLOC_LIMBS (tsize); 71 new_vp = NULL; 72 if (rp == vp) 73 new_vp = TMP_ALLOC_LIMBS (vsize); 74 } 75 else 76 { 77 /* one alloc with calculated size, for efficiency */ 78 mp_size_t size = vsize + tsize + (rp == vp ? vsize : 0); 79 remp = TMP_ALLOC_LIMBS (size); 80 tp = remp + vsize; 81 new_vp = tp + tsize; 82 } 83 84 /* ensure divisor doesn't overlap quotient */ 85 if (rp == vp) 86 { 87 MPN_COPY (new_vp, vp, vsize); 88 vp = new_vp; 89 } 90 91 MPN_ZERO (tp, tsize-1); 92 93 tp[tsize - 1] = u & GMP_NUMB_MASK; 94#if BITS_PER_ULONG > GMP_NUMB_BITS 95 if (u > GMP_NUMB_MAX) 96 { 97 /* tsize-vsize+1 == rsize, so tsize >= rsize. rsize == prec+1 >= 2, 98 so tsize >= 2, hence there's room for 2-limb u with nails */ 99 ASSERT (tsize >= 2); 100 tp[tsize - 1] = u >> GMP_NUMB_BITS; 101 tp[tsize - 2] = u & GMP_NUMB_MASK; 102 rexp++; 103 } 104#endif 105 106 ASSERT (tsize-vsize+1 == rsize); 107 mpn_tdiv_qr (rp, remp, (mp_size_t) 0, tp, tsize, vp, vsize); 108 109 /* strip possible zero high limb */ 110 high_zero = (rp[rsize-1] == 0); 111 rsize -= high_zero; 112 rexp -= high_zero; 113 114 r->_mp_size = sign_quotient >= 0 ? rsize : -rsize; 115 r->_mp_exp = rexp; 116 TMP_FREE; 117} 118