~ubuntu-branches/debian/sid/genius/sid

« back to all changes in this revision

Viewing changes to mpfr/set_q.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2006-08-21 12:57:45 UTC
  • Revision ID: james.westby@ubuntu.com-20060821125745-sl9ks8v7fq324bdf
Tags: upstream-0.7.6.1
ImportĀ upstreamĀ versionĀ 0.7.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mpfr_set_q -- set a floating-point number from a multiple-precision rational
 
2
 
 
3
Copyright 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
 
4
 
 
5
This file is part of the MPFR Library.
 
6
 
 
7
The MPFR 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 MPFR 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 MPFR Library; see the file COPYING.LIB.  If not, write to
 
19
the Free Software Foundation, Inc., 51 Franklin Place, Fifth Floor, Boston,
 
20
MA 02110-1301, USA. */
 
21
 
 
22
#define MPFR_NEED_LONGLONG_H
 
23
#include "mpfr-impl.h"
 
24
 
 
25
/*
 
26
 * Set f to z, choosing the smallest precision for f
 
27
 * so that z = f*(2^BPML)*zs*2^(RetVal)
 
28
 */
 
29
static int
 
30
set_z (mpfr_ptr f, mpz_srcptr z, mp_size_t *zs)
 
31
{
 
32
  mp_limb_t *p;
 
33
  mp_size_t s;
 
34
  int c;
 
35
  mp_prec_t pf;
 
36
 
 
37
  MPFR_ASSERTD (mpz_sgn (z) != 0);
 
38
 
 
39
  /* Remove useless ending 0 */
 
40
  for (p = PTR (z), s = *zs = ABS (SIZ (z)) ; *p == 0; p++, s--)
 
41
    MPFR_ASSERTD (s >= 0);
 
42
 
 
43
  /* Get working precision */
 
44
  count_leading_zeros (c, p[s-1]);
 
45
  pf = s * BITS_PER_MP_LIMB - c;
 
46
  if (pf < MPFR_PREC_MIN)
 
47
    pf = MPFR_PREC_MIN;
 
48
  mpfr_init2 (f, pf);
 
49
 
 
50
  /* Copy Mantissa */
 
51
  if (MPFR_LIKELY (c))
 
52
    mpn_lshift (MPFR_MANT (f), p, s, c);
 
53
  else
 
54
    MPN_COPY (MPFR_MANT (f), p, s);
 
55
 
 
56
  MPFR_SET_SIGN (f, mpz_sgn (z));
 
57
  MPFR_SET_EXP (f, 0);
 
58
 
 
59
  return -c;
 
60
}
 
61
 
 
62
/* set f to the rational q */
 
63
int
 
64
mpfr_set_q (mpfr_ptr f, mpq_srcptr q, mp_rnd_t rnd)
 
65
{
 
66
  mpz_srcptr num, den;
 
67
  mpfr_t n, d;
 
68
  int inexact;
 
69
  int cn, cd;
 
70
  long shift;
 
71
  mp_size_t sn, sd;
 
72
  MPFR_SAVE_EXPO_DECL (expo);
 
73
 
 
74
  num = mpq_numref (q);
 
75
  den = mpq_denref (q);
 
76
  /* NAN and INF for mpq are not really documented, but could be found */
 
77
  if (MPFR_UNLIKELY (mpz_sgn (num) == 0))
 
78
    {
 
79
      if (MPFR_UNLIKELY (mpz_sgn (den) == 0))
 
80
        {
 
81
          MPFR_SET_NAN (f);
 
82
          MPFR_RET_NAN;
 
83
        }
 
84
      else
 
85
        {
 
86
          MPFR_SET_ZERO (f);
 
87
          MPFR_SET_POS (f);
 
88
          MPFR_RET (0);
 
89
        }
 
90
    }
 
91
  if (MPFR_UNLIKELY (mpz_sgn (den) == 0))
 
92
    {
 
93
      MPFR_SET_INF (f);
 
94
      MPFR_SET_SIGN (f, mpz_sgn (num));
 
95
      MPFR_RET (0);
 
96
    }
 
97
 
 
98
  MPFR_SAVE_EXPO_MARK (expo);
 
99
 
 
100
  cn = set_z (n, num, &sn);
 
101
  cd = set_z (d, den, &sd);
 
102
 
 
103
  sn -= sd;
 
104
  if (MPFR_UNLIKELY (sn > MPFR_EMAX_MAX / BITS_PER_MP_LIMB))
 
105
    {
 
106
      inexact = mpfr_overflow (f, rnd, MPFR_SIGN (f));
 
107
      goto end;
 
108
    }
 
109
  if (MPFR_UNLIKELY (sn < MPFR_EMIN_MIN / BITS_PER_MP_LIMB -1))
 
110
    {
 
111
      if (rnd == GMP_RNDN)
 
112
        rnd = GMP_RNDZ;
 
113
      inexact = mpfr_underflow (f, rnd, MPFR_SIGN (f));
 
114
      goto end;
 
115
    }
 
116
 
 
117
  inexact = mpfr_div (f, n, d, rnd);
 
118
  shift = BITS_PER_MP_LIMB*sn+cn-cd;
 
119
  MPFR_ASSERTD (shift == BITS_PER_MP_LIMB*sn+cn-cd);
 
120
  cd = mpfr_mul_2si (f, f, shift, rnd);
 
121
  MPFR_SAVE_EXPO_FREE (expo);
 
122
  if (MPFR_UNLIKELY (cd != 0))
 
123
    inexact = cd;
 
124
  else
 
125
    inexact = mpfr_check_range (f, inexact, rnd);
 
126
 end:
 
127
  mpfr_clear (d);
 
128
  mpfr_clear (n);
 
129
  return inexact;
 
130
}
 
131
 
 
132