Raw File
bisect.R
##
##  b i s e c t . R
##


bisect <- function(f, a, b, maxiter=100, tol=.Machine$double.eps^0.5)
# Bisection search for zero of a univariate function in a bounded interval
{
	if (f(a)*f(b) > 0) stop("f(a) and f(b) must have different signs.")
	x1 <- min(a, b); x2 <- max(a,b)
	xm <- (x1+x2)/2.0
	n <- 0
	while (abs(x1-x2)/2.0 > tol) {
		n <- n+1
		if (abs(f(xm)) <= tol) break
		if (f(x1)*f(xm) < 0) {
			x2 <- xm
		} else {
			x1 <- xm
		}
		xm <- (x1+x2)/2.0  # xm <- x1 - f(x1) * (x2-x1) / (f(x2)-f(x1))
		if (n >= maxiter) break
	}
	return(list(root=xm, f.root=f(xm), iter=n, estim.prec=abs(x1-x2)/2.0))
}


regulaFalsi <- function(f, a, b, maxiter=100, tol=.Machine$double.eps^0.5)
#Regula Falsi search for zero of a univariate function in a bounded interval
{
	x1 <- a;      x2 <- b
	f1 <- f(x1);  f2 <- f(x2)
	if (f1*f2 > 0) stop("f(a) and f(b) must have different signs.")

	m <- 0.5                                         # Illinois rule
	niter <- 0
	while (abs(x2-x1) >= tol && niter <= maxiter) {
		niter <- niter + 1
		x3 <- (x1*f2-x2*f1)/(f2-f1); f3 <- f(x3)

		if(f3*f2 < 0) {
			x1 <- x2;  f1 <- f2
			x2 <- x3;  f2 <- f3
		} else {
			# m <- f2/(f2+f3)                         # Pegasus rule
			# m <- if (1-f3/f2 > 0) 1-f3/f2 else 0.5  # Andersen/Bjoerk
			f1 <- m * f1
			x2 <- x3;  f2 <- f3
		}
	}
	if (niter > maxiter && abs(x2-x1) >= tol)
		cat("regulaFalsi stopped without converging.\n")
	return(list(root = x3, f.root = f3, niter = niter, estim.prec = x1-x2))
}


ridder <- function(f, a, b, maxiter = 100, tol = .Machine$double.eps^0.5) {
	x1 <- a;      x2 <- b
	f1 <- f(x1);  f2 <- f(x2)
	if (f1*f2 >= 0) stop("f(a) and f(b) must have different signs.")

    niter <- 2
    while(abs(x1 - x2) > tol && niter < maxiter) {
        xm <- (x1 + x2)/2;  fm <- f(xm)
        if (fm == 0)
            return(list(root = xm, f.root = 0, niter = niter, estim.prec = 0))

        x3 <- xm + (xm - x1) * sign(f1 - f2) * fm / sqrt(fm^2 - f1 * f2)
        f3 <- f(x3);  niter <- niter + 2
        if (f3 == 0)
            return(list(root = x3, f.root = 0, niter = niter, estim.prec = 0))

        if (fm * f3 < 0) {
            x1 <- xm;  f1 <- fm
            x2 <- x3;  f2 <- f3
        } else if (f1 * f3 < 0) {
            x2 <- xm;  f2 <- fm
        } else if (f2 * f3 < 0) {
            x1 <- x3;  f1 <- f3
        } else {
            stop("Inform the maintainer: you should never get here.")
        }
     }

    if (abs(f1) < abs(f2)) {
        x0 <- x1;  f0 <- f1
    } else {
        x0 <- x2;  f0 <- f2
    }
    ep <- abs(x1 - x2)
    return(list(root = x0, f.root = f0, niter = niter, estim.prec = ep))
}
back to top