Skip to content

An NA in any argument disables length validation in the skewnorm/skewlnorm d/p/q/r functions #154

Description

@StefanoMezzini

Problem

All eight density/probability/quantile functions in R/skewnorm.R and R/skewlnorm.R guard the length check behind an NA check:

if (lengths >= 4) {
  nas <- any(is.na(q), is.na(mean), is.na(sd), is.na(shape))
  if (!nas) chk_compatible_lengths(q, mean, sd, shape)
}

If any argument contains an NA, chk_compatible_lengths() never runs. Incompatible lengths then flow through to mapply/sn::*, which recycle silently (with a base R warning) and produce output of the wrong length with NAs in the wrong positions.

The NA masking that follows compounds it — na_shape is length(shape) but is used to index a result of max(length(...)):

p[na_shape] <- NA_real_

Reproduction

Adding an NA turns a hard error into silently wrong output:

pskewnorm(1:6, 0, 1, c(1, 2, 3, 4))
#> Error: ... objects must be all zero length or the same length with some of
#>   length of 1 but not lengths 1, 4 and 6.

pskewnorm(1:6, 0, 1, c(NA, 1, 2, 3))
#> Warning: longer argument not a multiple of length of shorter
#> [1]        NA 0.9550173 0.9973002 0.9999367        NA 1.0000000

Only element 1 should be NA; element 5 is a recycling artefact. dskewnorm behaves the same way:

dskewnorm(1:6, 0, 1, c(NA, 1, 2, 3))
#> Warning: number of rows of result is not a multiple of vector length (arg 2)
#> [1]           NA 1.055253e-01 8.863697e-03 2.676605e-04           NA 1.215177e-08

Affected

dskewnorm, pskewnorm, qskewnorm, dskewlnorm, pskewlnorm, qskewlnorm (and rskewnorm/rskewlnorm, which use the same if (!nas) pattern around their own length check).

Suggestion

The length check is a statement about argument lengths and doesn't need to care whether the values are NA — chk_compatible_lengths() should be able to run unconditionally. If it was gated for a reason, the NA masks should at least be recycled to the result length first (e.g. rep_len(is.na(shape), n)), the way dskewlnorm already does for x via xr <- rep_len(x, length(log_lik)).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions