trizen has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

Just wondering: what is the most efficient way to convert a Math::MPFR object into a Math::GMPq. Ideally, without loosing too much precision.
So far, I tried converting Math::MPFR to Math::GMPf, then Math::GMPf to Math::GMPq, which works correctly, but it's not the best solution in terms of efficiency.

Here is the code for that:

use strict; use warnings; use Math::MPFR qw(:mpfr); use Math::GMPf qw(:mpf); use Math::GMPq qw(:mpq); my $PREC = 128; # Compute log(3) my $fr = Rmpfr_init2($PREC); Rmpfr_set_ui($fr, 3, MPFR_RNDN); Rmpfr_log($fr, $fr, MPFR_RNDN); print "$fr\n"; # print as float # MPFR -> floating-point my $f = Rmpf_init2($PREC); Rmpfr_get_f($f, $fr, MPFR_RNDN); # floating-point -> rational my $q = Rmpq_init(); Rmpq_set_f($q, $f); print "$q\n"; # print as rational

I'm pretty sure this can be done better, but just can't figure it how. I would be very happy if someone will point out an easier way for doing this.
Thank you very much and happy holidays!

Replies are listed 'Best First'.
Re: Converting Math::MPFR to Math::GMPq
by syphilis (Archbishop) on Dec 28, 2015 at 13:08 UTC
    So far, I tried converting Math::MPFR to Math::GMPf, then Math::GMPf to Math::GMPq, which works correctly

    I think that's about the best you can do - ie, I can't spot anything better.
    The mpfr library provides direct conversion to mpf_t and mpz_t types (using the mpfr_get_f and mpfr_get_z functions), but the mpfr_get_q function is not there - and hence no Rmpfr_get_q function in Math::MPFR.

    It would be nice to avoid the overhead of having to load Math::GMPf but, other than that, I think your conversion should be working quite efficiently.

    For 128 bits of precision, the value of the mpfr_t and mpf_t will be exactly equivalent, and the final mpq_t will be an exact representation of that floating point value.

    Belated update: That last statement of mine is poorly thought out - the value of the mpfr_t and mpf_t will be exactly equivalent if the precision allocated to the mpfr_t equals the precision allocated to the mpf_t (irrespective of whether the precision is 128 or not).

    Cheers,
    Rob

      Thank you very much, Rob, for your reply and also for the Math::* modules.

      Definitely, would be nice to avoid the overhead of loading Math::GMPf, as I'm using it only in one place to do this particular conversion, but, nevertheless, I can live with that. :)

      All the best,
      Daniel

        would be nice to avoid the overhead of loading Math::GMPf

        Thinking a bit more about it, it's no big deal to include an Rmpfr_get_q() XSub in Math::MPFR that does the mpfr_t to mpf_t to mpq_t conversion, and thereby avoids the need to load Math::GMPf.

        That function will be in the next release of Math::MPFR.
        I'm not sure when that will be - I could send you a patch against current (Math-MPFR-3.28) if you don't want to wait for 3.29.

        Cheers,
        Rob