
function kleineLoesung(r,imax,gr0)
{
	if(gr0==null)gr0=gr0!=null;//;-)
	var i,j,k,m=0,a=new Array(r[0].length-1),n=a.length,s,ss,ii="0",rr=new Array(r.length);
	if(gr0){for(j=0;j<r.length;j++){s=r[j][n];if(s<0)break;m+=s;}}
	else{for(j=0;j<r.length;j++){s=r[j][n];m+=s*s;}}
	for(i=1;i<n;i++)ii+=" 0";
	for(i=0;i<imax;i++)
	{
		for(j=0;j<n;j++)
		{
			a[j]=Math.round(Math.random()*Math.random()*Math.random()*100);if(Math.random()>.5)a[j]=-a[j];
		}
		ss=0;
		if(gr0){for(j=0;j<r.length;j++){s=r[j][n];for(k=0;k<n;k++)s+=r[j][k]*a[k];if(s<0){break;}ss+=(s);}}
		else{for(j=0;j<r.length;j++){s=r[j][n];for(k=0;k<n;k++)s+=r[j][k]*a[k];ss+=s*s;}}
		if((s<0)&&(gr0))continue;
		if(Math.abs(ss)<Math.abs(m)){ii=a.join(" ");m=ss;}
		//alert(a+"  "+ss);
	}
	//alert(gr0?m:Math.sqrt(m));
	a=ii.split(" ");//alert(a);
	for(i=0;i<r.length;i++){rr[i]=r[i][n];for(j=0;j<n;j++)rr[i]+=a[j]*r[i][j];}
	return rr;
}
function solvediophb(x,C)
{
	var i,k,g,y=new Array(x.length);
	k=x[0][1]*C[1]/dggt(x[0][1],C[1]);
	for(i=2;i<x.length;i++)k=k*x[i][1]/dggt(k,x[i][1]);
	for(i=0;i<x.length;i++)y[i]=x[i][0]*k/x[i][1];
	return solvedioph(y,C[0]*k/C[1]);
}
function solvedioph(x,C)
{
	//alert("Diophant-Start:  " +x+", "+C);
	var i,n=0,nn,y=new Array(),j,m,z,zz,ii=0,yy,k=new Array(),c=new Array(),g=dggt(x[0],x[1]);
	y[0]=new Array(n);c[0]=C;
	for(i=0;i<x.length;i++){y[0][i]=x[i];g=(i>1)?dggt(g,x[i]):g;}
	if((C%g)!=0)return null;
	//alert(y+"  "+c);
	do
	{
		//kleinsten Parameter finden
		m=1e+300;z=zz=0;ii++;
		for(i=0;i<y[n].length;i++){if((m>Math.abs(y[n][i]))&&(y[n][i]!=0))m=Math.abs(y[n][j=i]);}
		//Modulodivision
		yy=y[n][j];
		y[n+1]=new Array(y[n].length);
		for(i=0;i<y[n].length;i++)y[n+1][i]=(Math.abs(y[n][i])%m)*((y[n][i]>0)?1:-1);
		k[j]=n;
		n++;
		y[n][y[n].length]=yy;
		c[n]=(Math.abs(c[n-1])%m)*((c[n-1]>0)?1:-1);
		//alert(y.join("\n")+"\n\n"+c+"\n"+j);
		for(i=0;i<x.length;i++)if(y[n][i]!=0)z++;
		for(i=x.length;i<y[n].length;i++)if(y[n][i]!=0)zz++;
	}while(((z>0)||(zz+z>1))&&(ii<=20));
	nn=y[n].length;
	//alert(y.join("\n"));
	for(i=0;i<n;i++)for(j=y[i].length;j<nn;j++)y[i][j]=0;
	for(i=n-1;i>=0;i--)
	{
		for(j=0;j<y[i].length;j++)
		{
			if((k[j]<=i)||(y[i][j]==0)||(j>=k.length)||(isNaN(k[j])))continue;
			//alert("j = "+j+"\nk[j] = "+k[j]+"\ny[k[j]][j] = "+y[k[j]][j]);
			for(ii=0;ii<y[k[j]].length;ii++)
			{
				if((ii!=j)&&(y[k[j]][ii]!=0))
				{
					y[i][ii]-=y[k[j]][ii]*y[i][j]/y[k[j]][j];
					//alert("ii="+ii);
				}
			}
			c[i]-=c[k[j]]*y[i][j]/y[k[j]][j];
			y[i][j]=0;
		}
		c[i]=krzn(y[i],c[i]);
		//alert(i+". Zeile:\n"+y[i]+"   C="+c[i]);
	}
	//alert(y.join("\n"));
	var r=new Array(x.length),cr=new Array(x.length);
	for(i=0;i<x.length;i++)
	{
		r[i]=new Array(nn);
		if(isNaN(k[i])){for(j=0;j<r[i].length;j++)r[i][j]=0;r[i][i]=((y[0][i]>0)?1:1);cr[i]=0;}
		else {for(j=0;j<nn;j++)r[i][j]=(i!=j)?-y[k[i]][j]/y[k[i]][i]:0;cr[i]=c[k[i]]/y[k[i]][i];}
		if(isNaN(cr[i]))cr[i]=0;
	}
	//alert("Urzustand\n"+r.join("\n"));
	for(i=r[0].length-1;i>=x.length;i--)
	{
		for(j=0;j<r.length;j++)if(r[j][i]!=0)break;
		if(j==r.length)loeschespalte(r,i);
	}
	//alert("leere Spalten weg\n"+r.join("\n"));
	for(i=0;i<x.length;i++)
	{
		if(r[i][i]!=0)
		{
			for(j=0;j<x.length;j++){r[j][r[j].length]=r[j][i];r[j][i]=0;}
		}
	}
	//alert("freie Variablen nach hinten\n"+r.join("\n"));
	for(i=0;i<x.length;i++)r[i][r[i].length]=cr[i];
	//alert("Konstante ergänzt\n"+r.join("\n"));
	for(i=0;i<x.length;i++)loeschespalte(r,0);
	//alert("erste Spalten weg\n"+r.join("\n"));
	return r;
	// Rückgabe: erste bis vorletzte Spalte: jeweilige freie Parameter
	//           letzte Spalte: Zahl
	// Zeilen:   Variablen
}
function loeschespalte(a,s)
{	var i,j,k,b=new Array(a[0].length-1);
	for(i=0;i<a.length;i++)
	{
		k=0;
		for(j=0;j<a[i].length;j++)if(j!=s)b[k++]=a[i][j];
		a[i]=new Array(b.length);
		for(j=0;j<b.length;j++)a[i][j]=b[j];
	}
}
function krzn(a,c)
{
	var i,g=dggt(a[0],c);
	for(i=1;i<a.length;i++)g=dggt(g,a[i]);
	for(i=0;i<a.length;i++)a[i]/=g;
	return c/g;
}
function dggt(a,b)
{
	if(isNaN(a)||isNaN(b))return 1;if(a==0)return b;if(b==0)return a;
	var r;a=Math.abs(a);b=Math.abs(b);
	do{r=a%b;a=b;b=r;}while(r!=0);
	return a;
}


