R/assert.R

Defines functions .stopf .is_scalar_whole .is_whole .all_negative_or_na .all_positive_or_na .all_negative .all_positive .all_non_positive .all_non_negative .all_non_positive_or_na .all_non_negative_or_na assert_between assert_negative_or_na assert_positive_or_na assert_negative assert_positive assert_non_positive assert_non_negative assert_non_positive_or_na assert_non_negative_or_na assert_scalar_character_not_na assert_scalar_character assert_bool assert_scalar_whole assert_scalar_logical_not_na assert_scalar_logical assert_scalar_numeric_not_na assert_scalar_numeric assert_scalar_double_not_na assert_scalar_double assert_scalar_integer_not_na assert_scalar_integer assert_whole assert_list assert_data_frame assert_character_not_na assert_character assert_logical_not_na assert_logical assert_numeric_not_na assert_numeric assert_double_not_na assert_double assert_integer_not_na assert_integer

Documented in assert_between assert_bool assert_character assert_character_not_na assert_data_frame assert_double assert_double_not_na assert_integer assert_integer_not_na assert_list assert_logical assert_logical_not_na assert_negative assert_negative_or_na assert_non_negative assert_non_negative_or_na assert_non_positive assert_non_positive_or_na assert_numeric assert_numeric_not_na assert_positive assert_positive_or_na assert_scalar_character assert_scalar_character_not_na assert_scalar_double assert_scalar_double_not_na assert_scalar_integer assert_scalar_integer_not_na assert_scalar_logical assert_scalar_logical_not_na assert_scalar_numeric assert_scalar_numeric_not_na assert_scalar_whole assert_whole

#' Argument assertions (Experimental)
#'
# -------------------------------------------------------------------------
#' Assertions for function arguments. Motivated by assertions from the vctrs
#' package but with lower overhead at a cost of less informative error messages.
#' Designed to make it easy to identify the top level calling function whether
#' used within a user facing function or internally. They are somewhat
#' experimental in nature and should be treated accordingly.
#'
# -------------------------------------------------------------------------
#' @param x
#'
#' Argument to check.
#'
#' @param .arg `[character]`
#'
#' Name of argument being checked (used in error message).
#'
#' @param .call `[call]`
#'
#' Call to use in error message.
#'
#' @param .subclass `[character]`
#'
#' The (optional) subclass of the returned error condition.
#'
#' @param lower `[numeric]`
#'
#' The lower bound to compare against.
#'
#' @param upper `[numeric]`
#'
#' The upper bound to compare against.
#'
#' @param left_inclusive `[bool]`
#'
#' Should the left (lower) bound be compared inclusively (`<=`) or exclusive (`<`).
#'
#' @param right_inclusive `[bool]`
#'
#' Should the right (upper) bound be compared inclusively (`>=`) or exclusive (`>`).
#'
# -------------------------------------------------------------------------
#' @return
#'
#' If the assertion succeeds then the input is returned invisibly.
#'
#' Otherwise and erro (with optional subclass if supplied when calling).
#'
# -------------------------------------------------------------------------
#' @examples
#'
#' # Use in a user facing function
#' fun <- function(i, d, l, chr, b) {
#'     assert_scalar_int(i)
#'     TRUE
#' }
#' fun(i=1L)
#' try(fun(i="cat"))
#'
#' # Use in an internal function
#' internal_fun <- function(a) {
#'     assert_string(
#'         a,
#'         .arg = deparse(substitute(x)),
#'         .call = sys.call(-1L),
#'         .subclass = "example_error"
#'     )
#'     TRUE
#' }
#' external_fun <- function(b) {
#'     internal_fun(a=b)
#' }
#' external_fun(b="cat")
#' try(external_fun(b = letters))
#' tryCatch(external_fun(b = letters), error = class)
#'
# -------------------------------------------------------------------------
#' @name assertions
NULL

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_integer <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.integer(x)) {
        .stopf(
            gettextf("`%s` must be an integer vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass

        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_int <- assert_integer

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_integer_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.integer(x) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a non-missing integer vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass

        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_int_not_na <- assert_integer_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_double <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.double(x)) {
        .stopf(
            gettextf("`%s` must be a double vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_dbl <- assert_double

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_double_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.double(x) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a non-missing double vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_dbl_not_na <- assert_double_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_numeric <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.numeric(x)) {
        .stopf(
            gettextf("`%s` must be a numeric vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_num <- assert_numeric

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_dbl_not_na <- assert_double_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_numeric_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.numeric(x) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a non-missing numeric vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_num_not_na <- assert_numeric_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_logical <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.logical(x)) {
        .stopf(
            gettextf("`%s` must be a logical vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_lgl <- assert_logical

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_logical_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.logical(x) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a non-missing logical vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_lgl_not_na <- assert_logical_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_character <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.character(x)) {
        .stopf(
            gettextf("`%s` must be a character vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_chr <- assert_character

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_character_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.character(x) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a non-missing character vector.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_chr_not_na <- assert_character_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_data_frame <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.data.frame(x)) {
        .stopf(
            gettextf("`%s` must be a data frame.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_list <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!is.list(x)) {
        .stopf(
            gettextf("`%s` must be a list.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_whole <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!.is_whole(x)) {
        .stopf(
            gettextf("`%s` must be integerish.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_integerish <- assert_whole


# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_integer <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.integer(x) && length(x) == 1L)) {
        .stopf(
            gettextf("`%s` must be an integer vector of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_int <- assert_scalar_integer

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_integer_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.integer(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be an integer vector of length 1 and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_int_not_na <- assert_scalar_integer_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_double <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.double(x) && length(x) == 1L)) {
        .stopf(
            gettextf("`%s` must be a double vector of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_dbl <- assert_scalar_double

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_double_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.double(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a double vector of length 1 and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_dbl_not_na <- assert_scalar_double_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_numeric <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.numeric(x) && length(x) == 1L)) {
        .stopf(
            gettextf("`%s` must be a numeric vector of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_num <- assert_scalar_numeric

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_numeric_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.numeric(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a numeric vector of length 1 and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_num_not_na <- assert_scalar_numeric_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_logical <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.logical(x) && length(x) == 1L)) {
        .stopf(
            gettextf("`%s` must be a logical vector of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_lgl <- assert_scalar_logical

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_logical_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.logical(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a logical vector of length 1 and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_lgl_not_na <- assert_scalar_logical_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_whole <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!.is_scalar_whole(x)) {
        .stopf(
            gettextf("`%s` must be integerish and of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_integerish <- assert_scalar_whole


#' @rdname assertions
#' @export
assert_bool <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.logical(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be boolean (TRUE/FALSE).", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_boolean <- assert_bool

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_character <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.character(x) && length(x) == 1L)) {
        .stopf(
            gettextf("`%s` must be a character vector of length 1.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_chr <- assert_scalar_character

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_string <- assert_scalar_character

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_character_not_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    if (!(is.character(x) && length(x) == 1L) || anyNA(x)) {
        .stopf(
            gettextf("`%s` must be a character vector of length 1 and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_scalar_chr_not_na <- assert_scalar_character_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_string_not_na <- assert_scalar_character_not_na

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_non_negative_or_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_non_negative_or_na(x)) {
        .stopf(
            gettextf("`%s` values must be non-negative or NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_non_positive_or_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_non_positive_or_na(x)) {
        .stopf(
            gettextf("`%s` values must be non-positive or NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_non_negative <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_non_negative(x)) {
        .stopf(
            gettextf("`%s` values must be non-negative and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)

}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_non_positive <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_non_positive(x)) {
        .stopf(
            gettextf("`%s` values must be non-positive and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_positive <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_positive(x)) {
        .stopf(
            gettextf("`%s` values must be positive and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_negative <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_negative(x)) {
        .stopf(
            gettextf("`%s` values must be negative and not NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_positive_or_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_positive_or_na(x)) {
        .stopf(
            gettextf("`%s` values must be positive or NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}

# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_negative_or_na <- function(
    x,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {
    assert_numeric(x, .arg = .arg, .call = .call, .subclass = .subclass)
    if (!.all_negative_or_na(x)) {
        .stopf(
            gettextf("`%s` values must be negative or NA.", .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}


# -------------------------------------------------------------------------
#' @rdname assertions
#' @export
assert_between <- function(
    x,
    lower = -Inf,
    upper = Inf,
    left_inclusive = TRUE,
    right_inclusive = TRUE,
    .arg = deparse(substitute(x)),
    .call = sys.call(-1L),
    .subclass = NULL
) {

    assert_numeric_not_na(x, .arg = .arg, .call = .call, .subclass = .subclass)
    assert_scalar_numeric_not_na(lower, .arg = .arg, .call = .call, .subclass = .subclass)
    assert_scalar_numeric_not_na(upper, .arg = .arg, .call = .call, .subclass = .subclass)
    assert_bool(left_inclusive)
    assert_bool(right_inclusive)

    if (left_inclusive) {
        left_condition <- lower <= x
        left_char <- "<="
    } else {
        left_condition <- lower < x
        left_char <- "<"
    }

    if (right_inclusive) {
        right_condition <- x <= upper
        right_char <- "<="
    } else {
        right_condition <- x < upper
        right_char <- "<"
    }

    if (!all(left_condition & right_condition)) {
        condition_char <- sprintf("lower %s value %s upper", left_char, right_char)
        .stopf(
            gettextf("`%s` does not for all values in `%s`.", condition_char, .arg, domain = "R-ympes"),
            .call = .call,
            .subclass = .subclass
        )
    }
    invisible(x)
}



# ------------------------------------------------------------------------- #
# ------------------------------------------------------------------------- #
# -------------------------------- INTERNALS ------------------------------ #
# ------------------------------------------------------------------------- #
# ------------------------------------------------------------------------- #

.all_non_negative_or_na <- function(x) {
    min(0, x, na.rm = TRUE) >= 0
}

# -------------------------------------------------------------------------

.all_non_positive_or_na <- function(x) {
    max(0, x, na.rm = TRUE) <= 0
}

# -------------------------------------------------------------------------

.all_non_negative <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    min <- min(x)
    if (is.na(min))
        return(FALSE)
    if (min >= 0) TRUE else FALSE
}

# -------------------------------------------------------------------------

.all_non_positive <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    max <- max(x)
    if (is.na(max))
        return(FALSE)
    if (max <= 0) TRUE else FALSE
}

# -------------------------------------------------------------------------

.all_positive <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    min <- min(x)
    if (is.na(min))
        return(FALSE)
    if (min > 0) TRUE else FALSE
}

# -------------------------------------------------------------------------

.all_negative <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    max <- max(x)
    if (is.na(max))
        return(FALSE)
    if (max < 0) TRUE else FALSE
}

# -------------------------------------------------------------------------

.all_positive_or_na <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    nax <- is.na(x)
    if (sum(nax) == length(x))
        return(TRUE)
    if (min(x, na.rm = TRUE) <= 0) FALSE else TRUE
}

# -------------------------------------------------------------------------

.all_negative_or_na <- function(x) {
    if (length(x) == 0L)
        return(TRUE)
    nax <- is.na(x)
    if (sum(nax) == length(x))
        return(TRUE)
    if (max(x, na.rm = TRUE) >= 0) FALSE else TRUE
}

# -------------------------------------------------------------------------
.is_whole <- function(x, tol = .Machine$double.eps^0.5) {

    # TODO - document that we do not accept NA_integer_!!!
    if (anyNA(x))
        return(FALSE)

    if (is.integer(x))
        return(TRUE)

    # TODO - note down why I use is.vector here (once I remember)
    if (is.vector(x, "double") && all(abs(x - round(x)) < tol))
        return(TRUE)

    FALSE
}

# -------------------------------------------------------------------------

.is_scalar_whole <- function(x, tol = .Machine$double.eps^0.5) {
    if (length(x) != 1L || anyNA(x))
        return(FALSE)

    if (is.integer(x))
        return(TRUE)

    # TODO - note down why I use is.vector here (once I remember)
    if (is.vector(x, "double") && (abs(x - round(x)) < tol))
        return(TRUE)

    FALSE
}

# -------------------------------------------------------------------------

.stopf <- function(msg, .call = sys.call(-1L), .subclass = NULL) {
    call <- .call[1L]
    err <- errorCondition(msg, class = .subclass, call = call)
    stop(err)
}

Try the ympes package in your browser

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

ympes documentation built on April 15, 2025, 1:17 a.m.