/************************************************
    Numerical Methods Library - JavaScript
    root finder
    TechniSolve Software
    Bruce Wernick PrEng BScEng
    Copyright 2006
************************************************/

function rangecheck(label,s,defx,minx,maxx,digs) {
  var x=parseFloat(s);
  if (isNaN(x)) {
    alert("you must enter a valid " + label+"...");
    x=defx;
  }
  if (x<minx) {
    alert(label+" must be at least "+minx+"...");
    x=minx;
  }
  if (x>maxx) {
    alert(label+" must be less than "+maxx+"...");
    x=maxx;
  }
  return roundup(x,digs);
}

function roundup(x,n) {
// Round up with n places
  var d=Math.pow(10,n);
  return Math.round(x*d)/d;
}

function sign(x) {
  if (x>=0) return 1; else return -1;
}

function broyden(f,x,tol,maxits) {
// broyden method, tol and maxits are optional
// x is 1st guess at root

  // default parameters
  var tol = (tol == null) ? 1e-6 : tol;
  var maxits = (maxits == null) ? 100 : maxits;
  
  // check if already solved
  var fo=f(x);
  if (Math.abs(fo)<=tol) {return x;}
  
  var dK;
  var dx;
  var fx;
  var dfx;
  var a;
  
  // estimate of slope inverse
  var K=-0.08/(fo-f(x+0.1));
  
  var i;
  for (i=0; i<=maxits; i++) {
    dx=-K*fo;
    x=x+dx;
    fx=f(x);
    dfx=fx-fo;
    a=dx*K*dfx;
    dK=-K*(a-(dx*dx))/a;
    K=K+dK;
    if (Math.abs(fx)<=tol) {return x;}
    fo=fx;
  }
  return x;
}

function bisect(f,a,b,tol,maxits) {
// solve for root using the bisection method
// a and b must bracket the root

  // default parameters
  var tol = (tol == null) ? 1e-6 : tol;
  var maxits = (maxits == null) ? 100 : maxits;

  var ya=f(a);
  var yb=f(b);
  var c;
  var yc;
  var i;
  for (i=0; i<=maxits; i++) {
    c=0.5*(a+b);
    yc=f(c);
    if (Math.abs(yc)<=tol) {return c;}
    if (sign(yb) == sign(yc)) 
      {b=c; yb=yc;} 
    else 
      {a=c; ya=yc;}
  }
}
