tests/testthat/test_W.R

context("Testing Lambert W function\n")

test_that("specific mathematical identities for the W function", {
  
  expect_equal(W(0, branch = 0), 0)
  expect_equal(W(exp(1), branch = 0), 1)
  expect_equal(W(-exp(-1), branch = 0), -1)
  
  # coincide at z = -1
  expect_equal(W(-1, branch = -1), W(-1, branch = 0))
  for (bb in c(0, -1)) {
    # for values z < -1, both branches are NA
    expect_true(all(is.na(W(-c(2:10), branch = bb))))
  }

  expect_equal(W(Inf, branch = 0), Inf)
  
  # At the critical point z = -1, both branches coincide.
  expect_equal(W(-1, branch = -1), W(-1, branch = 0))
  
  #  see also https://en.wikipedia.org/wiki/Lambert_W_function
  pos.vals <- rexp(100)
  # log(W(x)) = log(x) - W(x)
  expect_equal(log(W(pos.vals)), log(pos.vals) - W(pos.vals))
  # W(x) * exp(W(x)) = x
  expect_equal(W(pos.vals) * exp(W(pos.vals)), pos.vals)
})

test_that("W has branch hast length 1, and is either 0 or -1", {
  
  # by default it's branch 0
  expect_equal(W(c(-100, 100)), W(c(-100, 100), branch = 0))
  expect_error(W(0, branch = -2))
  expect_error(W(0, branch = c(0, 0)))
})

test_that("input to W must be numeric", {
  for (vv in list("foo")) {
    expect_error(W(vv))
  }
  
})

test_that("W is inverse of xexp", {
  pos.vals <- rexp(100, rate = 10)
  expect_equal(W(xexp(pos.vals), branch = 0), pos.vals)
  
  neg.vals <- seq(-2, -10)
  expect_equal(W(xexp(neg.vals), branch = -1), neg.vals)
})


test_that("W(z) is asymptotically like log(z)", {
  # after ~exp(4) the ration is converging monotonically from below to 1
  z.vals <- exp(c(4:20))

  W.log.ratio <- W(z.vals) / log(z.vals)
  
  expect_true(all(W.log.ratio > 0))
  expect_true(all(W.log.ratio < 1))
  # monotonically increasing
  expect_true(all(diff(W.log.ratio) > 0))
})

test_that("W throws warning if input is NA or NaN and returns NA; Inf for Inf", {

  expect_equal(W(c(0, Inf)), c(0, Inf))
  
  expect_warning(W(c(1, NaN)))
  expect_equal(W(c(0, NaN)), c(0, NA))
  expect_equal(W(c(NA, 0, NA)), c(NA, 0, NA))

})

test_that("W is vectorized and maintins input dimension", {
  
  data.list <- list("single" = 5,
                    "vector" = cbind(1:5),
                    "matrix" = matrix(rnorm(100), ncol = 2))
  
  for (dd in data.list) {
    expect_equal(dim(dd), dim(W(dd)))
  }
})

Try the LambertW package in your browser

Any scripts or data that you put into this service are public.

LambertW documentation built on Nov. 2, 2023, 6:17 p.m.