Nothing
##### interval class
### FIXME: actually, multi-intervals -> change class name?
## FIXME: which functions should convert their arguments via
## as.interval?
## constructors
## FIXME: allow for "boxes" (dimensionality > 1)?
## FIXME: what should interval() / integers() etc. return: the domain,
## or an empty set? Currently, intergers/reals/naturals return the domain,
## interval the empty interval.
"%..%" <-
integers <-
function(l = NULL, r = NULL)
{
if (is.null(l)) l <- -Inf
if (is.null(r)) r <- Inf
if (!is.numeric(l) || !is.numeric(r))
stop("Need numeric bounds.")
l <- round(l)
r <- round(r)
interval(l = l, r = r, domain = "Z")
}
naturals <-
function(l = NULL, r = NULL)
{
if (is.null(l)) l <- 1
if (is.null(r)) r <- Inf
if (!is.numeric(l) || !is.numeric(r))
stop("Need numeric bounds.")
l <- round(l)
r <- round(r)
if (l < 1L) stop("Positive integers start with 1.")
interval(l = l, r = r, domain = "N")
}
naturals0 <-
function(l = NULL, r = NULL)
{
if (is.null(l)) l <- 0
if (is.null(r)) r <- Inf
if (!is.numeric(l) || !is.numeric(r))
stop("Need numeric bounds.")
l <- round(l)
r <- round(r)
if (l < 0) stop("Non-negative integers start with 0.")
interval(l = l, r = r, domain = "N0")
}
reals <-
function(l = NULL, r = NULL,
bounds = c("[]", "[)", "(]", "()",
"[[", "]]", "][",
"open", "closed", "left-open", "right-open",
"left-closed", "right-closed")
)
{
if (is.null(l)) l <- -Inf
if (is.null(r)) r <- Inf
if (!is.numeric(l) || !is.numeric(r))
stop("Need numeric bounds.")
interval(l = l, r = r, bounds = bounds, domain = "R")
}
interval <-
function(l = NULL, r = l,
bounds = c("[]", "[)", "(]", "()",
"[[", "]]", "][",
"open", "closed", "left-open", "right-open",
"left-closed", "right-closed"),
domain = NULL)
{
## bounds
bounds <- match.arg(bounds)
bounds <- switch(bounds,
"open"=, "]["= "()", "closed"= "[]",
"left-open"=, "right-closed"=, "]]"= "(]",
"right-open"=, "left-closed"=, "[["= "[)", bounds)
## check for empty interval
if (is.null(l) || is.null(r) || r < l ||
isTRUE(all.equal(l, r)) && bounds != "[]")
return(.empty_interval())
## domain
if (is.null(domain)) {
## guess domain from mode
domain <- if ((is.double(l) || is.double(r)) &&
!(is.integer(l) && is.infinite(r)) &&
!(is.integer(r) && is.infinite(l)))
"R"
else if (l > 0)
"N"
else if (l > -1L)
"N0"
else
"Z"
} else {
## enforce domain
domain <- match.arg(domain, c("R", "Z", "N", "N0"))
if (domain == "R") {
l <- as.double(l)
r <- as.double(r)
} else {
l <- round(l)
r <- round(r)
if (domain == "N" && l < 1L)
stop("Positive integers start with 1.")
if (domain == "N0" && l < 0)
stop("Non-negative integers start with 0.")
}
}
if (!is.numeric(l) || !is.numeric(r))
stop("Need numeric bounds.")
## create interval
.make_interval_from_list_and_domain(list(list(l = l, r = r,
lc = substr(bounds, 1L, 1L) == "[",
rc = substr(bounds, 2L, 2L) == "]"
)
),
domain = domain
)
}
## subsetting
`[.interval` <-
function(x, i)
{
i <- i[i <= length(x)]
.make_interval_from_list_and_domain(NextMethod(), interval_domain(x))
}
## subscripting
## FIXME: should that be the same than subsetting?
`[[.interval` <-
function(x, i)
.make_interval_from_list_and_domain(list(NextMethod()), interval_domain(x))
## union = combine
interval_union <-
function(...) c.interval(...)
c.interval <-
function(...)
{
## coerce to intervals
l <- lapply(list(...), as.interval)
## remove empty intervals
l <- l[!sapply(l, interval_is_empty)]
if (length(l) < 1L) return(.empty_interval())
## check domains
dom <- .maximal_domain(l)
## split countable intervals, if any uncountable exists
countables <- sapply(l, interval_is_countable)
if (any(countables) && !all(countables))
l[countables] <- lapply(l[countables], integers2reals)
l <- unlist(l, recursive = FALSE)
## canonicalize
.make_interval_from_list_and_domain(.canonicalize_interval(l, dom == "R"),
domain = dom)
}
## complement
interval_complement <-
function(x, y = NULL)
{
x <- as.interval(x)
x_is_c <- interval_is_countable(x)
if (!is.null(y)) {
y <- as.interval(y)
y_is_c <- interval_is_countable(y)
## trivial cases
if (interval_is_empty(y) || interval_is_empty(x))
return(y)
## promote/reduce x, depending on y
if (x_is_c && !y_is_c)
x <- integers2reals(x, min(y), max(y))
if (!x_is_c && y_is_c)
x <- reals2integers(x)
attr(x, "domain") <- attr(y, "domain")
return(interval_complement(interval_union(x, interval_complement(y))))
}
if (interval_is_empty(x))
return(reals())
dom <- interval_domain(x)
i_is_c <- interval_is_countable(x)
## bounded parts
len <- length.interval(x)
l <- if (len > 1L)
lapply(seq_len(len - 1L),
function(i) list(l = max(x[[i]]) + x_is_c,
r = min(x[[i + 1L]]) - x_is_c,
lc = x_is_c || interval_is_right_open(x[[i]]),
rc = x_is_c || interval_is_left_open(x[[i + 1L]])
)
)
else
list()
## unbounded parts
if (dom %in% c("R","Z") && interval_is_left_bounded(x) ||
dom == "N" && min(x) > 1L ||
dom == "N0" && min(x) > 0L)
l <- c(list(list(l = if (dom == "N0") 0 else if (dom == "N") 1 else -Inf,
r = min(x) - x_is_c,
lc = TRUE,
rc = x_is_c || interval_is_left_open(x)
)
),
l
)
if (interval_is_right_bounded(x))
l <- c(l,
list(list(l = max(x) + x_is_c,
r = +Inf,
rc = TRUE,
lc = x_is_c || interval_is_right_open(x)
)
)
)
.make_interval_from_list_and_domain(l, domain = dom)
}
## intersection
interval_intersection <-
function(...)
{
## coerce
len <- length(l <- lapply(list(...), as.interval))
## trivial case
if (any(sapply(l, interval_is_empty)))
return(.empty_interval())
## find minimal domain
dom <- .minimal_domain(l)
Dom <- switch(dom, N = naturals(), N0 = naturals0(), Z = integers(), reals())
## check for mixture of countables and uncountables
uc <- sapply(l, interval_is_uncountable)
if (any(uc) && !all(uc))
l[uc] <- lapply(l[uc], reals2integers)
## workhorse
IS <- function(x, y)
interval_complement(interval_union(interval_complement(x),
interval_complement(y),
if (dom == "N") integers(-Inf, 0),
if (dom == "N0") integers(-Inf, -1)
),
Dom)
## reduce
if (len < 1L)
.empty_interval()
else if (len < 2L)
l[[1L]]
else
Reduce(IS, l)
}
## symdiff
interval_symdiff <-
function(...)
{
len <- length(l <- lapply(list(...), as.interval))
SD <- function(x, y) interval_union(interval_complement(x, y),
interval_complement(y, x))
if (len < 1L)
.empty_interval()
else if (len < 2L)
l[[1L]]
else
Reduce(SD, l)
}
## length
length.interval <-
function(x)
length(unclass(x))
interval_measure <-
function(x)
sum(sapply(unclass(x), `[[`, "r") - sapply(unclass(x), `[[`, "l"))
## Summary methods
## FIXME: min/max not defined for open intervals??
## -> we actually compute the infimum / supremum here.
min.interval <-
function(...)
{
l <- list(...)
l <- unclass(do.call(c, l[-length(l)]))
l[[1L]]$l
}
max.interval <-
function(...)
{
l <- list(...)
l <- unclass(do.call(c, l[-length(l)]))
l[[length(l)]]$r
}
range.interval <- function(...) c(min(...), max(...))
sum.interval <-
function(...)
{
l <- list(...)
do.call(interval_sum, l[-length(l)])
}
prod.interval <-
function(...)
{
l <- list(...)
do.call(interval_product, l[-length(l)])
}
mean.interval <-
function(...)
{
l <- list(...)
do.call(interval_sum, l) / length(l)
}
## operators
Ops.interval <-
function(e1, e2)
{
if (nargs() == 1L) {
if(!((ch <- as.character(.Generic)) %in% c("-", "!")))
stop(gettextf("Unary '%s' not defined for \"%s\" objects.",
.Generic, .Class),
domain = NA)
if (ch == "!")
return(interval_complement(e1))
else
return(0L-e1)
}
if(!(as.character(.Generic)
%in% c("<", "<=", ">", ">=", "==", "!=",
"&", "|", "*", "+", "-", "/", "^")))
stop(gettextf("Generic '%s' not defined for \"%s\" objects.",
.Generic, .Class),
domain = NA)
switch(.Generic,
"|" = interval_union(e1, e2),
"&" = interval_intersection(e1, e2),
"+" = interval_sum(e1, e2),
"-" = interval_difference(e1, e2),
"*" = interval_product(e1, e2),
"/" = interval_division(e1, e2),
"<" = interval_is_proper_subinterval(e1, e2),
"<=" = interval_is_subinterval(e1, e2),
">" = interval_is_proper_subinterval(e2, e1),
">=" = interval_is_subinterval(e2, e1),
"==" = interval_is_equal(e1, e2),
"!=" = !interval_is_equal(e1, e2),
"^" = if (is.interval(e1) && is.numeric(e2))
interval_power(e1, e2)
else if (min(e1) > 0)
exp(log(e1) * e2)
else stop("Exponentiation undefined for negative base.")
)
}
abs.interval <-
function(x)
{
dom <- interval_domain(x)
FUN <- function(i) if (i$l >= 0)
.make_interval_from_list_and_domain(list(i), dom)
else if (i$r <= 0)
.make_interval_from_list_and_domain(list(list(l = abs(i$r),
r = abs(i$l),
lc = i$rc,
rc = i$lc
)
),
domain = dom
)
else
.make_interval_from_list_and_domain(list(list(l = 0,
r = max(abs(i$l), i$r),
lc = TRUE,
rc = if (abs(i$l) > i$r) i$lc else i$rc
)
),
domain = dom
)
do.call(c.interval, lapply(unclass(x), FUN))
}
Math.interval <-
function(x, ...)
{
if (.Generic %in% c("log", "sqrt") && min(x) < 0)
stop(.Generic, " only defined for positive reals.")
if (!.Generic %in% c("sqrt", "exp", "log", "log2", "log10",
"trunc", "round", "ceiling", "floor",
"sin", "cos", "tan", "asin", "acos", "atan"))
stop(.Generic, " not implemented for intervals.")
dom <- interval_domain(x)
FUN <- if (dom == "R")
function(i) {
if (.Generic %in% c("sin", "cos", "tan")) {
if (.Generic %in% c("sin", "cos") &&
(i$r - i$l > 2 * pi ||
isTRUE(all.equal(i$r - i$l, 2 * pi)))) {
l <- -1
r <- 1
} else if (.Generic == "tan" &&
(i$r - i$l > pi ||
isTRUE(all.equal(i$r - i$l, pi)))) {
l <- -Inf
r <- Inf
} else {
shift <- ceiling(i$l / (2 * pi)) * 2 * pi
l <- i$l - shift
r <- i$r - shift
p <- pi * -3:3 / 2
fp <- p[p > l & p < r |
sapply(p, function(i) isTRUE(all.equal(i, l))) |
sapply(p, function(i) isTRUE(all.equal(i, r)))]
x <- get(.Generic)(c(l, fp, r))
l <- min(x)
r <- max(x)
}
} else if (.Generic == "acos") { ## cos is monotonic decreasing
l <- get(.Generic)(i$r, ...)
r <- get(.Generic)(i$l, ...)
} else { ## all monotonic increasing funs
l <- get(.Generic)(i$l, ...)
r <- get(.Generic)(i$r, ...)
}
ret <- .make_interval_from_list_and_domain(list(list(l = l,
r = r,
lc = i$lc,
rc = i$rc
)
),
domain = dom
)
## dicretize for rounding functions
if (.Generic %in% c("trunc", "round", "floor")) {
digits <- list(...)
if (.Generic != "round" || !length(digits))
digits <- 0
ret <- do.call(c.interval,
as.list(seq.int(unclass(ret)[[1]]$l,
unclass(ret)[[1]]$r,
by = 10 ^ -digits[[1]])))
}
ret
} else
function(i) as.interval(lapply(seq.int(i$l, i$r), .Generic, ...))
do.call(c.interval, lapply(unclass(x), FUN))
}
## interval arithmetic
.interval_ops <-
function(l, OP)
{
len <- length(l <- lapply(unclass(l),
function(i) integers2reals(as.interval(i))))
FUN <- function(x, y)
do.call(c.interval, set_outer(unclass(x), unclass(y), OP))
if (len < 1L)
.empty_interval()
else if (len < 2L)
l[[1L]]
else
Reduce(FUN, unclass(l))
}
.bounds <- function(x, y)
c("()", "[)", "(]", "[]")[1 + x + 2 * y]
interval_sum <-
function(...)
{
FUN <- function(x, y)
interval(x$l + y$l, x$r + y$r,
.bounds(x$lc && y$lc, x$rc && y$rc))
.interval_ops(list(...), FUN)
}
interval_difference <-
function(...)
{
FUN <- function(x, y)
interval(x$l - y$r, x$r - y$l,
.bounds(x$lc && y$rc, x$rc && y$lc))
.interval_ops(list(...), FUN)
}
interval_product <-
function(...)
{
FUN <- function(x, y) {
p <- c(x$l * y$l, x$l * y$r, x$r * y$l, x$r * y$r)
b <- c(x$lc && y$lc, x$lc && y$rc, x$rc && y$lc, x$rc && y$rc)
mi <- which.min(p)
ma <- which.max(p)
interval(p[mi], p[ma], .bounds(b[mi], b[ma]))
}
.interval_ops(list(...), FUN)
}
interval_division <-
function(...)
{
FUN <- function(x, y) {
if (0 < y$l || 0 > y$r)
interval_product(interval(x$l, x$r, .bounds(x$lc, x$rc)),
interval(1 / y$r, 1 / y$l, .bounds(y$rc, y$lc)))
else if (x$l < 0 && 0 < x$r && y$l <= 0 && 0 <= y$r ||
y$l == 0 && y$r == 0)
reals()
else if (x$r <= 0 && y$l < 0 && y$r == 0)
interval(x$r / y$l, Inf, .bounds(x$rc && y$lc, TRUE))
else if (x$r <= 0 && y$l < 0 && 0 < y$r)
c.interval(interval(-Inf, x$r / y$r, .bounds(TRUE, x$rc && y$rc)),
interval(x$r / y$l, Inf, .bounds(x$rc && y$lc, TRUE)))
else if (x$r <= 0 && y$r > 0 && y$l == 0)
interval(-Inf, x$r / y$r, .bounds(TRUE, x$rc && y$rc))
else if (x$l >= 0 && y$l < 0 && y$r == 0)
interval(-Inf, x$l / y$l, .bounds(TRUE, x$lc && y$lc))
else if (x$l >= 0 && y$l < 0 && 0 < y$r)
c.interval(interval(-Inf, x$l / y$l, .bounds(TRUE, x$lc && y$lc)),
interval(x$l / y$r, Inf, .bounds(x$lc && y$rc, TRUE)))
else if (x$l >= 0 && y$r > 0 && y$l == 0)
interval(x$l / y$r, Inf, .bounds(x$lc && y$rc, TRUE))
else
stop("This should not happen.")
}
.interval_ops(list(...), FUN)
}
interval_power <-
function(x, n)
{
x <- as.interval(x)
if (!isTRUE(all.equal(as.integer(n), n)))
stop("Power of intervals only defined for integer exponents.")
if (n == 0)
return(reals(1,1))
if (n < 0)
return(1 / interval_power(x, abs(n)))
FUN <- function(X)
{
if (n %% 2 == 0 && (X$l < 0 || X$r < 0))
interval_power(abs(x), n)
else
.make_interval_from_list_and_domain(list(list(l = X$l ^ n,
r = X$r ^ n,
lc = X$lc,
rc = X$rc
)
),
interval_domain(x)
)
}
do.call(c.interval, lapply(unclass(x), FUN))
}
## coercing functions
integers2reals <-
function(x, min = -Inf, max = Inf)
{
if(interval_is_uncountable(x)) return(x)
## split
x <- unlist(lapply(unclass(x),
function(i) unlist(lapply(seq.int(from = max(i$l, min),
to = min(i$r, max)),
interval),
recursive = FALSE)
),
recursive = FALSE)
## canonicalize
.make_interval_from_list_and_domain(.canonicalize_interval(x, reals = TRUE),
"R")
}
reals2integers <-
function(x)
{
if(interval_is_countable(x)) return(x)
x <- unclass(x)
for(i in seq_along(x)) {
X <- x[[i]]
if (!X$lc || X$l != round(X$l)) X$l <- floor(X$l) + 1
if (!X$rc || X$r != round(X$r)) X$r <- trunc(X$r)
if (X$r < X$l)
X <- NULL
else
X$lc <- X$rc <- TRUE
x[[i]] <- X
}
## canonicalize
.make_interval_from_list_and_domain(.canonicalize_interval(x, reals = FALSE),
domain = "Z")
}
as.character.interval <-
function(x, ...)
{
if (length.interval(x) < 1L)
return("{}")
if (interval_is_uncountable(x)) {
bounds <- if (sets_options("openbounds") == "][")
c("]", "[", "[", "]")
else
c("(", "[", ")", "]")
## merge adjacent degenerate intervals into sets
.merge = function(x, y) {
i = length(x)
X <- x[[i]]
Y <- y[[1]]
if ((is.set(X) || isTRUE(all.equal(X$l, X$r))) &&
isTRUE(all.equal(Y$l, Y$r))) {
if (!is.set(X)) X <- set(X$l)
c(x[-i], list(c(X, Y$l)))
} else
c(x, y)
}
l <- Reduce(.merge, lapply(unclass(x), list))
## format individual interval
.format <- function(x) {
if (is.set(x))
format(x)
else if (isTRUE(all.equal(x$l, x$r)))
paste("{", as.character(x$l), "}", sep = "")
else
paste(bounds[1 + x$lc], x$l, ", ", x$r,
bounds[3 + x$rc], sep = "")
}
paste(sapply(unclass(l), .format), collapse = " U ")
} else {
.format <- function(x)
if (x$l == x$r) x$l else paste(x$l, "..", x$r, sep = "")
paste(sapply(unclass(x), .format), collapse = ", ")
}
}
as.interval <-
function(x)
UseMethod("as.interval")
as.interval.default <- function(x) stop("Not implemented.")
as.interval.numeric <-
function(x)
{
if (all(is.finite(x)) && isTRUE(all.equal(as.integer(x), x)))
return(do.call(c.interval, lapply(unclass(x),
function(i) integers(i, i))))
else
reals(min(x, na.rm = TRUE), max(x, na.rm = TRUE))
}
as.interval.interval <- function(x) x
as.interval.set <- function(x) as.interval(unclass(x))
as.interval.list <- function(x) do.call(c.interval, x)
as.interval.tuple <- function(x) interval(x[[1]], x[[2]])
as.interval.logical <-
as.interval.NULL <- function(x) .empty_interval()
as.vector.interval <-
function(x, ...)
as.list.interval(x, ...)
as.list.interval <-
function(x, ...)
lapply(seq_along(x), function(i) x[[i]])
make_set_with_order.interval <-
function(x) {
if (interval_domain(x) == "R") {
FUN <- function(i)
if (isTRUE(all.equal(i$l, i$r))) i$l else pair(i$l, i$r)
.make_set_with_order(.make_set_from_list(lapply(unclass(x), FUN)))
} else {
.make_set_with_order(.make_set_from_list(unlist(lapply(unclass(x),
function(i) seq.int(i$l, i$r)))))
}
}
as.double.interval <-
function(x, ...) {
if (length.interval(x) < 1L)
return(NULL)
r <- range(x)
x <- as.list(reals2integers(x))
if (r[1] == -Inf) x <- x[-1]
l <- length(x)
if (l > 0L && r[2] == Inf) x <- x[-l]
unlist(lapply(unclass(x), function(i) seq.int(i$l, i$r)))
}
### print and summary stuff
print.interval <-
function(x, ...)
{
writeLines(as.character(x))
invisible(x)
}
summary.interval <-
function(object, ...)
{
len <- length.interval(object)
uc <- interval_is_uncountable(object)
out <- if (len < 1L)
gettext("The empty interval.")
else if (len < 2L) {
if (uc)
gettext("An interval.")
else
gettext("A sequence.")
} else {
if (uc)
gettextf("A union of %d disjoint intervals.", len)
else
gettextf("A union of %d sequences.", len)
}
.structure(out, class = "summary.interval")
}
print.summary.interval <-
function(x, ...)
{
writeLines(x)
invisible(x)
}
format.interval <-
function(x, ...)
as.character(x)
## extractors
interval_domain <-
function(x)
attr(as.interval(x), "domain")
### predicates
interval_is_uncountable <-
function(x)
interval_domain(x) == "R"
interval_is_countable <- Negate(interval_is_uncountable)
interval_is_bounded <-
interval_is_finite <-
function(x)
interval_is_left_bounded(x) && interval_is_right_bounded(x)
interval_is_left_bounded <-
function(x)
is.finite(min(x)) || interval_is_left_open(x)
interval_is_right_bounded <-
function(x)
is.finite(max(x)) || interval_is_right_open(x)
interval_is_left_unbounded <-
function(x)
interval_is_left_closed(x) && is.infinite(min(x))
interval_is_right_unbounded <-
function(x)
interval_is_right_closed(x) && is.infinite(max(x))
interval_is_unbounded <-
function(x)
interval_is_left_unbounded(x) && interval_is_right_unbounded(x)
interval_is_half_bounded <-
function(x)
xor(interval_is_left_bounded(x), interval_is_right_bounded(x))
interval_is_degenerate <-
function(x)
interval_is_empty(x) || isTRUE(all.equal(min(x), max(x)))
interval_is_proper <- Negate(interval_is_degenerate)
interval_is_empty <-
function(x)
length.interval(x) < 1L
interval_is_closed <-
function(x)
interval_is_left_closed(x) && interval_is_right_closed(x)
interval_is_left_closed <-
function(x)
unclass(as.interval(x))[[1]]$lc
interval_is_right_closed <-
function(x) {
x <- as.interval(x)
i <- length.interval(x)
unclass(x)[[i]]$rc
}
interval_is_left_open <- Negate(interval_is_left_closed)
interval_is_right_open <- Negate(interval_is_right_closed)
interval_is_equal <-
function(x, y)
{
x <- as.interval(x)
y <- as.interval(y)
ctbls <- interval_is_countable(x) && interval_is_countable(y)
uc <- interval_is_uncountable(x) && interval_is_uncountable(y)
x <- unclass(x)
y <- unclass(y)
length(x) == length(y) && (ctbls || uc) &&
isTRUE(all.equal(sapply(x, `[[`, "l"), sapply(y, `[[`, "l"))) &&
isTRUE(all.equal(sapply(x, `[[`, "r"), sapply(y, `[[`, "r"))) &&
(ctbls || all(sapply(x, `[[`, "lc") == sapply(y, `[[`, "lc")) &&
all(sapply(x, `[[`, "rc") == sapply(y, `[[`, "rc")))
}
"%<%" <-
interval_is_less_than <-
function(x, y)
{
mx <- max(x)
my <- min(y)
mx < my ||
mx == my && (interval_is_right_open(x) || interval_is_left_open(y))
}
"%>%" <-
interval_is_greater_than <-
function(x, y)
{
mx <- min(x)
my <- max(y)
mx > my ||
mx == my && (interval_is_right_open(x) || interval_is_left_open(y))
}
"%<=%" <-
interval_is_less_than_or_equal <-
function(x, y)
max(x) <= min(y)
"%>=%" <-
interval_is_greater_than_or_equal <-
function(x, y)
min(x) >= max(y)
interval_is_proper_subinterval <-
function(x, y)
interval_is_subinterval(x, y) && !interval_is_equal(x, y)
interval_is_subinterval <-
function(x, y)
{
x <- as.interval(x)
y <- as.interval(y)
## trivial cases
if (interval_is_empty(x))
return(TRUE)
if (interval_is_empty(y))
return(FALSE)
if (interval_is_uncountable(x) &&
interval_is_proper(x) &&
interval_is_countable(y))
return(FALSE)
## FIXME: is Real(Inf) == Integer(Inf)?
## check if bounds are nested
if (min(x) < min(y) || max(x) > max(y))
return(FALSE)
## check each element in x against y
uc <- interval_is_uncountable(x) || interval_is_uncountable(y)
l <- length(y <- unclass(y))
j <- 1
.not_contained <-
function(a, b) {
a$l < b$l || a$r > b$r ||
uc && (isTRUE(all.equal(a$l, b$l)) && a$lc && !b$lc ||
isTRUE(all.equal(a$r, b$r)) && a$rc && !b$rc)
}
for (i in x) {
while (.not_contained(i, y[[j]])) {
j <- j + 1
if (j > l) return(FALSE)
}
}
TRUE
}
interval_contains_element <-
function(x, y)
interval_is_subinterval(y, x)
is.interval <- function(x) inherits(x, "interval")
## str method
str.interval <- function(object, ...) str(unclass(object), ...)
### internal functions
.empty_interval <-
function()
.make_interval_from_list_and_domain(list(), NA)
.make_interval_from_list_and_domain <- function(x, domain = "R")
.structure(x, class = "interval", domain = domain)
.sort_interval <-
function(x)
x[order(sapply(unclass(x), `[[`, "l"), sapply(unclass(x), `[[`, "r"))]
.merge_uncountables <-
function(x, y)
{
len <- length(x)
if (len < 1L) return(y)
if (length(y) < 1L) return(x)
X <- x[[len]]
Y <- y[[1L]]
if (Y$l < X$r || isTRUE(all.equal(Y$l, X$r)) && (X$rc || Y$lc)) {
## X and Y overlap
if (isTRUE(all.equal(Y$l, X$l)) && (X$lc != Y$lc))
## X left-open, but Y left-closed -> left-close X
X$lc <- TRUE
if (Y$r < X$r || isTRUE(all.equal(Y$r, X$r)) && (!Y$rc || X$rc)) {
## Y included in X -> discard Y
c(x[-len], list(X))
} else {
## true overlap -> merge X and Y
Y$l <- X$l
Y$lc <- X$lc
c(x[-len], list(Y))
}
} else c(x, y) ## X and Y are disjoint -> return both
}
.merge_countables <-
function(x, y)
{
len <- length(x)
if (len < 1L) return(y)
if (length(y) < 1L) return(x)
X <- x[[len]]
Y <- y[[1L]]
if (Y$l - X$r < 2L) {
## X and Y overlap
if (Y$r <= X$r)
## Y included in X -> discard Y
c(x[-len], list(X))
else {
## true overlap -> merge X and Y
Y$l <- X$l
c(x[-len], list(Y))
}
} else c(x, y) ## X and Y are disjoint -> return both
}
.simplify_interval <-
function(x, reals = TRUE)
{
Reduce(if (reals) .merge_uncountables else .merge_countables,
lapply(unclass(x), list))
}
.canonicalize_interval <-
function(x, reals = TRUE)
.simplify_interval(.sort_interval(x), reals = reals)
.minimal_domain <-
function(l)
{
dom <- rep.int(sapply(l, interval_domain), sapply(l, length.interval))
if (any(dom == "N"))
"N"
else if (any(dom == "N0"))
"N0"
else if (any(dom == "Z"))
"Z"
else
"R"
}
.maximal_domain <-
function(l)
{
dom <- rep.int(sapply(l, interval_domain), sapply(l, length.interval))
if (any(dom == "R"))
"R"
else if (any(dom == "Z"))
"Z"
else if (any(dom == "N0"))
"N0"
else
"N"
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.