LCOV - code coverage report
Current view: top level - lib/gltests - test-float.c (source / functions) Hit Total Coverage
Test: GNU SASL Lines: 121 121 100.0 %
Date: 2012-05-28 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 69 90 76.7 %

           Branch data     Line data    Source code
       1                 :            : /* Test of <float.h> substitute.
       2                 :            :    Copyright (C) 2011-2012 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 <http://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                 :         99 : pow2f (int n)
      34                 :            : {
      35                 :         99 :   int k = n;
      36                 :         99 :   volatile float x = 1;
      37                 :         99 :   volatile float y = 2;
      38                 :            :   /* Invariant: 2^n == x * y^k.  */
      39         [ +  + ]:         99 :   if (k < 0)
      40                 :            :     {
      41                 :         49 :       y = 0.5f;
      42                 :         49 :       k = - k;
      43                 :            :     }
      44         [ +  + ]:        471 :   while (k > 0)
      45                 :            :     {
      46         [ +  + ]:        469 :       if (k != 2 * (k / 2))
      47                 :            :         {
      48                 :        266 :           x = x * y;
      49                 :        266 :           k = k - 1;
      50                 :            :         }
      51         [ +  + ]:        469 :       if (k == 0)
      52                 :         97 :         break;
      53                 :        372 :       y = y * y;
      54                 :        372 :       k = k / 2;
      55                 :            :     }
      56                 :            :   /* Now k == 0, hence x == 2^n.  */
      57                 :         99 :   return x;
      58                 :            : }
      59                 :            : 
      60                 :            : /* Return 2^n.  */
      61                 :            : static double
      62                 :        215 : pow2d (int n)
      63                 :            : {
      64                 :        215 :   int k = n;
      65                 :        215 :   volatile double x = 1;
      66                 :        215 :   volatile double y = 2;
      67                 :            :   /* Invariant: 2^n == x * y^k.  */
      68         [ +  + ]:        215 :   if (k < 0)
      69                 :            :     {
      70                 :        107 :       y = 0.5;
      71                 :        107 :       k = - k;
      72                 :            :     }
      73         [ +  + ]:       1256 :   while (k > 0)
      74                 :            :     {
      75         [ +  + ]:       1254 :       if (k != 2 * (k / 2))
      76                 :            :         {
      77                 :        695 :           x = x * y;
      78                 :        695 :           k = k - 1;
      79                 :            :         }
      80         [ +  + ]:       1254 :       if (k == 0)
      81                 :        213 :         break;
      82                 :       1041 :       y = y * y;
      83                 :       1041 :       k = k / 2;
      84                 :            :     }
      85                 :            :   /* Now k == 0, hence x == 2^n.  */
      86                 :        215 :   return x;
      87                 :            : }
      88                 :            : 
      89                 :            : /* Return 2^n.  */
      90                 :            : static long double
      91                 :        259 : pow2l (int n)
      92                 :            : {
      93                 :        259 :   int k = n;
      94                 :        259 :   volatile long double x = 1;
      95                 :        259 :   volatile long double y = 2;
      96                 :            :   /* Invariant: 2^n == x * y^k.  */
      97         [ +  + ]:        259 :   if (k < 0)
      98                 :            :     {
      99                 :        129 :       y = 0.5L;
     100                 :        129 :       k = - k;
     101                 :            :     }
     102         [ +  + ]:       1570 :   while (k > 0)
     103                 :            :     {
     104         [ +  + ]:       1568 :       if (k != 2 * (k / 2))
     105                 :            :         {
     106                 :        911 :           x = x * y;
     107                 :        911 :           k = k - 1;
     108                 :            :         }
     109         [ +  + ]:       1568 :       if (k == 0)
     110                 :        257 :         break;
     111                 :       1311 :       y = y * y;
     112                 :       1311 :       k = k / 2;
     113                 :            :     }
     114                 :            :   /* Now k == 0, hence x == 2^n.  */
     115                 :        259 :   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                 :          1 : test_float (void)
     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                 :          1 :     volatile float m = FLT_MAX;
     157                 :            :     int n;
     158                 :            : 
     159         [ -  + ]:          1 :     ASSERT (m + m > m);
     160         [ +  + ]:         50 :     for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
     161                 :            :       {
     162                 :         49 :         volatile float pow2_n = pow2f (n); /* 2^n */
     163                 :         49 :         volatile float x = m + (m / pow2_n);
     164         [ +  + ]:         49 :         if (x > m)
     165         [ -  + ]:         25 :           ASSERT (x + x == x);
     166                 :            :         else
     167         [ -  + ]:         24 :           ASSERT (!(x + x == x));
     168                 :            :       }
     169                 :            :   }
     170                 :            : 
     171                 :            :   /* Check the value of FLT_MIN.  */
     172                 :            :   {
     173                 :          1 :     volatile float m = FLT_MIN;
     174                 :          1 :     volatile float x = pow2f (FLT_MIN_EXP - 1);
     175         [ -  + ]:          1 :     ASSERT (m == x);
     176                 :            :   }
     177                 :            : 
     178                 :            :   /* Check the value of FLT_EPSILON.  */
     179                 :            :   {
     180                 :          1 :     volatile float e = FLT_EPSILON;
     181                 :            :     volatile float me;
     182                 :            :     int n;
     183                 :            : 
     184                 :          1 :     me = 1.0f + e;
     185         [ -  + ]:          1 :     ASSERT (me > 1.0f);
     186         [ -  + ]:          1 :     ASSERT (me - 1.0f == e);
     187         [ +  + ]:         50 :     for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
     188                 :            :       {
     189                 :         49 :         volatile float half_n = pow2f (- n); /* 2^-n */
     190                 :         49 :         volatile float x = me - half_n;
     191         [ +  + ]:         49 :         if (x < me)
     192         [ -  + ]:         25 :           ASSERT (x <= 1.0f);
     193                 :            :       }
     194                 :            :   }
     195                 :          1 : }
     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                 :          1 : test_double (void)
     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                 :          1 :     volatile double m = DBL_MAX;
     236                 :            :     int n;
     237                 :            : 
     238         [ -  + ]:          1 :     ASSERT (m + m > m);
     239         [ +  + ]:        108 :     for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
     240                 :            :       {
     241                 :        107 :         volatile double pow2_n = pow2d (n); /* 2^n */
     242                 :        107 :         volatile double x = m + (m / pow2_n);
     243         [ +  + ]:        107 :         if (x > m)
     244         [ -  + ]:         54 :           ASSERT (x + x == x);
     245                 :            :         else
     246         [ -  + ]:         53 :           ASSERT (!(x + x == x));
     247                 :            :       }
     248                 :            :   }
     249                 :            : 
     250                 :            :   /* Check the value of DBL_MIN.  */
     251                 :            :   {
     252                 :          1 :     volatile double m = DBL_MIN;
     253                 :          1 :     volatile double x = pow2d (DBL_MIN_EXP - 1);
     254         [ -  + ]:          1 :     ASSERT (m == x);
     255                 :            :   }
     256                 :            : 
     257                 :            :   /* Check the value of DBL_EPSILON.  */
     258                 :            :   {
     259                 :          1 :     volatile double e = DBL_EPSILON;
     260                 :            :     volatile double me;
     261                 :            :     int n;
     262                 :            : 
     263                 :          1 :     me = 1.0 + e;
     264         [ -  + ]:          1 :     ASSERT (me > 1.0);
     265         [ -  + ]:          1 :     ASSERT (me - 1.0 == e);
     266         [ +  + ]:        108 :     for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
     267                 :            :       {
     268                 :        107 :         volatile double half_n = pow2d (- n); /* 2^-n */
     269                 :        107 :         volatile double x = me - half_n;
     270         [ +  + ]:        107 :         if (x < me)
     271         [ -  + ]:         54 :           ASSERT (x <= 1.0);
     272                 :            :       }
     273                 :            :   }
     274                 :          1 : }
     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                 :          1 : test_long_double (void)
     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                 :          1 :     volatile long double m = LDBL_MAX;
     316                 :            :     int n;
     317                 :            : 
     318         [ -  + ]:          1 :     ASSERT (m + m > m);
     319         [ +  + ]:        130 :     for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
     320                 :            :       {
     321                 :        129 :         volatile long double pow2_n = pow2l (n); /* 2^n */
     322                 :        129 :         volatile long double x = m + (m / pow2_n);
     323         [ +  + ]:        129 :         if (x > m)
     324         [ -  + ]:         65 :           ASSERT (x + x == x);
     325                 :            :         else
     326         [ -  + ]:         64 :           ASSERT (!(x + x == x));
     327                 :            :       }
     328                 :            :   }
     329                 :            : 
     330                 :            :   /* Check the value of LDBL_MIN.  */
     331                 :            :   {
     332                 :          1 :     volatile long double m = LDBL_MIN;
     333                 :          1 :     volatile long double x = pow2l (LDBL_MIN_EXP - 1);
     334         [ -  + ]:          1 :     ASSERT (m == x);
     335                 :            :   }
     336                 :            : 
     337                 :            :   /* Check the value of LDBL_EPSILON.  */
     338                 :            :   {
     339                 :          1 :     volatile long double e = LDBL_EPSILON;
     340                 :            :     volatile long double me;
     341                 :            :     int n;
     342                 :            : 
     343                 :          1 :     me = 1.0L + e;
     344         [ -  + ]:          1 :     ASSERT (me > 1.0L);
     345         [ -  + ]:          1 :     ASSERT (me - 1.0L == e);
     346         [ +  + ]:        130 :     for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
     347                 :            :       {
     348                 :        129 :         volatile long double half_n = pow2l (- n); /* 2^-n */
     349                 :        129 :         volatile long double x = me - half_n;
     350         [ +  + ]:        129 :         if (x < me)
     351         [ -  + ]:         65 :           ASSERT (x <= 1.0L);
     352                 :            :       }
     353                 :            :   }
     354                 :          1 : }
     355                 :            : 
     356                 :            : int
     357                 :          1 : main ()
     358                 :            : {
     359                 :          1 :   test_float ();
     360                 :          1 :   test_double ();
     361                 :            : 
     362                 :            :   {
     363                 :            :     DECL_LONG_DOUBLE_ROUNDING
     364                 :            : 
     365                 :          1 :     BEGIN_LONG_DOUBLE_ROUNDING ();
     366                 :            : 
     367                 :          1 :     test_long_double ();
     368                 :            : 
     369                 :          1 :     END_LONG_DOUBLE_ROUNDING ();
     370                 :            :   }
     371                 :            : 
     372                 :          1 :   return 0;
     373                 :            : }
     374                 :            : 
     375                 :            : #else
     376                 :            : 
     377                 :            : int
     378                 :            : main ()
     379                 :            : {
     380                 :            :   fprintf (stderr, "Skipping test: FLT_RADIX is not 2.\n");
     381                 :            :   return 77;
     382                 :            : }
     383                 :            : 
     384                 :            : #endif

Generated by: LCOV version 1.9