Question about mpf_t comparison behavior for x - tiny

Maho NAKATA maho.nakata at gmail.com
Fri Apr 24 13:02:16 CEST 2026


Hello,

I hope this is an appropriate place to ask this question.

While debugging a numerical issue in MPLAPACK, I encountered an `mpf_t`
behavior that I found a little surprising, and I would be very grateful
if someone could tell me whether this is expected GMP behavior.

The pattern is roughly the following:

- `wu == d`
- `pivmin > 0`
- but `wu < d - pivmin`

So mathematically,

`wu - (d - pivmin) = (wu - d) + pivmin`

seems as though it should remain positive if `wu == d` and `pivmin > 0`.

If this were behaving in the most straightforward way, I would expect
either

- `d - pivmin` to compare equal to `d`, in which case both comparisons
  would agree, or
- `d - pivmin` to be strictly smaller than `d`, in which case `wu == d`
  should still imply `wu > d - pivmin`.

In either case, I would not expect to see

- `mpf_cmp(wu, d) == 0`
- but at the same time `mpf_cmp(wu, d - pivmin) < 0`.

However, with `mpf_t` I observe exactly that, which is why I thought it
might be worth asking whether this is simply a consequence of `mpf_t`
semantics at extreme exponents, or whether I may be misunderstanding
something about how these values are represented and compared.

I reduced the issue to the following small example:

```cpp
#include <cstdio>
#include <cstdlib>
#include <gmp.h>

static void set_or_die(mpf_t x, const char *s) {
    if (mpf_set_str(x, s, 10) != 0) {
        std::fprintf(stderr, "mpf_set_str failed for: %s\n", s);
        std::exit(1);
    }
}

int main() {
    const mp_bitcnt_t prec = 512;

    mpf_t d, wu, pivmin, d_minus_pivmin, diff_d, diff_p;
    mpf_inits(d, wu, pivmin, d_minus_pivmin, diff_d, diff_p, nullptr);

    mpf_set_prec(d, prec);
    mpf_set_prec(wu, prec);
    mpf_set_prec(pivmin, prec);
    mpf_set_prec(d_minus_pivmin, prec);
    mpf_set_prec(diff_d, prec);
    mpf_set_prec(diff_p, prec);

    mpf_set_str(d,
"-2.4616939245935578262292233824060520172893599354879699820500368499e+347063955532709820",
10);
    mpf_set_str(wu,
"-2.4616939245935578262292233824060520172893599354879699820500368499e+347063955532709820",
10);
    mpf_set_str(pivmin,
"1.7019382623481672278259575819240965611355119939659392498165297957e-1388255822130839283",
10);

    mpf_sub(d_minus_pivmin, d, pivmin);
    mpf_sub(diff_d, wu, d);
    mpf_sub(diff_p, wu, d_minus_pivmin);

    gmp_printf("d                    = %.40Fe\n", d);
    gmp_printf("wu                   = %.40Fe\n", wu);
    gmp_printf("pivmin               = %.40Fe\n", pivmin);
    gmp_printf("d_minus_pivmin       = %.40Fe\n", d_minus_pivmin);
    gmp_printf("wu_minus_d           = %.40Fe\n", diff_d);
    gmp_printf("wu_minus_d_minus_piv = %.40Fe\n", diff_p);

    std::printf("mpf_cmp(wu, d) = %d\n", mpf_cmp(wu, d));
    std::printf("mpf_cmp(wu, d_minus_pivmin) = %d\n", mpf_cmp(wu,
d_minus_pivmin));

    mpf_clears(d, wu, pivmin, d_minus_pivmin, diff_d, diff_p, nullptr);
    return 0;
}
```

On my system, this produces:

```text
d = -2.4616939245935578262292233824060520172894e+347063955532709820
wu = -2.4616939245935578262292233824060520172894e+347063955532709820
pivmin = 1.7019382623481672278259575819240965611355e-1388255822130839283
d_minus_pivmin =
-2.4616939245935578262292233824060520172894e+347063955532709820
wu_minus_d = 0.0000000000000000000000000000000000000000e+00
wu_minus_d_minus_pivmin =
-1.6856831808738259700179295042359981612965e+347063955532709647
mpf_cmp(wu, d) = 0
mpf_cmp(wu, d_minus_pivmin) = -1
```

My environment is:

- GMP 6.3.0
- GCC 13.3.0
- `gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0`
- Ubuntu 24.04 amd64

I understand that `mpf_t` is not intended to provide MPFR-style
guarantees, so this may well be normal behavior. I am mainly hoping to
understand whether this is an expected consequence of `mpf_t` arithmetic
at extreme exponents, or whether it suggests something more subtle.

If it would be helpful, I would be happy to provide:

- a version that prints internal fields / limbs
- any additional environment details

Thank you very much for your time.

Best regards,
Nakata Mho


More information about the gmp-discuss mailing list