// Copyright, 2001-2003, Astra Network Inc.  All Rights Reserved

// This source code has been published by Astra Network Inc. However, any
// use, reproduction, modification, distribution or transfer of this
// software, or any software which includes or is based upon any of this
// code, is only permitted if expressly authorized by a written license
// agreement from Astra. Contact your Astra representative directly for
// more information.

#include "plat.h"
#include <stdio.h>

#ifndef HAVEINT64

int
main ()
{
  fprintf (stderr,
	   "These tests can only be used on a system whose compiler\n");
  fprintf (stderr, "has a long long integer type.");
  return 0;
}

#else /* HAVEINT64 */

#include <stdlib.h>
#include <stdarg.h>
#include <quad.h>
#include <time.h>

#include <ctest.h>

int rounds = 1000;

extern int verbosity;		/* from libctest */

ct_test_t *start_tests ();
int add_test ();
int and_test ();
int ashl_test ();
int ashr_test ();
int cmp_test ();
int div_test ();
int ior_test ();
int lshl_test ();
int lshr_test ();
int ltoq_test ();
int qtol_test ();
int qtobool_test ();
int mod_test ();
int mul_test ();
int neg_test ();
int not_test ();
int divrem_test ();
int sub_test ();
int swap_test ();
int ucmp_test ();
int udiv_test ();
int umod_test ();
int xor_test ();
int qtostr_test ();
int strtoq_test ();

void
myerror (char *format, ...)
{
  va_list arglist;

  if (verbosity > 3)
    {
      va_start (arglist, format);
      vprintf (format, arglist);
      va_end (arglist);
    }
}

void
myprintf (char *format, ...)
{
  va_list arglist;

  if (verbosity > 2)
    {
      va_start (arglist, format);
      vprintf (format, arglist);
      va_end (arglist);
    }
}

int
main (int argc, char *argv[])
{
  srand48 (time (NULL));
  return ct_auto_run (argc, argv, start_tests);
}

ct_test_t *
start_tests ()
{
  ct_test_t *all;

  all = ct_create_testsuite ("All", NULL, NULL, NULL);

  ct_create_testcase ("Addition", all, NULL, NULL, add_test);
  ct_create_testcase ("Subtraction", all, NULL, NULL, sub_test);
  ct_create_testcase ("Multiplication", all, NULL, NULL, mul_test);
  ct_create_testcase ("Division", all, NULL, NULL, div_test);
  ct_create_testcase ("Division with remainder", all, NULL, NULL,
		      divrem_test);
  ct_create_testcase ("Modulo", all, NULL, NULL, mod_test);
  ct_create_testcase ("Unsigned division", all, NULL, NULL, udiv_test);
  ct_create_testcase ("Unsigned modulo", all, NULL, NULL, umod_test);
  ct_create_testcase ("Arithmetic Negate", all, NULL, NULL, neg_test);
  ct_create_testcase ("Logical AND", all, NULL, NULL, and_test);
  ct_create_testcase ("Logical OR", all, NULL, NULL, ior_test);
  ct_create_testcase ("Logical XOR", all, NULL, NULL, xor_test);
  ct_create_testcase ("Logical Not", all, NULL, NULL, not_test);
  ct_create_testcase ("Logical shift left", all, NULL, NULL, lshl_test);
  ct_create_testcase ("Logical shift right", all, NULL, NULL, lshr_test);
  ct_create_testcase ("Arithmetic shift left", all, NULL, NULL, ashl_test);
  ct_create_testcase ("Arithmetic shift right", all, NULL, NULL, ashr_test);
  ct_create_testcase ("Comparisons", all, NULL, NULL, cmp_test);
  ct_create_testcase ("Unsigned comparisons", all, NULL, NULL, ucmp_test);
  ct_create_testcase ("Convert: long to ___quad_t", all, NULL, NULL,
		      ltoq_test);
  ct_create_testcase ("Convert: ___quad_t to long", all, NULL, NULL,
		      qtol_test);
  ct_create_testcase ("Convert: ___quad_t to bool", all, NULL, NULL,
		      qtobool_test);
  ct_create_testcase ("Convert: ___quad_t to string", all, NULL, NULL,
		      qtostr_test);
  ct_create_testcase ("Convert: string to ___quad_t", all, NULL, NULL,
		      strtoq_test);
  // ct_create_testcase( "Endian swap", all, NULL, NULL, swap_test );

  return all;
}

int
qtostr_test ()
{
  return (CT_TEST_FAIL);
}

int
strtoq_test ()
{
  return (CT_TEST_FAIL);
}

int
add_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_add (a.q, b.q);
      ll = a.ll + b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX + %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
and_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_and (a.q, b.q);
      ll = a.ll && b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX & %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
ashl_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;
  unsigned short shift;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      /* Shifts > than 63 are undefined in ISO-C, so no sense testing,
         by the way libquad gives 0, gcc gives the unshifted value. */
      for (shift = 0; shift <= 63; shift++)
	{
	  r.q = quad_ashl (a.q, shift);
	  ll = a.ll << shift;
	  if (r.ll != ll)
	    {
	      myerror ("Wrong. %llX << %hX != %llX (gcc %llX)\n",
		       a.ll, shift, r.ll, ll);
	      errors++;
	    }
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
ashr_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;
  unsigned short shift;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      for (shift = 0; shift <= 63; shift++)
	{
	  r.q = quad_ashr (a.q, shift);
	  ll = a.ll >> shift;
	  if (r.ll != ll)
	    {
	      myerror ("Wrong. %llX >> %hX != %llX (gcc %llX)\n",
		       a.ll, shift, r.ll, ll);
	      errors++;
	    }
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
cmp_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b;
  int i, errors = 0;
  int cmpq;
  int equal = 0, gt = 0, lt = 0;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      cmpq = quad_cmp (a.q, b.q);
      if ((cmpq == 0) && (!(a.ll < b.ll)))
	{
	  myerror ("Wrong. ! %llX < %llX\n", a.ll, b.ll);
	  errors++;
	  lt = 1;
	}
      else if ((cmpq == 1) && (!(a.ll == b.ll)))
	{
	  myerror ("Wrong. ! %llX == %llX\n", a.ll, b.ll);
	  errors++;
	  equal = 1;
	}
      else if ((cmpq == 2) && (!(a.ll > b.ll)))
	{
	  myerror ("Wrong. ! %llX > %llX\n", a.ll, b.ll);
	  errors++;
	  gt = 1;
	}
    }

  /* Check if it can recognize equal quad's */
  for (i = 0; i < rounds; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b = a;

      cmpq = quad_cmp (a.q, b.q);

      if ((cmpq != 1) || (!(a.ll == b.ll)))
	{
	  myerror ("Wrong. ! %llX == %llX\n", a.ll, b.ll);
	  equal = 1;
	  errors++;
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      if (equal)
	return (CT_TEST_FAILNUM (1));
      else if (gt)
	return (CT_TEST_FAILNUM (2));
      else if (lt)
	return (CT_TEST_FAILNUM (3));
      else
	return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}


int
div_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_div (a.q, b.q);
      ll = a.ll / b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX / %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}


int
ior_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_ior (a.q, b.q);
      ll = a.ll || b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX | %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
lshl_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;
  unsigned short shift;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();


      for (shift = 0; shift <= 63; shift++)
	{
	  r.q = quad_lshl (a.q, shift);
	  ll = a.ll << shift;
	  if (r.ll != ll)
	    {
	      myerror ("Wrong. %llX << %hX != %llX (gcc %llX)\n",
		       a.ll, shift, r.ll, ll);
	      errors++;
	    }
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
lshr_test ()
{
  union
  {
    ___u_quad_t q;
    unsigned long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  unsigned long long ll;
  unsigned short shift;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      for (shift = 0; shift <= 63; shift++)
	{
	  r.q = quad_lshr (a.q, shift);
	  ll = a.ll >> shift;
	  if (r.ll != ll)
	    {
	      myerror ("Wrong. %llX >> %hX != %llX (gcc %llX)\n",
		       a.ll, shift, r.ll, ll);
	      errors++;
	    }
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
ltoq_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  r;
  int i, errors = 0;
  long long ll;
  long l;

  for (i = 0; i < rounds * 100; i++)
    {
      l = mrand48 ();

      r.q = quad_ltoq (l);
      ll = (long long) l;
      if (r.ll != ll)
	{
	  myerror ("Wrong. ltoq( %lX ) != %llX (gcc %llX)\n", l, r.ll, ll);
	  myerror ("       ltoq( %ld ) != %lld (gcc %lld)\n", l, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
qtol_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a;
  int i, errors = 0;
  long r, rq;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      rq = quad_qtol (a.q);
      r = (long) a.ll;
      if (rq != r)
	{
	  myerror ("Wrong. qtol( %llX ) != %lX (gcc %lX)\n", a.ll, rq, r);
	  errors++;
	}

    }

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = 0L;

      rq = quad_qtol (a.q);
      r = (long) a.ll;
      if (rq != r)
	{
	  myerror ("Wrong. qtol( %llX ) != %lX (gcc %lX)\n", a.ll, rq, r);
	  errors++;
	}

    }

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = 0L;
      a.v[1] = mrand48 ();

      rq = quad_qtol (a.q);
      r = (long) a.ll;
      if (rq != r)
	{
	  myerror ("Wrong. qtol( %llX ) != %lX (gcc %lX)\n", a.ll, rq, r);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
qtobool_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a;
  int i, errors = 0;
  int r;

  for (i = 0; i < rounds * 100; i++)
    {
      if ((i % 1000) == 0)
	{
	  a.v[0] = 0;
	  a.v[1] = 0;
	}
      else if ((i % 1001) == 0)
	{
	  a.v[0] = 0;
	  a.v[1] = 1;
	}
      else if ((i % 1002) == 0)
	{
	  a.v[0] = 1;
	  a.v[1] = 0;
	}
      else
	{
	  a.v[0] = mrand48 ();
	  a.v[1] = mrand48 ();
	}
      r = quad_qtobool (a.q);
      if ((a.ll) && !(r))
	{
	  myerror ("Wrong. qtobool(%llX) == false(%d) (gcc true)\n", a.ll, r);
	  errors++;
	}
      if (!(a.ll) && (r))
	{
	  myerror ("Wrong. qtobool(%llX) == true(%d) (gcc false)\n", a.ll, r);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}


int
mod_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_mod (a.q, b.q);
      ll = a.ll % b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX %% %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}


int
mul_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_mul (a.q, b.q);
      ll = a.ll * b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX * %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
neg_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      r.q = quad_neg (a.q);
      ll = 0 - a.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. 0 - %llX != %llX (gcc %llX)\n", a.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
not_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();

      r.q = quad_not (a.q);
      ll = !a.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. ~%llX != %llX (gcc %llX)\n", a.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
divrem_test ()
{
  union
  {
    ___u_quad_t q;
    unsigned long long ll;
    unsigned long v[2];
  }
  a, b, rem, r;
  int i, errors = 0;
  unsigned long long ll, llrem;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_divrem (a.q, b.q, &rem.q);
      ll = a.ll / b.ll;
      llrem = a.ll % b.ll;
      if ((r.ll != ll) || (rem.ll != llrem))
	{
	  myerror ("Wrong. %llX / %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  myerror ("       %llX %% %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, rem.ll, llrem);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
sub_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_sub (a.q, b.q);
      ll = a.ll - b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX - %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

#if 0
// FIXME - Need something to compare to.
int
swap_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_swap (a.q);
      ll = ? ? BITSWAP ? ? (a.ll);
      if (r.ll != ll)
	{
	  myerror ("Wrong. SWAP(%llX) != %llX (gcc %llX)\n", a.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

#endif

int
ucmp_test ()
{
  union
  {
    ___u_quad_t q;
    unsigned long long ll;
    unsigned long v[2];
  }
  a, b;
  int i, errors = 0;
  int cmpq;
  int equal = 0, gt = 0, lt = 0;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      cmpq = quad_ucmp (a.q, b.q);
      if ((cmpq == 0) && (!(a.ll < b.ll)))
	{
	  myerror ("Wrong. ! %llX < %llX\n", a.ll, b.ll);
	  errors++;
	  lt = 1;
	}
      else if ((cmpq == 1) && (!(a.ll == b.ll)))
	{
	  myerror ("Wrong. ! %llX == %llX\n", a.ll, b.ll);
	  errors++;
	  equal = 1;
	}
      else if ((cmpq == 2) && (!(a.ll > b.ll)))
	{
	  myerror ("Wrong. ! %llX > %llX\n", a.ll, b.ll);
	  errors++;
	  gt = 1;
	}
    }

  /* Check if it can recognize equal quad's */
  for (i = 0; i < rounds; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b = a;

      cmpq = quad_ucmp (a.q, b.q);

      if ((cmpq != 1) || (!(a.ll == b.ll)))
	{
	  myerror ("Wrong. ! %llX == %llX\n", a.ll, b.ll);
	  equal = 1;
	  errors++;
	}
    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      if (equal)
	return (CT_TEST_FAILNUM (1));
      else if (gt)
	return (CT_TEST_FAILNUM (2));
      else if (lt)
	return (CT_TEST_FAILNUM (3));
      else
	return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
udiv_test ()
{
  union
  {
    ___u_quad_t q;
    unsigned long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  unsigned long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_udiv (a.q, b.q);
      ll = a.ll / b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX / %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
umod_test ()
{
  union
  {
    ___u_quad_t q;
    unsigned long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  unsigned long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[L] = mrand48 ();
      b.v[H] = 0L;

      r.q = quad_umod (a.q, b.q);
      ll = a.ll % b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX %% %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}

int
xor_test ()
{
  union
  {
    ___quad_t q;
    long long ll;
    unsigned long v[2];
  }
  a, b, r;
  int i, errors = 0;
  long long ll;

  for (i = 0; i < rounds * 100; i++)
    {
      a.v[0] = mrand48 ();
      a.v[1] = mrand48 ();
      b.v[0] = mrand48 ();
      b.v[1] = mrand48 ();

      r.q = quad_xor (a.q, b.q);
      ll = a.ll ^ b.ll;
      if (r.ll != ll)
	{
	  myerror ("Wrong. %llX ^ %llX != %llX (gcc %llX)\n",
		   a.ll, b.ll, r.ll, ll);
	  errors++;
	}

    }

  if (errors)
    {
      myerror ("\n%d errors.\n", errors);
      return (CT_TEST_FAIL);
    }
  else
    {
      return (CT_TEST_PASS);
    }

}


#endif /* #ifdef HAVEINT64 */
