/* mtest.c	RD, 19.7.92	Tests fuer imod */

#include "imod.h"
#include "iint.h"
#include <stdio.h>

#define LIMIT	300
#define NLOOPS 	1000

void main()
{
    Integer imod, ia, ib, ic, iout, limit, id;
    Minteger a, b, c;
    ModulusType mod;
    int i;

    cIasint(&limit, 1);
    IslasD(&limit, LIMIT);	/* 2^300 */
    cI(&id);

    for (i = 0; i < NLOOPS; i++)
    {
	cI(&imod);
	IasrandomI(&imod, &limit);
	if (Ieven(&imod))
	    continue;
	cI(&ia);
	cI(&ib);
	cI(&ic);
	cI(&iout);
	cMod(&mod, &imod);
	cM(&a, &mod);
	cM(&b, &mod);
	cM(&c, &mod);

	IasrandomI(&ia, &limit);
	MasI(&a, &ia);
	Mrandom(&b);
	IasM(&ib, &b);

/*	    fprintI(stdout, &imod);
	    printf("\n");
	    fprintI(stdout, &ia);
	    printf("\n");
	    fprintI(stdout, &ib);
	    printf("\n");
*/

/* Addition */
	MasMplM(&c, &a, &b);
	IasM(&iout, &c);
	IasIplI(&ic, &ia, &ib);
	IreasI(&ic, &imod);
	if (!IeqI(&ic, &iout))
	{
	    printf("Error: MasMplM\n");
	    printf("a + b (mod) :\n");
	    fprintI(stdout, &iout);
	    printf("\n");
	}
/* Subtraktion */
	MasMmiM(&c, &a, &b);
	IasM(&iout, &c);
	IasImiI(&ic, &ia, &ib);
	IreasI(&ic, &imod);
	if (!IeqI(&ic, &iout))
	{
	    printf("Error: MasMmiM\n");
	    printf("a - b (mod) :\n");
	    fprintI(stdout, &iout);
	    printf("\n");
	}
/* Multiplikation */
	MasMmuM(&c, &a, &b);
	IasM(&iout, &c);
	IasImuI(&ic, &ia, &ib);
	IreasI(&ic, &imod);
	if (!IeqI(&ic, &iout))
	{
	    printf("Error: MasMmuM\n");
	    printf("a * b (mod) :\n");
	    fprintI(stdout, &iout);
	    printf("\n");
	}
/* Inversion */
	if (!MasinvM(&c, &a))
	{
	    Igcd(&id, &ia, &imod);
	    if (Ieq1(&id))
	    {
		printf("Error: MasinvM, gcd is 1!\n");
	    }
	}
	else
	{
	    IasM(&iout, &c);
	    MasMmuM(&c, &c, &a);
	    IasM(&ic, &c);
	    if (!Ieq1(&ic))
	    {
		printf("Error: MasinvM\n");
		printf("1/a (mod) :\n");
		fprintI(stdout, &iout);
		printf("\n");
		fprintI(stdout, &ic);
		printf("\n");
	    }
	}

	dM(&a);
	dM(&b);
	dM(&c);
	dMod(&mod);
	dI(&iout);
	dI(&ic);
	dI(&ib);
	dI(&ia);
	dI(&imod);
    }
    dI(&limit);
    dI(&id);
}
