// Javascript: (c) Arndt Brünner, Juli 2005
// Ändern verboten!
// Version: 7.7.2005

var v=new Array();
var dn=0,lz=new Array(),ln=new Array(),ablz=new Array(1),abln=new Array(1),glsz=new Array(1),glsn=new Array(1);
var grex=1,jv=1==0,sym=0;
function berechnen()
{
	var t=document.f.t.value.replace(/\n+/g,"\n").replace(/,/g,".").replace(/ /g,"").replace(/\n+/g,"\n").replace(/\"/g,"''").toLowerCase();
	while(t.charAt(t.length-1)=="\n")t=t.substr(0,t.length-1);
	if(jv){if(!navigator.javaEnabled())document.f.jvc.checked=false;}
	jv=document.f.jvc.checked;
	if(jv)
	if((navigator.javaEnabled())&&jv&&(document.plotter.plot!=null)&&(document.plotter!=null))
	{
		document.plotter.parse(" ");
		document.plotter.plot();
	}
	//else
	//document.f.jvc.checked=false;
	if(t=="")return;
	//sym=(document.f.as.checked)?1:((document.f.ps.checked)?2:0);
	//var symf=(sym>0)?2:1;
	var symf=1,sym=0;
	var f=t.split("\n");
	var n=f.length,i,j,k,l,g,ii,v,vv,o=1==2,p=new Array(),zz,nn,x,xx,x0=0,x1=0,y0=0,y1=0,XX=new Array(n);
	lz=new Array(n);ln=new Array(n);
	document.f.fkt.value="";
	var Z=new Array(n*(n+1)),N=new Array(n*(n+1));abln=new Array(n*(n+1));glsz=new Array(n*(n+1));
	for(i=0;i<Z.length;i++){Z[i]=0;N[i]=1;}
	for(i=0;i<n;i++)
	{
		g=f[i];o=false;v=vv=1;zz=0;nn=1;
		if(g.indexOf("=")==-1){alert("Keine Gleichung:\n"+g);return;}
		for(j=0;j<g.length;j++)
		{
			if(g.charAt(j)=="f")
			{
				k=j+1;while((g.charAt(k)=="'")&&(k<g.length))k++;
				if(g.charAt(k)!="("){alert("Klammer erwartet!\n"+g);return;}
				l=k+1;k-=j+1;j=l+1;//alert(g.charAt(l));
				if(k>(n-1)/symf){alert("Mit "+n+" Gleichungen können die Koeffizienten einer Funktion "+(n-1)+". Grades bestimmt werden.\nDie "+k+". Ableitung ist für jede ganzrationale Funktion "+(n-1)+". Grades konstant 0.");return;}
				//if(k==n-1){alert(""+k+". Ableitung ist für Polynom "+(n-1)+". Grades konstant.");return;}
				o=true;
			}
			if(g.charAt(j)==")")
			{
				if(!o){alert("Klammerfehler\n"+g);return;}
				o=false;
				x=parse(g.substring(l,j));if(x==null)return;//alert(x);
				p=diffkoeff(k,n-1);
				for(ii=0;ii<n-k;ii++)
				{
					xx=add(v*vv*p[ii]*Math.pow(x[0],ii),Math.pow(x[1],ii),Z[ii+i*(n+1)+k],N[ii+i*(n+1)+k]);
					Z[ii+i*(n+1)+k]=xx[0];N[ii+i*(n+1)+k]=xx[1];//if(ii+i*(n+1)+k>29)alert(i+" "+ii+" "+k);
				}
				x0=Math.min(x0,x[0]/x[1]);x1=Math.max(x1,x[0]/x[1]);XX[i]=x[0]/x[1];
				j++;
			}
			if(g.charAt(j)=="-")vv=-1;
			if(g.charAt(j)=="+")vv=1;
			if(g.charAt(j)=="=")v=-1;
			if(("0123456789".indexOf(g.charAt(j))>-1)&&(!o))
			{
				l=ii=j;while(("0123456789./".indexOf(g.charAt(ii))>-1)&&(ii<g.length))ii++;
				x=parse(g.substring(l,ii));if(x==null)return;
				x=add(-v*vv*x[0],x[1],zz,nn);zz=x[0];nn=x[1];
				j=ii;
			}
		}
		Z[i*(n+1)+n]=zz;N[i*(n+1)+n]=nn;
	}
	if(sym>0)
	{
		for(i=0;i<n;i++)
		{
			for(j=(sym%2);j<n;j+=2)Z[i*(n+1)+j]=0;
		}
	}
	//alert(Z+"\n"+N);


	for(i=0;i<Z.length;i++){glsz[i]=Z[i];glsn[i]=N[i];}//alert(Z+"\n"+N+"\n"+Z.length+"   "+(n*(n+1))+"\n"+n);
	zeigegleichungssystem();

	GLSLB(Z,N,lz,ln,n);status="";

	if(!testM(Z,N,n)){alert("Dieses Gleichungssystem hat keine eindeutige Lösung");return;}

	//alert(lz+"\n"+ln);
	//alert(document.plotter);
	//if(jv)if((navigator.javaEnabled())&&(jv))
	ablz[0]=new Array(1);abln[0]=new Array(1);
	for(i=0;i<n;i++){ablz[0][i]=lz[i];abln[0][i]=ln[i];}
	for(i=1;i<n;i++)
	{
		ablz[i]=new Array();abln[i]=new Array();
		abl(ablz[i-1],abln[i-1],ablz[i],abln[i]);
	}
	zeige_loesung();var kd_=1==0;
	if((jv)&&(navigator.javaEnabled()))
	if((document.plotter!=null))
	{
		kd();kd_=true;
		var T=PStrB("x",lz,ln).replace(/³/,"^3").replace(/²/,"^2").replace(/·/g,"*").replace(/,/g,".");
		document.plotter.parse(T,'x');
		var Y,i;
		for(i=0;i<n;i++)
		{
			Y=document.plotter.calcY(XX[i]);
			y0=Math.min(y0,Y);y1=Math.max(y1,Y);
		}
		for(i=0;i<ns[1].length;i++)
		{
			Y=document.plotter.calcY(ns[1][i]);
			y0=Math.min(y0,Y);y1=Math.max(y1,Y);
			x0=Math.min(x0,ns[1][i]);x1=Math.max(x1,ns[1][i]);
		}
		for(i=0;i<ns[0].length;i++)
		{
			x0=Math.min(x0,ns[0][i]);x1=Math.max(x1,ns[0][i]);
		}
		var xm=(x0+x1)/2,ym=(y0+y1)/2,m=Math.max(Math.max(x1-x0,(y1-y0)*.95),3.8);
		document.plotter.setRange(xm-m*0.6,xm+m*0.6,ym-m*0.6,ym+m*0.6);
		document.plotter.plot();
	}


	if((document.f.kda.checked)&&!kd_)kd();
	calc();
}

function funktionplotten()
{
}

function zeige_loesung()
{
	var mdl=0,i,j,n=ln.length,t="";
	for(i=0;i<n;i++)mdl=Math.max(dezlen(ln[i]),mdl);
	j=document.f.d.selectedIndex;
	if(j==0)dn=0;
	if(j==1)dn=8;
	if(j==2){for(i=0;i<n;i++)mdl=Math.max(dezlen(ln[i]),mdl);dn=(mdl>8)?0:4;}
	if(j==3){dn=15;}
	for(i=0;i<n;i++)
	t+="f"+"'''''''''''''''''''''''''''''''''''".substr(0,i)+"(x) = "+PStrB("x",ablz[i],abln[i])+((i<n-1)?"\n":"");
	document.f.fkt.value=t;
	document.f.funktion.value=PStrB("x",ablz[0],abln[0]);
}

function diffkoeff(k,g)
{
	var a=new Array(g+1),i,j;
	for(i=0;i<a.length;i++)a[i]=1;
	for(i=1;i<=k;i++){for(j=0;j<g-i+1;j++)a[j]=a[j+1]*(j+1);a[j]=0;}
	return a;
}
function abl(z,n,zz,nn)
{
	var i,g;
	for(i=0;i<z.length-1;i++){zz[i]=z[i+1]*(i+1);nn[i]=n[i+1];g=ggt(nn[i],zz[i]);nn[i]/=g;zz[i]/=g;}
}
function ggt(a,b)
{
	var r;a=Math.abs(a);b=Math.abs(b);if((a==0)||(b==0))return 1;if(isNaN(a)||isNaN(b))return 1;
	do{r=a%b;a=b;b=r;}while(r>0);
	return a;
}
function add(z1,n1,z2,n2)
{
	var z=z1*n2+z2*n1,n=n1*n2;
	g=ggt(z,n);
	return new Array(z/g,n/g);
}
var keinemeldung=1==0;
function parse(x)
{//alert(x);
	x=x.replace(/,/,".").replace(/[\(\)]/g,"").replace(/ /g,"");
	if(x=="")return new Array(0,1);
	if(x.replace(/[\d\.\-\/]/g,"").length>0){if(!keinemeldung)alert("Ungültige Eingabe: "+x);return null;}
	if(x.indexOf("/")>-1)
	{
		b=x.split("/");
		b[0]=parseInt(b[0]);b[1]=parseInt(b[1]);
		if(b[1]==0){if(!keinemeldung)alert("Ungültige Eingabe: "+x);return null;}
		if(isNaN(b[0])||isNaN(b[1])){if(!keinemeldung)alert("Ungültige Eingabe: "+x);return null;}
		var g=ggt(b[0],b[1]);
		b[0]/=g;b[1]/=g;
	}
	else {b=kettenbruchapprox(x,1e15,1e-12);}
	if(b[0]==0)b[1]=1;
	return new Array(b[0],b[1]);
}
function dezlen(n)
{
	var i2=0,i5=0;
	while((n%2)==0){n/=2;i2++;}
	while((n%5)==0){n/=5;i5++;}
	return (n==1)?Math.max(i2,i5):15;
}
function bstr(z,n)
{
	if(n<0){n=-n;z=-z;}
	var d=dezlen(n);
	if(d>dn)return z+(((z!=0)&&(n!=1))?"/"+n:"");
	return String(Math.round(z*1000000000000/n)/1000000000000).replace(/\./g,",");
}
function PStrB(v,z,n)
{
	var t="",g=z.length-1;kk=new Array(g+1);
	kk[0]=bstr(z[0],n[0]);
	for(i=1;i<=g;i++) kk[i]=((z[i]==n[i])||(z[i]==-n[i]))?((z[i]==n[i])?"":"-"):bstr(z[i],n[i]);
	for(i=0;i<=g;i++) {kk[i]=kk[i].replace(/\-\./,"-0,").replace(/\./,",");if(kk[i].charAt(0)==",")kk[i]="0"+kk[i];}
	for(i=g;i>1;i--) if(z[i]!=0)t+="+"+kk[i]+(((z[i]!=0)&&(Math.abs(z[i]/n[i])!=1))?"·":"")+v+"^"+i;
	if((z[1]!=0)&&(g>0))t+="+"+kk[1]+((Math.abs(z[1]/n[i])!=1)?"·":"")+v; if(z[0]!=0)t+="+"+kk[0];
	t=t.replace(/\+\-/g,"-").replace(/\+/g," + ").replace(/\-/g," - ").replace(/\+/g," + ").replace(/\s\s/g," ");
	if(t.substr(0,3)==" - ")t="-"+t.substring(3,t.length);
	if(t.substr(0,2)==" +")t=t.substring(2,t.length);
	while(t.substr(0,1)==" ")t=t.substring(1,t.length);
	if(t=="")t="0";
	if((grex==2)||((grex==1)&&(g<3)))t=t.replace(/\^2/,"²").replace(/\^3/,"³");
	t=t.replace(/e \- /g,"e-").replace(/e \+ /g,"e+");
	return t;
}
function eigenschaft_lesen()
{
	var i=document.f.s.selectedIndex,x=document.f.p.value,xx,p;
	if((i==0)||((x=="")&&(i<17)))return;
	var t=document.f.s[i].text;
	document.f.p.select();
	if(t.indexOf(" =")>-1){xx=parse(x);if(xx==null){alert("Zahl ungültig: "+x);document.f.p.focus();return;}}
	if(t.indexOf(" Punkt")>-1)
	{
		xx=x.replace(/[\(\|\)]/g," ").replace(/ +/g," ");
		while(xx.charAt(0)==" ")xx=xx.substring(1,xx.length);
		while(xx.charAt(xx.length-1)==" ")xx=xx.substr(0,xx.length-1);
		p=xx.split(" ");
		if(p.length!=2){alert("Fehler in Eingabe des Punktes: "+x);document.f.p.focus();return;}
		p[0]=parse(p[0]);p[1]=parse(p[1]);
		if((p[0]==null)||(p[1]==null)){alert("Koordinaten ungültig: "+x);document.f.p.focus();return;}
	}
	switch(i)
	{
	case 1:t="f("+bstr(p[0][0],p[0][1])+") = "+bstr(p[1][0],p[1][1]);break;
	case 2:t="f("+bstr(xx[0],xx[1])+") = 0";break;
	case 3:t="f'("+bstr(p[0][0],p[0][1])+") = 0\nf("+bstr(p[0][0],p[0][1])+") = "+bstr(p[1][0],p[1][1]);break;
	case 4:t="f'("+bstr(xx[0],xx[1])+") = 0";break;
	case 5:t="f\"("+bstr(p[0][0],p[0][1])+") = 0\nf("+bstr(p[0][0],p[0][1])+") = "+bstr(p[1][0],p[1][1]);break;
	case 6:t="f\"("+bstr(xx[0],xx[1])+") = 0";break;
	case 7:do{var tt=prompt("Steigung in "+x,"");if(tt==null)return;}while((xx=parse(tt))==null);
		t="f'("+bstr(p[0][0],p[0][1])+") = "+bstr(xx[0],xx[1])+"\nf("+bstr(p[0][0],p[0][1])+") = "+bstr(p[1][0],p[1][1]);break;
		break;
	case 8:do{var xxx,tt=prompt("Steigung bei x = "+x,"");if(tt==null)return;}while((xxx=parse(tt))==null);
		t="f'("+bstr(xx[0],xx[1])+") = "+bstr(xxx[0],xxx[1]);break;
	case 9:t="f'("+bstr(p[0][0],p[0][1])+") = 0\nf''("+bstr(p[0][0],p[0][1])+") = 0\n";
		  t+="f("+bstr(p[0][0],p[0][1])+") = "+bstr(p[1][0],p[1][1]);break;
	case 10:t="f'("+bstr(xx[0],xx[1])+") = 0\nf''("+bstr(xx[0],xx[1])+") = 0";break;
	case 11:t="f(0) = "+bstr(xx[0],xx[1]);break;
	case 12:t="f'(0) = "+bstr(xx[0],xx[1]);break;
	case 13:g=ggt(xx[0]*2,xx[1]);t="f\"(0) = "+bstr(2*xx[0]/g,xx[1]/g);break;
	case 14:g=ggt(xx[0]*6,xx[1]);t="f'''(0) = "+bstr(6*xx[0]/g,xx[1]/g);break;
	case 15:g=ggt(xx[0]*24,xx[1]);t="f\"\"(0) = "+bstr(24*xx[0]/g,xx[1]/g);break;
	case 16:g=ggt(xx[0]*120,xx[1]);t="f'''''(0) = "+bstr(120*xx[0]/g,xx[1]/g);break;
	case 17:
	default:;
	}
	if((document.f.t.value.charAt(document.f.t.value.length-1)!="\n")&&(document.f.t.value.replace(/ /g,"")!=""))document.f.t.value+="\n";
	document.f.t.value+=t;
	document.f.p.value="";
	document.f.s.selectedIndex=0;
}

function neu()
{
	document.f.t.value="";
	document.f.fkt.value="";
	document.f.tkd.value="";
	document.f.gs.value="";
	document.f.y.value="";
}
function calc()
{
	var x=document.f.x.value,i,yy,t="";
	document.f.y.value="";if((x=="")||(x=="-"))return;
	keinemeldung=true;
	//alert(ablz[1]+"\n"+abln[1]+"\n"+horner1(ablz[1],abln[1],1,2));
	var xx=parse(x);if(xx==null)return;
	for(i=0;i<ln.length;i++)
	{
		yy=horner1(ablz[i],abln[i],xx[0],xx[1]);
		t+="f'''''''''''''''''''''''''".substr(0,i+1)+"("+x+") = "+bstr(yy[0],yy[1])+((i<ln.length-1)?"\n":"");
	}
	document.f.y.value=t;
	keinemeldung=false;
}
function horner1(kz,kn,xz,xn)
{
	var g=kz.length-1,y=kz[g]/kn[g],i;
	for(i=g-1;i>=0;i--)
	{
		y*=xz/xn;
		y+=kz[i]/kn[i];
	}
	return new Array(y,1);
}
function horner_d(k,x)
{
	var g=k.length-1,y=k[g],i;
	for(i=g-1;i>=0;i--)
	{
		y*=x;
		y+=k[i];
	}
	return y;
}
function zeigegleichungssystem()
{
	var i,j,k=0,t,tt,ttt="",n=(Math.sqrt(4*glsz.length+1)-1)/2,km=document.f.km.selectedIndex;
	for(i=0;i<n;i++)
	{
		tt=bstr(glsz[i*(n+1)+n],glsn[i*(n+1)+n]);
		for(j=0;j<n;j++)
		{
			k=i*(n+1)+j;
			if((sym>0)&&((k%2)==(sym%2)))glsz[k]=0;
			t=bstr(glsz[k],glsn[k]);
			tt=((t!="0")?t+"·"+koeffname(j,n-1,km):"")+((j>0)?" + ":" = ")+tt;
		}
		while(tt.substr(0,3)==" + ")tt=tt.substring(3,tt.length);
		while(tt.substr(0,2)=="1·")tt=tt.substring(2,tt.length);
		while(tt.substr(0,3)=="-1·")tt="-"+tt.substring(3,tt.length);
		ttt+=tt+((i<n-1)?"\n":"");
	}
	ttt=ttt.replace(/\+ \-/g,"- ").replace(/ 1·/g," ").replace(/\+  /g," ").replace(/ +/g," ").replace(/e - /g,"e-");
	if((km==1)&&(ttt.indexOf("/")==-1))ttt=ttt.replace(/·/g,"");
	document.f.gs.value=ttt;
}
function koeffname(i,g,m)
{
	return (m==0)?"a"+i:"abcdefghijklmnopqrstuvwxyz".charAt(g-i);
}
function testM(Z,N,n)
{
	var i;
	for(i=0;i<Z.length;i++){if((((i%(n+1))!=n)&&((i%(n+2))!=0)&&(Z[i]!=0))||(((i%(n+2))==0)&&(Z[i]==0)))return false;}
	return true;
}
function kd()
{
	jv=document.f.jvc.checked;
	if(funktiongeaendert)
	{
		if(!erkennePolynom(document.f.funktion.value)){alert("Funktion nicht erkannt");return;}
	}
	document.f.tkd.value=kurvendiskussion(lz,ln);
	if(funktiongeaendert)
	{
		document.f.tkd.value="f(x) = "+PStrB("x",lz,ln)+"\n\n"+document.f.tkd.value;
		if(jv)
		{
			document.plotter.parse(PStrB("x",lz,ln));
			document.plotter.plot();
		}
	}
}
var funktiongeaendert=1==0;
function erkennePolynom(t)
{
	var g,x=new Array(12),y=new Array(12),i,j,k,m=new Array(),v=new Array(),tt;
	t=t.replace(/,/g,".").replace(/ /g,"").replace(/X/g,"x").replace(/²/g,"^2").replace(/³/g,"^3").replace(/·/g,"*").replace(/[—–]/g,"-");
	if(t.replace(/[x0-9\.*\-\+\^\(\)\/]/g,"")!=""){return false;}
	var MultErg=new Array(/\dx/,/\d\(/,/\)\(/,/x\(/,/\)x/,/pi\(/,/e_\(/,/\dpi/,/\de_/);
	for(j=0;j<MultErg.length;j++)
		do{i=t.search(MultErg[j]);if(i==-1)break;t=t.substr(0,i+1)+"*"+t.substring(i+1,t.length);}while(true);
	while((i=t.indexOf("x^"))>-1)
	{
		j=parseInt(t.charAt(i+2));
		t=t.substr(0,i+1)+"*x*x*x*x*x*x*x*x*x*x".substr(0,j*2-2)+t.substring(i+3,t.length);
	}
	tt=t.replace(/[a-z\-\+*\.0-9\^\/ ]/g,"");
	while(tt.indexOf("()")>-1)tt=tt.replace(/\(\)/g,"");
	if(tt!=""){alert("Klammerung falsch");return false;}
	t=translate(t);
	for(i=0;i<12;i++)
	{
		x[i]=i/2*(((i%2)==1)?-1:1);
		y[i]=eval(t.replace(/X/g,"("+x[i]+")"));
		if(isNaN(y[i]))return false;
	}
	//alert(x.join("\n")+"\n\n"+y.join("\n"));
	i=0;
	for(g=1;g<=10;g++)
	{
		v=new Array(g+1);i=0;
		for(k=0;k<g+1;k++)
		{m[i]=1;i++;for(j=1;j<=g;j++){m[i]=m[i-1]*x[k];i++;};m[i]=y[k];i++;}
		GLSL(m,v,g+1);//alert(m);
		for(k=0;k<12;k++){if(Math.abs(horner_d(v,x[k])-y[k])>1e-10)break;}
		if(k<12)continue;
		lz=new Array(g+1);ln=new Array(g+1);
		for(i=0;i<=g;i++){lz[i]=v[i];ln[i]=1;}
		//alert(v);
		return true;
	}
	return false;
}
