blob: 7c5dc88bb3a385c2ce331ce5873b77fc2609aedd [file] [log] [blame]
# File src/library/stats/R/filter.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1999-2017 The R Core Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License is available at
# https://www.R-project.org/Licenses/
filter <- function(x, filter, method = c("convolution", "recursive"),
sides = 2L, circular = FALSE, init=NULL)
{
method <- match.arg(method)
x <- as.ts(x)
storage.mode(x) <- "double"
xtsp <- tsp(x)
n <- as.integer(NROW(x))
if (is.na(n)) stop(gettextf("invalid value of %s", "NROW(x)"), domain = NA)
nser <- NCOL(x)
filter <- as.double(filter)
nfilt <- as.integer(length(filter))
if (is.na(nfilt)) stop(gettextf("invalid value of %s", "length(filter)"),
domain = NA)
if(anyNA(filter)) stop("missing values in 'filter'")
if(method == "convolution") {
if(nfilt > n) stop("'filter' is longer than time series")
sides <- as.integer(sides)
if(is.na(sides) || (sides != 1L && sides != 2L))
stop("argument 'sides' must be 1 or 2")
circular <- as.logical(circular)
if (is.na(circular)) stop("'circular' must be logical and not NA")
if (is.matrix(x)) {
y <- matrix(NA, n, nser)
for (i in seq_len(nser))
y[, i] <- .Call(C_cfilter, x[, i], filter, sides, circular)
} else
y <- .Call(C_cfilter, x, filter, sides, circular)
} else {
if(missing(init)) {
init <- matrix(0, nfilt, nser)
} else {
ni <- NROW(init)
if(ni != nfilt)
stop("length of 'init' must equal length of 'filter'")
if(NCOL(init) != 1L && NCOL(init) != nser) {
stop(sprintf(ngettext(nser,
"'init' must have %d column",
"'init' must have 1 or %d columns",
domain = "R-stats"),
nser), domain = NA)
}
if(!is.matrix(init)) dim(init) <- c(nfilt, nser)
}
ind <- seq_len(nfilt)
## NB: this .Call alters its third argument
if (is.matrix(x)) {
y <- matrix(NA, n, nser)
for (i in seq_len(nser))
y[, i] <-
.Call(C_rfilter, x[, i], filter,
c(rev(init[, i]), double(n)))[-ind]
} else
y <-
.Call(C_rfilter, x, filter,
c(rev(init[, 1L]), double(n)))[-ind]
}
# y <- drop(y)
tsp(y) <- xtsp
class(y) <- if(nser > 1L) c("mts", "ts") else "ts"
y
}