#include <v_lib.h>
#include "../utils/math_u.h"

void	DumpSLE(vhandle_t out,matrix_t *a,vector_t *b,char *vars)
{
	u32_t r,c;
	for(r=0;r<a->rows;r++)
	{
		filePrintf(out,"%s%g%c ",a->cell[r][0] < 0 ? "" : " ",a->cell[r][0],vars[0]);
		for(c=1;c<a->cols;c++)
		{
			filePrintf(out,"%c %g%c ",a->cell[r][c] < 0 ? '-' : '+',
				v_abs(a->cell[r][c]),vars[c]);
		}
		filePrintf(out,"= %g\n",b->elements[r]);
	}
}

void	DumpBigSLE(vhandle_t out,matrix_t *a,vector_t *b)
{
	u32_t r,c;
	for(r=0;r<a->rows;r++)
	{
		filePrintf(out,"%s%g*x1 ",a->cell[r][0] < 0 ? "" : " ",a->cell[r][0]);
		for(c=1;c<a->cols;c++)
		{
			filePrintf(out,"%c %g*x%d ",a->cell[r][c] < 0 ? '-' : '+',
				v_abs(a->cell[r][c]),c+1);
		}
		filePrintf(out,"= %g\n",b->elements[r]);
	}
}

int main(int argc,char *argv[])
{
	matrix_t **mset;
	vector_t **vset;
	matrix_t *A;
	vector_t *B;
	int i,j,k,order,n,lower,upper;
	vhandle_t out, an, an_out;
	puts(
		"Generator of SLE for manual solving ver. 2.0.\n"
		"Copyright (C) Vladimir A. Smirnov, 1997-2000.");
	if(argc<5)
	{
		puts("Usage: sgen <order> <lower limit> <upper limit> "
			"<number of systems> [output file name] [file name for answers]");
		return -1;
	}
	order=atoi(argv[1]);
	lower=atoi(argv[2]);
	upper=atoi(argv[3]);
	n=atoi(argv[4]);
	out=fileOpenWrite(argc<6 ? "CON" : argv[5]);
	an=argc < 7 ? 0 : fileOpenWrite(argv[6]);
	umCreateRandomMatrixSet(&mset,n,order,order,lower,upper,false,true);
	umCreateRandomVectorSet(&vset,n,order,lower,upper,true);
	B=vecAlloc(order);
	filePrintf(out,";\t%d systems of order %d\n;\tproduced by %s\n",
		n,order,argv[0]);
	an_out = an ? an : out;
	for(i=0;i<n;i++)
	{
		matVecMul(B,mset[i],vset[i]);
		filePrintf(out,"------ %d -------\n",i+1);
		if(an)
			filePrintf(an,"System #%d: X=",i+1);
		else
			filePrintf(out,"X=");
		umDumpVector(an_out,vset[i],"{",";","}; ",true);
		filePrintf(an_out,"determinants: %g; ",matDeterm(mset[i],true));
		for(j=0;j<order-1;j++)
		{
			A=matDuplicate(mset[i]);
			for(k=0;k<order;k++)
				A->cell[k][j]=B->elements[k];
			filePrintf(an_out,"%g, ",matDeterm(A,false));
		}
		A=matDuplicate(mset[i]);
		for(k=0;k<order;k++)
			A->cell[k][j]=B->elements[k];
		filePrintf(an_out,"%g.\n",matDeterm(A,false));
		if(order<=7)
			DumpSLE(out,mset[i],B,"xyztuvw");
		else
			DumpBigSLE(out,mset[i],B);
	}
	fileClose(out);
	umDestroyRandomMatrixSet(mset,n);
	umDestroyRandomVectorSet(vset,n);
	free(B);
	return 0;
}
