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

Revision 18191, 3.4 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_set_q (mpf_t rop, mpq_t op) -- Convert the rational op to the float rop.
2
3Copyright 1996, 1999, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 2.1 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20MA 02111-1307, USA. */
21
22#include "gmp.h"
23#include "gmp-impl.h"
24#include "longlong.h"
25
26void
27mpf_set_q (mpf_t r, mpq_srcptr q)
28{
29  mp_ptr np, dp;
30  mp_ptr rp;
31  mp_size_t nsize, dsize;
32  mp_size_t qsize, rsize;
33  mp_size_t sign_quotient;
34  mp_limb_t qlimb;
35  mp_ptr qp;
36  mp_size_t prec;
37  mp_exp_t exp;
38  TMP_DECL (marker);
39
40  nsize = SIZ (&q->_mp_num);
41  dsize = SIZ (&q->_mp_den);
42
43  if (nsize == 0)
44    {
45      SIZ (r) = 0;
46      EXP (r) = 0;
47      return;
48    }
49
50  prec = PREC (r) + 1;
51
52  TMP_MARK (marker);
53
54  qp = PTR (r);
55
56  sign_quotient = nsize ^ dsize;
57  nsize = ABS (nsize);
58  dsize = ABS (dsize);
59  np = PTR (&q->_mp_num);
60  dp = PTR (&q->_mp_den);
61
62  exp = nsize - dsize;
63
64  if (nsize > prec)
65    {
66      np += nsize - prec;
67      nsize = prec;
68    }
69  if (dsize > prec)
70    {
71      dp += dsize - prec;
72      dsize = prec;
73    }
74
75  rsize = MAX (nsize, dsize);
76  rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB);
77
78  /* Normalize the denominator, i.e. make its most significant bit set by
79     shifting it NORMALIZATION_STEPS bits to the left.  Also shift the
80     numerator the same number of steps (to keep the quotient the same!).  */
81  if ((dp[dsize - 1] & GMP_NUMB_HIGHBIT) == 0)
82    {
83      mp_ptr tp;
84      mp_limb_t nlimb;
85      unsigned normalization_steps;
86
87      count_leading_zeros (normalization_steps, dp[dsize - 1]);
88      normalization_steps -= GMP_NAIL_BITS;
89
90      /* Shift up the denominator setting the most significant bit of
91         the most significant limb.  Use temporary storage not to clobber
92         the original contents of the denominator.  */
93      tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
94      mpn_lshift (tp, dp, dsize, normalization_steps);
95      dp = tp;
96
97      if (rsize != nsize)
98        {
99          MPN_ZERO (rp, rsize - nsize);
100          nlimb = mpn_lshift (rp + (rsize - nsize),
101                              np, nsize, normalization_steps);
102        }
103      else
104        {
105          nlimb = mpn_lshift (rp, np, rsize, normalization_steps);
106        }
107      if (nlimb != 0)
108        {
109          rp[rsize] = nlimb;
110          exp++;
111          /* Don't just increase rsize, chop off rp at the low end instead.  */
112          if (rsize == prec)
113            rp++;
114          else
115            rsize++;
116        }
117    }
118  else
119    {
120      if (rsize != nsize)
121        {
122          MPN_ZERO (rp, rsize - nsize);
123          MPN_COPY (rp + (rsize - nsize), np, nsize);
124        }
125      else
126        {
127          MPN_COPY (rp, np, rsize);
128        }
129    }
130
131  qlimb = mpn_divrem (qp, prec - 1 - (rsize - dsize), rp, rsize, dp, dsize);
132  qsize = prec - 1;
133  if (qlimb)
134    {
135      qp[qsize] = qlimb;
136      qsize++;
137      exp++;
138    }
139
140  EXP (r) = exp;
141  SIZ (r) = sign_quotient >= 0 ? qsize : -qsize;
142
143  TMP_FREE (marker);
144}
Note: See TracBrowser for help on using the repository browser.