version 1.1.1.2, 2000/09/09 14:13:04 |
version 1.1.1.3, 2003/08/25 16:06:34 |
|
|
/* double mpq_get_d (mpq_t src) -- Return the double approximation to SRC. |
/* double mpq_get_d (mpq_t src) -- Return the double approximation to SRC. |
|
|
Copyright (C) 1995, 1996 Free Software Foundation, Inc. |
Copyright 1995, 1996, 2001, 2002 Free Software Foundation, Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
|
|
Line 49 MA 02111-1307, USA. */ |
|
Line 49 MA 02111-1307, USA. */ |
|
*/ |
*/ |
|
|
double |
double |
#if __STDC__ |
|
mpq_get_d (const MP_RAT *src) |
mpq_get_d (const MP_RAT *src) |
#else |
|
mpq_get_d (src) |
|
const MP_RAT *src; |
|
#endif |
|
{ |
{ |
mp_ptr np, dp; |
mp_ptr np, dp; |
mp_ptr rp; |
mp_ptr rp; |
|
|
mp_size_t dsize = src->_mp_den._mp_size; |
mp_size_t dsize = src->_mp_den._mp_size; |
mp_size_t qsize, rsize; |
mp_size_t qsize, rsize; |
mp_size_t sign_quotient = nsize ^ dsize; |
mp_size_t sign_quotient = nsize ^ dsize; |
unsigned normalization_steps; |
|
mp_limb_t qlimb; |
mp_limb_t qlimb; |
#define N_QLIMBS (1 + (sizeof (double) + BYTES_PER_MP_LIMB-1) / BYTES_PER_MP_LIMB) |
#define N_QLIMBS (1 + (sizeof (double) + BYTES_PER_MP_LIMB-1) / BYTES_PER_MP_LIMB) |
mp_limb_t qarr[N_QLIMBS + 1]; |
mp_limb_t qarr[N_QLIMBS + 1]; |
|
|
rsize = dsize + N_QLIMBS; |
rsize = dsize + N_QLIMBS; |
rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); |
rp = (mp_ptr) TMP_ALLOC ((rsize + 1) * BYTES_PER_MP_LIMB); |
|
|
count_leading_zeros (normalization_steps, dp[dsize - 1]); |
|
|
|
/* Normalize the denominator, i.e. make its most significant bit set by |
/* Normalize the denominator, i.e. make its most significant bit set by |
shifting it NORMALIZATION_STEPS bits to the left. Also shift the |
shifting it NORMALIZATION_STEPS bits to the left. Also shift the |
numerator the same number of steps (to keep the quotient the same!). */ |
numerator the same number of steps (to keep the quotient the same!). */ |
if (normalization_steps != 0) |
if ((dp[dsize - 1] & GMP_NUMB_HIGHBIT) == 0) |
{ |
{ |
mp_ptr tp; |
mp_ptr tp; |
mp_limb_t nlimb; |
mp_limb_t nlimb; |
|
unsigned normalization_steps; |
|
|
|
count_leading_zeros (normalization_steps, dp[dsize - 1]); |
|
normalization_steps -= GMP_NAIL_BITS; |
|
|
/* Shift up the denominator setting the most significant bit of |
/* Shift up the denominator setting the most significant bit of |
the most significant limb. Use temporary storage not to clobber |
the most significant limb. Use temporary storage not to clobber |
the original contents of the denominator. */ |
the original contents of the denominator. */ |
|
|
{ |
{ |
double res; |
double res; |
mp_size_t i; |
mp_size_t i; |
int scale = nsize - dsize - N_QLIMBS; |
mp_size_t scale = nsize - dsize - N_QLIMBS; |
|
|
#if defined (__vax__) |
#if defined (__vax__) |
/* Ignore excess quotient limbs. This is necessary on a vax |
/* Ignore excess quotient limbs. This is necessary on a vax |
|
|
for (i = qsize - 2; i >= 0; i--) |
for (i = qsize - 2; i >= 0; i--) |
res = res * MP_BASE_AS_DOUBLE + qp[i]; |
res = res * MP_BASE_AS_DOUBLE + qp[i]; |
|
|
res = __gmp_scale2 (res, BITS_PER_MP_LIMB * scale); |
res = __gmp_scale2 (res, GMP_NUMB_BITS * scale); |
|
|
TMP_FREE (marker); |
TMP_FREE (marker); |
return sign_quotient >= 0 ? res : -res; |
return sign_quotient >= 0 ? res : -res; |