Blame gl/tests/test-float.c

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