Back to index

glibc  2.9
Classes | Defines | Typedefs | Enumerations | Functions | Variables
test-arith.c File Reference
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fenv.h>
#include <assert.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

union  union_t
struct  optest_t

Defines

#define _GNU_SOURCE
#define ESIZE   11
#define MSIZE   52
#define FUNC(x)   x
#define R_NEAREST   1
#define R_ZERO   2
#define R_UP   4
#define R_DOWN   8
#define R_ALL   (R_NEAREST|R_ZERO|R_UP|R_DOWN)
#define bitset(count, value)
#define except_entry(ex)   { ex, #ex } ,
#define FE_INEXACT   0
#define FE_DIVBYZERO   0
#define FE_UNDERFLOW   0
#define FE_OVERFLOW   0
#define FE_INVALID   0
#define FE_INVALID_SNAN   FE_INVALID
#define FE_INVALID_ISI   FE_INVALID
#define FE_INVALID_IDI   FE_INVALID
#define FE_INVALID_ZDZ   FE_INVALID
#define FE_INVALID_COMPARE   FE_INVALID
#define FE_INVALID_SOFTWARE   FE_INVALID
#define FE_INVALID_SQRT   FE_INVALID
#define FE_INVALID_INTEGER_CONVERSION   FE_INVALID

Typedefs

typedef double tocheck_t

Enumerations

enum  pattern_t {
  P_Z = 0x0, P_000O = 0x1, P_001Z = 0x2, P_00O = 0x3,
  P_01Z = 0x4, P_010O = 0x5, P_011Z = 0x6, P_0O = 0x7,
  P_1Z = 0x8, P_100O = 0x9, P_101Z = 0xa, P_10O = 0xb,
  P_11Z = 0xc, P_110O = 0xd, P_111Z = 0xe, P_O = 0xf,
  P_Z1 = 0x11, P_Z10 = 0x12, P_Z11 = 0x13, P_0O00 = 0x14,
  P_0O01 = 0x15, P_0O0 = 0x16, P_1Z1 = 0x19, P_1Z10 = 0x1a,
  P_1Z11 = 0x1b, P_O00 = 0x1c, P_O01 = 0x1d, P_O0 = 0x1e,
  P_R = 0x20, P_Ro = 0x21, P_0R = 0x22, P_1R = 0x23,
  P_Rno = 0x24
}
enum  op_t {
  B_ADD, B_SUB, B_MUL, B_DIV,
  B_NEG, B_ABS, B_SQRT
}

Functions

static void pattern_fill (pattern_t ptn, unsigned char *start, int bitoffset, int count)
static tocheck_t pattern (int negative, pattern_t exp, pattern_t mant)
static tocheck_t delta (tocheck_t x, int direction)
static void check_result (int line, const char *rm, tocheck_t expected, tocheck_t actual)
static void check_excepts (int line, const char *rm, int expected, int actual)
static void check_op (void)
static void fail_xr (int line, const char *rm, tocheck_t x, tocheck_t r, tocheck_t xx, int xflag)
static void check_sqrt (tocheck_t a)
int main (int argc, char **argv)

Variables

static fenv_t rmodes [4]
static const char *const rmnames [4]
static int nerrors = 0
static const int all_exceptions = FE_ALL_EXCEPT
struct {
int except
const char * name
excepts []
static int excepts_missing = 0
static const optest_t optests []

Class Documentation

union union_t

Definition at line 45 of file test-arith.c.

Class Members
unsigned char c
tocheck_t tc
struct optest_t

Definition at line 348 of file test-arith.c.

Class Members
pattern_t a_exp
pattern_t a_mant
int a_sgn
pattern_t b_exp
pattern_t b_mant
int b_sgn
int excepts
int line
op_t op
int rmode
pattern_t x_exp
pattern_t x_mant
int x_sgn

Define Documentation

#define _GNU_SOURCE

Definition at line 20 of file test-arith.c.

#define bitset (   count,
  value 
)
Value:
start[(count)/8] = (start[(count)/8] & ~(1 << 7-(count)%8)  \
                          |  (value) << 7-(count)%8)
#define ESIZE   11

Definition at line 31 of file test-arith.c.

#define except_entry (   ex)    { ex, #ex } ,
#define FE_DIVBYZERO   0
#define FE_INEXACT   0
#define FE_INVALID   0
#define FE_INVALID_IDI   FE_INVALID
#define FE_INVALID_ISI   FE_INVALID
#define FE_INVALID_ZDZ   FE_INVALID
#define FE_OVERFLOW   0
#define FE_UNDERFLOW   0
#define FUNC (   x)    x

Definition at line 33 of file test-arith.c.

#define MSIZE   52

Definition at line 32 of file test-arith.c.

#define R_ALL   (R_NEAREST|R_ZERO|R_UP|R_DOWN)

Definition at line 40 of file test-arith.c.

#define R_DOWN   8

Definition at line 39 of file test-arith.c.

#define R_NEAREST   1

Definition at line 36 of file test-arith.c.

#define R_UP   4

Definition at line 38 of file test-arith.c.

#define R_ZERO   2

Definition at line 37 of file test-arith.c.


Typedef Documentation

typedef double tocheck_t

Definition at line 30 of file test-arith.c.


Enumeration Type Documentation

enum op_t
Enumerator:
B_ADD 
B_SUB 
B_MUL 
B_DIV 
B_NEG 
B_ABS 
B_SQRT 

Definition at line 345 of file test-arith.c.

enum pattern_t
Enumerator:
P_Z 
P_000O 
P_001Z 
P_00O 
P_01Z 
P_010O 
P_011Z 
P_0O 
P_1Z 
P_100O 
P_101Z 
P_10O 
P_11Z 
P_110O 
P_111Z 
P_O 
P_Z1 
P_Z10 
P_Z11 
P_0O00 
P_0O01 
P_0O0 
P_1Z1 
P_1Z10 
P_1Z11 
P_O00 
P_O01 
P_O0 
P_R 
P_Ro 
P_0R 
P_1R 
P_Rno 

Definition at line 52 of file test-arith.c.

             {
  P_Z    = 0x0,  /* 00000...0 */
  P_000O = 0x1,  /* 00011...1 */
  P_001Z = 0x2,  /* 00100...0 */
  P_00O  = 0x3,  /* 00111...1 */
  P_01Z  = 0x4,  /* 01000...0 */
  P_010O = 0x5,  /* 01011...1 */
  P_011Z = 0x6,  /* 01100...0 */
  P_0O   = 0x7,  /* 01111...1 */
  P_1Z   = 0x8,  /* 10000...0 */
  P_100O = 0x9,  /* 10011...1 */
  P_101Z = 0xa,  /* 10100...0 */
  P_10O  = 0xb,  /* 10111...1 */
  P_11Z  = 0xc,  /* 11000...0 */
  P_110O = 0xd,  /* 11011...1 */
  P_111Z = 0xe,  /* 11100...0 */
  P_O    = 0xf,  /* 11111...1 */
  P_Z1   = 0x11, /* 000...001 */
  P_Z10  = 0x12, /* 000...010 */
  P_Z11  = 0x13, /* 000...011 */
  P_0O00 = 0x14, /* 011...100 */
  P_0O01 = 0x15, /* 011...101 */
  P_0O0  = 0x16, /* 011...110 */
  P_1Z1  = 0x19, /* 100...001 */
  P_1Z10 = 0x1a, /* 100...010 */
  P_1Z11 = 0x1b, /* 100...011 */
  P_O00  = 0x1c, /* 111...100 */
  P_O01  = 0x1d, /* 111...101 */
  P_O0   = 0x1e, /* 111...110 */
  P_R    = 0x20, /* rrr...rrr */ /* ('r' means random. ) */
  P_Ro   = 0x21, /* rrr...rrr, with odd parity.  */
  P_0R   = 0x22, /* 0rr...rrr */
  P_1R   = 0x23, /* 1rr...rrr */
  P_Rno  = 0x24, /* rrr...rrr, but not all ones.  */
} pattern_t;

Function Documentation

static void check_excepts ( int  line,
const char *  rm,
int  expected,
int  actual 
) [static]

Definition at line 320 of file test-arith.c.

{
  if (expected & excepts_missing)
    expected = expected & ~excepts_missing | FE_INVALID_SNAN;
  if ((expected & all_exceptions) != actual)
    {
      size_t i;
      printf("%s:%d:round %s:exceptions failed\n"
            " expected exceptions ", __FILE__, line,rm);
      for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++)
       if (expected & excepts[i].except)
         printf("%s ",excepts[i].name);
      if ((expected & all_exceptions) == 0)
       printf("- ");
      printf("got");
      for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++)
       if (actual & excepts[i].except)
         printf(" %s",excepts[i].name);
      if ((actual & all_exceptions) == 0)
       printf("- ");
      printf(".\n");
      nerrors++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_op ( void  ) [static]

Definition at line 460 of file test-arith.c.

{
  size_t i;
  int j;
  tocheck_t r, a, b, x;
  int raised;

  for (i = 0; i < sizeof(optests)/sizeof(optests[0]); i++)
    {
      a = pattern(optests[i].a_sgn, optests[i].a_exp,
                optests[i].a_mant);
      b = pattern(optests[i].b_sgn, optests[i].b_exp,
                optests[i].b_mant);
      x = pattern(optests[i].x_sgn, optests[i].x_exp,
                optests[i].x_mant);
      for (j = 0; j < 4; j++)
       if (optests[i].rmode & 1<<j)
         {
           fesetenv(rmodes+j);
           switch (optests[i].op)
             {
             case B_ADD: r = a + b; break;
             case B_SUB: r = a - b; break;
             case B_MUL: r = a * b; break;
             case B_DIV: r = a / b; break;
             case B_NEG: r = -a; break;
             case B_ABS: r = FUNC(fabs)(a); break;
             case B_SQRT: r = FUNC(sqrt)(a); break;
             }
           raised = fetestexcept(all_exceptions);
           check_result(optests[i].line,rmnames[j],x,r);
           check_excepts(optests[i].line,rmnames[j],
                       optests[i].excepts,raised);
         }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_result ( int  line,
const char *  rm,
tocheck_t  expected,
tocheck_t  actual 
) [static]

Definition at line 224 of file test-arith.c.

{
  if (memcmp(&expected, &actual, sizeof(tocheck_t)) != 0)
    {
      unsigned char *ex, *ac;
      size_t i;

      printf("%s:%d:round %s:result failed\n"
            " expected result 0x", __FILE__, line, rm);
      ex = (unsigned char *)&expected;
      ac = (unsigned char *)&actual;
      for (i = 0; i < sizeof(tocheck_t); i++)
       printf("%02x", ex[i]);
      printf(" got 0x");
      for (i = 0; i < sizeof(tocheck_t); i++)
       printf("%02x", ac[i]);
      printf("\n");
      nerrors++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_sqrt ( tocheck_t  a) [static]

Definition at line 521 of file test-arith.c.

{
  int j;
  tocheck_t r0, r1, r2, x0, x1, x2;
  int raised = 0;
  int ok;

  for (j = 0; j < 4; j++)
    {
      int excepts;

      fesetenv(rmodes+j);
      r1 = FUNC(sqrt)(a);
      excepts = fetestexcept(all_exceptions);
      fesetenv(FE_DFL_ENV);
      raised |= excepts & ~FE_INEXACT;
      x1 = r1 * r1 - a;
      if (excepts & FE_INEXACT)
       {
         r0 = delta(r1,-1); r2 = delta(r1,1);
         switch (1 << j)
           {
           case R_NEAREST:
             x0 = r0 * r0 - a; x2 = r2 * r2 - a;
             ok = fabs(x0) >= fabs(x1) && fabs(x1) <= fabs(x2);
             break;
           case R_ZERO:  case R_DOWN:
             x2 = r2 * r2 - a;
             ok = x1 <= 0 && x2 >= 0;
             break;
           case R_UP:
             x0 = r0 * r0 - a;
             ok = x1 >= 0 && x0 <= 0;
             break;
           default:
             assert(0);
           }
       }
      else
       ok = x1 == 0;
      if (!ok)
       fail_xr(__LINE__,rmnames[j],a,r1,x1,excepts&FE_INEXACT);
    }
  check_excepts(__LINE__,"all",0,raised);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static tocheck_t delta ( tocheck_t  x,
int  direction 
) [static]

Definition at line 185 of file test-arith.c.

{
  union_t xx;
  int i;

  xx.tc = x;
  if (xx.c[0] & 0x80)
    direction = -direction;
  if (direction == +1)
    {
      union_t tx;
      tx.tc = pattern(xx.c[0] >> 7, P_O, P_Z);
      if (memcmp(tx.c, xx.c, sizeof(tocheck_t)) == 0)
       return x;
    }
  for (i = sizeof(tocheck_t)-1; i > 0; i--)
    {
      xx.c[i] += direction;
      if (xx.c[i] != (direction > 0 ? 0 : 0xff))
       return xx.tc;
    }
  if (direction < 0 && (xx.c[0] & 0x7f) == 0)
    return pattern(~(xx.c[0] >> 7) & 1, P_Z, P_Z1);
  else
    {
      xx.c[0] += direction;
      return xx.tc;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fail_xr ( int  line,
const char *  rm,
tocheck_t  x,
tocheck_t  r,
tocheck_t  xx,
int  xflag 
) [static]

Definition at line 498 of file test-arith.c.

{
  size_t i;
  unsigned char *cx, *cr, *cxx;

  printf("%s:%d:round %s:fail\n with x=0x", __FILE__, line,rm);
  cx = (unsigned char *)&x;
  cr = (unsigned char *)&r;
  cxx = (unsigned char *)&xx;
  for (i = 0; i < sizeof(tocheck_t); i++)
    printf("%02x", cx[i]);
  printf(" r=0x");
  for (i = 0; i < sizeof(tocheck_t); i++)
    printf("%02x", cr[i]);
  printf(" xx=0x");
  for (i = 0; i < sizeof(tocheck_t); i++)
    printf("%02x", cxx[i]);
  printf(" inexact=%d\n", xflag != 0);
  nerrors++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 567 of file test-arith.c.

{
  int i;

  _LIB_VERSION = _IEEE_;

  /* Set up environments for rounding modes.  */
  fesetenv(FE_DFL_ENV);
  fesetround(FE_TONEAREST);
  fegetenv(rmodes+0);
  fesetround(FE_TOWARDZERO);
  fegetenv(rmodes+1);
  fesetround(FE_UPWARD);
  fegetenv(rmodes+2);
  fesetround(FE_DOWNWARD);
  fegetenv(rmodes+3);

#if defined(FE_INVALID_SOFTWARE) || defined(FE_INVALID_SQRT)
  /* There's this really stupid feature of the 601... */
  fesetenv(FE_DFL_ENV);
  feraiseexcept(FE_INVALID_SOFTWARE);
  if (!fetestexcept(FE_INVALID_SOFTWARE))
    excepts_missing |= FE_INVALID_SOFTWARE;
  fesetenv(FE_DFL_ENV);
  feraiseexcept(FE_INVALID_SQRT);
  if (!fetestexcept(FE_INVALID_SQRT))
    excepts_missing |= FE_INVALID_SQRT;
#endif

  check_op();
  for (i = 0; i < 100000; i++)
    check_sqrt(pattern(0, P_Rno, P_R));
  for (i = 0; i < 100; i++)
    check_sqrt(pattern(0, P_Z, P_R));
  check_sqrt(pattern(0,P_Z,P_Z1));

  printf("%d errors.\n", nerrors);
  return nerrors == 0 ? 0 : 1;
}

Here is the call graph for this function:

static tocheck_t pattern ( int  negative,
pattern_t  exp,
pattern_t  mant 
) [static]

Definition at line 162 of file test-arith.c.

{
  union_t result;
#if 0
  int i;
#endif

  pattern_fill(negative ? P_O : P_Z, result.c, 0, 1);
  pattern_fill(exp, result.c, 1, ESIZE);
  pattern_fill(mant, result.c, ESIZE+1, MSIZE);
#if 0
  printf("neg=%d exp=%02x mant=%02x: ", negative, exp, mant);
  for (i = 0; i < sizeof(tocheck_t); i++)
    printf("%02x", result.c[i]);
  printf("\n");
#endif
  return result.tc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void pattern_fill ( pattern_t  ptn,
unsigned char *  start,
int  bitoffset,
int  count 
) [static]

Definition at line 89 of file test-arith.c.

{
#define bitset(count, value) \
      start[(count)/8] = (start[(count)/8] & ~(1 << 7-(count)%8)  \
                          |  (value) << 7-(count)%8)
  int i;

  if (ptn >= 0 && ptn <= 0xf)
    {
      /* Patterns between 0 and 0xF have the following format:
        The LSBit is used to fill the last n-3 bits of the pattern;
        The next 3 bits are the first 3 bits of the pattern. */
      for (i = 0; i < count; i++)
       if (i < 3)
         bitset((bitoffset+i), ptn >> (3-i) & 1);
       else
         bitset((bitoffset+i), ptn >> 0 & 1);
    }
  else if (ptn <= 0x1f)
    {
      /* Patterns between 0x10 and 0x1F have the following format:
        The two LSBits are the last two bits of the pattern;
        The 0x8 bit is the first bit of the pattern;
        The 0x4 bit is used to fill the remainder. */
      for (i = 0; i < count; i++)
       if (i == 0)
         bitset((bitoffset+i), ptn >> 3 & 1);
       else if (i >= count-2)
         bitset((bitoffset+i), ptn >> (count-1-i) & 1);
       else
         bitset((bitoffset+i), ptn >> 2 & 1);
    }
  else switch (ptn)
    {
    case P_0R: case P_1R:
      assert(count > 0);
      bitset(bitoffset, ptn & 1);
      count--;
      bitoffset++;
    case P_R:
      for (; count > 0; count--, bitoffset++)
       bitset(bitoffset, rand() & 1);
      break;
    case P_Ro:
      {
       int op = 1;
       assert(count > 0);
       for (; count > 1; count--, bitoffset++)
         bitset(bitoffset, op ^= (rand() & 1));
       bitset(bitoffset, op);
       break;
      }
    case P_Rno:
      {
       int op = 1;
       assert(count > 0);
       for (; count > 1; count--, bitoffset++)
       {
         int r = rand() & 1;
         op &= r;
         bitset(bitoffset, r);
       }
       bitset(bitoffset, rand() & (op ^ 1));
       break;
      }

    default:
      assert(0);
    }
#undef bitset
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 220 of file test-arith.c.

struct { ... } excepts[] [static]
int excepts_missing = 0 [static]

Definition at line 317 of file test-arith.c.

int nerrors = 0 [static]

Definition at line 215 of file test-arith.c.

const optest_t optests[] [static]

Definition at line 360 of file test-arith.c.

const char* const rmnames[4] [static]
Initial value:
{ "nearest","zero","+Inf","-Inf" }

Definition at line 42 of file test-arith.c.

fenv_t rmodes[4] [static]

Definition at line 41 of file test-arith.c.