0

I'm trying to obtain the machine precision on gmp variables.

To that end, I adapted the code from wikipedia, to compute the precision of a gmp with a fixed precision:

int main( int argc, char **argv )
{
    long int precision = 100;

mpf_set_default_prec(precision); // in principle redundant, but who cares

    mpf_t machEps, one, temp; // "one" is the "1" in gmp. tmp is to comparison.
    mpf_init2(machEps, precision); 
    mpf_set_ui(machEps, 1); // eps = 1
    mpf_init_set(one,machEps); // ensure "one" has the same precision as machEps
    mpf_init_set(temp,machEps); // ensure "temp" has the same precision as machEps

    do {
        mpf_div_ui(machEps,machEps,2); // eps = eps/2
        mpf_div_ui(temp,machEps,2);    // temp = eps/2
        mpf_add(temp,temp,one);        // temp += 1
    }
    while ( mpf_cmp(temp,one)); // temp == 1
    /// print the result...
    char *t = new char[400];
    mp_exp_t expprt;
    mpf_get_str(NULL, &expprt, 10, 10, machEps);

    sprintf(t, "%se%ld", mpf_get_str(NULL, &expprt, 10, mpf_get_default_prec(), machEps), expprt);

    printf( "Calculated Machine epsilon: %s\n", t);
    return 0;
}

However, the result is not consistent with the wikipedia's formula, neither changes with the precision I set. What am I missing? I've also tried with double and float (c standard), and the result is correct...

Jorge Leitao
  • 19,085
  • 19
  • 85
  • 121

1 Answers1

3

I get results that are consistent with wikipedia's formula, and the values depend on the precision.

However, the value - and the effective precision - only change when crossing a limb-boundary(1). For me, that means multiples of 64, so for

(k-1)*64 < precision <= k*64

the calculated machine epsilon is

0.5^(k*64)

Some results:

$ ./a.out 192
Calculated Machine epsilon: 15930919111324522770288803977677118055911045551926187860739e-57
$ ./a.out 193
Calculated Machine epsilon: 8636168555094444625386351862800399571116000364436281385023703470168591803162427e-77

For comparison:

Prelude> 0.5^192
1.5930919111324523e-58
Prelude> 0.5^256
8.636168555094445e-78

The output of the GMP programme is in the form mantissa,'e',exponent where the value is

0.mantissa * 10^exponent

(1) GMP represents the floating point numbers as a pair of exponent (for base 2) and mantissa (and sign). The mantissa is maintained as an array of unsigned integers, the limbs. For me, the limbs are 64 bits, on 32 bit systems usually 32 bits (iirc). So when the desired precision is between (k-1)*LIMB_BITS (exclusive) and k*LIMB_BITS (inclusive), the array for the mantissa contains k limbs, and all of them are used, thus the effective precision is k*LIMB_BITS bits. Therefore the epsilon only changes when the number of limbs changes.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Ok, my results are in agreement with yours. What means "However, the value - and the effective precision - only change when crossing a limb-boundary". Can you explain on the answer? apparently that was my problem, I don't know why there is this discrete steps. (or any reference to "limb-boundary") Thanks anyway, helped a lot! – Jorge Leitao Jun 12 '12 at 12:04
  • Okay, will add an explanation. – Daniel Fischer Jun 12 '12 at 12:08
  • You may want to look at using the [MPFR](http://www.mpfr.org/) library. The mpfr type uses the exact number of bits of precision requested instead of rounding up by limbs. – casevh Jun 12 '12 at 14:17