var LF=new Array();

function linfakt(p)
{
	var x,y=new Array(),ns=new Array(),nsi=0,L=new Array(),i,j,g=p.length-1,a,b,pp,ggt=Math.abs(p[0]),L0="";
	LF=new Array(1);
	LF[0]=1;
	for(i=1;i<p.length;i++)ggt=lfggt(ggt,p[i]);//alert(ggt);
	if(p[p.length-1]<0)ggt=-ggt;//alert(p+"\n"+p[p.length-1]+"\n"+ggt);
	if(ggt!=1){for(i=0;i<p.length;i++)p[i]/=ggt;L0=String(ggt);LF[0]=L0;}
	while(p[0]==0){for(j=0;j<p.length-1;j++)p[j]=p[j+1];p[j]=0;ns[nsi++]=0;L[L.length]="x";LF[LF.length]=new Array(0,1);}
	while(p[p.length-1]==0){var pp=new Array(p.length-1);for(i=0;i<pp.length;i++)pp[i]=p[i];p=new Array();for(i=0;i<pp.length;i++)p[i]=pp[i];}
	for(j=1;j<=p[p.length-1];j++)
	{
		if((p[p.length-1]%j)!=0)continue;
		if(L.length==g)break;
		for(x=-Math.abs(p[0]);x<=Math.abs(p[0]);x++)
		{
			if((Math.abs(p[0])%Math.abs(x))!=0)continue;
			if(L.length==g)break;
			if(((Math.abs(x)%j)==0)&&(j>1))continue;
			while(Math.abs(hornerpdiv(x/j,p,y))<1e-12)
			{
				p=new Array(p.length-1);
				for(i=0;i<p.length;i++)
					p[i]=y[i]/j;
				ns[ns.length]=x;nsi++;//alert(ns);
				L[L.length]="("+((j>1)?j:"")+"x"+((x<0)?"+"+(-x):"-"+x)+")";
				LF[LF.length]=new Array(-x,j);
			}
		}
	}
	//alert(pstr(p));
	if(L.length<g-2)
	{
		for(a=1;a<=Math.abs(p[p.length-1]);a++)
		{
			if((Math.abs(p[p.length-1])%a)!=0)continue;
			for(c=-Math.abs(p[0]);c<=Math.abs(p[0]);c++)
			{
				if((Math.abs(p[0])%Math.abs(c))!=0)continue;
				for(bb=0;bb<=30;bb++)
				{
					do{
					b=bb;
					pp=polydivnsk(p,p.length-1,a,b,c);
					if(pp==null){b=-bb;pp=polydivnsk(p,p.length-1,a,b,c);}
					if(pp!=null)
					{
						//alert(a+"  "+b+"  "+c);
						p=new Array(pp.length-1);
						for(i=0;i<pp.length;i++)p[i]=pp[i];
						var k=new Array(c,b,a);
						L[L.length]="("+pstr(k).replace(/ +/g,"")+")";
						ns[nsi++]="k";
						ns[nsi++]="k";
						LF[LF.length]=new Array(c,b,a);
					}
					}while(pp!=null);
					if(ns.length==g)break;
				}
				if(ns.length==g)break;
			}
			if(ns.length==g)break;
		}
	}
	else
	{
		LF[LF.length]=new Array(p.length);for(i=0;i<p.length;i++)LF[LF.length-1][i]=p[i];
	}
	if(ns.length<g)L[L.length]="("+pstr(p).replace(/ /g,"")+")";
	return L0+"·"+L.join("·");
}

function horner(x,p)
{
	var y=p[p.length-1],i;
	for(i=p.length-2;i>=0;i--){y*=x;y+=p[i];}
	return y;
}
function hornerpdiv(x,p,y)
{
	var i,yy=p[p.length-1];
	for(i=p.length-1;i<y.length;i++)y[i]=0;
	for(i=p.length-2;i>=0;i--){y[i]=yy;yy*=x;yy+=p[i];}
	return yy;
}
//x² - 2re*x + re² + im²
function polydivnsk(k,g,a,b,c)
{
	var q=new Array(g);
	kk=new Array(g+1);
	var i,gg=g;
	for(i=0;i<kk.length;i++)kk[i]=k[i];
	for(i=0;i<kk.length-1;i++)q[i]=0;
	while(g>1)
	{
	 //	alert("Polynomdivision, g="+g+"  Rest: "+pstr(kk));
		if(g>1)q[g-2]=kk[g]/a;
		kk[g-1]-=kk[g]*b/a;
		if(g>1)kk[g-2]-=kk[g]*c/a;
		kk[g]=0;
	//	alert("g: "+g+"\nq: "+q.join("  ")+"\nk: "+kk.join("  "));
		while((kk[g]==0)&&(g>0))g--;
	}
	//alert("fertig\ng="+g+"\nq: "+q.join("  ")+"\nk: "+kk.join("  "));
	if((Math.abs(kk[0])>1e-8)||(Math.abs(kk[1])>1e-8)||(g>0)){return null;}
	return q;
}
function lfggt(a,b)
{
	if(a==0)return Math.abs(b);if(b==0)return Math.abs(a);
	if((a==0)||(b==0)||(isNaN(a))||(isNaN(b)))return 1;
	if((Math.abs(a)>1e+15)||(Math.abs(b)>1e+15))return 1;
	a=Math.abs(a);b=Math.abs(b);
	var r;do{r=a%b;a=b;b=r;}while(r!=0);return a;
}
function lfkgv(a,b)
{
	return Math.abs(a*b/lfggt(a,b));
}
function parsepoly(t,k)
{
	var p=new Array();
	t=t.toLowerCase().replace(/,/g,".");
	t=t.replace(/ /g,"").replace(/\+/g," ").replace(/\-/g," -").replace(/\*x/g,"x").replace(/·x/g,"x");
	while(t.charAt(0)==" ")t=t.substring(1,t.length);
	var tt=t.split(" ");
	var i,j;
	for(i=0;i<tt.length;i++)
	{
		if(tt[i].indexOf("x")==-1){if(p[0]==null)p[0]=new Array(0,1);addkoeff(p,0,tt[i]);}
		else if(tt[i].indexOf("x^")>-1)
		{t=tt[i].split("x^");if(p[j=parseInt(t[1])]==null)p[j]=new Array(0,1);addkoeff(p,j,t[0]);}
		else if(tt[i].indexOf("x")>-1)
		{t=tt[i].split("x");if(p[1]==null)p[1]=new Array(0,1);addkoeff(p,1,t[0]);}
	}//alert(p);
	for(i=0;i<p.length;i++){if(p[i]==null){p[i]=new Array(0,1);}}
	var kgv=p[0][1];
	for(i=1;i<p.length;i++){kgv=lfkgv(kgv,p[i][1]);}
	for(i=0;i<p.length;i++)k[i]=p[i][0]*kgv/p[i][1];
	return kgv;
}
function addkoeff(p,i,x)
{
	var b;
	if(x=="")x=1;
	if(x=="-")x=-1;
	if(String(x).indexOf("/")>-1)b=x.split("/");
	else b=kettenbruchapprox(x);
	var n=p[i][1]*b[1],z=p[i][0]*b[1]+b[0]*p[i][1];
	var g=lfggt(z,n);if(n<0){n=-n;z=-z;}if(z==0)n=1;
	p[i][0]=z/g;p[i][1]=n/g;
}
