source: trunk/third/gmp/mpf/ui_div.c @ 18191

Revision 18191, 3.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18190, which included commits to RCS files with non-trunk default branches.
Line 
1/* mpf_ui_div -- Divide an unsigned integer with a float.
2
3Copyright 1993, 1994, 1995, 1996, 2000, 2001, 2002 Free Software Foundation,
4Inc.
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 2.1 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; see the file COPYING.LIB.  If not, write to
20the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21MA 02111-1307, USA. */
22
23#include "gmp.h"
24#include "gmp-impl.h"
25#include "longlong.h"
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;
32  mp_size_t vsize;
33  mp_size_t rsize, tsize;
34  mp_size_t sign_quotient;
35  mp_size_t prec;
36  mp_limb_t q_limb;
37  mp_exp_t rexp;
38  TMP_DECL (marker);
39
40  vsize = v->_mp_size;
41  sign_quotient = vsize;
42  vsize = ABS (vsize);
43  prec = r->_mp_prec;
44
45  if (vsize == 0)
46    DIVIDE_BY_ZERO;
47
48  if (u == 0)
49    {
50      r->_mp_size = 0;
51      r->_mp_exp = 0;
52      return;
53    }
54
55  TMP_MARK (marker);
56  rexp = 1 - v->_mp_exp;
57
58  rp = r->_mp_d;
59  vp = v->_mp_d;
60
61  if (vsize > prec)
62    {
63      vp += vsize - prec;
64      vsize = prec;
65    }
66
67  tsize = vsize + prec;
68  tp = (mp_ptr) TMP_ALLOC ((tsize + 1) * BYTES_PER_MP_LIMB);
69  MPN_ZERO (tp, tsize);
70
71  /* Normalize the divisor and the dividend.  */
72  if ((vp[vsize - 1] & GMP_NUMB_HIGHBIT) == 0)
73    {
74      mp_ptr tmp;
75      mp_limb_t dividend_high, dividend_low;
76      unsigned normalization_steps;
77
78      count_leading_zeros (normalization_steps, vp[vsize - 1]);
79      normalization_steps -= GMP_NAIL_BITS;
80
81      /* Shift up the divisor setting the most significant bit of
82         the most significant limb.  Use temporary storage not to clobber
83         the original contents of the divisor.  */
84      tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
85      mpn_lshift (tmp, vp, vsize, normalization_steps);
86      vp = tmp;
87
88      /* Shift up the dividend, possibly introducing a new most
89         significant word.  */
90      dividend_high = (mp_limb_t) u >> (GMP_NUMB_BITS - normalization_steps);
91      dividend_low = ((mp_limb_t) u << normalization_steps) & GMP_NUMB_MASK;
92
93      tp[tsize - 1] = dividend_low;
94      if (dividend_high != 0)
95        {
96#if GMP_NAIL_BITS != 0
97          if (dividend_high > vp[vsize - 1])
98            {
99              tp[tsize - 2] = dividend_low;
100              tp[tsize - 1] = dividend_high & GMP_NUMB_MASK;
101              tp[tsize] = dividend_high >> GMP_NUMB_BITS;
102              tsize++;
103              rexp += 2;
104            }
105          else
106#endif
107            {
108              tp[tsize] = dividend_high;
109              tsize++;
110              rexp++;
111            }
112        }
113    }
114  else
115    {
116      /* The divisor is already normalized, as required.
117         Copy it to temporary space if it overlaps with the quotient.  */
118      if (vp - rp <= tsize - vsize)
119        {
120          mp_ptr tmp = (mp_ptr) TMP_ALLOC (vsize * BYTES_PER_MP_LIMB);
121          MPN_COPY (tmp, vp, vsize);
122          vp = (mp_srcptr) tmp;
123        }
124
125      tp[tsize - 1] = u & GMP_NUMB_MASK;
126#if GMP_NAIL_BITS != 0
127      if (u > GMP_NUMB_MAX)
128        {
129          tp[tsize] = u >> GMP_NUMB_BITS;
130          tsize++;
131          rexp++;
132        }
133#endif
134    }
135
136  q_limb = mpn_divmod (rp, tp, tsize, vp, vsize);
137  rsize = tsize - vsize;
138  if (q_limb)
139    {
140      rp[rsize] = q_limb;
141      rsize++;
142      rexp++;
143    }
144
145  r->_mp_size = sign_quotient >= 0 ? rsize : -rsize;
146  r->_mp_exp = rexp;
147  TMP_FREE (marker);
148}
Note: See TracBrowser for help on using the repository browser.