root/maint/gnulib/tests/test-float.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pow2f
  2. pow2d
  3. pow2l
  4. test_float
  5. test_double
  6. test_long_double
  7. main
  8. main

   1 /* Test of <float.h> substitute.
   2    Copyright (C) 2011-2021 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 /* Written by Bruno Haible <bruno@clisp.org>, 2011.  */
  18 
  19 #include <config.h>
  20 
  21 #include <float.h>
  22 
  23 #include "fpucw.h"
  24 #include "macros.h"
  25 
  26 /* Check that FLT_RADIX is a constant expression.  */
  27 int a[] = { FLT_RADIX };
  28 
  29 #if FLT_RADIX == 2
  30 
  31 /* Return 2^n.  */
  32 static float
  33 pow2f (int n)
     /* [previous][next][first][last][top][bottom][index][help] */
  34 {
  35   int k = n;
  36   volatile float x = 1;
  37   volatile float y = 2;
  38   /* Invariant: 2^n == x * y^k.  */
  39   if (k < 0)
  40     {
  41       y = 0.5f;
  42       k = - k;
  43     }
  44   while (k > 0)
  45     {
  46       if (k != 2 * (k / 2))
  47         {
  48           x = x * y;
  49           k = k - 1;
  50         }
  51       if (k == 0)
  52         break;
  53       y = y * y;
  54       k = k / 2;
  55     }
  56   /* Now k == 0, hence x == 2^n.  */
  57   return x;
  58 }
  59 
  60 /* Return 2^n.  */
  61 static double
  62 pow2d (int n)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64   int k = n;
  65   volatile double x = 1;
  66   volatile double y = 2;
  67   /* Invariant: 2^n == x * y^k.  */
  68   if (k < 0)
  69     {
  70       y = 0.5;
  71       k = - k;
  72     }
  73   while (k > 0)
  74     {
  75       if (k != 2 * (k / 2))
  76         {
  77           x = x * y;
  78           k = k - 1;
  79         }
  80       if (k == 0)
  81         break;
  82       y = y * y;
  83       k = k / 2;
  84     }
  85   /* Now k == 0, hence x == 2^n.  */
  86   return x;
  87 }
  88 
  89 /* Return 2^n.  */
  90 static long double
  91 pow2l (int n)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93   int k = n;
  94   volatile long double x = 1;
  95   volatile long double y = 2;
  96   /* Invariant: 2^n == x * y^k.  */
  97   if (k < 0)
  98     {
  99       y = 0.5L;
 100       k = - k;
 101     }
 102   while (k > 0)
 103     {
 104       if (k != 2 * (k / 2))
 105         {
 106           x = x * y;
 107           k = k - 1;
 108         }
 109       if (k == 0)
 110         break;
 111       y = y * y;
 112       k = k / 2;
 113     }
 114   /* Now k == 0, hence x == 2^n.  */
 115   return x;
 116 }
 117 
 118 /* ----------------------- Check macros for 'float' ----------------------- */
 119 
 120 /* Check that the FLT_* macros expand to constant expressions.  */
 121 int fb[] =
 122   {
 123     FLT_MANT_DIG, FLT_MIN_EXP, FLT_MAX_EXP,
 124     FLT_DIG, FLT_MIN_10_EXP, FLT_MAX_10_EXP
 125   };
 126 float fc[] = { FLT_EPSILON, FLT_MIN, FLT_MAX };
 127 
 128 static void
 129 test_float (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131   /* Check that the value of FLT_MIN_EXP is well parenthesized.  */
 132   ASSERT ((FLT_MIN_EXP % 101111) == (FLT_MIN_EXP) % 101111);
 133 
 134   /* Check that the value of DBL_MIN_10_EXP is well parenthesized.  */
 135   ASSERT ((FLT_MIN_10_EXP % 101111) == (FLT_MIN_10_EXP) % 101111);
 136 
 137   /* Check that 'float' is as specified in IEEE 754.  */
 138   ASSERT (FLT_MANT_DIG == 24);
 139   ASSERT (FLT_MIN_EXP == -125);
 140   ASSERT (FLT_MAX_EXP == 128);
 141 
 142   /* Check the value of FLT_MIN_10_EXP.  */
 143   ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103));
 144 
 145   /* Check the value of FLT_DIG.  */
 146   ASSERT (FLT_DIG == (int) ((FLT_MANT_DIG - 1) * 0.30103));
 147 
 148   /* Check the value of FLT_MIN_10_EXP.  */
 149   ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103));
 150 
 151   /* Check the value of FLT_MAX_10_EXP.  */
 152   ASSERT (FLT_MAX_10_EXP == (int) (FLT_MAX_EXP * 0.30103));
 153 
 154   /* Check the value of FLT_MAX.  */
 155   {
 156     volatile float m = FLT_MAX;
 157     int n;
 158 
 159     ASSERT (m + m > m);
 160     for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
 161       {
 162         volatile float pow2_n = pow2f (n); /* 2^n */
 163         volatile float x = m + (m / pow2_n);
 164         if (x > m)
 165           ASSERT (x + x == x);
 166         else
 167           ASSERT (!(x + x == x));
 168       }
 169   }
 170 
 171   /* Check the value of FLT_MIN.  */
 172   {
 173     volatile float m = FLT_MIN;
 174     volatile float x = pow2f (FLT_MIN_EXP - 1);
 175     ASSERT (m == x);
 176   }
 177 
 178   /* Check the value of FLT_EPSILON.  */
 179   {
 180     volatile float e = FLT_EPSILON;
 181     volatile float me;
 182     int n;
 183 
 184     me = 1.0f + e;
 185     ASSERT (me > 1.0f);
 186     ASSERT (me - 1.0f == e);
 187     for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
 188       {
 189         volatile float half_n = pow2f (- n); /* 2^-n */
 190         volatile float x = me - half_n;
 191         if (x < me)
 192           ASSERT (x <= 1.0f);
 193       }
 194   }
 195 }
 196 
 197 /* ----------------------- Check macros for 'double' ----------------------- */
 198 
 199 /* Check that the DBL_* macros expand to constant expressions.  */
 200 int db[] =
 201   {
 202     DBL_MANT_DIG, DBL_MIN_EXP, DBL_MAX_EXP,
 203     DBL_DIG, DBL_MIN_10_EXP, DBL_MAX_10_EXP
 204   };
 205 double dc[] = { DBL_EPSILON, DBL_MIN, DBL_MAX };
 206 
 207 static void
 208 test_double (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 209 {
 210   /* Check that the value of DBL_MIN_EXP is well parenthesized.  */
 211   ASSERT ((DBL_MIN_EXP % 101111) == (DBL_MIN_EXP) % 101111);
 212 
 213   /* Check that the value of DBL_MIN_10_EXP is well parenthesized.  */
 214   ASSERT ((DBL_MIN_10_EXP % 101111) == (DBL_MIN_10_EXP) % 101111);
 215 
 216   /* Check that 'double' is as specified in IEEE 754.  */
 217   ASSERT (DBL_MANT_DIG == 53);
 218   ASSERT (DBL_MIN_EXP == -1021);
 219   ASSERT (DBL_MAX_EXP == 1024);
 220 
 221   /* Check the value of DBL_MIN_10_EXP.  */
 222   ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103));
 223 
 224   /* Check the value of DBL_DIG.  */
 225   ASSERT (DBL_DIG == (int) ((DBL_MANT_DIG - 1) * 0.30103));
 226 
 227   /* Check the value of DBL_MIN_10_EXP.  */
 228   ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103));
 229 
 230   /* Check the value of DBL_MAX_10_EXP.  */
 231   ASSERT (DBL_MAX_10_EXP == (int) (DBL_MAX_EXP * 0.30103));
 232 
 233   /* Check the value of DBL_MAX.  */
 234   {
 235     volatile double m = DBL_MAX;
 236     int n;
 237 
 238     ASSERT (m + m > m);
 239     for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
 240       {
 241         volatile double pow2_n = pow2d (n); /* 2^n */
 242         volatile double x = m + (m / pow2_n);
 243         if (x > m)
 244           ASSERT (x + x == x);
 245         else
 246           ASSERT (!(x + x == x));
 247       }
 248   }
 249 
 250   /* Check the value of DBL_MIN.  */
 251   {
 252     volatile double m = DBL_MIN;
 253     volatile double x = pow2d (DBL_MIN_EXP - 1);
 254     ASSERT (m == x);
 255   }
 256 
 257   /* Check the value of DBL_EPSILON.  */
 258   {
 259     volatile double e = DBL_EPSILON;
 260     volatile double me;
 261     int n;
 262 
 263     me = 1.0 + e;
 264     ASSERT (me > 1.0);
 265     ASSERT (me - 1.0 == e);
 266     for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
 267       {
 268         volatile double half_n = pow2d (- n); /* 2^-n */
 269         volatile double x = me - half_n;
 270         if (x < me)
 271           ASSERT (x <= 1.0);
 272       }
 273   }
 274 }
 275 
 276 /* -------------------- Check macros for 'long double' -------------------- */
 277 
 278 /* Check that the LDBL_* macros expand to constant expressions.  */
 279 int lb[] =
 280   {
 281     LDBL_MANT_DIG, LDBL_MIN_EXP, LDBL_MAX_EXP,
 282     LDBL_DIG, LDBL_MIN_10_EXP, LDBL_MAX_10_EXP
 283   };
 284 long double lc1 = LDBL_EPSILON;
 285 long double lc2 = LDBL_MIN;
 286 #if 0 /* LDBL_MAX is not a constant expression on some platforms.  */
 287 long double lc3 = LDBL_MAX;
 288 #endif
 289 
 290 static void
 291 test_long_double (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293   /* Check that the value of LDBL_MIN_EXP is well parenthesized.  */
 294   ASSERT ((LDBL_MIN_EXP % 101111) == (LDBL_MIN_EXP) % 101111);
 295 
 296   /* Check that the value of LDBL_MIN_10_EXP is well parenthesized.  */
 297   ASSERT ((LDBL_MIN_10_EXP % 101111) == (LDBL_MIN_10_EXP) % 101111);
 298 
 299   /* Check that 'long double' is at least as wide as 'double'.  */
 300   ASSERT (LDBL_MANT_DIG >= DBL_MANT_DIG);
 301   ASSERT (LDBL_MIN_EXP - LDBL_MANT_DIG <= DBL_MIN_EXP - DBL_MANT_DIG);
 302   ASSERT (LDBL_MAX_EXP >= DBL_MAX_EXP);
 303 
 304   /* Check the value of LDBL_DIG.  */
 305   ASSERT (LDBL_DIG == (int)((LDBL_MANT_DIG - 1) * 0.30103));
 306 
 307   /* Check the value of LDBL_MIN_10_EXP.  */
 308   ASSERT (LDBL_MIN_10_EXP == - (int) (- (LDBL_MIN_EXP - 1) * 0.30103));
 309 
 310   /* Check the value of LDBL_MAX_10_EXP.  */
 311   ASSERT (LDBL_MAX_10_EXP == (int) (LDBL_MAX_EXP * 0.30103));
 312 
 313   /* Check the value of LDBL_MAX.  */
 314   {
 315     volatile long double m = LDBL_MAX;
 316     int n;
 317 
 318     ASSERT (m + m > m);
 319     for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
 320       {
 321         volatile long double pow2_n = pow2l (n); /* 2^n */
 322         volatile long double x = m + (m / pow2_n);
 323         if (x > m)
 324           ASSERT (x + x == x);
 325         else
 326           ASSERT (!(x + x == x));
 327       }
 328   }
 329 
 330   /* Check the value of LDBL_MIN.  */
 331   {
 332     volatile long double m = LDBL_MIN;
 333     volatile long double x = pow2l (LDBL_MIN_EXP - 1);
 334     ASSERT (m == x);
 335   }
 336 
 337   /* Check the value of LDBL_EPSILON.  */
 338   {
 339     volatile long double e = LDBL_EPSILON;
 340     volatile long double me;
 341     int n;
 342 
 343     me = 1.0L + e;
 344     ASSERT (me > 1.0L);
 345     ASSERT (me - 1.0L == e);
 346     for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
 347       {
 348         volatile long double half_n = pow2l (- n); /* 2^-n */
 349         volatile long double x = me - half_n;
 350         if (x < me)
 351           ASSERT (x <= 1.0L);
 352       }
 353   }
 354 }
 355 
 356 int
 357 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359   test_float ();
 360   test_double ();
 361 
 362   {
 363     DECL_LONG_DOUBLE_ROUNDING
 364 
 365     BEGIN_LONG_DOUBLE_ROUNDING ();
 366 
 367     test_long_double ();
 368 
 369     END_LONG_DOUBLE_ROUNDING ();
 370   }
 371 
 372   return 0;
 373 }
 374 
 375 #else
 376 
 377 int
 378 main ()
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380   fprintf (stderr, "Skipping test: FLT_RADIX is not 2.\n");
 381   return 77;
 382 }
 383 
 384 #endif

/* [previous][next][first][last][top][bottom][index][help] */