// Javascript-Klasse für komplexe Zahlen
// (c) Arndt Brünner 3.4.2002 - 21.4.2002

function Komplex(r,i)
{
	if(isNaN(r))r=0.0;
	if(isNaN(i))i=0.0;
	this.r=r*1.0;this.i=i*1.0;
	this.set=new Function("r,i","this.r=r;this.i=i;return this;");	
	this.cl=new Function("","this.r=0;this.i=0;return this;");
	this.conj=new Function("","this.i=-this.i;return this;");
	this.setK=new Function("x","this.r=x.r;this.i=x.i;return this;");
	this.add=new Function("x","this.r+=x.r;this.i+=x.i;return this;");
	this.sub=new Function("x","this.r-=x.r;this.i-=x.i;return this;");
	this.add1=new Function("x","this.r++;return this;");
	this.sub1=new Function("x","this.r--;return this;");
	this.add2=new Function("x","this.r+=2;return this;");
	this.sub2=new Function("x","this.r-=2;return this;");
	this.mult2=new Function("x","this.r*=2;this.i*=2;return this;");
	this.div2=new Function("x","this.r/=2;this.i/=2;return this;");
	this.mult=new Function("x","var rr=x.r*this.r-x.i*this.i;this.i=this.r*x.i+this.i*x.r;this.r=rr;return this;");
	this.div=new Function("x","var N=x.i*x.i+x.r*x.r,rr=(x.r*this.r+x.i*this.i)/N;this.i=(this.i*x.r-this.r*x.i)/N;this.r=rr;return this;");
	this.sqr=new Function("","var w=this.betrag(),c=Math.sqrt((w+this.r)/2),d=Math.sqrt((w-this.r)/2);this.r=c;this.i=d;return this;");
	this.sqrx=new Function("n","return this.setK(this.powK((new Komplex(1,0)).div(n)));");
	this.quad=new Function("","this.setK(this.mult(this));return this;");
	this.betrag=new Function("","return Math.sqrt(this.r*this.r+this.i*this.i);");
	this.clone=new Function("","return new Komplex(this.r,this.i);");
	this.pow=new Function("x","var p=Math.pow(this.r*this.r+this.i*this.i,x/2), rr=p*Math.cos(Math.PI*x*sgn(this.i)/2-x*Math.atan(this.r/this.i));this.i=p*Math.sin(Math.PI*sgn(this.i)/2-x*Math.atan(this.r/this.i));this.r=rr; return this;");
	this.powK=new Function("c","var rr=powKr(this.r,this.i,c.r,c.i);this.i=powKi(this.r,this.i,c.r,c.i);this.r=rr;return this;");
	this.sin=new Function("","var rr=Math.sin(this.r)*(Math.exp(this.i)+Math.exp(-this.i))/2;	this.i=Math.cos(this.r)*(Math.exp(this.i)-Math.exp(-this.i))/2; this.r=rr; return this;");
	this.asin=new Function("","var rr=asinr(this.r,this.i);this.i=asini(this.r,this.i);this.r=rr;return this;");
	this.acos=new Function("","var rr=acosr(this.r,this.i);this.i=acosi(this.r,this.i);this.r=rr;return this;");
	this.cos=new Function("","var rr=Math.cos(this.r)*(Math.exp(this.i)+Math.exp(-this.i))/2;this.i=Math.sin(this.r)*(Math.exp(-this.i)-Math.exp(this.i))/2; this.r=rr; return this;");
	this.tan=new Function("","var N=Math.exp(4*this.i)+2*Math.exp(2*this.i)*(2*Math.pow(Math.cos(this.r),2)-1)+1,rr=4*Math.exp(2*this.i)*Math.sin(this.r)*Math.cos(this.r)/N;this.i=(Math.exp(4*this.i)-1)/N;this.r=rr;return this;");
	this.atan=new Function("","var q=this.i*this.i+this.r*this.r, rr=Math.PI*SGN(this.r)/4+Math.atan((q-1)/(2*this.r))/2;this.i=-Math.log((q-2*this.i+1)/(q+2*this.i+1))/4;this.r=rr;return this;");
	this.exp=new Function("","var rr=expKr(this);this.i=expKi(this);this.r=rr;return this;");
	this.ln=new Function("","return this.log();");
	this.log=new Function("","var rr=Math.log(this.r*this.r+this.i*this.i)/2;this.i=Math.PI*SGN(this.i)/2-Math.atan(this.r/this.i);this.r=rr;return this;");
	this.log10=new Function("","return this.log().div((new Komplex(10,0)).log());");
	this.logx=new Function("x","return this.log().div(x.clone().log());");
	this.random=new Function("a,b,c,d","this.r=Math.random()*(b-a)+a;this.i=Math.random()*(d-c)+c;return this;");
	this.str=new Function("","return KomplexToString(this.r,this.i);");
	this.swap=new Function("x","var rr=x.r,ii=x.i;x.setK(this);this.set(rr,ii);");
	this.rez=new Function("","var rr=this.r/(this.i*this.i+this.r*this.r);this.i= -this.i/(this.i*this.i+this.r*this.r);this.r=rr;return this;");
	this.csgn=new Function("","this.set(-this.r,-this.i);return this;");
	this.cot=new Function("","this.setK(_cot(this));return this;");
	this.sec=new Function("","this.setK(_sec(this));return this;");
	this.csc=new Function("","this.setK(_csc(this));return this;");
	this.acot=new Function("","this.setK(_acot(this));return this;");
	this.asec=new Function("","this.setK(_asec(this));return this;");
	this.acsc=new Function("","this.setK(_acsc(this));return this;");
	this.sinh=new Function("","this.setK(_sinh(this));return this;");
	this.cosh=new Function("","this.setK(_cosh(this));return this;");
	this.tanh=new Function("","this.setK(_tanh(this));return this;");
	this.coth=new Function("","this.setK(_coth(this));return this;");
	this.sech=new Function("","this.setK(_sech(this));return this;");
	this.csch=new Function("","this.setK(_csch(this));return this;");
	this.asinh=new Function("","this.setK(_asinh(this));return this;");
	this.acosh=new Function("","this.setK(_acosh(this));return this;");
	this.atanh=new Function("","this.setK(_atanh(this));return this;");
	this.acoth=new Function("","this.setK(_acoth(this));return this;");
	this.asech=new Function("","this.setK(_asech(this));return this;");
	this.acsch=new Function("","this.setK(_acsch(this));return this;");
	this.arg=new Function("","return atan2(this.i,this.r);");
}



function asinr(r,i){return - Math.asin((Math.sqrt(i*i+(r-1)*(r-1))-Math.sqrt(i*i+(r+1)*(r+1)))/2);}
function asini(r,i){return SGN(i)*Math.log((Math.SQRT2*Math.sqrt(Math.sqrt(i*i+(r+1)*(r+1))*Math.sqrt(i*i+(r-1)*(r-1))+i*i+r*r-1)+Math.sqrt(i*i+(r-1)*(r-1))+Math.sqrt(i*i+(r+1)*(r+1)))/2);}
function acosr(r,i){return Math.acos((Math.sqrt(i*i + (r+1)*(r+1))-Math.sqrt(i*i+(r-1)*(r-1)))/2);}
function acosi(r,i){return - SGN(i)*Math.log((Math.SQRT2*Math.sqrt(Math.sqrt(i*i+(r+1)*(r+1))*Math.sqrt(i*i+(r-1)*(r-1))+i*i+r*r-1)+Math.sqrt(i*i+(r-1)*(r-1))+Math.sqrt(i*i+(r+1)*(r+1)))/2);}
function expKr(c){return Math.exp(c.r)*Math.cos(c.i);}
function expKi(c){return Math.exp(c.r)*Math.sin(c.i);}
function powKr(a,b,c,d){return Math.exp(d*Math.atan(a/b)-Math.PI*d*SGN(b)/2)*Math.pow(a*a+b*b,c/2)*Math.cos(Math.PI*c*SGN(b)/2-c*Math.atan(a/b)+d*Math.log(a*a+b*b)/2);}
function powKi(a,b,c,d){return Math.exp(d*Math.atan(a/b)-Math.PI*d*SGN(b)/2)*Math.pow(a*a+b*b,c/2)*Math.sin(Math.PI*c*SGN(b)/2-c*Math.atan(a/b)+d*Math.log(a*a+b*b)/2);}
function sgn(x){return (x<0)?(-1):((x==0)?0:1);}
function SGN(x){return (x<0)?(-1):1;}
function sgnK(x){var y=(x.clone()).betrag(); return new Komplex(x.r/y,x.i/y);}

function _cot(x){return (x.tan()).rez();}
function _sec(x){return (x.cos()).rez();}
function _csc(x){return (x.sin()).rez();}
function _acot(x){return (new Komplex(Math.PI/2,0)).sub(x.atan());}
function _asec(x){return (x.rez()).acos();}
function _acsc(x){return (x.rez()).asin();}
function _sinh(x){var y=x.clone();return (x.exp().sub((y.exp()).rez())).div(kZwei);}
function _cosh(x){var y=x.clone();return (x.exp().add((y.exp()).rez())).div(kZwei);}
function _tanh(x){var y=((x.mult(kZwei)).exp()).clone(); return (x.sub(kEins)).div(y.add(kEins));}
function _coth(x){return (x.tanh()).rez();}
function _sech(x){var y=x.clone();return x.exp().mult(kZwei).div(y.mult(kZwei).exp().add(kEins));}
function _csch(x){var y=x.clone();return x.exp().mult(kZwei).div(y.mult(kZwei).exp().sub(kEins));}
function _asinh(x){var y=x.clone();return x.quad().add(kEins).sqr().add(y).ln();}
function _acosh(x){return x.acos().mult(kI);}
function _atanh(x){x.setK(x.mult(kI).atan().mult(kI)); x.set(-x.r,-x.i);return x;}
function _acoth(x){var y=x.clone(); return x.add(kEins).div(y.sub(kEins)).ln().div(kZwei);}
function _acsch(x){ return x.rez().mult(kI).asin().mult(kI).csgn();}
function _asech(x){ return x.rez().acos().mult(kI);}
function atan2(y,x)
{
	if(x==0)return(y>0)?Math.PI/2:(y<0)?Math.PI*1.5:null;
	var t=Math.atan(Math.abs(y)/Math.abs(x));
	if(x<0){if(y>0)t=Math.PI-t; else t+=Math.PI;}
	else if(y<0)t=Math.PI*2-t;
	return t;
}
function KomplexToString(r,i)
{
	var t=new String(r);if (i>0)t+=" + "+i+"·î";else if(i<0)t+=" - "+Math.abs(i)+"·î";if(t.charAt(0)==".")t=0+t;
	return t.replace(/\./g,",").replace(/-,/g,"-0,").replace(/ ,/g," 0,").replace(/ 1·î/," î").replace(/0 \+ /,"").replace(/0 - /,"-");
}


var kEins=new Komplex(1,0),kZwei=new Komplex(2,0),kNull=new Komplex(0,0),kI=new Komplex(0,1);
