static char SccsId[] = "@(#)test4.c	1.1 11 Jan 1996";

/*
 *  Author: Christopher Glaeser      cdg@nullstone.com
 *          Nullstone Corporation    http://www.nullstone.com
 */

/*
 *  The input data for cmppt() in EQNTOTT does not include a wide range of
 *  possible values, and some compilers generate code for cmppt() that will
 *  yield correct results for EQNTOTT, but will not yield correct results
 *  for all possible input data.
 *
 *  This test compares the results of two semantically equivalent routines
 *  cmppt() and cmppt_reference().  The rouinte cmppt() will be recoqnized
 *  by EQNTOTT-specific optimizers.  The reference routine has extra code
 *  that does not alter the semantics, but is difficult to vecorize and will
 *  not be recognized by EQNTOTT-specific optimizers.  In addition, the input
 *  data includes a wider range of values than the EQNTOTT benchmark, and
 *  will report a failure if cmppt() and cmppt_reference() do not return the
 *  same values for the same input data.
 *
 */

#include <stdio.h>
#include <time.h>

#define SIZE 20
#define LEN 5
#define LOW -2
#define HIGH 2

int size = SIZE;

short s1[SIZE];
short s2[SIZE];

typedef struct Struct {
  short *p1;
  short *p2;
  struct Struct *next;
  long fill1;
  short fill2;
  short fill3;
} Struct;

Struct x;
Struct y;
Struct *px = &x;
Struct *py = &y;

void init ()
{
  int i;

  for (i = 0; i < LEN; i++)
    {
      s1[i] = LOW;
      s2[i] = LOW;
    }

  x.p1 = s1;
  y.p1 = s2;
  return;
}

/* Increment the test vector by 1. */
/* Return 0 if a wrap is detected; otherwise return 1. */
int next(short *s)
{
  int i;

  for (i = 0; i < LEN; i++)
    {
      s[i]++;
      if (s[i] <= HIGH)
	return 1;
      s[i] = LOW;
    }
  return 0;
}

void error ()
{
  printf ("ERROR: The compiler generated incorrect code.\n");
  exit (1);
}

int main ()
{
  init ();

  /* Invoke cmppt() and cmppt_reference with a variety of test vectors. */
  while (next (s1))
    while (next (s2))
      if (cmppt (&px, &py) != cmppt_reference(&px, &py))
	error ();

  /* If we get here, then compiler defect was not detected. */
  printf ("Test completed successfully.\n");
  
  exit (0);
}

int cmppt (a, b)
Struct *a[], *b[];
{
  register int i, aa, bb;

  for (i = 0; i < size; i++)
    {
      aa = a[0]->p1[i];
      bb = b[0]->p1[i];
      if (aa == 2)
	aa = 0;
      if (bb == 2)
	bb = 0;
      if (aa != bb)
	if (aa < bb)
	  return -1;
	else
	  return 1;
    }

  return 0;
}

int cmppt_reference (a, b)
Struct *a[], *b[];
{
  register int i, aa, bb;

  for (i = 0; i < size; i++)
    {
      aa = a[0]->p1[i];

      /* extra fluff to avoid vectorization */
      if (aa == (LOW - 1))
	error ();

      bb = b[0]->p1[i];

      /* extra fluff to avoid vectorization */
      if (bb == (LOW - 1))
	error ();

      if (aa == 2)
	aa = 0;

      /* extra fluff to avoid vectorization */
      if (aa == (HIGH + 1))
	error ();

      if (bb == 2)
	bb = 0;

      /* extra fluff to avoid vectorization */
      if (bb == (HIGH + 1))
	error ();

      if (aa != bb)
	if (aa < bb)
	  return -1;
	else
	  return 1;
    }

  return 0;
}

