Annotation of OpenXM_contrib/gmp/mpq/set_f.c, Revision 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>