Home | History | Annotate | Line # | Download | only in mini-gmp
      1      1.1  mrg /* mini-mpq, a minimalistic implementation of a GNU GMP subset.
      2      1.1  mrg 
      3      1.1  mrg    Contributed to the GNU project by Marco Bodrato
      4      1.1  mrg 
      5      1.1  mrg    Acknowledgment: special thanks to Bradley Lucier for his comments
      6      1.1  mrg    to the preliminary version of this code.
      7      1.1  mrg 
      8  1.1.1.2  mrg Copyright 2018-2020 Free Software Foundation, Inc.
      9      1.1  mrg 
     10      1.1  mrg This file is part of the GNU MP Library.
     11      1.1  mrg 
     12      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     13      1.1  mrg it under the terms of either:
     14      1.1  mrg 
     15      1.1  mrg   * the GNU Lesser General Public License as published by the Free
     16      1.1  mrg     Software Foundation; either version 3 of the License, or (at your
     17      1.1  mrg     option) any later version.
     18      1.1  mrg 
     19      1.1  mrg or
     20      1.1  mrg 
     21      1.1  mrg   * the GNU General Public License as published by the Free Software
     22      1.1  mrg     Foundation; either version 2 of the License, or (at your option) any
     23      1.1  mrg     later version.
     24      1.1  mrg 
     25      1.1  mrg or both in parallel, as here.
     26      1.1  mrg 
     27      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     28      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     29      1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     30      1.1  mrg for more details.
     31      1.1  mrg 
     32      1.1  mrg You should have received copies of the GNU General Public License and the
     33      1.1  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     34      1.1  mrg see https://www.gnu.org/licenses/.  */
     35      1.1  mrg 
     36      1.1  mrg #include <assert.h>
     37      1.1  mrg #include <limits.h>
     38      1.1  mrg #include <stdio.h>
     39      1.1  mrg #include <stdlib.h>
     40      1.1  mrg #include <string.h>
     41      1.1  mrg 
     42      1.1  mrg #include "mini-mpq.h"
     43      1.1  mrg 
     44      1.1  mrg #ifndef GMP_LIMB_HIGHBIT
     45      1.1  mrg /* Define macros and static functions already defined by mini-gmp.c */
     46      1.1  mrg #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT)
     47      1.1  mrg #define GMP_LIMB_HIGHBIT ((mp_limb_t) 1 << (GMP_LIMB_BITS - 1))
     48      1.1  mrg #define GMP_NEG_CAST(T,x) (-((T)((x) + 1) - 1))
     49      1.1  mrg #define GMP_MIN(a, b) ((a) < (b) ? (a) : (b))
     50      1.1  mrg 
     51      1.1  mrg static mpz_srcptr
     52      1.1  mrg mpz_roinit_normal_n (mpz_t x, mp_srcptr xp, mp_size_t xs)
     53      1.1  mrg {
     54      1.1  mrg   x->_mp_alloc = 0;
     55      1.1  mrg   x->_mp_d = (mp_ptr) xp;
     56      1.1  mrg   x->_mp_size = xs;
     57      1.1  mrg   return x;
     58      1.1  mrg }
     59      1.1  mrg 
     60      1.1  mrg static void
     61      1.1  mrg gmp_die (const char *msg)
     62      1.1  mrg {
     63      1.1  mrg   fprintf (stderr, "%s\n", msg);
     64      1.1  mrg   abort();
     65      1.1  mrg }
     66      1.1  mrg #endif
     67      1.1  mrg 
     68      1.1  mrg 
     69      1.1  mrg /* MPQ helper functions */
     71      1.1  mrg static mpq_srcptr
     72      1.1  mrg mpq_roinit_normal_nn (mpq_t x, mp_srcptr np, mp_size_t ns,
     73      1.1  mrg 		     mp_srcptr dp, mp_size_t ds)
     74      1.1  mrg {
     75      1.1  mrg   mpz_roinit_normal_n (mpq_numref(x), np, ns);
     76      1.1  mrg   mpz_roinit_normal_n (mpq_denref(x), dp, ds);
     77      1.1  mrg   return x;
     78      1.1  mrg }
     79      1.1  mrg 
     80      1.1  mrg static mpq_srcptr
     81      1.1  mrg mpq_roinit_zz (mpq_t x, mpz_srcptr n, mpz_srcptr d)
     82      1.1  mrg {
     83      1.1  mrg   return mpq_roinit_normal_nn (x, n->_mp_d, n->_mp_size,
     84      1.1  mrg 			       d->_mp_d, d->_mp_size);
     85      1.1  mrg }
     86      1.1  mrg 
     87      1.1  mrg static void
     88      1.1  mrg mpq_nan_init (mpq_t x)
     89      1.1  mrg {
     90      1.1  mrg   mpz_init (mpq_numref (x));
     91      1.1  mrg   mpz_init (mpq_denref (x));
     92      1.1  mrg }
     93      1.1  mrg 
     94      1.1  mrg void
     95      1.1  mrg mpq_init (mpq_t x)
     96      1.1  mrg {
     97      1.1  mrg   mpz_init (mpq_numref (x));
     98      1.1  mrg   mpz_init_set_ui (mpq_denref (x), 1);
     99      1.1  mrg }
    100      1.1  mrg 
    101      1.1  mrg void
    102      1.1  mrg mpq_clear (mpq_t x)
    103      1.1  mrg {
    104      1.1  mrg   mpz_clear (mpq_numref (x));
    105      1.1  mrg   mpz_clear (mpq_denref (x));
    106      1.1  mrg }
    107      1.1  mrg 
    108      1.1  mrg static void
    109      1.1  mrg mpq_canonical_sign (mpq_t r)
    110  1.1.1.2  mrg {
    111  1.1.1.2  mrg   mp_size_t ds = mpq_denref (r)->_mp_size;
    112      1.1  mrg   if (ds <= 0)
    113  1.1.1.2  mrg     {
    114      1.1  mrg       if (ds == 0)
    115      1.1  mrg 	gmp_die("mpq: Fraction with zero denominator.");
    116      1.1  mrg       mpz_neg (mpq_denref (r), mpq_denref (r));
    117      1.1  mrg       mpz_neg (mpq_numref (r), mpq_numref (r));
    118      1.1  mrg     }
    119      1.1  mrg }
    120      1.1  mrg 
    121      1.1  mrg static void
    122      1.1  mrg mpq_helper_canonicalize (mpq_t r, const mpz_t num, const mpz_t den, mpz_t g)
    123      1.1  mrg {
    124      1.1  mrg   if (num->_mp_size == 0)
    125      1.1  mrg     mpq_set_ui (r, 0, 1);
    126      1.1  mrg   else
    127      1.1  mrg     {
    128      1.1  mrg       mpz_gcd (g, num, den);
    129      1.1  mrg       mpz_tdiv_q (mpq_numref (r), num, g);
    130      1.1  mrg       mpz_tdiv_q (mpq_denref (r), den, g);
    131      1.1  mrg       mpq_canonical_sign (r);
    132      1.1  mrg     }
    133      1.1  mrg }
    134      1.1  mrg 
    135      1.1  mrg void
    136      1.1  mrg mpq_canonicalize (mpq_t r)
    137      1.1  mrg {
    138      1.1  mrg   mpz_t t;
    139      1.1  mrg 
    140      1.1  mrg   mpz_init (t);
    141      1.1  mrg   mpq_helper_canonicalize (r, mpq_numref (r), mpq_denref (r), t);
    142      1.1  mrg   mpz_clear (t);
    143      1.1  mrg }
    144      1.1  mrg 
    145      1.1  mrg void
    146      1.1  mrg mpq_swap (mpq_t a, mpq_t b)
    147      1.1  mrg {
    148      1.1  mrg   mpz_swap (mpq_numref (a), mpq_numref (b));
    149      1.1  mrg   mpz_swap (mpq_denref (a), mpq_denref (b));
    150      1.1  mrg }
    151      1.1  mrg 
    152      1.1  mrg 
    153      1.1  mrg /* MPQ assignment and conversions. */
    155      1.1  mrg void
    156      1.1  mrg mpz_set_q (mpz_t r, const mpq_t q)
    157      1.1  mrg {
    158      1.1  mrg   mpz_tdiv_q (r, mpq_numref (q), mpq_denref (q));
    159      1.1  mrg }
    160      1.1  mrg 
    161      1.1  mrg void
    162      1.1  mrg mpq_set (mpq_t r, const mpq_t q)
    163      1.1  mrg {
    164      1.1  mrg   mpz_set (mpq_numref (r), mpq_numref (q));
    165      1.1  mrg   mpz_set (mpq_denref (r), mpq_denref (q));
    166      1.1  mrg }
    167      1.1  mrg 
    168      1.1  mrg void
    169      1.1  mrg mpq_set_ui (mpq_t r, unsigned long n, unsigned long d)
    170      1.1  mrg {
    171      1.1  mrg   mpz_set_ui (mpq_numref (r), n);
    172      1.1  mrg   mpz_set_ui (mpq_denref (r), d);
    173      1.1  mrg }
    174      1.1  mrg 
    175      1.1  mrg void
    176      1.1  mrg mpq_set_si (mpq_t r, signed long n, unsigned long d)
    177      1.1  mrg {
    178      1.1  mrg   mpz_set_si (mpq_numref (r), n);
    179      1.1  mrg   mpz_set_ui (mpq_denref (r), d);
    180      1.1  mrg }
    181      1.1  mrg 
    182      1.1  mrg void
    183      1.1  mrg mpq_set_z (mpq_t r, const mpz_t n)
    184      1.1  mrg {
    185      1.1  mrg   mpz_set_ui (mpq_denref (r), 1);
    186      1.1  mrg   mpz_set (mpq_numref (r), n);
    187      1.1  mrg }
    188      1.1  mrg 
    189      1.1  mrg void
    190      1.1  mrg mpq_set_num (mpq_t r, const mpz_t z)
    191      1.1  mrg {
    192      1.1  mrg   mpz_set (mpq_numref (r), z);
    193      1.1  mrg }
    194      1.1  mrg 
    195      1.1  mrg void
    196      1.1  mrg mpq_set_den (mpq_t r, const mpz_t z)
    197      1.1  mrg {
    198      1.1  mrg   mpz_set (mpq_denref (r), z);
    199      1.1  mrg }
    200      1.1  mrg 
    201      1.1  mrg void
    202      1.1  mrg mpq_get_num (mpz_t r, const mpq_t q)
    203      1.1  mrg {
    204      1.1  mrg   mpz_set (r, mpq_numref (q));
    205      1.1  mrg }
    206      1.1  mrg 
    207      1.1  mrg void
    208      1.1  mrg mpq_get_den (mpz_t r, const mpq_t q)
    209      1.1  mrg {
    210      1.1  mrg   mpz_set (r, mpq_denref (q));
    211      1.1  mrg }
    212      1.1  mrg 
    213      1.1  mrg 
    214      1.1  mrg /* MPQ comparisons and the like. */
    216      1.1  mrg int
    217      1.1  mrg mpq_cmp (const mpq_t a, const mpq_t b)
    218      1.1  mrg {
    219      1.1  mrg   mpz_t t1, t2;
    220      1.1  mrg   int res;
    221      1.1  mrg 
    222      1.1  mrg   mpz_init (t1);
    223      1.1  mrg   mpz_init (t2);
    224      1.1  mrg   mpz_mul (t1, mpq_numref (a), mpq_denref (b));
    225      1.1  mrg   mpz_mul (t2, mpq_numref (b), mpq_denref (a));
    226      1.1  mrg   res = mpz_cmp (t1, t2);
    227      1.1  mrg   mpz_clear (t1);
    228      1.1  mrg   mpz_clear (t2);
    229      1.1  mrg 
    230      1.1  mrg   return res;
    231      1.1  mrg }
    232      1.1  mrg 
    233      1.1  mrg int
    234      1.1  mrg mpq_cmp_z (const mpq_t a, const mpz_t b)
    235      1.1  mrg {
    236      1.1  mrg   mpz_t t;
    237      1.1  mrg   int res;
    238      1.1  mrg 
    239      1.1  mrg   mpz_init (t);
    240      1.1  mrg   mpz_mul (t, b, mpq_denref (a));
    241      1.1  mrg   res = mpz_cmp (mpq_numref (a), t);
    242      1.1  mrg   mpz_clear (t);
    243      1.1  mrg 
    244      1.1  mrg   return res;
    245      1.1  mrg }
    246      1.1  mrg 
    247      1.1  mrg int
    248      1.1  mrg mpq_equal (const mpq_t a, const mpq_t b)
    249      1.1  mrg {
    250      1.1  mrg   return (mpz_cmp (mpq_numref (a), mpq_numref (b)) == 0) &&
    251      1.1  mrg     (mpz_cmp (mpq_denref (a), mpq_denref (b)) == 0);
    252      1.1  mrg }
    253      1.1  mrg 
    254      1.1  mrg int
    255      1.1  mrg mpq_cmp_ui (const mpq_t q, unsigned long n, unsigned long d)
    256      1.1  mrg {
    257      1.1  mrg   mpq_t t;
    258      1.1  mrg   assert (d != 0);
    259      1.1  mrg   if (ULONG_MAX <= GMP_LIMB_MAX) {
    260      1.1  mrg     mp_limb_t nl = n, dl = d;
    261      1.1  mrg     return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, n != 0, &dl, 1));
    262      1.1  mrg   } else {
    263      1.1  mrg     int ret;
    264      1.1  mrg 
    265      1.1  mrg     mpq_init (t);
    266      1.1  mrg     mpq_set_ui (t, n, d);
    267      1.1  mrg     ret = mpq_cmp (q, t);
    268      1.1  mrg     mpq_clear (t);
    269      1.1  mrg 
    270      1.1  mrg     return ret;
    271      1.1  mrg   }
    272      1.1  mrg }
    273      1.1  mrg 
    274      1.1  mrg int
    275      1.1  mrg mpq_cmp_si (const mpq_t q, signed long n, unsigned long d)
    276      1.1  mrg {
    277      1.1  mrg   assert (d != 0);
    278      1.1  mrg 
    279      1.1  mrg   if (n >= 0)
    280      1.1  mrg     return mpq_cmp_ui (q, n, d);
    281      1.1  mrg   else
    282      1.1  mrg     {
    283      1.1  mrg       mpq_t t;
    284      1.1  mrg 
    285      1.1  mrg       if (ULONG_MAX <= GMP_LIMB_MAX)
    286      1.1  mrg 	{
    287      1.1  mrg 	  mp_limb_t nl = GMP_NEG_CAST (unsigned long, n), dl = d;
    288      1.1  mrg 	  return mpq_cmp (q, mpq_roinit_normal_nn (t, &nl, -1, &dl, 1));
    289      1.1  mrg 	}
    290      1.1  mrg       else
    291      1.1  mrg 	{
    292      1.1  mrg 	  unsigned long l_n = GMP_NEG_CAST (unsigned long, n);
    293      1.1  mrg 
    294      1.1  mrg 	  mpq_roinit_normal_nn (t, mpq_numref (q)->_mp_d, - mpq_numref (q)->_mp_size,
    295      1.1  mrg 				mpq_denref (q)->_mp_d, mpq_denref (q)->_mp_size);
    296      1.1  mrg 	  return - mpq_cmp_ui (t, l_n, d);
    297      1.1  mrg 	}
    298      1.1  mrg     }
    299      1.1  mrg }
    300      1.1  mrg 
    301      1.1  mrg int
    302      1.1  mrg mpq_sgn (const mpq_t a)
    303      1.1  mrg {
    304      1.1  mrg   return mpz_sgn (mpq_numref (a));
    305      1.1  mrg }
    306      1.1  mrg 
    307      1.1  mrg 
    308      1.1  mrg /* MPQ arithmetic. */
    310      1.1  mrg void
    311      1.1  mrg mpq_abs (mpq_t r, const mpq_t q)
    312      1.1  mrg {
    313      1.1  mrg   mpz_abs (mpq_numref (r), mpq_numref (q));
    314      1.1  mrg   mpz_set (mpq_denref (r), mpq_denref (q));
    315      1.1  mrg }
    316      1.1  mrg 
    317      1.1  mrg void
    318      1.1  mrg mpq_neg (mpq_t r, const mpq_t q)
    319      1.1  mrg {
    320      1.1  mrg   mpz_neg (mpq_numref (r), mpq_numref (q));
    321      1.1  mrg   mpz_set (mpq_denref (r), mpq_denref (q));
    322      1.1  mrg }
    323      1.1  mrg 
    324      1.1  mrg void
    325      1.1  mrg mpq_add (mpq_t r, const mpq_t a, const mpq_t b)
    326      1.1  mrg {
    327      1.1  mrg   mpz_t t;
    328      1.1  mrg 
    329      1.1  mrg   mpz_init (t);
    330      1.1  mrg   mpz_gcd (t, mpq_denref (a), mpq_denref (b));
    331      1.1  mrg   if (mpz_cmp_ui (t, 1) == 0)
    332      1.1  mrg     {
    333      1.1  mrg       mpz_mul (t, mpq_numref (a), mpq_denref (b));
    334      1.1  mrg       mpz_addmul (t, mpq_numref (b), mpq_denref (a));
    335      1.1  mrg       mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
    336      1.1  mrg       mpz_swap (mpq_numref (r), t);
    337      1.1  mrg     }
    338      1.1  mrg   else
    339      1.1  mrg     {
    340      1.1  mrg       mpz_t x, y;
    341      1.1  mrg       mpz_init (x);
    342      1.1  mrg       mpz_init (y);
    343      1.1  mrg 
    344      1.1  mrg       mpz_tdiv_q (x, mpq_denref (b), t);
    345      1.1  mrg       mpz_tdiv_q (y, mpq_denref (a), t);
    346      1.1  mrg       mpz_mul (x, mpq_numref (a), x);
    347      1.1  mrg       mpz_addmul (x, mpq_numref (b), y);
    348      1.1  mrg 
    349      1.1  mrg       mpz_gcd (t, x, t);
    350      1.1  mrg       mpz_tdiv_q (mpq_numref (r), x, t);
    351      1.1  mrg       mpz_tdiv_q (x, mpq_denref (b), t);
    352      1.1  mrg       mpz_mul (mpq_denref (r), x, y);
    353      1.1  mrg 
    354      1.1  mrg       mpz_clear (x);
    355      1.1  mrg       mpz_clear (y);
    356      1.1  mrg     }
    357      1.1  mrg   mpz_clear (t);
    358      1.1  mrg }
    359      1.1  mrg 
    360      1.1  mrg void
    361      1.1  mrg mpq_sub (mpq_t r, const mpq_t a, const mpq_t b)
    362      1.1  mrg {
    363      1.1  mrg   mpq_t t;
    364      1.1  mrg 
    365      1.1  mrg   mpq_roinit_normal_nn (t, mpq_numref (b)->_mp_d, - mpq_numref (b)->_mp_size,
    366      1.1  mrg 			mpq_denref (b)->_mp_d, mpq_denref (b)->_mp_size);
    367      1.1  mrg   mpq_add (r, a, t);
    368      1.1  mrg }
    369      1.1  mrg 
    370      1.1  mrg void
    371      1.1  mrg mpq_div (mpq_t r, const mpq_t a, const mpq_t b)
    372      1.1  mrg {
    373      1.1  mrg   mpq_t t;
    374      1.1  mrg   mpq_mul (r, a, mpq_roinit_zz (t, mpq_denref (b), mpq_numref (b)));
    375      1.1  mrg }
    376      1.1  mrg 
    377      1.1  mrg void
    378      1.1  mrg mpq_mul (mpq_t r, const mpq_t a, const mpq_t b)
    379      1.1  mrg {
    380      1.1  mrg   mpq_t t;
    381      1.1  mrg   mpq_nan_init (t);
    382      1.1  mrg 
    383      1.1  mrg   if (a != b) {
    384      1.1  mrg     mpz_t g;
    385      1.1  mrg 
    386      1.1  mrg     mpz_init (g);
    387      1.1  mrg     mpq_helper_canonicalize (t, mpq_numref (a), mpq_denref (b), g);
    388      1.1  mrg     mpq_helper_canonicalize (r, mpq_numref (b), mpq_denref (a), g);
    389      1.1  mrg     mpz_clear (g);
    390      1.1  mrg 
    391      1.1  mrg     a = r;
    392      1.1  mrg     b = t;
    393      1.1  mrg   }
    394      1.1  mrg 
    395      1.1  mrg   mpz_mul (mpq_numref (r), mpq_numref (a), mpq_numref (b));
    396      1.1  mrg   mpz_mul (mpq_denref (r), mpq_denref (a), mpq_denref (b));
    397      1.1  mrg   mpq_clear (t);
    398      1.1  mrg }
    399      1.1  mrg 
    400      1.1  mrg void
    401      1.1  mrg mpq_div_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
    402      1.1  mrg {
    403      1.1  mrg   mp_bitcnt_t z = mpz_scan1 (mpq_numref (q), 0);
    404      1.1  mrg   z = GMP_MIN (z, e);
    405      1.1  mrg   mpz_mul_2exp (mpq_denref (r), mpq_denref (q), e - z);
    406      1.1  mrg   mpz_tdiv_q_2exp (mpq_numref (r), mpq_numref (q), z);
    407      1.1  mrg }
    408      1.1  mrg 
    409      1.1  mrg void
    410      1.1  mrg mpq_mul_2exp (mpq_t r, const mpq_t q, mp_bitcnt_t e)
    411      1.1  mrg {
    412      1.1  mrg   mp_bitcnt_t z = mpz_scan1 (mpq_denref (q), 0);
    413      1.1  mrg   z = GMP_MIN (z, e);
    414      1.1  mrg   mpz_mul_2exp (mpq_numref (r), mpq_numref (q), e - z);
    415      1.1  mrg   mpz_tdiv_q_2exp (mpq_denref (r), mpq_denref (q), z);
    416      1.1  mrg }
    417      1.1  mrg 
    418      1.1  mrg void
    419      1.1  mrg mpq_inv (mpq_t r, const mpq_t q)
    420      1.1  mrg {
    421      1.1  mrg   mpq_set (r, q);
    422      1.1  mrg   mpz_swap (mpq_denref (r), mpq_numref (r));
    423      1.1  mrg   mpq_canonical_sign (r);
    424      1.1  mrg }
    425      1.1  mrg 
    426      1.1  mrg 
    427      1.1  mrg /* MPQ to/from double. */
    429      1.1  mrg void
    430      1.1  mrg mpq_set_d (mpq_t r, double x)
    431      1.1  mrg {
    432      1.1  mrg   mpz_set_ui (mpq_denref (r), 1);
    433      1.1  mrg 
    434      1.1  mrg   /* x != x is true when x is a NaN, and x == x * 0.5 is true when x is
    435      1.1  mrg      zero or infinity. */
    436      1.1  mrg   if (x == x * 0.5 || x != x)
    437      1.1  mrg     mpq_numref (r)->_mp_size = 0;
    438      1.1  mrg   else
    439      1.1  mrg     {
    440      1.1  mrg       double B;
    441      1.1  mrg       mp_bitcnt_t e;
    442      1.1  mrg 
    443      1.1  mrg       B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
    444      1.1  mrg       for (e = 0; x != x + 0.5; e += GMP_LIMB_BITS)
    445      1.1  mrg 	x *= B;
    446      1.1  mrg 
    447      1.1  mrg       mpz_set_d (mpq_numref (r), x);
    448      1.1  mrg       mpq_div_2exp (r, r, e);
    449      1.1  mrg     }
    450      1.1  mrg }
    451      1.1  mrg 
    452      1.1  mrg double
    453      1.1  mrg mpq_get_d (const mpq_t u)
    454      1.1  mrg {
    455      1.1  mrg   mp_bitcnt_t ne, de, ee;
    456      1.1  mrg   mpz_t z;
    457      1.1  mrg   double B, ret;
    458      1.1  mrg 
    459      1.1  mrg   ne = mpz_sizeinbase (mpq_numref (u), 2);
    460      1.1  mrg   de = mpz_sizeinbase (mpq_denref (u), 2);
    461      1.1  mrg 
    462      1.1  mrg   ee = CHAR_BIT * sizeof (double);
    463      1.1  mrg   if (de == 1 || ne > de + ee)
    464      1.1  mrg     ee = 0;
    465      1.1  mrg   else
    466      1.1  mrg     ee = (ee + de - ne) / GMP_LIMB_BITS + 1;
    467      1.1  mrg 
    468      1.1  mrg   mpz_init (z);
    469      1.1  mrg   mpz_mul_2exp (z, mpq_numref (u), ee * GMP_LIMB_BITS);
    470      1.1  mrg   mpz_tdiv_q (z, z, mpq_denref (u));
    471      1.1  mrg   ret = mpz_get_d (z);
    472      1.1  mrg   mpz_clear (z);
    473      1.1  mrg 
    474      1.1  mrg   B = 4.0 * (double) (GMP_LIMB_HIGHBIT >> 1);
    475      1.1  mrg   for (B = 1 / B; ee != 0; --ee)
    476      1.1  mrg     ret *= B;
    477      1.1  mrg 
    478      1.1  mrg   return ret;
    479      1.1  mrg }
    480      1.1  mrg 
    481      1.1  mrg 
    482      1.1  mrg /* MPQ and strings/streams. */
    484      1.1  mrg char *
    485      1.1  mrg mpq_get_str (char *sp, int base, const mpq_t q)
    486      1.1  mrg {
    487      1.1  mrg   char *res;
    488      1.1  mrg   char *rden;
    489      1.1  mrg   size_t len;
    490      1.1  mrg 
    491      1.1  mrg   res = mpz_get_str (sp, base, mpq_numref (q));
    492      1.1  mrg   if (res == NULL || mpz_cmp_ui (mpq_denref (q), 1) == 0)
    493      1.1  mrg     return res;
    494      1.1  mrg 
    495      1.1  mrg   len = strlen (res) + 1;
    496      1.1  mrg   rden = sp ? sp + len : NULL;
    497      1.1  mrg   rden = mpz_get_str (rden, base, mpq_denref (q));
    498      1.1  mrg   assert (rden != NULL);
    499      1.1  mrg 
    500      1.1  mrg   if (sp == NULL) {
    501      1.1  mrg     void * (*gmp_reallocate_func) (void *, size_t, size_t);
    502      1.1  mrg     void (*gmp_free_func) (void *, size_t);
    503      1.1  mrg     size_t lden;
    504      1.1  mrg 
    505      1.1  mrg     mp_get_memory_functions (NULL, &gmp_reallocate_func, &gmp_free_func);
    506      1.1  mrg     lden = strlen (rden) + 1;
    507      1.1  mrg     res = (char *) gmp_reallocate_func (res, 0, (lden + len) * sizeof (char));
    508      1.1  mrg     memcpy (res + len, rden, lden);
    509      1.1  mrg     gmp_free_func (rden, 0);
    510      1.1  mrg   }
    511      1.1  mrg 
    512      1.1  mrg   res [len - 1] = '/';
    513      1.1  mrg   return res;
    514      1.1  mrg }
    515      1.1  mrg 
    516      1.1  mrg size_t
    517      1.1  mrg mpq_out_str (FILE *stream, int base, const mpq_t x)
    518  1.1.1.2  mrg {
    519  1.1.1.2  mrg   char * str;
    520      1.1  mrg   size_t len;
    521      1.1  mrg   void (*gmp_free_func) (void *, size_t);
    522      1.1  mrg 
    523      1.1  mrg   str = mpq_get_str (NULL, base, x);
    524      1.1  mrg   if (!str)
    525      1.1  mrg     return 0;
    526      1.1  mrg   len = strlen (str);
    527      1.1  mrg   len = fwrite (str, 1, len, stream);
    528      1.1  mrg   mp_get_memory_functions (NULL, NULL, &gmp_free_func);
    529      1.1  mrg   gmp_free_func (str, 0);
    530      1.1  mrg   return len;
    531      1.1  mrg }
    532      1.1  mrg 
    533      1.1  mrg int
    534      1.1  mrg mpq_set_str (mpq_t r, const char *sp, int base)
    535      1.1  mrg {
    536      1.1  mrg   const char *slash;
    537      1.1  mrg 
    538      1.1  mrg   slash = strchr (sp, '/');
    539      1.1  mrg   if (slash == NULL) {
    540      1.1  mrg     mpz_set_ui (mpq_denref(r), 1);
    541      1.1  mrg     return mpz_set_str (mpq_numref(r), sp, base);
    542      1.1  mrg   } else {
    543      1.1  mrg     char *num;
    544      1.1  mrg     size_t numlen;
    545      1.1  mrg     int ret;
    546      1.1  mrg     void * (*gmp_allocate_func) (size_t);
    547      1.1  mrg     void (*gmp_free_func) (void *, size_t);
    548      1.1  mrg 
    549      1.1  mrg     mp_get_memory_functions (&gmp_allocate_func, NULL, &gmp_free_func);
    550      1.1  mrg     numlen = slash - sp;
    551      1.1  mrg     num = (char *) gmp_allocate_func ((numlen + 1) * sizeof (char));
    552      1.1  mrg     memcpy (num, sp, numlen);
    553      1.1  mrg     num[numlen] = '\0';
    554      1.1  mrg     ret = mpz_set_str (mpq_numref(r), num, base);
    555      1.1  mrg     gmp_free_func (num, 0);
    556      1.1  mrg 
    557                   if (ret != 0)
    558                     return ret;
    559               
    560                   return mpz_set_str (mpq_denref(r), slash + 1, base);
    561                 }
    562               }
    563