Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript conversion #3

Open
viridia opened this issue Nov 24, 2022 · 0 comments
Open

TypeScript conversion #3

viridia opened this issue Nov 24, 2022 · 0 comments

Comments

@viridia
Copy link

viridia commented Nov 24, 2022

I wanted to use this in my project, but I needed to convert it to TypeScript / ES6. Here's what I did:

// Copied from https://github.com/scijs/newton-raphson-method
// Converted to TypeScript and ES6

interface INewtonRaphsonOptions {
  tolerance?: number;
  epsilon?: number;
  maxIterations?: number;
  h?: number;
  verbose?: boolean;
}

export function newtonRaphson(
  f: (n: number) => number,
  fp: (n: number) => number,
  x0: number,
  options?: INewtonRaphsonOptions
): number | boolean;
export function newtonRaphson(
  f: (n: number) => number,
  x0: number,
  options?: INewtonRaphsonOptions
): number | boolean;
export function newtonRaphson(
  f: (n: number) => number,
  fp: number | ((n: number) => number),
  x0?: number | INewtonRaphsonOptions,
  options?: INewtonRaphsonOptions
): number | boolean {
  // Iterpret variadic forms:
  const fnp = typeof fp === 'function' ? fp : null;

  const {
    tolerance: tol = 1e-7,
    epsilon: eps = 2.220446049250313e-16,
    maxIterations: maxIter = 20,
    h = 1e-4,
    verbose = false,
  } = (fnp ? (options as INewtonRaphsonOptions) : (x0 as INewtonRaphsonOptions)) ?? {};

  let x1, y, yp, yph, ymh, yp2h, ym2h;
  let hr = 1 / h;
  let x = (fnp ? x0 : fp) as number;

  let iter = 0;
  while (iter++ < maxIter) {
    // Compute the value of the function:
    y = f(x);

    if (fnp) {
      yp = fnp(x);
    } else {
      // Needs numerical derivatives:
      yph = f(x + h);
      ymh = f(x - h);
      yp2h = f(x + 2 * h);
      ym2h = f(x - 2 * h);

      yp = ((ym2h - yp2h + 8 * (yph - ymh)) * hr) / 12;
    }

    // Check for badly conditioned update (extremely small first deriv relative to function):
    if (Math.abs(yp) <= eps * Math.abs(y)) {
      if (verbose) {
        console.log('Newton-Raphson: failed to converged due to nearly zero first derivative');
      }
      return false;
    }

    // Update the guess:
    x1 = x - y / yp;

    // Check for convergence:
    if (Math.abs(x1 - x) <= tol * Math.abs(x1)) {
      if (verbose) {
        console.log('Newton-Raphson: converged to x = ' + x1 + ' after ' + iter + ' iterations');
      }
      return x1;
    }

    // Transfer update to the new guess:
    x = x1;
  }

  if (verbose) {
    console.log('Newton-Raphson: Maximum iterations reached (' + maxIter + ')');
  }

  return false;
}

I also converted the unit tests to Vitest (since that's what I am using). I can supply the code if you are interested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant