// Javascript zum Rechner für große/kleine Zahlen mit hoher Genauigkeit
// (c) Arndt Brünner, 8.6.2003, alle Rechte vorbehalten!
// Version: 22.6.2003

var sp=new Array("@","@"),spn=new Array("pi","e"),spt=new Array("16*atan(1/5)-4*atan(1/239)","exp(1)");
var sps=new Array(100,100);
var working=(1==0);
var x="",xx="",sdisp=50,scale=100;
var endnullen=(1==0);
var R;
var faktorisierung="";
var funktionen=new Array("abs","sqr","log","ln","sin","cos","tan","asin","acos","atan","sinh","cosh","tanh","asinh","acosh","atanh","exp","e","pi","fak","faktor","root","bk");

function gzcalc()
{
	if(working)return;
	status="parsing";
	var t=document.f.t.value;
	R=document.Rechner;
	if(R==null){document.f.tt.value="nicht bereit";return;}
	endnullen=!document.f.cen.checked;
	var i,j,s="";
	if((i=t.indexOf("="))>-1){s=t.substr(0,i);t=t.substring(i+1,t.length);}
	t=t.toLowerCase();
	if(t.replace(/ /g,"").charAt(0)=='"')
	{
		x=t.replace(/\"/g,"");
		speichern(s);
		status="";
		document.f.t.focus();
		document.f.t.select();
		return;
	}	
	i=Number(document.f.scale.value);
	if(i>99999){i=99999;document.f.scale.value=i;}
	if(i>scale){document.f.tt.value="Berechne pi auf "+i+" Dezimalstellen";status="calculating "+i+" digits of pi";}
	R.setScale((scale=i)+20);
	i=Number(document.f.sdisp.value);
	if(isNaN(i))i=50;
	if(i<10)i=10;
	if(i>scale)i=scale;
	document.f.sdisp.value=sdisp=i;

	document.f.tt.value="";

	var T=t.replace(/[^\(\)]/g,"");
	//for(i=T.length-1;i>=0;i--)
	//{
	//	if((T.charAt(i)!="(")&&(T.charAt(i)!=")"))T=T.substr(0,i)+T.substring(i+1,T.length);
	//}
	while((i=T.indexOf("()"))>-1)T=T.replace(/\(\)/g,"");
	if(T!=""){alert("Klammerfehler!");return;}

	for(i=0;i<sp.length;i++)
	{
		if(sp[i]=="@")continue;
		if(spn[i]=="")continue;
		if(sp[i]=="")continue;
		while((j=t.toLowerCase().indexOf(spn[i].toLowerCase()))>-1)
		{
			var t0=(j>0)?t.charAt(j-1):" ", t1=(j+spn[i].length<=t.length-1)?t.charAt(j+spn[i].length):" ";
			var e0=t0.charCodeAt(0),e1=t1.charCodeAt(0);
			//alert(t0+"  "+e0+"\n"+t1+"   "+e1);
			var w=(1==0);
			if((e0>=65)&&(e0<=90))w=true;
			if((e1>=65)&&(e1<=90))w=true;
			if((e0>=97)&&(e0<=122))w=true;
			if((e1>=97)&&(e1<=122))w=true;
		
			if(!w)
				t=t.substr(0,j)+"("+sp[i]+")"+t.substring(j+spn[i].length,t.length);
			else
				t=t.substr(0,j)+"§"+t.substring(j+spn[i].length,t.length);
		}
		t=t.replace(/§/g,spn[i]).toLowerCase();
	}	

	t=t.replace(/,/g,".").replace(/ +/g,"").replace(/ln\(/gi,"log(");
	t=t.replace(/·/g,"*");
	t=translate(t);
	t=gztranslate(t);
	var tt=t;
	t=t.replace(/Math\./g,"R.");
	t=t.replace(/asinh/g,"R.as§inh");
	t=t.replace(/acosh/g,"R.ac§osh");
	t=t.replace(/atanh/g,"R.at§anh");
	t=t.replace(/sinh/g,"R.s§inh");
	t=t.replace(/cosh/g,"R.c§osh");
	t=t.replace(/tanh/g,"R.t§anh");
	t=t.replace(/asin/g,"R.as§in");
	t=t.replace(/acos/g,"R.ac§os");
	t=t.replace(/atan/g,"R.at§an");
	t=t.replace(/sin/g,"R.sin");
	t=t.replace(/cos/g,"R.cos");
	t=t.replace(/tan/g,"R.tan");
	t=t.replace(/root/g,"R.root");
	t=t.replace(/R.floor/g,"R.int_");
	t=t.replace(/fak\(/g,"R.fak(");
	t=t.replace(/R\.pi/gi,"R.PI()");
	t=t.replace(/R\.e/gi,"R.E()");
	t=t.replace(/R\.e\(\)xp/gi,"R.exp");
	t=t.replace(/§/g,"");
	
	if((t.indexOf("(,")>-1)||(t.indexOf(",)")>-1)){alert("Fehler im Term: Argument fehlt");document.f.t.focus();document.f.t.select();return;}
	 
	tt=tt.replace(/Math\./g," ");
	tt=tt.replace(/asinh/g," ");
	tt=tt.replace(/acosh/g," ");
	tt=tt.replace(/atanh/g," ");
	tt=tt.replace(/sinh/g," ");
	tt=tt.replace(/cosh/g," ");
	tt=tt.replace(/tanh/g," ");
	tt=tt.replace(/asin/g," ");
	tt=tt.replace(/acos/g," ");
	tt=tt.replace(/atan/g," ");
	tt=tt.replace(/sin/g," ");
	tt=tt.replace(/cos/g," ");
	tt=tt.replace(/tan/g," ");
	tt=tt.replace(/abs/g," ");
	tt=tt.replace(/root/g," ");
	tt=tt.replace(/floor/g," ");
	tt=tt.replace(/log/g," ");
	tt=tt.replace(/pow/g," ");
	tt=tt.replace(/R.floor/g," ");
	tt=tt.replace(/fak\(/g," ");
	tt=tt.replace(/faktor\(/g," ");
	tt=tt.replace(/pi/gi," ");
	tt=tt.replace(/E/g,"");
	tt=tt.replace(/exp/gi," ");
	tt=tt.replace(/§/g," ");
	tt=tt.replace(/R\./g," ").replace(/\./g," ").replace(/subtract/g," ").replace(/plus/g," ").replace(/multiply/g," ");
	tt=tt.replace(/divide/g," ").replace(/sqrt/g," ").replace(/[\(\),\."]/g," ");
	tt=tt.replace(/ +/g," ");
	var RE=new RegExp(/\D+\d/g); 
	var fundst=RE.exec(tt.replace(/ /g,""));
	if(fundst!=null){alert("Fehler:\nUnbekannte Variable(n)");return;}
	tt=tt.replace(/\d+/g,"");
	if(tt.replace(/ /g,"")!=""){alert("Fehler:\nUnbekannte Funktion oder Variable\n");document.f.t.focus();document.f.t.select();return;}

	//	if(!confirm(t)){working=false;return;}

	working=true;
	document.f.berbut.disabled=true;
	document.f.tt.value="Berechne: "+t.replace(/R\./g,"").replace(/\(\)/g,"").replace(/_/g,"").replace(/"/g,"").replace(/plus\)/g,"add(");

	status="calculating";

	//t=t.replace(/R\./g,"document.Rechner.");

	R.setTimeout((isNaN(Number(document.f.maxzeit.value)))?0:Number(document.f.maxzeit.value.replace(/,/,"."))*1000);
	var tt=String(eval(t));
	x=xx=tt;

	if(x.indexOf("·")==-1)
	{
		//x=R.roundS(tt,scale);
		tt=String(R.roundS(tt,sdisp));
		if(!endnullen){while(tt.charAt(tt.length-1)=="0")tt=tt.substr(0,tt.length-1);}
		if(tt.charAt(tt.length-1)==".")tt=tt.substr(0,tt.length-1);
		tt=tt.replace(/\./,",");
	}
	else
	{
		var ta=tt.split("·"),ta_=new Array(ta.length);for(i=0;i<ta.length;i++)ta_[i]=parseInt(ta[i]);
		quicksort2(ta_,ta)
		tt=ta.join("·");
	}
	document.f.tt.value=tt;
	if(s!="")speichern(s);
	document.f.berbut.disabled=false;
	working=false;
	if(R.interruptreset()==1)alert("Abbruch wegen Zeitüberschreitung\nDas Ergebnis ist mit hoher Wahrscheinlichkeit ungenau oder unvollständig!");
	status="";
	document.f.t.focus();
	document.f.t.select();
}

function erroroff()
{
	working=false;status=(document.Rechner!=null)?"OK":"Seite muß neu geladen werden";
	document.f.berbut.disabled=false;
	document.f.tt.value="Bereit!";showspeicher();
}

function speichern(s)
{
	if(s==null)s=prompt("Name der Variable","");
	var i,j;
	if(s==null)return;
	for(i=0;i<funktionen.length;i++)
	if(s.toLowerCase()==funktionen[i]){alert("Fehler:\nVariablenname "+s+" ungültig, da reserviert");return;}
	if(!isNaN(s.charAt(0))){alert("Fehler:\nUngültiger Variablenname: "+s+"\n\n(Variablennamen müssen mit Buchstaben beginnen");return;}
	for(i=0;i<sp.length;i++)if(spn[i].toLowerCase()==s.toLowerCase())break;
	while(s.charAt(0)==" ")s=s.substr(1,s.length-1);
	while(s.charAt(s.length-1)==" ")s=s.substr(0,s.length-1);
	spn[i]=s;
	sp[i]=x;
	sps[i]=(x.indexOf(".")==-1)?0:scale;
	var A=document.f.t.value.split("=");
	spt[i]=A[A.length-1];
	while(spt[i].charAt(0)==" ")spt[i]=spt[i].substr(1,spt[i].length-1);
	while(spt[i].charAt(spt[i].length-1)==" ")spt[i]=spt[i].substr(0,spt[i].length-1);
	for(j=0;j<sp.length-1;j++)
	for(i=j+1;i<sp.length;i++)
	{
		if(spn[i].indexOf(spn[j])>-1)
		{
			var ss=sp[i];sp[i]=sp[j];sp[j]=ss;ss=spn[i];spn[i]=spn[j];spn[j]=ss;
			ss=spt[i];spt[i]=spt[j];spt[j]=ss;ss=sps[i];sps[i]=sps[j];sps[j]=ss;
		}
	}
	showspeicher();
	document.f.t.focus();
	document.f.t.select();
}

function speicherloeschen()
{
	//var s=document.f.delsp.value;
	var s=prompt("zu löschende Variable angeben! \nden Stern (*) für alle","");
	if((s=="")||(s==null))return;
	//document.f.delsp.value="";
	var i,j;
	if(s=="*")
	{
		if(confirm("Bestätigung: Alle löschen?"))
		{
			for(i=0;i<spn.length;i++){sp[i]="";spn[i]="";spt[i]="";sps[i]=0;}
			showspeicher();
		}
		return;
	}
	for(i=0;i<spn.length;i++)if(spn[i].toLowerCase()==s.toLowerCase())break;
	if((s.toLowerCase()=="pi")||(s.toLowerCase()=="e")){alert("Konstanten können nicht gelöscht werden");return;}
	if(i==spn.length){alert("Fehler:\nVariable "+s+" nicht vorhanden.");return;}
	for(j=i;j<spn.length-1;j++){spn[j]=spn[j+1];sp[j]=sp[j+1];spt[j]=spt[j+1];}
	spn[j]="";sp[j]="";spt[j]="";sps[j]=0;
	showspeicher();
}

function showspeicher(terme)
{
	var s=-1,i,t="",tt="",si;
	terme=document.f.termezeigen.checked;
	switch(si=document.f.ssp.selectedIndex)
	{case 0:s=10;break;case 1:s=sdisp;break;default:s=-1;}
	if(s==scale)s=-1;
	if(R==null)s=-1;
	for(i=0;i<sp.length;i++)
	{
		if((spn[i]!="pi")&&(spn[i]!="e")&&(spn[i]!=""))
		{
			tt=(((s==-1)||(sp[i].indexOf("·")>-1))?(((sp[i].indexOf("·")==-1)&&(sp[i].indexOf(".")>-1))?R.roundS(sp[i],sps[i]):sp[i]):R.roundS(sp[i],s)+";");
			if(tt.indexOf("Error")>-1)tt=spt[i].replace(/\"/g,"");
			t+=spn[i]+" = "+(((terme==true)&&(tt!=spt[i]))?spt[i]+" = ":"")+tt+"\n";
		}
	}
	document.f.ts.value=t.replace(/\./g,",").replace(/;/g,"...");//+"\n"+spn.join("   ");
	document.f.t.focus();document.f.t.select();
	document.f.ssp.selectedIndex=si;
}

function showalle()
{
	if((!isNaN(x.charAt(0)))||(x.charAt(0)=="-"))
	{
		document.f.tt.value=String(R.roundS(x,scale)).replace(/\./,",");
	}
}

function showTerme()
{
	showspeicher(true);
}

function anzeigerunden(N)
{
	var n=Number(N);
	if(R==null)return;
	if((isNaN(n))||(n<0)){document.f.sdisp.value=0;n=0;}
	if(n>scale+10){document.f.sdisp.value=scale;n=scale;}
	document.f.tt.value=String(R.roundS(x,n)).replace(/\./,",");
	sdisp=n;
}

function changetrigmod()
{
	if(document.Rechner!=null)document.Rechner.setTrigMode(document.f.trigmod.selectedIndex);
}

var op="*/+-,",opp=new Array(1,1,2,2,10),
	opr=new Array("R.multiply","R.divide","R.plus","R.subtract");

function gztranslate(t)
{
	var i=0,j,k,kk=0,ii=0;
	var r1=/Math\.pow\(/,r2=/\(\d+\/\d+\)/,r3=/\(-\d+\/\d+\)/;
	//if(t.charAt(0)=="-")t="0"+t;
	t="("+t+")";
	t=binkoeffs(t);
	while((i=kk+t.substring(kk,t.length).search(r1))>=kk)
	{
		//if(!confirm(t))break;
		k=0;
		for(j=i+9;j<t.length;j++)
			{if(t.charAt(j)=="(")k++;if(t.charAt(j)==")")k--;
			if((t.charAt(j)==",")&&(k==0))break;}
		//alert(t.substring(j+1,t.length)+"\n"+j+"\n"+t);
		if((t.substring(j+1,t.length).search(r2)==0)||(t.substring(j+1,t.length).search(r3)==0))
		{
			k=j+t.substring(j,t.length).indexOf("/");
			kk=j+t.substring(j,t.length).indexOf(")");
			var tt=t;
			var n=t.substring(k+1,kk),p=t.substring(j+2,k);
			if((Math.abs(Number(n))<51)&&(Math.abs(Number(n))<21))
			t=t.substr(0,i)+"root("+t.substring(i,j+1)+t.substring(j+2,k)+"),"+t.substring(k+1,kk)+t.substring(kk+1,t.length);
		}
		else kk=i+10;
	}
	for(i=1;i<t.length;i++)
	{
		j=op.indexOf(t.charAt(i));
		if((j>-1)&&(t.charAt(i)!=","))
		{
			t=gzrepl(t,i,j);	
			ii++;
		}
		if(ii==99999)break;
	}
	t=t.replace(/subtract\(,/g,"subtract(0,");

	var r=new Array(/\(\d/,/,\d/,/\d,/,/\d\)/),ir;
	for(ir=0;ir<r.length;ir++)
	while((i=t.search(r[ir]))>-1){t=t.substr(0,i+1)+"\""+t.substring(i+1,t.length);}
	return t.substring(1,t.length-1);
}

function gzrepl(t,i,o)
{
	var j=gzparsefind(t,i,-1,o), k=gzparsefind(t,i,1,o);
	t=t.substring(0,j+1)
	+opr[o] +"("
	+ t.substring(j+1,i)
	+ ","+t.substring(i+1,k)+")"
	+ t.substring(k,t.length);
	//alert("o="+o+"\ni="+i+"\nopr[o]="+opr[o]+"\n"+t);
	return t;
}

function gzparsefind(t,i,r,o)
{
	var L_=t.length, k=0, j=0, p=opp[o];
	for(j=i+r;(j<L_)&&(j>=0);j+=r)
	{
		var u=t.substr(j,1);
		if(u=="(")k++; else if(u==")")k--;
		if(k*r<0)return j;
		if(k!=0)continue;
		if((k==0)&&((j+r==L_+1)||(j+r==-1)))return j;
		if((k==0)&&((u=="+")||(u=="-")||(u=="*")||(u=="/")||(u==",")))
		{
			var ip=op.indexOf(u);
			if((ip>-1)&&(opp[ip]>=p))return j;
		}
	}
	return j;
}

function binkoeffs(t)
{
	var i,j,b,bb,n,k,tt="",ttt="",ii;
	status="übersetze Binomialkoeffizient";
	while((i=t.indexOf("bk("))>-1)
	{
		j=gzparsefind(t,i+3,1);
		b=t.substring(i+3,j);
		b=b.replace(/\D/g," ");
		bb=b.split(" "); 
		if(bb.length>2)alert("Mehr als zwei Argumente im Binomialkoeffizienten sind unzulässig.");
		//n=parseInt(bb[0]);k=parseInt(bb[1]);tt=n;
		//for(ii=1;ii<k;ii++){tt+="*"+(n-ii);tt+="/"+(ii+1);}
		//t=t.substr(0,i)+"("+tt+"/("+ttt+")"+t.substring(j,t.length);
		t=t.substr(0,i)+ "fak("+bb[0]+")/(fak("+bb[1]+")*fak(("+bb[0]+")-("+bb[1]+"))"+t.substring(j,t.length);
	}
	return t;
}

function faktor(t)
{
	//alert(R.round(t)+"\n"+R.round(R.int_(t))+"\n"+(R.round(t)!=R.round(R.int_(t))));
	//if(R.round(t)!=R.round(R.int_(t)))return "Error";
	t=R.int_(t);
	faktorisierung="";
	status="factorize "+t;
	document.faktorapplet.alg=Number(document.f.f_alg.selectedIndex);
	var fak=String(document.faktorapplet.faktor(t,"·",Number(document.f.maxzeit.value))).replace(/·+/g,"·");
	while(fak.charAt(0)=="·")fak=fak.substring(1,fak.length);
	faktorisierung=fak;
	return fak;
}

function zahlwort(i)
{
	var t,j,z,T;
	if(document.f.tt.value.indexOf("·")>-1)
	{
		var t=document.f.tt.value.split("·");
		if((j=(z=document.f.t.value.toLowerCase()).indexOf("faktor("))>-1)
				{z=z.substring(j+7,z.length);i=z.indexOf(")");T="von "+z.substr(0,i)+" ";}
		for(j=0;j<t.length;j++)t[j]=getZahlwort(t[j],true);
		document.f.ts.value="Die Primfaktoren "+T+"sind: "+t.join(", ")+"\n\n"+document.f.ts.value;
		return;
	}
	t=document.f.tt.value.split(",");
	if(t[0]=="")t=document.f.t.value.split(",");
	showspeicher();
	if(i==1)document.f.ts.value=getZahlwort(t.join(","),true)+"\n\n"+document.f.ts.value;
	else document.f.ts.value=getZahlwort(t[0],true)+"\n\n"+document.f.ts.value;
}

