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...)?