library(rstpm2)

## for coping with weird test behaviour from CRAN and R-devel
.CRAN <- FALSE
## pstpm2+frailty models are slow
slow <- FALSE

expect_eps <- function(expr, value, eps=1e-7)
    expect_lt(max(abs(expr-value)),eps)

context("vuniroot")
##
test_that("examples", {
    ## some platforms hit zero exactly on the first step:
    ## if so the estimated precision is 2/3.
    f <- function (x, a) x - a
    xmin <- vuniroot(f, lower=c(0, 0), upper=c(1,1), tol = 0.0001, a = c(1/3,2/3))
    expect_eps(xmin$root, c(1/3,2/3), 1e-10)
    ## handheld calculator example: fixed point of cos(.):
    expect_eps(vuniroot(function(x) cos(x) - x, lower = -pi, upper = pi, tol = 1e-9)$f.root,
               0, 1e-10)
    expect_eps(vuniroot(function(x) x*(x^2-1) + .5, lower = -2, upper = 2,
            tol = 0.0001)$f.root, 0, 1e-5)
    expect_eps(vuniroot(function(x) x*(x^2-1) + .5, lower = -2, upper = 2,
                        tol = 1e-10)$f.root, 0, 1e-10)
    ## Find the smallest value x for which exp(x) > 0 (numerically):
    expect_eps((r <- vuniroot(function(x) 1e80*exp(x) - 1e-300, cbind(-1000, 0), tol = 1e-15))$root,
               -745.133219101941, 1e1)
    ##--- vuniroot() with new interval extension + checking features: --------------
    f1 <- function(x) (121 - x^2)/(x^2+1)
    f2 <- function(x) exp(-x)*(x - 12)
    expect_error(vuniroot(f1, cbind(0,10)),
                 "f[(][)] values at end points not of opposite sign")
    expect_error(vuniroot(f1, cbind(0,2)),
                 "f[(][)] values at end points not of opposite sign")
    ## where as  'extendInt="yes"'  simply first enlarges the search interval:
    u1 <- vuniroot(f1, cbind(0,10),extendInt="yes")
    u2 <- vuniroot(f2, cbind(0,2), extendInt="yes")
    expect_eps(u1$root, 11, 1e-4)
    expect_eps(u2$root, 12, 1e-5)
    ## The *danger* of interval extension:
    ## No way to find a zero of a positive function, but
    ## numerically, f(-|M|) becomes zero :
    expect_error(vuniroot(exp, cbind(0,2), extendInt="yes"),
                 "did not succeed extending the interval endpoints for f[(]lower[)] [*] f[(]upper[)] <= 0")
    ## Nonsense example (must give an error):
    expect_error(vuniroot(function(x) 1, cbind(0,1), extendInt="yes"),
                 "no sign change found in 1000 iterations")
    ## Convergence checking :
    sinc <- function(x) ifelse(x == 0, 1, sin(x)/x)
    expect_warning(vuniroot(sinc, cbind(0,5), extendInt="yes", maxiter=4),
                   "_NOT_ converged in 4 iterations")
    ## now with  check.conv=TRUE, must signal a convergence error :
    expect_error(vuniroot(sinc, cbind(0,5), extendInt="yes", maxiter=4, check.conv=TRUE),
                   "_NOT_ converged in 4 iterations")
    ## Weibull cumulative hazard (example origin, Ravi Varadhan):
    cumhaz <- function(t, a, b) b * (t/b)^a
    froot <- function(x, u, a, b) cumhaz(x, a, b) - u
    set.seed(12345)
    n <- 10
    u <- -log(runif(n))
    a <- 1/2
    b <- 1
    ## Find failure times
    ru <- vuniroot(froot, u=u, a=a, b=b, interval= cbind(rep(1.e-14,n), rep(1e4,n)),
                   extendInt="yes")$root
    ru2 <- vuniroot(froot, u=u, a=a, b=b, interval= cbind(rep(0.01,n), rep(10,n)),
                    extendInt="yes")$root
    expect_eps(ru, ru2, 1e-4)
    r1 <- vuniroot(froot, u= 0.99, a=a, b=b, interval= cbind(0.01, 10),
                   extendInt="up")
    expect_eps(0.99, cumhaz(r1$root, a=a, b=b), 1e-8)
    expect_error(vuniroot(froot, u= 0.99, a=a, b=b, interval= cbind(0.1, 10), extendInt="down"),
                 "no sign change found in 1000 iterations")
})
