Subject: Re: bug#10519: guile and (mini-)gmp

From: Mark H Weaver <[email-masked]>
Date: Mon, 16 Jan 2012 05:19:33 -0500

Hi Niels, thanks for looking into this!

[email-masked] (Niels Möller) writes:
> 2. The next problem is maybe more a nuisance than a real problem. I'm
>    looking at scm_i_big2dbl, in numbers.c.
>
>    I notice this code doesn't currently use mpz_get_d (comment says
>    that's because gmp-4.2 and earlier didn't do well-defined rounding).
>
>    Next, mpz_get_d in current gmp rounds towards zero. guile wants
>    rounding to nearest, and it arranges this by testing the next lower
>    bit. Unfortunately, it can't use mpz_tstbit directly, since for
>    negative values it needs the bit of the abolute value, not of the
>    two's complement. The code instead uses mpz_getlimbn and
>    GMP_NUMB_BITS.
>
>    That's not an unreasonable way to do it, but it causes problems for
>    me because mini-gmp.h doesn't declare GMP_NUMB_BITS (and can't do,

Don't worry about this.  I have a patch set that (among other things)
reimplements scm_i_big2dbl in a much more robust way, with proper
rounding, and without using such low-level GMP accessors.  I posted this
patch set to guile-devel on 7 Oct, "[PATCH] Improvements to exact
rationals et al".  I will resubmit it soon.

> 3. Occcasional use of mpq functions (do_divide, scm_inexact_to_exact),
>    for conversion of fradctions to and from doubles. mini-gmp has no
>    mpq-functions (and it shouldn't have), so these calls have to either
>    be eliminated altogether, or be made conditional on HAVE_LIBGMP.
>
>    For conversion double->fraction, mpq seems overkill: Just multiply by
>    a power of two to make the number an integer, to construct a fraction
>    p / 2^k, and then eliminate any common factors of two (if fractions
>    are required to be in some canonical form).

Agreed.  I can easily reimplement this to avoid the mpq functions, and
will do so.

>    For fraction->double, I think the current code using mpq_get_d rounds
>    towards zero rather than towards nearest, which might not be what's
>    desired. To avoid using mpq, I think converting p/q to a double could
>    be done as follows:

The aforementioned patch set already eliminates this use of the mpq
functions.

> 4. mini-gmp has no mp_set_memory_functions. If I understand the the
>    conservative gc used with guile right, having mini-gmp always use
>    plain malloc and free should not cause any errors, just a slight
>    waste of memory in case some limbs happen to be valid pointers.

No, it's much worse than that.  If most of the memory being allocated
are bignums, then GC might not be run until the heap is quite large.
That's because the GC decides when to run based on the allocations that
it knows about.  A potentially large amount of bignum data may be
allocated before the GC heap gets big enough to trigger a collection.
It doesn't know about memory allocated with plain malloc.  However, it
_does_ now know about memory allocated with scm_malloc.

It would be good if you could duplicate the `mp_set_memory_functions'
interface in mini-gmp.

    Thanks,
      Mark