Blame gl/tests/test-float.c

Packit 549fdc
/* Test of <float.h> substitute.
Packit 549fdc
   Copyright (C) 2011-2016 Free Software Foundation, Inc.
Packit 549fdc
Packit 549fdc
   This program is free software: you can redistribute it and/or modify
Packit 549fdc
   it under the terms of the GNU General Public License as published by
Packit 549fdc
   the Free Software Foundation; either version 3 of the License, or
Packit 549fdc
   (at your option) any later version.
Packit 549fdc
Packit 549fdc
   This program is distributed in the hope that it will be useful,
Packit 549fdc
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 549fdc
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 549fdc
   GNU General Public License for more details.
Packit 549fdc
Packit 549fdc
   You should have received a copy of the GNU General Public License
Packit 549fdc
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit 549fdc
Packit 549fdc
/* Written by Bruno Haible <bruno@clisp.org>, 2011.  */
Packit 549fdc
Packit 549fdc
#include <config.h>
Packit 549fdc
Packit 549fdc
#include <float.h>
Packit 549fdc
Packit 549fdc
#include "fpucw.h"
Packit 549fdc
#include "macros.h"
Packit 549fdc
Packit 549fdc
#if 0
Packit 549fdc
Packit 549fdc
/* Check that FLT_RADIX is a constant expression.  */
Packit 549fdc
int a[] = { FLT_RADIX };
Packit 549fdc
Packit 549fdc
/* Return 2^n.  */
Packit 549fdc
static float
Packit 549fdc
pow2f (int n)
Packit 549fdc
{
Packit 549fdc
  int k = n;
Packit 549fdc
  volatile float x = 1;
Packit 549fdc
  volatile float y = 2;
Packit 549fdc
  /* Invariant: 2^n == x * y^k.  */
Packit 549fdc
  if (k < 0)
Packit 549fdc
    {
Packit 549fdc
      y = 0.5f;
Packit 549fdc
      k = - k;
Packit 549fdc
    }
Packit 549fdc
  while (k > 0)
Packit 549fdc
    {
Packit 549fdc
      if (k != 2 * (k / 2))
Packit 549fdc
        {
Packit 549fdc
          x = x * y;
Packit 549fdc
          k = k - 1;
Packit 549fdc
        }
Packit 549fdc
      if (k == 0)
Packit 549fdc
        break;
Packit 549fdc
      y = y * y;
Packit 549fdc
      k = k / 2;
Packit 549fdc
    }
Packit 549fdc
  /* Now k == 0, hence x == 2^n.  */
Packit 549fdc
  return x;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Return 2^n.  */
Packit 549fdc
static double
Packit 549fdc
pow2d (int n)
Packit 549fdc
{
Packit 549fdc
  int k = n;
Packit 549fdc
  volatile double x = 1;
Packit 549fdc
  volatile double y = 2;
Packit 549fdc
  /* Invariant: 2^n == x * y^k.  */
Packit 549fdc
  if (k < 0)
Packit 549fdc
    {
Packit 549fdc
      y = 0.5;
Packit 549fdc
      k = - k;
Packit 549fdc
    }
Packit 549fdc
  while (k > 0)
Packit 549fdc
    {
Packit 549fdc
      if (k != 2 * (k / 2))
Packit 549fdc
        {
Packit 549fdc
          x = x * y;
Packit 549fdc
          k = k - 1;
Packit 549fdc
        }
Packit 549fdc
      if (k == 0)
Packit 549fdc
        break;
Packit 549fdc
      y = y * y;
Packit 549fdc
      k = k / 2;
Packit 549fdc
    }
Packit 549fdc
  /* Now k == 0, hence x == 2^n.  */
Packit 549fdc
  return x;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* Return 2^n.  */
Packit 549fdc
static long double
Packit 549fdc
pow2l (int n)
Packit 549fdc
{
Packit 549fdc
  int k = n;
Packit 549fdc
  volatile long double x = 1;
Packit 549fdc
  volatile long double y = 2;
Packit 549fdc
  /* Invariant: 2^n == x * y^k.  */
Packit 549fdc
  if (k < 0)
Packit 549fdc
    {
Packit 549fdc
      y = 0.5L;
Packit 549fdc
      k = - k;
Packit 549fdc
    }
Packit 549fdc
  while (k > 0)
Packit 549fdc
    {
Packit 549fdc
      if (k != 2 * (k / 2))
Packit 549fdc
        {
Packit 549fdc
          x = x * y;
Packit 549fdc
          k = k - 1;
Packit 549fdc
        }
Packit 549fdc
      if (k == 0)
Packit 549fdc
        break;
Packit 549fdc
      y = y * y;
Packit 549fdc
      k = k / 2;
Packit 549fdc
    }
Packit 549fdc
  /* Now k == 0, hence x == 2^n.  */
Packit 549fdc
  return x;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* ----------------------- Check macros for 'float' ----------------------- */
Packit 549fdc
Packit 549fdc
/* Check that the FLT_* macros expand to constant expressions.  */
Packit 549fdc
int fb[] =
Packit 549fdc
  {
Packit 549fdc
    FLT_MANT_DIG, FLT_MIN_EXP, FLT_MAX_EXP,
Packit 549fdc
    FLT_DIG, FLT_MIN_10_EXP, FLT_MAX_10_EXP
Packit 549fdc
  };
Packit 549fdc
float fc[] = { FLT_EPSILON, FLT_MIN, FLT_MAX };
Packit 549fdc
Packit 549fdc
static void
Packit 549fdc
test_float (void)
Packit 549fdc
{
Packit 549fdc
  /* Check that the value of FLT_MIN_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((FLT_MIN_EXP % 101111) == (FLT_MIN_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that the value of DBL_MIN_10_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((FLT_MIN_10_EXP % 101111) == (FLT_MIN_10_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that 'float' is as specified in IEEE 754.  */
Packit 549fdc
  ASSERT (FLT_MANT_DIG == 24);
Packit 549fdc
  ASSERT (FLT_MIN_EXP == -125);
Packit 549fdc
  ASSERT (FLT_MAX_EXP == 128);
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_MIN_10_EXP.  */
Packit 549fdc
  ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_DIG.  */
Packit 549fdc
  ASSERT (FLT_DIG == (int) ((FLT_MANT_DIG - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_MIN_10_EXP.  */
Packit 549fdc
  ASSERT (FLT_MIN_10_EXP == - (int) (- (FLT_MIN_EXP - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_MAX_10_EXP.  */
Packit 549fdc
  ASSERT (FLT_MAX_10_EXP == (int) (FLT_MAX_EXP * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_MAX.  */
Packit 549fdc
  {
Packit 549fdc
    volatile float m = FLT_MAX;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    ASSERT (m + m > m);
Packit 549fdc
    for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile float pow2_n = pow2f (n); /* 2^n */
Packit 549fdc
        volatile float x = m + (m / pow2_n);
Packit 549fdc
        if (x > m)
Packit 549fdc
          ASSERT (x + x == x);
Packit 549fdc
        else
Packit 549fdc
          ASSERT (!(x + x == x));
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_MIN.  */
Packit 549fdc
  {
Packit 549fdc
    volatile float m = FLT_MIN;
Packit 549fdc
    volatile float x = pow2f (FLT_MIN_EXP - 1);
Packit 549fdc
    ASSERT (m == x);
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of FLT_EPSILON.  */
Packit 549fdc
  {
Packit 549fdc
    volatile float e = FLT_EPSILON;
Packit 549fdc
    volatile float me;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    me = 1.0f + e;
Packit 549fdc
    ASSERT (me > 1.0f);
Packit 549fdc
    ASSERT (me - 1.0f == e);
Packit 549fdc
    for (n = 0; n <= 2 * FLT_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile float half_n = pow2f (- n); /* 2^-n */
Packit 549fdc
        volatile float x = me - half_n;
Packit 549fdc
        if (x < me)
Packit 549fdc
          ASSERT (x <= 1.0f);
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* ----------------------- Check macros for 'double' ----------------------- */
Packit 549fdc
Packit 549fdc
/* Check that the DBL_* macros expand to constant expressions.  */
Packit 549fdc
int db[] =
Packit 549fdc
  {
Packit 549fdc
    DBL_MANT_DIG, DBL_MIN_EXP, DBL_MAX_EXP,
Packit 549fdc
    DBL_DIG, DBL_MIN_10_EXP, DBL_MAX_10_EXP
Packit 549fdc
  };
Packit 549fdc
double dc[] = { DBL_EPSILON, DBL_MIN, DBL_MAX };
Packit 549fdc
Packit 549fdc
static void
Packit 549fdc
test_double (void)
Packit 549fdc
{
Packit 549fdc
  /* Check that the value of DBL_MIN_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((DBL_MIN_EXP % 101111) == (DBL_MIN_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that the value of DBL_MIN_10_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((DBL_MIN_10_EXP % 101111) == (DBL_MIN_10_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that 'double' is as specified in IEEE 754.  */
Packit 549fdc
  ASSERT (DBL_MANT_DIG == 53);
Packit 549fdc
  ASSERT (DBL_MIN_EXP == -1021);
Packit 549fdc
  ASSERT (DBL_MAX_EXP == 1024);
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_MIN_10_EXP.  */
Packit 549fdc
  ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_DIG.  */
Packit 549fdc
  ASSERT (DBL_DIG == (int) ((DBL_MANT_DIG - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_MIN_10_EXP.  */
Packit 549fdc
  ASSERT (DBL_MIN_10_EXP == - (int) (- (DBL_MIN_EXP - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_MAX_10_EXP.  */
Packit 549fdc
  ASSERT (DBL_MAX_10_EXP == (int) (DBL_MAX_EXP * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_MAX.  */
Packit 549fdc
  {
Packit 549fdc
    volatile double m = DBL_MAX;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    ASSERT (m + m > m);
Packit 549fdc
    for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile double pow2_n = pow2d (n); /* 2^n */
Packit 549fdc
        volatile double x = m + (m / pow2_n);
Packit 549fdc
        if (x > m)
Packit 549fdc
          ASSERT (x + x == x);
Packit 549fdc
        else
Packit 549fdc
          ASSERT (!(x + x == x));
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_MIN.  */
Packit 549fdc
  {
Packit 549fdc
    volatile double m = DBL_MIN;
Packit 549fdc
    volatile double x = pow2d (DBL_MIN_EXP - 1);
Packit 549fdc
    ASSERT (m == x);
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of DBL_EPSILON.  */
Packit 549fdc
  {
Packit 549fdc
    volatile double e = DBL_EPSILON;
Packit 549fdc
    volatile double me;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    me = 1.0 + e;
Packit 549fdc
    ASSERT (me > 1.0);
Packit 549fdc
    ASSERT (me - 1.0 == e);
Packit 549fdc
    for (n = 0; n <= 2 * DBL_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile double half_n = pow2d (- n); /* 2^-n */
Packit 549fdc
        volatile double x = me - half_n;
Packit 549fdc
        if (x < me)
Packit 549fdc
          ASSERT (x <= 1.0);
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
/* -------------------- Check macros for 'long double' -------------------- */
Packit 549fdc
Packit 549fdc
/* Check that the LDBL_* macros expand to constant expressions.  */
Packit 549fdc
int lb[] =
Packit 549fdc
  {
Packit 549fdc
    LDBL_MANT_DIG, LDBL_MIN_EXP, LDBL_MAX_EXP,
Packit 549fdc
    LDBL_DIG, LDBL_MIN_10_EXP, LDBL_MAX_10_EXP
Packit 549fdc
  };
Packit 549fdc
long double lc1 = LDBL_EPSILON;
Packit 549fdc
long double lc2 = LDBL_MIN;
Packit 549fdc
#if 0 /* LDBL_MAX is not a constant expression on some platforms.  */
Packit 549fdc
long double lc3 = LDBL_MAX;
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
static void
Packit 549fdc
test_long_double (void)
Packit 549fdc
{
Packit 549fdc
  /* Check that the value of LDBL_MIN_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((LDBL_MIN_EXP % 101111) == (LDBL_MIN_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that the value of LDBL_MIN_10_EXP is well parenthesized.  */
Packit 549fdc
  ASSERT ((LDBL_MIN_10_EXP % 101111) == (LDBL_MIN_10_EXP) % 101111);
Packit 549fdc
Packit 549fdc
  /* Check that 'long double' is at least as wide as 'double'.  */
Packit 549fdc
  ASSERT (LDBL_MANT_DIG >= DBL_MANT_DIG);
Packit 549fdc
  ASSERT (LDBL_MIN_EXP - LDBL_MANT_DIG <= DBL_MIN_EXP - DBL_MANT_DIG);
Packit 549fdc
  ASSERT (LDBL_MAX_EXP >= DBL_MAX_EXP);
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_DIG.  */
Packit 549fdc
  ASSERT (LDBL_DIG == (int)((LDBL_MANT_DIG - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_MIN_10_EXP.  */
Packit 549fdc
  ASSERT (LDBL_MIN_10_EXP == - (int) (- (LDBL_MIN_EXP - 1) * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_MAX_10_EXP.  */
Packit 549fdc
  ASSERT (LDBL_MAX_10_EXP == (int) (LDBL_MAX_EXP * 0.30103));
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_MAX.  */
Packit 549fdc
  {
Packit 549fdc
    volatile long double m = LDBL_MAX;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    ASSERT (m + m > m);
Packit 549fdc
    for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile long double pow2_n = pow2l (n); /* 2^n */
Packit 549fdc
        volatile long double x = m + (m / pow2_n);
Packit 549fdc
        if (x > m)
Packit 549fdc
          ASSERT (x + x == x);
Packit 549fdc
        else
Packit 549fdc
          ASSERT (!(x + x == x));
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_MIN.  */
Packit 549fdc
  {
Packit 549fdc
    volatile long double m = LDBL_MIN;
Packit 549fdc
    volatile long double x = pow2l (LDBL_MIN_EXP - 1);
Packit 549fdc
    ASSERT (m == x);
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  /* Check the value of LDBL_EPSILON.  */
Packit 549fdc
  {
Packit 549fdc
    volatile long double e = LDBL_EPSILON;
Packit 549fdc
    volatile long double me;
Packit 549fdc
    int n;
Packit 549fdc
Packit 549fdc
    me = 1.0L + e;
Packit 549fdc
    ASSERT (me > 1.0L);
Packit 549fdc
    ASSERT (me - 1.0L == e);
Packit 549fdc
    for (n = 0; n <= 2 * LDBL_MANT_DIG; n++)
Packit 549fdc
      {
Packit 549fdc
        volatile long double half_n = pow2l (- n); /* 2^-n */
Packit 549fdc
        volatile long double x = me - half_n;
Packit 549fdc
        if (x < me)
Packit 549fdc
          ASSERT (x <= 1.0L);
Packit 549fdc
      }
Packit 549fdc
  }
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
main ()
Packit 549fdc
{
Packit 549fdc
  test_float ();
Packit 549fdc
  test_double ();
Packit 549fdc
Packit 549fdc
  {
Packit 549fdc
    DECL_LONG_DOUBLE_ROUNDING
Packit 549fdc
Packit 549fdc
    BEGIN_LONG_DOUBLE_ROUNDING ();
Packit 549fdc
Packit 549fdc
    test_long_double ();
Packit 549fdc
Packit 549fdc
    END_LONG_DOUBLE_ROUNDING ();
Packit 549fdc
  }
Packit 549fdc
Packit 549fdc
  return 0;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#else
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
main ()
Packit 549fdc
{
Packit 549fdc
  return 77;
Packit 549fdc
}
Packit 549fdc
Packit 549fdc
#endif