~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to gmp3/mpf/set_q.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mpf_set_q (mpf_t rop, mpq_t op) -- Convert the rational op to the float rop.
 
2
 
 
3
Copyright 1996, 1999, 2001 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 the GNU Lesser General Public License as published by
 
9
the Free Software Foundation; either version 2.1 of the License, or (at your
 
10
option) any later version.
 
11
 
 
12
The GNU MP Library is distributed in the hope that it will be useful, but
 
13
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
14
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
15
License for more details.
 
16
 
 
17
You should have received a copy of the GNU Lesser General Public License
 
18
along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
 
19
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
20
MA 02111-1307, USA. */
 
21
 
 
22
#include "gmp.h"
 
23
#include "gmp-impl.h"
 
24
#include "longlong.h"
 
25
 
 
26
void
 
27
mpf_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] & MP_LIMB_T_HIGHBIT))
 
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
 
 
89
      /* Shift up the denominator setting the most significant bit of
 
90
         the most significant limb.  Use temporary storage not to clobber
 
91
         the original contents of the denominator.  */
 
92
      tp = (mp_ptr) TMP_ALLOC (dsize * BYTES_PER_MP_LIMB);
 
93
      mpn_lshift (tp, dp, dsize, normalization_steps);
 
94
      dp = tp;
 
95
 
 
96
      if (rsize != nsize)
 
97
        {
 
98
          MPN_ZERO (rp, rsize - nsize);
 
99
          nlimb = mpn_lshift (rp + (rsize - nsize),
 
100
                              np, nsize, normalization_steps);
 
101
        }
 
102
      else
 
103
        {
 
104
          nlimb = mpn_lshift (rp, np, rsize, normalization_steps);
 
105
        }
 
106
      if (nlimb != 0)
 
107
        {
 
108
          rp[rsize] = nlimb;
 
109
          exp++;
 
110
          /* Don't just increase rsize, chop off rp at the low end instead.  */
 
111
          if (rsize == prec)
 
112
            rp++;
 
113
          else
 
114
            rsize++;
 
115
        }
 
116
    }
 
117
  else
 
118
    {
 
119
      if (rsize != nsize)
 
120
        {
 
121
          MPN_ZERO (rp, rsize - nsize);
 
122
          MPN_COPY (rp + (rsize - nsize), np, nsize);
 
123
        }
 
124
      else
 
125
        {
 
126
          MPN_COPY (rp, np, rsize);
 
127
        }
 
128
    }
 
129
 
 
130
  qlimb = mpn_divrem (qp, prec - 1 - (rsize - dsize), rp, rsize, dp, dsize);
 
131
  qsize = prec - 1;
 
132
  if (qlimb)
 
133
    {
 
134
      qp[qsize] = qlimb;
 
135
      qsize++;
 
136
      exp++;
 
137
    }
 
138
 
 
139
  EXP (r) = exp;
 
140
  SIZ (r) = sign_quotient >= 0 ? qsize : -qsize;
 
141
 
 
142
  TMP_FREE (marker);
 
143
}