https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102475
Bug ID: 102475 Summary: incorrect definition of "normal" long doubles in libgcc/config/rs6000/ibm-ldouble-format Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: vincent-gcc at vinc17 dot net Target Milestone: --- In libgcc/config/rs6000/ibm-ldouble-format as seen at https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libgcc/config/rs6000/ibm-ldouble-format;hb=HEAD I can read: A long double can represent any value of the form s * 2^e * sum(k=0...105: f_k * 2^(-k)) where 's' is +1 or -1, 'e' is between 1022 and -968 inclusive, f_0 is 1, and f_k for k>0 is 0 or 1. These are the 'normal' long doubles. By "These are *the* 'normal' long doubles." I understand that the other long double values are not 'normal' long doubles. This contradicts the following definition in gcc/builtins.c: /* isnormal(x) -> isgreaterequal(fabs(x),DBL_MIN) & islessequal(fabs(x),DBL_MAX). */ and the implementation. The following is a test I had posted to comp.std.c on 2021-07-30 (thread "isnormal and non-FP values: possible defect"): Here's a test program for long double, which shows the issue on PowerPC. Here, 1 + 2^(-120) is exactly representable as a double-double number (the exact sum of 1 and 2^(-120), which are both double-precision numbers). This is verified by the output of x - 1, which gives 2^(-120) instead of 0. ------------------------------------------------------------------ #include <stdio.h> #include <float.h> #include <math.h> int main (void) { volatile long double x = 1 + 0x1.p-120L; int c; printf ("LDBL_MANT_DIG = %d\n", (int) LDBL_MANT_DIG); printf ("x - 1 = %La\n", x - 1); c = fpclassify (x); printf ("fpclassify(x) = %s\n", c == FP_NAN ? "FP_NAN" : c == FP_INFINITE ? "FP_INFINITE" : c == FP_ZERO ? "FP_ZERO" : c == FP_SUBNORMAL ? "FP_SUBNORMAL" : c == FP_NORMAL ? "FP_NORMAL" : "unknown"); printf ("isfinite/isnormal/isnan/isinf(x) = %d/%d/%d/%d\n", isfinite (x), isnormal (x), isnan (x), isinf (x)); return 0; } ------------------------------------------------------------------ I get the following result: LDBL_MANT_DIG = 106 x - 1 = 0x1p-120 fpclassify(x) = FP_NORMAL isfinite/isnormal/isnan/isinf(x) = 1/1/0/0 So x is a number with more than the 106-bit precision of normal numbers, and both fpclassify(x) and isnormal(x) regard it as a "normal number". In the CFP group, it seems that it is currently agreed that "normal number" should match the current gcc/builtins.c definition and implementation. Hence the current definition in libgcc/config/rs6000/ibm-ldouble-format should be regarded as incorrect. Note: about another error in this file, see PR94073.