(root)/
gettext-0.22.4/
gettext-tools/
gnulib-tests/
snan.h
       1  /* Macros for signalling not-a-number.
       2     Copyright (C) 2007-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #ifndef _SNAN_H
      18  #define _SNAN_H
      19  
      20  #include <float.h>
      21  #include <limits.h>
      22  #include <math.h>
      23  
      24  #include "nan.h"
      25  
      26  
      27  /* The bit that distinguishes a quiet NaN from a signalling NaN is, according to
      28     <https://en.wikipedia.org/wiki/NaN#Encoding>, the most significant bit of the
      29     mantissa field.
      30     According to <https://en.wikipedia.org/wiki/IEEE_754#Formats>, this is the
      31     next bit, right below the bit 0 of the exponent.
      32     This bit is
      33       *  == 0 to indicate a quiet NaN or Infinity,
      34          == 1 to indicate a signalling NaN,
      35          on these CPUs: hppa, mips (*), sh4.
      36       *  == 1 to indicate a quiet NaN,
      37          == 0 to indicate a signalling NaN or Infinity,
      38          on all other CPUs.
      39          On these platforms, additionally a signalling NaN must have some other
      40          mantissa bit == 1, because when all exponent bits are == 1 and all
      41          mantissa bits are == 0, the number denotes ±Infinity.
      42          This NaN encoding is specified by IEEE 754-2008 § 6.2.1.
      43  
      44     (*) On mips CPUs, it depends on the CPU model.  The classical behaviour is
      45     as indicated above.  On some newer models, it's like on the other CPUs.
      46     On some (but not all!) models this meta-info can be determined from two
      47     special CPU registers: If the "Floating Point Implementation Register" (fir)
      48     bit 23, also known as Has2008 bit, is set, the "Floating Point Control and
      49     Status Register" (fcsr) bit 18, also known as the NAN2008 bit, has the value
      50       - 0 for the classical behaviour,
      51       - 1 for like on the other CPUs.
      52     Both of these bits are read-only.
      53     This module has determined the behaviour at configure time and defines the
      54     C macros MIPS_NAN2008_FLOAT, MIPS_NAN2008_DOUBLE, MIPS_NAN2008_LONG_DOUBLE
      55     accordingly.  */
      56  
      57  
      58  /* 'float' = IEEE 754 single-precision
      59     <https://en.wikipedia.org/wiki/Single-precision_floating-point_format>  */
      60  
      61  #define NWORDS \
      62    ((sizeof (float) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
      63  typedef union { float value; unsigned int word[NWORDS]; } memory_float;
      64  
      65  #if defined FLT_EXPBIT0_WORD && defined FLT_EXPBIT0_BIT
      66  
      67  # define HAVE_SNANF 1
      68  
      69  _GL_UNUSED static memory_float
      70  construct_memory_SNaNf (float quiet_value)
      71  {
      72    memory_float m;
      73    m.value = quiet_value;
      74    /* Turn the quiet NaN into a signalling NaN.  */
      75    #if FLT_EXPBIT0_BIT > 0
      76      m.word[FLT_EXPBIT0_WORD] ^= (unsigned int) 1 << (FLT_EXPBIT0_BIT - 1);
      77    #else
      78      m.word[FLT_EXPBIT0_WORD + (FLT_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
      79        ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
      80    #endif
      81    /* Set some arbitrary mantissa bit.  */
      82    if (FLT_EXPBIT0_WORD < NWORDS / 2) /* NWORDS > 1 and big endian */
      83      m.word[FLT_EXPBIT0_WORD + 1] |= (unsigned int) 1 << FLT_EXPBIT0_BIT;
      84    else /* NWORDS == 1 or little endian */
      85      m.word[0] |= (unsigned int) 1;
      86    return m;
      87  }
      88  
      89  /* Returns a signalling 'float' NaN in memory.  */
      90  _GL_UNUSED static memory_float
      91  memory_SNaNf ()
      92  {
      93    return construct_memory_SNaNf (NaNf ());
      94  }
      95  
      96  _GL_UNUSED static float
      97  construct_SNaNf (float quiet_value)
      98  {
      99    return construct_memory_SNaNf (quiet_value).value;
     100  }
     101  
     102  /* Returns a signalling 'float' NaN.
     103     Note: On 32-bit x86 processors, as well as on x86_64 processors with
     104     CC="gcc -mfpmath=387", this function may return a quiet NaN instead.
     105     Use memory_SNaNf() if you need to avoid this.  See
     106     <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
     107     for details.  */
     108  _GL_UNUSED static float
     109  SNaNf ()
     110  {
     111    return memory_SNaNf ().value;
     112  }
     113  
     114  #endif
     115  
     116  #undef NWORDS
     117  
     118  
     119  /* 'double' = IEEE 754 double-precision
     120     <https://en.wikipedia.org/wiki/Double-precision_floating-point_format>  */
     121  
     122  #define NWORDS \
     123    ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
     124  typedef union { double value; unsigned int word[NWORDS]; } memory_double;
     125  
     126  #if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
     127  
     128  # define HAVE_SNAND 1
     129  
     130  _GL_UNUSED static memory_double
     131  construct_memory_SNaNd (double quiet_value)
     132  {
     133    memory_double m;
     134    m.value = quiet_value;
     135    /* Turn the quiet NaN into a signalling NaN.  */
     136    #if DBL_EXPBIT0_BIT > 0
     137      m.word[DBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (DBL_EXPBIT0_BIT - 1);
     138    #else
     139      m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
     140        ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
     141    #endif
     142    /* Set some arbitrary mantissa bit.  */
     143    m.word[DBL_EXPBIT0_WORD + (DBL_EXPBIT0_WORD < NWORDS / 2 ? 1 : - 1)]
     144      |= (unsigned int) 1 << DBL_EXPBIT0_BIT;
     145    return m;
     146  }
     147  
     148  /* Returns a signalling 'double' NaN in memory.  */
     149  _GL_UNUSED static memory_double
     150  memory_SNaNd ()
     151  {
     152    return construct_memory_SNaNd (NaNd ());
     153  }
     154  
     155  _GL_UNUSED static double
     156  construct_SNaNd (double quiet_value)
     157  {
     158    return construct_memory_SNaNd (quiet_value).value;
     159  }
     160  
     161  /* Returns a signalling 'double' NaN.
     162     Note: On 32-bit x86 processors, as well as on x86_64 processors with
     163     CC="gcc -mfpmath=387", this function may return a quiet NaN instead.
     164     Use memory_SNaNf() if you need to avoid this.  See
     165     <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
     166     for details.  */
     167  _GL_UNUSED static double
     168  SNaNd ()
     169  {
     170    return memory_SNaNd ().value;
     171  }
     172  
     173  #endif
     174  
     175  #undef NWORDS
     176  
     177  
     178  /* 'long double' =
     179     * if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE:
     180       IEEE 754 double-precision
     181       <https://en.wikipedia.org/wiki/Double-precision_floating-point_format>
     182     * Otherwise:
     183       - On i386, x86_64, ia64:
     184         80-bits extended-precision
     185         <https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format>
     186       - On alpha, arm64, loongarch64, mips64, riscv64, s390x, sparc64:
     187         IEEE 754 quadruple-precision
     188         <https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#IEEE_754_quadruple-precision_binary_floating-point_format:_binary128>
     189       - On powerpc, powerpc64, powerpc64le:
     190         2x64-bits double-double
     191         <https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic>
     192       - On m68k:
     193         80-bits extended-precision, padded to 96 bits, with non-IEEE exponent
     194   */
     195  
     196  #define NWORDS \
     197    ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
     198  typedef union { long double value; unsigned int word[NWORDS]; }
     199          memory_long_double;
     200  
     201  #if defined LDBL_EXPBIT0_WORD && defined LDBL_EXPBIT0_BIT
     202  
     203  # define HAVE_SNANL 1
     204  
     205  _GL_UNUSED static memory_long_double
     206  construct_memory_SNaNl (long double quiet_value)
     207  {
     208    memory_long_double m;
     209    m.value = quiet_value;
     210    #if defined __powerpc__ && LDBL_MANT_DIG == 106
     211      /* This is PowerPC "double double", a pair of two doubles.  Inf and NaN are
     212         represented as the corresponding 64-bit IEEE values in the first double;
     213         the second is ignored.  Manipulate only the first double.  */
     214      #define HNWORDS \
     215        ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
     216    #else
     217      #define HNWORDS NWORDS
     218    #endif
     219    /* Turn the quiet NaN into a signalling NaN.  */
     220    #if ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_)) && !HAVE_SAME_LONG_DOUBLE_AS_DOUBLE
     221    /* In this representation, the leading 1 of the mantissa is explicitly
     222       stored.  */
     223     #if LDBL_EXPBIT0_BIT > 1
     224      m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 2);
     225     #else
     226      m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
     227        ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 2);
     228     #endif
     229    #else
     230    /* In this representation, the leading 1 of the mantissa is implicit.  */
     231     #if LDBL_EXPBIT0_BIT > 0
     232      m.word[LDBL_EXPBIT0_WORD] ^= (unsigned int) 1 << (LDBL_EXPBIT0_BIT - 1);
     233     #else
     234      m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
     235        ^= (unsigned int) 1 << (sizeof (unsigned int) * CHAR_BIT - 1);
     236     #endif
     237    #endif
     238    /* Set some arbitrary mantissa bit.  */
     239    m.word[LDBL_EXPBIT0_WORD + (LDBL_EXPBIT0_WORD < HNWORDS / 2 ? 1 : - 1)]
     240      |= (unsigned int) 1 << LDBL_EXPBIT0_BIT;
     241    #undef HNWORDS
     242    return m;
     243  }
     244  
     245  /* Returns a signalling 'long double' NaN in memory.  */
     246  _GL_UNUSED static memory_long_double
     247  memory_SNaNl ()
     248  {
     249    return construct_memory_SNaNl (NaNl ());
     250  }
     251  
     252  _GL_UNUSED static long double
     253  construct_SNaNl (long double quiet_value)
     254  {
     255    return construct_memory_SNaNl (quiet_value).value;
     256  }
     257  
     258  /* Returns a signalling 'long double' NaN.
     259     Note: On 32-bit x86 processors, as well as on x86_64 processors with
     260     CC="gcc -mfpmath=387", if HAVE_SAME_LONG_DOUBLE_AS_DOUBLE is 1, this
     261     function may return a quiet NaN instead.  Use memory_SNaNf() if you
     262     need to avoid this.  See
     263     <https://lists.gnu.org/archive/html/bug-gnulib/2023-10/msg00060.html>
     264     for details.  */
     265  _GL_UNUSED static long double
     266  SNaNl ()
     267  {
     268    return memory_SNaNl ().value;
     269  }
     270  
     271  #endif
     272  
     273  #undef NWORDS
     274  
     275  
     276  #endif /* _SNAN_H */