diff --git a/NEWS.md b/NEWS.md index 87d8c86e..e8f6828a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,13 +3,16 @@ ## Bug fixes * Fixed error when using '-' as a unary operator on a distribution different from - `dist_normal()` by @venpopov (#95) + `dist_normal()` (@venpopov, #95) * Density for transformed distributions now correctly gives 0 instead of NaNs for - values outside the support of the distribution (#97); by @venpopov + values outside the support of the distribution (@venpopov, #97) +* Fixed `quantile()` and `cdf()` for transformed distributions with + monotonically decreasing transformations (#100). ## New features -* support() now shows whether the interval of support is open or closed (#97); by @venpopov +* `support()` now shows whether the interval of support is open or + closed (@venpopov, #97) # distributional 0.4.0 diff --git a/R/transformed.R b/R/transformed.R index c052d08b..56975517 100755 --- a/R/transformed.R +++ b/R/transformed.R @@ -68,6 +68,7 @@ density.dist_transformed <- function(x, at, ...){ cdf.dist_transformed <- function(x, q, ...){ inv <- function(v) suppressWarnings(x[["inverse"]](v)) p <- cdf(x[["dist"]], inv(q), ...) + if(!monotonic_increasing(x[["transform"]], support(x[["dist"]]))) p <- 1 - p limits <- field(support(x), "lim")[[1]] if (!any(is.na(limits))) { p[q <= limits[1]] <- 0 @@ -78,6 +79,7 @@ cdf.dist_transformed <- function(x, q, ...){ #' @export quantile.dist_transformed <- function(x, p, ...){ + if(!monotonic_increasing(x[["transform"]], support(x[["dist"]]))) p <- 1 - p x[["transform"]](quantile(x[["dist"]], p, ...)) } @@ -153,3 +155,9 @@ Ops.dist_transformed <- function(e1, e2) { vec_data(dist_transformed(wrap_dist(list(list(e1,e2)[[which(is_dist)[1]]][["dist"]])), trans, inverse))[[1]] } + +monotonic_increasing <- function(f, support) { + # Currently assumes (without checking, #9) monotonicity of f over the domain + x <- f(field(support, "lim")[[1]]) + x[[2L]] > x[[1L]] +} diff --git a/tests/testthat/test-transformations.R b/tests/testthat/test-transformations.R index 44db6592..8a388605 100644 --- a/tests/testthat/test-transformations.R +++ b/tests/testthat/test-transformations.R @@ -179,3 +179,27 @@ test_that("transformed distributions pdf integrates to 1", { } }) + +test_that("monotonically decreasing transformations (#100)", { + dist <- dist_lognormal() + + expect_equal( + quantile(-dist, 0.2), -quantile(dist, 1 - 0.2) + ) + expect_equal( + quantile(1/dist, 0.2), 1/quantile(dist, 1 - 0.2) + ) + expect_equal( + quantile(-1/dist, 0.7), -1/quantile(dist, 0.7) + ) + + expect_equal( + cdf(-dist, -2), 1 - cdf(dist, 2) + ) + expect_equal( + cdf(1/dist, 2), 1 - cdf(dist, 1/2) + ) + expect_equal( + cdf(-1/dist, -2), cdf(dist, 1/2) + ) +})