https://github.com/cran/rstpm2
Raw File
Tip revision: a7579fe5c45e3037ff1d25ecf1ed763a91d6ba89 authored by Mark Clements on 05 December 2023, 15:30:02 UTC
version 1.6.3
Tip revision: a7579fe
vuniroot.R
vuniroot <- 
    function (f, interval, ..., lower=pmin(interval[,1], interval[,2]),
              upper=pmax(interval[,1], interval[,2]),
              f.lower = f(lower, ...), f.upper = f(upper, ...),
              extendInt = c("no", "yes", "downX", "upX"),
              check.conv = FALSE, tol = .Machine$double.eps^0.25,
              maxiter = 1000, trace = 0, n=NULL)
{
    if (!missing(interval) && ncol(interval) != 2L)
        stop("'interval' must be a matrix with two columns")
    if (all(!is.numeric(lower) | !is.numeric(upper) | lower >= upper))
        stop("lower < upper  is not fulfilled")
    if (is.null(n) && length(lower) == 1 && length(upper) == 1 && length(f.lower) > 1)
        n <- length(f.lower)
    ## warning("Bounds have length 1: possibly replicate for the bounds to have the correct length")
    if (!is.null(n) && length(lower) == 1 && length(upper) == 1) {
        lower = rep(lower,n)
        upper = rep(upper,n)
        f.lower = f(lower, ...)
        f.upper = f(upper, ...)
    }
    if (any(is.na(f.lower)))
        stop("f.lower = f(lower) is NA at least once")
    if (any(is.na(f.upper)))
        stop("f.upper = f(upper) is NA at least once")
    Sig <- switch(match.arg(extendInt), yes = NULL, downX = -1,
        no = 0, upX = 1, stop("invalid 'extendInt'; please report"))
    truncate <- function(x) pmax.int(pmin(x, .Machine$double.xmax),
                                     -.Machine$double.xmax)
    NAF <- function(x) ifelse(is.na(x),FALSE,x)
    f.low. <- truncate(f.lower)
    f.upp. <- truncate(f.upper)
    fun <- function(x) f(x, ...)
    doX <- (is.null(Sig) && any(f.low. * f.upp. > 0, na.rm=TRUE) ||
            (is.numeric(Sig) &&
             (any(Sig * f.low. > 0, na.rm=TRUE) || any(Sig * f.upp. < 0, na.rm=TRUE))))
    if (doX) {
        if (trace)
            cat(sprintf("search in [%g,%g]%s", lower, upper,
                if (trace >= 2)
                  "\n"
                else " ... "))
        Delta <- function(l,u) 0.01 * cbind(pmax(1e-04, abs(l)), pmax(1e-04, abs(u)))
        it <- 0L
        delta <- Delta(lower, upper)
        if (is.null(Sig)) {
            while (any(i <- NAF(f.lower * f.upper > 0)) &&
                   (any((iFl <- is.finite(lower)) | (iFu <- is.finite(upper))))) {
                       if ((it <- it + 1L) > maxiter)
                           stop(gettextf("no sign change found in %d iterations",
                                         it - 1), domain = NA)
                       if (any(j <- iFl & i)) {
                           ol <- lower[j]
                           of <- f.lower[j]
                           lower[j] <- lower[j] - delta[j,1]
                           f.lower[j] <- fun(lower)[j]
                           if (any(k <- is.na(f.lower[j]))) {
                               lower[j][k] <- ol[k]
                               f.lower[j][k] <- of[k]
                               delta[j,1][k] <- delta[j,1][k]/4
                           }
                       }
                       if (any(j <- iFu & i)) {
                           ol <- upper[j]
                           of <- f.upper[j]
                           upper[j] <- upper[j] + delta[j,2]
                           f.upper[j] <- fun(upper)[j]
                           if (any(k <- is.na(f.upper[j]))) {
                               upper[j][k] <- ol[k]
                               f.upper[j][k] <- of[k]
                               delta[j,2][k] <- delta[j,2][k]/4
                           }
                       }
                       if (trace >= 2)
                           cat(sprintf(" .. modified lower,upper: (%15g,%15g)\n",
                                       lower, upper))
                       delta[i & (iFl | iFu)] <- 2 * delta[i & (iFl | iFu)]
                   }
        }
        else {
            while (any(i <- NAF(Sig * f.lower > 0))) {
                if ((it <- it + 1L) > maxiter)
                    stop(gettextf("no sign change found in %d iterations",
                                  it - 1), domain = NA)
                lower[i] <- lower[i]-delta[i,1]
                f.lower[i] <- fun(lower)[i]
                if (trace >= 2)
                    cat(sprintf(" .. modified lower: %g\n", lower))
                delta[i] <- 2 * delta[i]
            }
            while (any(i <- NAF(Sig * f.upper < 0))) {
                if ((it <- it + 1L) > maxiter)
                    stop(gettextf("no sign change found in %d iterations",
                                  it - 1), domain = NA)
                upper[i] <- upper[i] + delta[i,2]
                f.upper[i] <- f(upper, ...)[i]
                if (trace >= 2)
                    cat(sprintf(" .. modified upper: %g\n", upper))
                delta[i] <- 2 * delta[i]
            }
        }
        if (trace && trace < 2)
            cat(sprintf("extended to [%g, %g] in %d steps\n",
                lower, upper, it))
    }
    if (any(!NAF(as.vector(f.lower * f.upper <= 0))))
        stop(if (doX)
                 "did not succeed extending the interval endpoints for f(lower) * f(upper) <= 0"
             else "f() values at end points not of opposite sign")
    if (check.conv) {
        val <- tryCatch(.Call("vunirootRcpp", fun, lower, upper, f.lower, f.upper, maxiter, tol, PACKAGE="rstpm2"),
                        warning = function(w) w)
        if (inherits(val, "warning")) 
            stop("convergence problem in zero finding: ", conditionMessage(val))
    }
    else {
        val <- .Call("vunirootRcpp", fun, lower, upper, f.lower, f.upper, as.integer(maxiter), tol, PACKAGE="rstpm2")
    }
    iter <- as.integer(val[[2L]])
    if (any(iter < 0)) {
        (if (check.conv) 
             stop
         else warning)(sprintf(ngettext(maxiter, "_NOT_ converged in %d iteration",
                                        "_NOT_ converged in %d iterations"), maxiter), domain = NA)
        iter[iter<0] <- maxiter
    }
    if (doX)
        iter <- iter + it
    else it <- NA_integer_
    list(root = val[[1L]], f.root = f(val[[1L]], ...), iter = iter,
         init.it = it, estim.prec = val[[3L]])
}

voptimize <- function (f, interval, ...,
                       lower=pmin(interval[,1], interval[,2]),
                       upper=pmax(interval[,1], interval[,2]),
                       maximum = FALSE, tol = .Machine$double.eps^0.25) 
{
    if (maximum) {
        val <- .Call("voptimizeRcpp", function(arg) -f(arg, ...), 
                     lower, upper, tol, PACKAGE="rstpm2")
        list(maximum = val, objective = f(val, ...))
    }
    else {
        val <- .Call("voptimizeRcpp", function(arg) f(arg, ...), 
            lower, upper, tol, PACKAGE="rstpm2")
        list(minimum = val, objective = f(val, ...))
    }
}

voptimise <- voptimize

vintegrate = function(f, lower, upper, ..., subdivisions = 100L, rel.tol=.Machine$double.eps^0.25,
                       abs.tol=rel.tol) {
    f <- match.fun(f)
    ff <- function(x) f(x, ...)
    ny = max(length(lower), length(upper))
    if (ny>1 && length(lower)==1) lower = rep(lower,ny)
    if (ny>1 && length(upper)==1) upper = rep(upper,ny)
    limit <- as.integer(subdivisions)
    if (limit < 1L || (abs.tol <= 0 && rel.tol < max(50 * .Machine$double.eps, 
                                                     5e-29))) 
        stop("invalid parameter values")
    if (any(is.na(lower) | is.na(upper)))
        stop("a limit is NA or NaN")
    if (!(all(is.finite(lower)) || all(!is.finite(lower))))
        stop("lower bounds are a mix of finite and infinite values")
    if (!(all(is.finite(upper)) || all(!is.finite(upper))))
        stop("upper bounds are a mix of finite and infinite values")
    if (all(is.finite(lower)) && all(is.finite(upper))) {
        res = vdqagsRcpp(ff, lower, upper, rel.tol, abs.tol, limit, ny)
        res$value = drop(res$value)
        res$abs.err = drop(res$abs.err)
        res$abserr = NULL
    } else {
        if (all(is.finite(lower))) {
            inf <- 1L
            bound <- lower
        }
        else if (all(is.finite(upper))) {
            inf <- -1L
            bound <- upper
        }
        else {
            inf <- 2L
            bound <- rep(0,ny) # ignored:)
        }
        res = vdqagiRcpp(ff, bound, inf, rel.tol, abs.tol, limit, ny)
        res$value = drop(res$value)
        res$abserr = drop(res$abserr)
    }
    res
}

back to top