Annotation of OpenXM_contrib/gmp/mpq/set_f.c, Revision 1.1.1.1
1.1 ohara 1: /* mpq_set_f -- set an mpq from an mpf.
2:
3: Copyright 2000, 2001, 2002 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:
27: void
28: mpq_set_f (mpq_ptr q, mpf_srcptr f)
29: {
30: mp_size_t fexp = EXP(f);
31: mp_ptr fptr = PTR(f);
32: mp_size_t fsize = SIZ(f);
33: mp_size_t abs_fsize = ABS(fsize);
34: mp_limb_t flow;
35:
36: if (fsize == 0)
37: {
38: /* set q=0 */
39: q->_mp_num._mp_size = 0;
40: q->_mp_den._mp_size = 1;
41: q->_mp_den._mp_d[0] = 1;
42: return;
43: }
44:
45: /* strip low zero limbs from f */
46: flow = *fptr;
47: MPN_STRIP_LOW_ZEROS_NOT_ZERO (fptr, abs_fsize, flow);
48:
49: if (fexp >= abs_fsize)
50: {
51: /* radix point is to the right of the limbs, no denominator */
52: mp_ptr num_ptr;
53:
54: MPZ_REALLOC (mpq_numref (q), fexp);
55: num_ptr = q->_mp_num._mp_d;
56: MPN_ZERO (num_ptr, fexp - abs_fsize);
57: MPN_COPY (num_ptr + fexp - abs_fsize, fptr, abs_fsize);
58:
59: q->_mp_num._mp_size = fsize >= 0 ? fexp : -fexp;
60: q->_mp_den._mp_size = 1;
61: q->_mp_den._mp_d[0] = 1;
62: }
63: else
64: {
65: /* radix point is within or to the left of the limbs, use demominator */
66: mp_ptr num_ptr, den_ptr;
67: mp_size_t den_size;
68:
69: den_size = abs_fsize - fexp;
70: MPZ_REALLOC (mpq_numref (q), abs_fsize);
71: MPZ_REALLOC (mpq_denref (q), den_size+1);
72: num_ptr = q->_mp_num._mp_d;
73: den_ptr = q->_mp_den._mp_d;
74:
75: if (flow & 1)
76: {
77: /* no powers of two to strip from numerator */
78:
79: MPN_COPY (num_ptr, fptr, abs_fsize);
80: MPN_ZERO (den_ptr, den_size);
81: den_ptr[den_size] = 1;
82: }
83: else
84: {
85: /* right shift numerator, adjust denominator accordingly */
86: int shift;
87:
88: den_size--;
89: count_trailing_zeros (shift, flow);
90:
91: mpn_rshift (num_ptr, fptr, abs_fsize, shift);
92: abs_fsize -= (num_ptr[abs_fsize-1] == 0);
93:
94: MPN_ZERO (den_ptr, den_size);
95: den_ptr[den_size] = GMP_LIMB_HIGHBIT >> (shift-1);
96: }
97:
98: q->_mp_num._mp_size = fsize >= 0 ? abs_fsize : -abs_fsize;
99: q->_mp_den._mp_size = den_size + 1;
100: }
101: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>