+2024-07-31 Bruno Haible <bruno@clisp.org>
+
+ float: Update to mostly guarantee ISO C 23 compliance.
+ * doc/posix-headers/float.texi: Mention the various portability
+ problems.
+ * lib/float.in.h (FLT_HAS_SUBNORM, FLT_DECIMAL_DIG, FLT_TRUE_MIN,
+ DBL_HAS_SUBNORM, DBL_DECIMAL_DIG, DBL_TRUE_MIN, LDBL_HAS_SUBNORM,
+ LDBL_DECIMAL_DIG, LDBL_TRUE_MIN): New macros.
+ (gl_LDBL_TRUE_MIN): New declaration.
+ (FLT_IS_IEC_60559, FLT_NORM_MAX, FLT_SNAN, GNULIB_defined_FLT_SNAN,
+ DBL_IS_IEC_60559, DBL_NORM_MAX, DBL_SNAN, GNULIB_defined_DBL_SNAN,
+ LDBL_IS_IEC_60559, LDBL_NORM_MAX, LDBL_SNAN, GNULIB_defined_LDBL_SNAN):
+ New macros.
+ (gl_FLT_SNAN_t, gl_DBL_SNAN_t, gl_LDBL_SNAN_t): New types.
+ (gl_FLT_SNAN, gl_DBL_SNAN, gl_LDBL_SNAN): New declarations.
+ * lib/float.c (gl_LDBL_TRUE_MIN): New variable.
+ (gl_FLT_SNAN, gl_DBL_SNAN, gl_LDBL_SNAN): New variables.
+ * m4/float_h.m4 (gl_FLOAT_H): Add check whether float.h conforms to
+ ISO C23. Set REPLACE_FLOAT_SNAN.
+ * modules/float (configure.ac): Test also REPLACE_FLOAT_SNAN. Require
+ gl_BIGENDIAN.
+ * tests/test-float.c: Also check FLT_EVAL_METHOD, FLT_HAS_SUBNORM,
+ FLT_DECIMAL_DIG, FLT_IS_IEC_60559, FLT_TRUE_MIN, FLT_NORM_MAX,
+ DBL_HAS_SUBNORM, DBL_DECIMAL_DIG, DBL_IS_IEC_60559, DBL_TRUE_MIN,
+ DBL_NORM_MAX, LDBL_HAS_SUBNORM, LDBL_DECIMAL_DIG, LDBL_IS_IEC_60559.
+ Conditionally check LDBL_TRUE_MIN, LDBL_NORM_MAX.
+ Include isnanf-nolibm.h, isnand-nolibm.h, isnanl-nolibm.h.
+ (test_float): Check the values of FLT_HAS_SUBNORM, FLT_DECIMAL_DIG,
+ FLT_TRUE_MIN, FLT_IS_IEC_60559, FLT_NORM_MAX, FLT_SNAN.
+ (test_double): Check the values of DBL_HAS_SUBNORM, DBL_DECIMAL_DIG,
+ DBL_TRUE_MIN, DBL_IS_IEC_60559, DBL_NORM_MAX, DBL_SNAN.
+ (test_long_double): Check the values of LDBL_HAS_SUBNORM,
+ LDBL_DECIMAL_DIG, LDBL_TRUE_MIN, LDBL_IS_IEC_60559, LDBL_NORM_MAX,
+ LDBL_SNAN.
+ * modules/float-tests (Depends-on): Add isnanf-nolibm, isnand-nolibm,
+ isnanl-nolibm.
+
2024-07-30 Bruno Haible <bruno@clisp.org>
attribute: Improve documentation.
On Linux/PowerPC with GCC 4.4, and on AIX 7.1 with GCC 4.2,
they don't reflect the ``double double'' representation of @code{long double}
correctly.
+@item
+The macros
+@code{FLT_HAS_SUBNORM}, @code{FLT_DECIMAL_DIG}, @code{FLT_TRUE_MIN},
+@code{DBL_HAS_SUBNORM}, @code{DBL_DECIMAL_DIG}, @code{DBL_TRUE_MIN},
+@code{LDBL_HAS_SUBNORM}, @code{LDBL_DECIMAL_DIG}, @code{LDBL_TRUE_MIN},
+that were added in ISO C 11, are missing on some platforms:
+gcc 4.5.4, clang 7, Solaris 11.3 with Sun C.
+@item
+The macro @code{LDBL_DECIMAL_DIG} is missing on some platforms:
+MSVC 14.
+@item
+The value of macro @code{FLT_TRUE_MIN} is not a @code{float} on some platforms:
+AIX 7.1 with xlc.
+@item
+The macros
+@code{FLT_IS_IEC_60559}, @code{FLT_NORM_MAX}, @code{FLT_SNAN},
+@code{DBL_IS_IEC_60559}, @code{DBL_NORM_MAX}, @code{DBL_SNAN},
+@code{LDBL_IS_IEC_60559}, @code{LDBL_NORM_MAX}, @code{LDBL_SNAN},
+that were added in ISO C 23, are missing on some platforms:
+gcc 14 without @code{-std=c23} or @code{-std=gnu23}, clang 18, musl libc 1.2.5, AIX 7.3 with xlclang, Solaris 11.3 with Sun C, MSVC 14.
@end itemize
Portability problems not fixed by Gnulib:
The macro @code{FLT_ROUNDS} is a constant expression and does not represent
the current rounding mode on some platforms:
glibc 2.11, HP-UX 11, mingw.
+@item
+The value of @code{FLT_TRUE_MIN} is not a constant on some platforms:
+FreeBSD/x86.
+@item
+The values of @code{FLT_SNAN}, @code{DBL_SNAN}, @code{LDBL_SNAN} are not
+constants on some platforms:
+AIX 7.3 with xlclang, and all platforms which use the gnulib replacements.
@end itemize
/* Specification. */
#include <float.h>
-#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__
+#if GNULIB_defined_long_double_union
+# if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__
const union gl_long_double_union gl_LDBL_MAX =
{ { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } };
-#elif defined __i386__
+# elif defined __i386__
const union gl_long_double_union gl_LDBL_MAX =
{ { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } };
-#else
+# endif
+# if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+/* We can't even simply evaluate the formula (LDBL_MIN / 9223372036854775808.0L)
+ at run time, because it would require BEGIN_LONG_DOUBLE_ROUNDING /
+ END_LONG_DOUBLE_ROUNDING invocations. It simpler to just write down the
+ representation of LDBL_TRUE_MIN, based on
+ <https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format>. */
+const union gl_long_double_union gl_LDBL_TRUE_MIN =
+ { { 0x00000001, 0x00000000, 0 } };
+# endif
+#endif
+
+#if GNULIB_defined_FLT_SNAN
+/* Define like memory_positive_SNaNf(), see signed-snan.h and snan.h,
+ or like setpayloadsigf() with an arbitrary payload. */
+gl_FLT_SNAN_t gl_FLT_SNAN =
+# if FLT_MANT_DIG == 24
+# if defined __hppa || (defined __mips__ && !MIPS_NAN2008_FLOAT) || defined __sh__
+ /* sign bit: 0, 8 exponent bits: all 1, next bit: 1, payload: 0b10...0 */
+ { { 0x7FE00000U } }
+# else
+ /* sign bit: 0, 8 exponent bits: all 1, next bit: 0, payload: 0b10...0 */
+ { { 0x7FA00000U } }
+# endif
+# endif
+ ;
+#endif
+
+#if GNULIB_defined_DBL_SNAN
+/* Define like memory_positive_SNaNd(), see signed-snan.h and snan.h,
+ or like setpayloadsig() with an arbitrary payload. */
+gl_DBL_SNAN_t gl_DBL_SNAN =
+# if DBL_MANT_DIG == 53
+# if defined __hppa || (defined __mips__ && !MIPS_NAN2008_FLOAT) || defined __sh__
+ /* sign bit: 0, 11 exponent bits: all 1, next bit: 1, payload: 0b10...0 */
+ { { 0x7FFC000000000000ULL } }
+# else
+ /* sign bit: 0, 11 exponent bits: all 1, next bit: 0, payload: 0b10...0 */
+ { { 0x7FF4000000000000ULL } }
+# endif
+# endif
+ ;
+#endif
+
+#if GNULIB_defined_LDBL_SNAN
+# ifdef WORDS_BIGENDIAN
+# define TWO(hi,lo) { hi, lo }
+# else
+# define TWO(hi,lo) { lo, hi }
+# endif
+/* Define like memory_positive_SNaNl(), see signed-snan.h and snan.h,
+ or like setpayloadsigl() with an arbitrary payload. */
+gl_LDBL_SNAN_t gl_LDBL_SNAN =
+# if LDBL_MANT_DIG == 53 /* on arm, hppa, mips, sh, but also MSVC */
+# if defined __hppa || (defined __mips__ && !MIPS_NAN2008_FLOAT) || defined __sh__
+ /* sign bit: 0, 11 exponent bits: all 1, next bit: 1, payload: 0b10...0 */
+ { { 0x7FFC000000000000ULL } }
+# else
+ /* sign bit: 0, 11 exponent bits: all 1, next bit: 0, payload: 0b10...0 */
+ { { 0x7FF4000000000000ULL } }
+# endif
+# elif LDBL_MANT_DIG == 64 /* on i386, x86_64, ia64, m68k */
+# if defined __m68k__
+ /* sign bit: 0, 15 exponent bits: all 1, 16 gap bits: all 0,
+ always=1 bit: 1, next bit: 0, payload: 0b10...0 */
+ { { 0x7FFF0000ULL, 0xA0000000ULL, 0x00000000ULL } }
+# else
+ /* sign bit: 0, 15 exponent bits: all 1, always=1 bit: 1, next bit: 0, payload: 0b10...0
+ (see <https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format>) */
+ { TWO (0x00007FFFULL, 0xA000000000000000ULL) }
+# endif
+# elif LDBL_MANT_DIG == 106 /* on powerpc, powerpc64, powerpc64le */
+ /* most-significant double:
+ sign bit: 0, 11 exponent bits: all 1, next bit: 0, payload: 0b10...0,
+ least-significant double: 0.0 */
+ { { 0x7FF4000000000000ULL, 0ULL } }
+# elif LDBL_MANT_DIG == 113 /* on alpha, arm64, loongarch64, mips64, riscv64, s390x, sparc64 */
+# if (defined __mips__ && !MIPS_NAN2008_FLOAT)
+ /* sign bit: 0, 15 exponent bits: all 1, next bit: 1, payload: 0b10...0 */
+ { TWO (0x7FFFC00000000000ULL, 0ULL) }
+# else
+ /* sign bit: 0, 15 exponent bits: all 1, next bit: 0, payload: 0b10...0 */
+ { TWO (0x7FFF400000000000ULL, 0ULL) }
+# endif
+# endif
+ ;
+#endif
+
/* This declaration is solely to ensure that after preprocessing
this file is never empty. */
typedef int dummy;
-#endif
#ifndef _@GUARD_PREFIX@_FLOAT_H
#define _@GUARD_PREFIX@_FLOAT_H
+/* ============================ ISO C99 support ============================ */
+
/* 'long double' properties. */
#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__)
# endif
#endif
+/* ============================ ISO C11 support ============================ */
+
+/* 'float' properties */
+
+#ifndef FLT_HAS_SUBNORM
+# define FLT_HAS_SUBNORM 1
+#endif
+#ifndef FLT_DECIMAL_DIG
+/* FLT_MANT_DIG = 24 => FLT_DECIMAL_DIG = 9 */
+# define FLT_DECIMAL_DIG ((int)(FLT_MANT_DIG * 0.3010299956639812 + 2))
+#endif
+#if defined _AIX && !defined __GNUC__
+/* On AIX, the value of FLT_TRUE_MIN in /usr/include/float.h is a 'double',
+ not a 'float'. */
+# undef FLT_TRUE_MIN
+#endif
+#ifndef FLT_TRUE_MIN
+/* FLT_MIN / 2^(FLT_MANT_DIG-1) */
+# define FLT_TRUE_MIN (FLT_MIN / 8388608.0f)
+#endif
+
+/* 'double' properties */
+
+#ifndef DBL_HAS_SUBNORM
+# define DBL_HAS_SUBNORM 1
+#endif
+#ifndef DBL_DECIMAL_DIG
+/* DBL_MANT_DIG = 53 => DBL_DECIMAL_DIG = 17 */
+# define DBL_DECIMAL_DIG ((int)(DBL_MANT_DIG * 0.3010299956639812 + 2))
+#endif
+#ifndef DBL_TRUE_MIN
+/* DBL_MIN / 2^(DBL_MANT_DIG-1) */
+# define DBL_TRUE_MIN (DBL_MIN / 4503599627370496.0)
+#endif
+
+/* 'long double' properties */
+
+#ifndef LDBL_HAS_SUBNORM
+# define LDBL_HAS_SUBNORM 1
+#endif
+#ifndef LDBL_DECIMAL_DIG
+/* LDBL_MANT_DIG = 53 => LDBL_DECIMAL_DIG = 17 */
+/* LDBL_MANT_DIG = 64 => LDBL_DECIMAL_DIG = 21 */
+/* LDBL_MANT_DIG = 106 => LDBL_DECIMAL_DIG = 33 */
+/* LDBL_MANT_DIG = 113 => LDBL_DECIMAL_DIG = 36 */
+# define LDBL_DECIMAL_DIG ((int)(LDBL_MANT_DIG * 0.3010299956639812 + 2))
+#endif
+#ifndef LDBL_TRUE_MIN
+/* LDBL_MIN / 2^(LDBL_MANT_DIG-1) */
+# if LDBL_MANT_DIG == 53
+# define LDBL_TRUE_MIN (LDBL_MIN / 4503599627370496.0L)
+# elif LDBL_MANT_DIG == 64
+# if defined __i386__ && (defined __FreeBSD__ || defined __DragonFly__)
+/* Work around FreeBSD/x86 problem mentioned above. */
+extern const union gl_long_double_union gl_LDBL_TRUE_MIN;
+# define LDBL_TRUE_MIN (gl_LDBL_TRUE_MIN.ld)
+# else
+# define LDBL_TRUE_MIN (LDBL_MIN / 9223372036854775808.0L)
+# endif
+# elif LDBL_MANT_DIG == 106
+# define LDBL_TRUE_MIN (LDBL_MIN / 40564819207303340847894502572032.0L)
+# elif LDBL_MANT_DIG == 113
+# define LDBL_TRUE_MIN (LDBL_MIN / 5192296858534827628530496329220096.0L)
+# endif
+#endif
+
+/* ============================ ISO C23 support ============================ */
+
+/* 'float' properties */
+
+#ifndef FLT_IS_IEC_60559
+# if defined __m68k__
+# define FLT_IS_IEC_60559 0
+# else
+# define FLT_IS_IEC_60559 1
+# endif
+#endif
+#ifndef FLT_NORM_MAX
+# define FLT_NORM_MAX FLT_MAX
+#endif
+#ifndef FLT_SNAN
+/* For sh, beware of <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111814>. */
+# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
+# define FLT_SNAN __builtin_nansf ("")
+# else
+typedef union { unsigned int word[1]; float value; } gl_FLT_SNAN_t;
+extern gl_FLT_SNAN_t gl_FLT_SNAN;
+# define FLT_SNAN (gl_FLT_SNAN.value)
+# define GNULIB_defined_FLT_SNAN 1
+# endif
+#endif
+
+/* 'double' properties */
+
+#ifndef DBL_IS_IEC_60559
+# if defined __m68k__
+# define DBL_IS_IEC_60559 0
+# else
+# define DBL_IS_IEC_60559 1
+# endif
+#endif
+#ifndef DBL_NORM_MAX
+# define DBL_NORM_MAX DBL_MAX
+#endif
+#ifndef DBL_SNAN
+/* For sh, beware of <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111814>. */
+# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
+# define DBL_SNAN __builtin_nans ("")
+# else
+typedef union { unsigned long long word[1]; double value; } gl_DBL_SNAN_t;
+extern gl_DBL_SNAN_t gl_DBL_SNAN;
+# define DBL_SNAN (gl_DBL_SNAN.value)
+# define GNULIB_defined_DBL_SNAN 1
+# endif
+#endif
+
+/* 'long double' properties */
+
+#ifndef LDBL_IS_IEC_60559
+# if defined __m68k__
+# define LDBL_IS_IEC_60559 0
+# elif LDBL_MANT_DIG == 53 || LDBL_MANT_DIG == 113
+# define LDBL_IS_IEC_60559 1
+# else
+# define LDBL_IS_IEC_60559 0
+# endif
+#endif
+#ifndef LDBL_NORM_MAX
+# define LDBL_NORM_MAX LDBL_MAX
+#endif
+#ifndef LDBL_SNAN
+/* For sh, beware of <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111814>. */
+# if ((__GNUC__ + (__GNUC_MINOR__ >= 3) > 3) || defined __clang__) && !defined __sh__
+# define LDBL_SNAN __builtin_nansl ("")
+# else
+# if LDBL_MANT_DIG == 53
+typedef union { unsigned long long word[1]; long double value; } gl_LDBL_SNAN_t;
+# elif defined __m68k__
+typedef union { unsigned int word[3]; long double value; } gl_LDBL_SNAN_t;
+# else
+typedef union { unsigned long long word[2]; long double value; } gl_LDBL_SNAN_t;
+# endif
+extern gl_LDBL_SNAN_t gl_LDBL_SNAN;
+# define LDBL_SNAN (gl_LDBL_SNAN.value)
+# define GNULIB_defined_LDBL_SNAN 1
+# endif
+#endif
+
+/* ================================= Other ================================= */
+
#if @REPLACE_ITOLD@
/* Pull in a function that fixes the 'int' to 'long double' conversion
of glibc 2.7. */
# float_h.m4
-# serial 14
+# serial 15
dnl Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
;;
esac
+ dnl Test for completeness w.r.t. ISO C 23.
+ REPLACE_FLOAT_SNAN=0
+ AC_CACHE_CHECK([whether float.h conforms to ISO C23],
+ [gl_cv_header_float_h_isoc23],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <float.h>
+ int x[] = { FLT_DECIMAL_DIG, DBL_DECIMAL_DIG, LDBL_DECIMAL_DIG };
+ float maxf = FLT_NORM_MAX;
+ double maxd = DBL_NORM_MAX;
+ long double maxl = LDBL_NORM_MAX;
+ ]],
+ [[float sf = FLT_SNAN;
+ double sd = DBL_SNAN;
+ long double sl = LDBL_SNAN;
+ return (sf != 0) + (sd != 0) + (sl != 0);
+ ]])],
+ [gl_cv_header_float_h_isoc23=yes],
+ [gl_cv_header_float_h_isoc23=no])
+ ])
+ if test $gl_cv_header_float_h_isoc23 != yes; then
+ GL_GENERATE_FLOAT_H=true
+ REPLACE_FLOAT_SNAN=1
+ fi
+
dnl Test against glibc-2.7 Linux/SPARC64 bug.
REPLACE_ITOLD=0
AC_CACHE_CHECK([whether conversion from 'int' to 'long double' works],
gl_FLOAT_H
gl_CONDITIONAL_HEADER([float.h])
AC_PROG_MKDIR_P
-gl_CONDITIONAL([GL_COND_OBJ_FLOAT], [test $REPLACE_FLOAT_LDBL = 1])
+gl_CONDITIONAL([GL_COND_OBJ_FLOAT],
+ [test $REPLACE_FLOAT_LDBL = 1 || test $REPLACE_FLOAT_SNAN = 1])
gl_CONDITIONAL([GL_COND_OBJ_ITOLD], [test $REPLACE_ITOLD = 1])
+dnl Prerequisites of lib/float.c.
+AC_REQUIRE([gl_BIGENDIAN])
Makefile.am:
BUILT_SOURCES += $(FLOAT_H)
Depends-on:
fpieee
fpucw
+isnanf-nolibm
+isnand-nolibm
+isnanl-nolibm
float-c++-tests
configure.ac:
#include <float.h>
-/* Check that FLT_RADIX is a constant expression. */
-int a[] = { FLT_RADIX };
+/* Check that some macros are constant expressions. */
+int a[] =
+ {
+ FLT_RADIX,
+ FLT_EVAL_METHOD /* added in ISO C 99 */
+ };
/* ----------------------- Check macros for 'float' ----------------------- */
int fb[] =
{
FLT_MANT_DIG, FLT_MIN_EXP, FLT_MAX_EXP,
- FLT_DIG, FLT_MIN_10_EXP, FLT_MAX_10_EXP
+ FLT_DIG, FLT_MIN_10_EXP, FLT_MAX_10_EXP,
+ FLT_HAS_SUBNORM, /* added in ISO C 11 */
+ FLT_DECIMAL_DIG, /* added in ISO C 11 */
+ FLT_IS_IEC_60559 /* added in ISO C 23 */
};
-float fc[] = { FLT_EPSILON, FLT_MIN, FLT_MAX };
+float fc[] =
+ {
+ FLT_EPSILON, FLT_MIN, FLT_MAX,
+ FLT_TRUE_MIN, /* added in ISO C 11 */
+ FLT_NORM_MAX /* added in ISO C 23 */
+ };
+#if 0 /* FLT_SNAN is not a constant expression on some platforms. */
+float fs = FLT_SNAN; /* added in ISO C 23 */
+#endif
/* ----------------------- Check macros for 'double' ----------------------- */
int db[] =
{
DBL_MANT_DIG, DBL_MIN_EXP, DBL_MAX_EXP,
- DBL_DIG, DBL_MIN_10_EXP, DBL_MAX_10_EXP
+ DBL_DIG, DBL_MIN_10_EXP, DBL_MAX_10_EXP,
+ DBL_HAS_SUBNORM, /* added in ISO C 11 */
+ DBL_DECIMAL_DIG, /* added in ISO C 11 */
+ DBL_IS_IEC_60559 /* added in ISO C 23 */
};
-double dc[] = { DBL_EPSILON, DBL_MIN, DBL_MAX };
+double dc[] =
+ {
+ DBL_EPSILON, DBL_MIN, DBL_MAX,
+ DBL_TRUE_MIN, /* added in ISO C 11 */
+ DBL_NORM_MAX /* added in ISO C 23 */
+ };
+#if 0 /* DBL_SNAN is not a constant expression on some platforms. */
+double ds = DBL_SNAN; /* added in ISO C 23 */
+#endif
/* -------------------- Check macros for 'long double' -------------------- */
int lb[] =
{
LDBL_MANT_DIG, LDBL_MIN_EXP, LDBL_MAX_EXP,
- LDBL_DIG, LDBL_MIN_10_EXP, LDBL_MAX_10_EXP
+ LDBL_DIG, LDBL_MIN_10_EXP, LDBL_MAX_10_EXP,
+ LDBL_HAS_SUBNORM, /* added in ISO C 11 */
+ LDBL_DECIMAL_DIG, /* added in ISO C 11 */
+ LDBL_IS_IEC_60559 /* added in ISO C 23 */
};
long double lc1 = LDBL_EPSILON;
long double lc2 = LDBL_MIN;
-#if 0 /* LDBL_MAX is not a constant expression on some platforms. */
+#if !GNULIB_defined_long_double_union
+/* LDBL_MAX is not a constant expression on some platforms. */
long double lc3 = LDBL_MAX;
#endif
+#if !GNULIB_defined_long_double_union
+/* LDBL_TRUE_MIN is not a constant expression on FreeBSD/i386. */
+long double lc4 = LDBL_TRUE_MIN; /* added in ISO C 11 */
+#endif
+#if !GNULIB_defined_long_double_union
+/* LDBL_MAX is not a constant expression on some platforms. */
+long double lc5 = LDBL_NORM_MAX; /* added in ISO C 23 */
+#endif
+#if 0
+/* LDBL_SNAN is not a constant expression on some platforms. */
+long double ls = LDBL_SNAN; /* added in ISO C 23 */
+#endif
/* ------------------------------------------------------------------------- */
#include "fpucw.h"
+#include "isnanf-nolibm.h"
+#include "isnand-nolibm.h"
+#include "isnanl-nolibm.h"
#include "macros.h"
#if FLT_RADIX == 2
ASSERT (x <= 1.0f);
}
}
+
+ /* Check the value of FLT_HAS_SUBNORM. */
+ ASSERT (FLT_HAS_SUBNORM == 1);
+
+ /* Check the value of FLT_DECIMAL_DIG. */
+ ASSERT (FLT_DECIMAL_DIG == (int)(FLT_MANT_DIG * 0.3010299956639812 + 2));
+
+ /* Check the value of FLT_TRUE_MIN. */
+ ASSERT (FLT_TRUE_MIN > 0.0f);
+ {
+ volatile float x = FLT_TRUE_MIN * 0.5f;
+ ASSERT (x == 0.0f);
+ }
+
+ /* Check the value of FLT_IS_IEC_60559. */
+#if !defined __m68k__
+ ASSERT (FLT_IS_IEC_60559);
+#elif 0
+ /* It is not clear what this macro actually means. Cf.
+ <http://mailman.oakapple.net/pipermail/cfp-interest/2023-April/002760.html> */
+ ASSERT (!FLT_IS_IEC_60559);
+#endif
+
+ /* Check the value of FLT_NORM_MAX. */
+ ASSERT (FLT_NORM_MAX == FLT_MAX);
+
+ /* Check the value of FLT_SNAN. */
+ ASSERT (isnanf (FLT_SNAN));
}
/* ----------------------- Check macros for 'double' ----------------------- */
ASSERT (x <= 1.0);
}
}
+
+ /* Check the value of DBL_HAS_SUBNORM. */
+ ASSERT (DBL_HAS_SUBNORM == 1);
+
+ /* Check the value of DBL_DECIMAL_DIG. */
+ ASSERT (DBL_DECIMAL_DIG == (int)(DBL_MANT_DIG * 0.3010299956639812 + 2));
+
+ /* Check the value of DBL_TRUE_MIN. */
+ ASSERT (DBL_TRUE_MIN > 0.0);
+ {
+ volatile double x = DBL_TRUE_MIN * 0.5;
+ ASSERT (x == 0.0);
+ }
+
+ /* Check the value of DBL_IS_IEC_60559. */
+#if !defined __m68k__
+ ASSERT (DBL_IS_IEC_60559);
+#elif 0
+ /* It is not clear what this macro actually means. Cf.
+ <http://mailman.oakapple.net/pipermail/cfp-interest/2023-April/002760.html> */
+ ASSERT (!DBL_IS_IEC_60559);
+#endif
+
+ /* Check the value of DBL_NORM_MAX. */
+ ASSERT (DBL_NORM_MAX == DBL_MAX);
+
+ /* Check the value of DBL_SNAN. */
+ ASSERT (isnand (DBL_SNAN));
}
/* -------------------- Check macros for 'long double' -------------------- */
ASSERT (x <= 1.0L);
}
}
+
+ /* Check the value of LDBL_HAS_SUBNORM. */
+ ASSERT (LDBL_HAS_SUBNORM == 1);
+
+ /* Check the value of LDBL_DECIMAL_DIG. */
+ ASSERT (LDBL_DECIMAL_DIG == (int)(LDBL_MANT_DIG * 0.3010299956639812 + 2));
+
+ /* Check the value of LDBL_TRUE_MIN. */
+ ASSERT (LDBL_TRUE_MIN > 0.0L);
+ {
+ volatile long double x = LDBL_TRUE_MIN * 0.5L;
+ ASSERT (x == 0.0L);
+ }
+
+ /* Check the value of LDBL_IS_IEC_60559. */
+#if (LDBL_MANT_DIG == 53 || LDBL_MANT_DIG == 113) && !defined __m68k__
+ ASSERT (LDBL_IS_IEC_60559);
+#elif 0
+ /* It is not clear what this macro actually means. Cf.
+ <http://mailman.oakapple.net/pipermail/cfp-interest/2023-April/002760.html> */
+ ASSERT (!LDBL_IS_IEC_60559);
+#endif
+
+ /* Check the value of LDBL_NORM_MAX. */
+ ASSERT (LDBL_NORM_MAX == LDBL_MAX);
+
+ /* Check the value of LDBL_SNAN. */
+ ASSERT (isnanl (LDBL_SNAN));
}
int