I thought GCC would currently (2023) implement 80-bit floats for long-double, and 128-bit floats with libquadmath...

However, with gcc 13.2.0 on an amd64 architecture (AMD FX-8320E), I see that the limits for long double and __float128 seem quite close. And bothLDBL_MAX and FLT128_MAX are very close to the maximum number represented by x87 80-bit standard (~ 1.18973 x 2^4932). And the denormalized minimum is exactly the one for x87 for LDBL_TRUE_MIN (~ 3.6452 x 2^-4951), but for FLT_128_DENORM_MIN its somewhat larger (~ 6.47518 x 2^-4966) The following program shows what I mean:

#include <math.h>
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <quadmath.h>


int main() {
    __float128 qmath_x;

    char *str = malloc(201*sizeof(char));

    /* MAX */
    printf("### MAX ###\n");
    
    printf("LDBL_MAX        %3.190Lg\n", LDBL_MAX);

    qmath_x = FLT128_MAX;
    quadmath_snprintf(str,200,"%3.190Qg",qmath_x);
    printf("FLT128_MAX      %s\n", str);

    if (LDBL_MAX == FLT128_MAX) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");
    
    /* Is max really max? */
    printf("LDBL_MAX*10     %3.190Lg\n", LDBL_MAX * 10);

    qmath_x = FLT128_MAX * 10;
    quadmath_snprintf(str,200,"%3.190Qg",qmath_x);
    printf("FLAT128_MAX*10  %s\n", str);

    
    /* MIN (NORMAL) */
    printf("\n### MIN (NORMAL) ###\n");

    printf("LDBL_MIN    %Lg\n", LDBL_MIN);

    qmath_x = FLT128_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x);
    printf("FLAT128_MIN %s\n", str);

    if (LDBL_MIN == FLT128_MIN) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");

    /* MIN (SUBNORMAL) */
    printf("\n### MIN (SUBNORMAL) ###\n");
   
    printf("LDBL_TRUE_MIN        %Lg\n", LDBL_TRUE_MIN);

    qmath_x = FLT128_DENORM_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x);
    printf("FLT_128_DENORM_MIN   %s\n", str);

    if (LDBL_TRUE_MIN == FLT128_DENORM_MIN) printf("Yes, they're the same\n");
    else                        printf("No, different!\n");
    
    /* Are these really subnormal minimum? */
    printf("LDBL_TRUE_MIN/2      %Lg\n", LDBL_TRUE_MIN/2);

    qmath_x = FLT128_DENORM_MIN;
    quadmath_snprintf(str,200,"%Qg",qmath_x/2);
    printf("FLT_128_DENORM_MIN/2 %s\n", str);
}

Compile with:

gcc -Wall -Wextra -O0 long-float-test.c -o long-float-test -lm -lquadmath

The output is:

### MAX ###
LDBL_MAX        1.189731495357231765021263853030970205169063322294624200440323733891737005522970722616410290336528882853545697807495577314427443153670288434198125573853743678673593200706973263201915918282962e+4932
FLT128_MAX      1.189731495357231765085759326628007016196469052641694045529698884212163579755312392324974012848462073525902033564749126859755265433573804462672698751945261490853461958725021262845865799405404e+4932
No, different!
LDBL_MAX*10     inf
FLAT128_MAX*10  inf

### MIN (NORMAL) ###
LDBL_MIN    3.3621e-4932
FLAT128_MIN 3.3621e-4932
Yes, they're the same

### MIN (SUBNORMAL) ###
LDBL_TRUE_MIN        3.6452e-4951
FLT_128_DENORM_MIN   6.47518e-4966
No, different!
LDBL_TRUE_MIN/2      0
FLT_128_DENORM_MIN/2 0

So the maximum represented number is the a little bit different (same exponent, and only different after the 20th; but the normalized minimum is the same. Now, the denormalized minimum is different, even with a different exponent, but not too far.

Are these just implementations of different 80-bit float representations? Or is the quadmath actually 128-bit, and I didn't get something about its internals? (If so, then it seems that it is more precise than x87 80-bit, particularly close to zero, and not that much of an advantage close to infinity?)

Or did I get something wrong -- is the difference between 80 and 128 bit precision standards not that large, actually? Did I made a mistake in the code? Or even, is that a bug in gcc (I doubt it would be...)?

0

There are 0 answers