<!--Define JavaScript functions.-->

function sign(y){
return ((y < 0) ? -1 : 1);
}  //End of function sign.

function EccAnomtoTrueAnom(e, y){
 var cE = Math.cos(y);  //Try to avoid subtraction with small numbers, to reduce rounding errors.
 var cN, N;
 if (cE >= 0)
  cN = (cE - e)/(1.0 - e*cE); 
 else
 {cE = -cE;
  cN = -((cE + e)/(1.0 + e*cE));
 }  //End else cE < 0.
 N = Math.acos(cN);   
 if (y > Math.PI)
  N = -N + 2*Math.PI;
 return N;
}  //End of function EccAnomtoTrueAnom

function KeplerSolve(dataForm){
var ecc = parseFloat(dataForm.ecc.value);
var T = parseFloat(dataForm.Period.value);
var tm = parseFloat(dataForm.time.value);

if ((ecc <= 0) || (ecc >= 1))
{alert("Eccentricity for an ellipse must be greater than 0 and less than 1.");
 return;
}  //End if ecc out of range.

if (tm < 0)
{alert("Time since periapse must be a positive quantity.");
 return;
}  //End if tm < 0.

if (!tm)
{dataForm.funcEval.value=dataForm.TrueAnomDeg.value=dataForm.TrueAnomRad.value=dataForm.eccAnomDeg.value=dataForm.eccAnomRad.value=0;
 dataForm.erCode.value = 2;
 return;
}  //End if tm == 0.

if (tm == T/2)
{dataForm.TrueAnomRad.value = dataForm.eccAnomRad.value = Math.PI;
 dataForm.TrueAnomDeg.value = dataForm.eccAnomDeg.value = 180;
 dataForm.funcEval.value = 0;
 dataForm.erCode.value = 2;
 return;
}  //End if tm == T/2.

if (tm > T) tm = tm%T;

if (tm == T)
{dataForm.TrueAnomRad.value = dataForm.eccAnomRad.value = 2*Math.PI;
 dataForm.TrueAnomDeg.value = dataForm.eccAnomDeg.value = 360;
 dataForm.funcEval.value = 0;
 dataForm.erCode.value = 2;
 return;
}  //End if tm == T.

var b, c, mAnom = 2*Math.PI*tm/T;

if (tm < T/2)
{if ((tm < (Math.PI/3 - ecc)*T/4/Math.PI) || (tm >= (5*Math.PI/3 - ecc)*T/4/Math.PI))
 {b = mAnom;
  c = mAnom + ecc/2;
 }
 else
 {b = mAnom + ecc/2;
  c = mAnom + ecc;
  }
 }// End if tm < T/2
else //Else tm >= T/2
{if ((tm < (7*Math.PI/3 + ecc)*T/4/Math.PI) || (tm >= (11*Math.PI/3 + ecc)*T/4/Math.PI))
 {b = mAnom - ecc/2;
  c = mAnom;
 }
 else
 {b = mAnom - ecc;
  c = mAnom - ecc/2;
 }	 
}  //End if t <> T/2

var z = b + ecc/2/2;
var fz = -(ecc*Math.sin(z)) + z - mAnom;
var fc = fz, t = b, kount = 2;
var fb = -(ecc*Math.sin(b)) + b - mAnom;

if (sign(fz) == sign(fb))
{t = c;
 fc = -(ecc*Math.sin(c)) + c - mAnom;
 kount = 3;
 if (sign(fz) != sign(fc))
 {b = z;
  fb = fz;
 }  //End if sign(fz) != sign(fc).
}  //End if sign(fz) == sign(fb).
else c = z;

var a = c, fa = fc, acmb, ic = 0, tol, p, q, acbs = ecc/2/2, MAXIT = 100, ae, cmb;

acmb = 1.0;
do {
  ae = acmb;
  acmb /= 2.0;
  cmb = 1.0 + acmb;
} while (cmb > 1.0);
// At this point, ae should equal the machine epsilon
dataForm.epmch.value = ae;

do {
 if (Math.abs(fc) < Math.abs(fb))  //Interchange if necessary.
 {a = b;
  fa = fb;
  b = c;
  fb = fc;
  c = a;
  fc = fa
 }  //End if abs(fc) < abs(fb)
 cmb = (-b + c)/2;
 acmb = Math.abs(cmb);
 tol = Math.abs(b);
 tol++;
 tol *= ae;

 if (acmb <= tol)
 {dataForm.erCode.value = 1;
  break;
 }  //End if acmb <= tol.

 if (!fb)
 {dataForm.erCode.value = 2;
  break;
 }  //End if fb == 0.

/* Calculate new iterate implicitly as b + p/q, where p is arranged to be >= 0. This implicit form is used to prevent overflow. */

 p = (-a + b)*fb;
 q = -fb + fa;
 if (p < 0)
 {p = -p;
  q = -q;
 }  //End if p < 0.

/* Update a and check for satisfactory reduction in the size of the bracketing interval. If not, perform bisection. */

 a = b;
 fa = fb;
 ic++;

 if ((ic >= 4) && (8*acmb >= acbs))
  b = (c + b)/2;  //Use bisection
 else
 {if (ic >= 4)
  {ic = 0;
   acbs = acmb;
  }  //End if ic >= 4
  if (p <= tol*Math.abs(q))  //Test for too small a change
   b += tol*sign(cmb);
  else    //Root between b and (b + c)/2
  {if (p < cmb*q)  //Use secant rule
    b += p/q;
   else            //Use bisection
    b = (c + b)/2;
  }  //End else
 }  //End else.

// Have now computed new iterate, b.

 fb = -(ecc*Math.sin(b)) + b - mAnom;
 kount++;

//Decide if next step interpolation or extrapolation

 if (sign(fb) == sign(fc))
 {c = a;
  fc = fa;
 }  //End sign(fb) == sign(fc).

} while (kount < MAXIT); //End do-while loop
if (kount >= MAXIT) dataForm.erCode.value = 3;

dataForm.eccAnomRad.value = b;
dataForm.eccAnomDeg.value = b*180/Math.PI;
t = EccAnomtoTrueAnom(ecc, b);
dataForm.TrueAnomRad.value = t;
dataForm.TrueAnomDeg.value = t*180/Math.PI;
dataForm.funcEval.value = kount;
return;
}  //End of KeplerSolve

// end of JavaScript function definitions -->