/* ========================== C MeatAxe =============================
   zzztest.c - Test the arithmetic module.

   (C) Copyright 1993 Michael Ringe, Lehrstuhl D fuer Mathematik,
   RWTH Aachen, Germany  <mringe@tiffy.math.rwth-aachen.de>
   This program is free software; see the file COPYING for details.
   ================================================================== */


/* $Id: zzztest.c,v 2.1 1993/10/20 18:17:07 mringe Exp $
 *
 * $Log: zzztest.c,v $
 * Revision 2.1  1993/10/20  18:17:07  mringe
 * MeatAxe-2.0, Phase II.
 *
 * Revision 2.0  1993/10/14  18:54:18  mringe
 * MeatAxe-2.0, Phase I
 *
 * Revision 1.12  1993/08/06  14:01:59  mringe
 * Neuer File-header.
 *
 * Revision 1.11  1993/02/16  18:32:46  mringe
 * string.h und stdio.h werden jetzt in meataxe.h included.
 *
 * Revision 1.10  1992/07/28  13:28:15  mringe
 * *** empty log message ***
 *
 * Revision 1.9  1992/07/28  12:58:41  mringe
 * *** empty log message ***
 *
 * Revision 1.8  1992/07/28  12:51:40  mringe
 * Fixed more bugs.
 *
 * Revision 1.7  1992/07/28  12:50:08  mringe
 * Fixed some bugs with BIG version.
 *
 * Revision 1.6  1992/07/28  09:10:55  mringe
 * Bug in prtab() behoben.
 *
 * Revision 1.5  1992/07/23  06:45:17  mringe
 * zgetgen() durch zgen ersetzt.
 *
 * Revision 1.4  1992/07/15  09:31:47  mringe
 * *** empty log message ***
 *
 * Revision 1.3  1992/07/10  15:23:28  mringe
 * *** empty log message ***
 *
 * Revision 1.2  1992/07/08  08:49:19  mringe
 * Alle Funktionen auch f"ur 'big' version.
 *
 * Revision 1.2  1992/07/08  08:49:19  mringe
 * Alle Funktionen auch f"ur 'big' version.
 *
 * Revision 1.1  1992/05/26  18:28:43  mringe
 * Initial revision
 *
 */


#include <stdlib.h>
#include "meataxe.h"


#if defined (BIG)
#define ISFEL(f) ((f) == 0xffff ||\
	(unsigned short)(f) < (unsigned short)fld-1)
#else
#define ISFEL(f) ((unsigned int)(f) < (unsigned int)fld)
#endif

#define TNOC 20	  /* Number of colums for testing row operations */



/* ------------------------------------------------------------------
   Function prototypes
   ------------------------------------------------------------------ */

void err _PL((int line, char *msg));
void init _PL((int argc, char *argv[]));
void testitof _PL((void));
void testfield _PL((void));
void testgen _PL((void));
void testextractinsert _PL((void));
void testfindmark _PL((void));
void testaddrow _PL((void));
void testrowops _PL((void));
void prtables _PL((void));


/* ------------------------------------------------------------------
   Global variables
   ------------------------------------------------------------------ */

long fld;
FEL *ftab;

char amsg[] = "zzztest aborted";

#define ERR(msg) err(__LINE__,msg)

void err(line,msg)
int line;
char *msg;
{	printf("Line %d: %s\n",line,msg);
	fflush(stdout);
	exit(1);
}


void init(argc, argv)
int argc;
char *argv[];

{	if (argc > 3)
		ERR("Usage: zzztest <fieldorder> [t]");
	fld = atol(argv[1]);
	printf("Testing with GF(%ld)\n",fld);
	printf("ZZZ version: %d\n",mtxinit());
	zsetlen(fld,(long)TNOC);
	ftab = (FEL *) malloc(sizeof(FEL)*(size_t)fld);
	if (argc == 3)
	{	testitof();
		prtables();
		exit(0);
	}
}


void testitof()

{	long l, m;

	printf("Testing int <--> FEL conversion\n");
	if (zitof((long)0) != F_ZERO) ERR("Error 1");
	if (zitof((long)1) != F_ONE) ERR("Error 2");
	if (zftoi(F_ZERO) != 0) ERR("Error 3");
	if (zftoi(F_ONE) != 1) ERR("Error 4");
	for (l = 0; l < fld; ++l)
	{	ftab[l] = zitof(l);
		if (!ISFEL(ftab[l])) ERR("Error 5");
		for (m = 0; m < l; ++m)
			if (ftab[m] == ftab[l]) ERR("Error 6");
		if (zftoi(ftab[l]) != l) ERR("Error 7");
	}
}



void testfield()

{   FEL a,b,c;
    int ai, bi, ci;
	
    printf("Testing field arithmetic\n");

    /* Test one and zero elements
       -------------------------- */
    for (ai = 0; ai < (int)fld; ++ai)
    {	a = ftab[ai];
	if (zadd(a,F_ZERO) != a)
	{   printf("%d+0=%d\n",(int)a,(int)zadd(a,F_ZERO));
	    ERR(amsg);
	}
	if (zmul(a,F_ONE) != a)
	{	printf("%d*1=%d\n",(int)a,(int)zmul(a,F_ONE));
		ERR(amsg);
	}
    }

    /* Test negative and inverse
       ------------------------- */
    for (ai = 0; ai < (int)fld; ++ai)
    {	a = ftab[ai];
	b = zsub(F_ZERO,a);
	if (!ISFEL(b) || zadd(a,b) != F_ZERO) 
	    ERR("Illegal negative");
	if (a != F_ZERO)
	{   b = zdiv(F_ONE,a);
	    if (!ISFEL(b) || zmul(a,b) != F_ONE) 
		ERR("Illegal inverse");
	}
    }

    /* Test arithmetic
       --------------- */
    for (ai = 0; ai < (int)fld; ++ai)
    {	a = ftab[ai];
	for (bi = ai; bi < (int)fld; ++bi)
	{   b = ftab[bi];
	    c = zadd(a,b);
	    if (!ISFEL(c)) ERR("zadd() error");
	    if (c != zadd(b,a)) ERR("'+' not commutative");
	    c = zmul(a,b);
	    if (!ISFEL(c)) ERR("zmul() error");
	    if (c != zmul(b,a)) ERR("'*' not commutative");
	    
	    for (ci = 0; ci < (int)fld; ++ci)
	    {	c = ftab[ci];
		if (zadd(a,zadd(b,c)) != zadd(zadd(a,b),c))
		    ERR("'+' not associative");
		if (zmul(a,zmul(b,c)) != zmul(zmul(a,b),c))
		    ERR("'*' not associative");
		if (zmul(a,zadd(b,c)) != zadd(zmul(a,b),zmul(a,c)))
		    ERR("a*(b+c) != a*b+a*c");
	    }
	}
    }
}


void testgen()
{	FEL a, b;
	int i;

	printf("Testing zgen\n");
	a = zgen;
	b = a;
	for (i = 1; i < (int)fld-1; ++i)
	{	
	
		if (b == F_ONE)
		{	ERR("Generator test failed");
			break;
		}
		b = zmul(a,b);
	}
	if (b != F_ONE)
		ERR("Generator test failed");
}


void testextractinsert()

{   PTR x;
    long i;
    int ai,d;
    FEL a;

    zsetlen(fld,(long)TNOC);
    printf("Testing zinsert()/zextract()\n");
    x = zalloc((long)1);

    for (ai = 0; ai < (int) fld; ++ai)
    {	a = ftab[ai];
    	for (i = 1; i <= 8; ++i)
	{   zinsert(x,i,a);
	    if (zextract(x,i) != a) ERR("Error 1");
	}
    }

    for (d = 1; d < 20; ++d)
    {	ai = 0;
	for (i = 1; i <= TNOC; ++i)
	{   zinsert(x,i,ftab[ai]);
	    ai = (ai + d) % (int) fld;
	}
    	ai = 0;
	for (i = 1; i <= TNOC; ++i)
	{   if (zextract(x,i) != ftab[ai]) ERR("Error 2");
	    ai = (ai + d) % (int) fld;
	}
    }

    free(x);
}


void testfindmark()

{	PTR x;
	FEL a;
	long i;

	zsetlen(fld,(long)TNOC);
	printf("Testing zfindpiv()\n");
	x = zalloc((long)1);

	for (i = 1; i <= TNOC; ++i)
		zinsert(x,i,ftab[i%(fld-1)+1]);
	for (i = 1; i <= TNOC; ++i)
	{	if (zfindpiv(x,&a) != i) ERR("Error 1");
		if (a != ftab[i%(fld-1)+1]) ERR("Error 2");
		zinsert(x,i,F_ZERO);
	}
	free(x);
}


void testaddrow()

{	PTR x, y;
	int a, b;
	FEL c;
	long i;

	zsetlen(fld,(long)TNOC);
	printf("Testing zaddrow()\n");
	x = zalloc((long)1);
	y = zalloc((long)1);
	for (a = 0; a < (int)fld; ++a)
	    for (b = 0; b < (int)fld; ++b)
	    {	for (i = 1; i <= TNOC; ++i)
		{	zinsert(x,i,ftab[a]);
			zinsert(y,i,ftab[b]);
		}
		zaddrow(x,y);
		c = zadd(ftab[a],ftab[b]);
                for (i = 1; i <= TNOC; ++i)
		{	if (zextract(x,i) != c)
				ERR("Test failed");
		}
	    }
	free(x);
	free(y);
}



void testrowops()

{	PTR m1,m2,m3;
	long i, k;
	int d;

	zsetlen(fld,(long)TNOC);
	printf("Testing row operations\n");
	m1 = zalloc((long)1);
	m2 = zalloc((long)1);
	m3 = zalloc((long)1);

	/* Test zmoverow() and zcmprow()
	   ----------------------------- */
	for (i = 1; i <= TNOC; ++i)
		zinsert(m1,i,ftab[i%fld]);
	for (i = 1; i <= TNOC; ++i)
	{	zmoverow(m2,m1);
		if (zcmprow(m2,m1)) ERR("Error 1");
		if (memcmp(m2,m1,zsize((long)1))) ERR("Error 2");
		zinsert(m1,i,ftab[(i+1)%fld]);
		if (!zcmprow(m2,m1)) ERR("Error 3");
	}

	/* Test zaddrow() and zaddmulrow()
	   ------------------------------- */
	for (d = 0; d < 6; ++d)
	{	for (i = 1; i <= TNOC; ++i)
		{	zinsert(m1,i,ftab[i%fld]);
			zinsert(m2,i,ftab[(i+d)%fld]);
		}
		zmoverow(m3,m1);
		zaddrow(m3,m2);
		for (i = 1; i <= TNOC; ++i)
		{	if (zextract(m3,i) !=
			    zadd(ftab[i%fld],ftab[(i+d)%fld]))
				ERR("Error 4");
		}
		for (k = 0; k < fld; ++k)
		{	zmoverow(m3,m1);
			zaddmulrow(m3,m2,ftab[k]);
			for (i = 1; i <= TNOC; ++i)
			{	if (zextract(m3,i) != zadd(ftab[i%fld],
				    zmul(ftab[(i+d)%fld],ftab[k])))
					ERR("Error 5");
			}
		}
	}
}


void prtables()
{	int a, b;

	printf(" + ");
	for (a = 0; a < (FEL)fld; ++a)
		printf("%3d", a);
	printf("\n");
	for (a = 0; a < (int)fld; ++a)
	{       printf("%3d",a);
		for (b = 0; b < (int)fld; ++b)
		    printf("%3ld",zftoi(zadd(ftab[a],ftab[b])));
		printf("\n");
	}

	printf("\n * ");
	for (a = 0; a < (FEL)fld; ++a)
		printf("%3d", a);
	printf("\n");
	for (a = 0; a < (int)fld; ++a)
	{       printf("%3d",a);
		for (b = 0; b < (int)fld; ++b)
			printf("%3ld",zftoi(zmul(ftab[a],ftab[b])));
		printf("\n");
	}

}


int main(argc, argv)

int argc;
char *argv[];

{	init(argc,argv);

	testitof();
	testfield();
	testgen();
	testextractinsert();
	testfindmark();
	testaddrow();
	testrowops();
	return 0;
}


