# Test the sexpm functions that are used for fast matrix exponentials
#
library(Matrix)
library(survival)
aeq <- function(x, y, ...) all.equal(as.vector(x),as.vector(y), ...)

nfun <- length(sexpm)
times <- c(.1, 1, 5)
test1 <- matrix(FALSE, nfun, length(times), 
                dimnames=list(names(sexpm), paste0("t=", times)))
test2 <- test1
eps <- 1e-8

dtest <- function(x, tmat, time= 1.3, eps=1e-8) {
    # Check a derivative
    if (missing(tmat)) {
        tmat <- matrix(0, x$nstate, x$nstate)
        tmat[x$nonzero] <- runif(length(x$nonzero), .1, 3)
        diag(tmat) <- -rowSums(tmat)
    }       
    else {
        if (!aeq(dim(tmat), c(x$nstate, x$nstate))) stop("invalid tmat")
        diag(tmat) <- diag(tmat) - rowSums(tmat)
    }

    d1 <- x$deriv(tmat, time)
    d2 <- 0*d1
    nz <- x$nonzero
    exp1 <- as.matrix(expm(tmat* time))

    for (j in 1:length(nz)) {
        temp <- tmat
        temp[nz[j]] <- temp[nz[j]] + eps
        diag(temp) <- diag(temp) - rowSums(temp)
        exp2 <- as.matrix(expm(temp* time))
        d2[,,j] <- (exp2 - exp1)/eps
    }       
    list(d1=d1, d2=d2)
}   
    
for (i in 1:nfun) {
    j <- sexpm[[i]]
    tmat <- matrix(0, j$nstate, j$nstate)
    tmat[j$nonzero] <- runif(length(j$nonzero), .1, 4)
    diag(tmat) <- -rowSums(tmat)
    
    dtemp <- logical(length(j$nonzero))
    for (k in 1:length(times)) {
        m1 <- j$mexp(tmat, times[k])
        m2 <- expm(tmat*times[k])
        test1[i,k] <- isTRUE(aeq(m1, as.matrix(m2)))
        # now derivatives
        temp <- dtest(j, tmat, times[k], eps)
        test2[i,k] <- isTRUE(aeq(temp$d1, temp$d2, tol=sqrt(eps)))
    }
}   

all(test1)  # should all be TRUE
all(test2)
