Skip to content

Commit

Permalink
coincides with CRAN v0.2.2 submission
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinushey committed Apr 4, 2015
1 parent a8aa432 commit e504ca1
Show file tree
Hide file tree
Showing 16 changed files with 394 additions and 383 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*.dll
RcppRoll/test
RcppRoll/src-i386
RcppRoll/src-x86_64
RcppRoll/src-x86_64
RcppRoll/src-x64
.DS_Store
.*
.*
bin/
23 changes: 12 additions & 11 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
Package: RcppRoll
Type: Package
Title: Fast rolling functions through Rcpp and RcppArmadillo
Version: 0.2.1
Date: 2013-01-10
Title: Efficient Rolling / Windowed Operations
Version: 0.2.2
Date: 2015-04-04
Author: Kevin Ushey
Maintainer: Kevin Ushey <kevinushey@gmail.com>
Description: RcppRoll supplies fast functions for 'roll'ing over vectors and
matrices, e.g. rolling means, medians and variances. It also provides the
utility functions 'rollit' and 'rollit_raw' as an interface for generating
your own C++ backed rolling functions.
Description: Provides fast and efficient routines for
common rolling / windowed operations. Routines for the
efficient computation of windowed mean, median,
sum, product, minimum, maximum, standard deviation
and variance are provided.
License: GPL (>= 2)
Depends:
R (>= 2.15.1)
Suggests:
zoo,
microbenchmark,
testthat
Imports:
Rcpp,
testthat,
RcppArmadillo
LinkingTo: Rcpp, RcppArmadillo
Imports:
Rcpp
LinkingTo: Rcpp
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by roxygen2 (4.0.1): do not edit by hand
# Generated by roxygen2 (4.1.0): do not edit by hand

export(get_rollit_source)
export(roll_max)
Expand Down
File renamed without changes.
155 changes: 83 additions & 72 deletions R/rollit.R
Original file line number Diff line number Diff line change
Expand Up @@ -100,83 +100,83 @@
#' )
#' }}
#' @importFrom Rcpp sourceCpp
rollit <- function( fun="x",
vector=FALSE,
const_vars=NULL,
combine="+",
final_trans=NULL,
includes=NULL,
depends=NULL,
inline=TRUE,
name=NULL,
... ) {

require( RcppArmadillo )
rollit <- function(fun = "x",
vector = FALSE,
const_vars = NULL,
combine = "+",
final_trans = NULL,
includes = NULL,
depends = NULL,
inline = TRUE,
name = NULL,
...) {

.Deprecated()

This comment has been minimized.

Copy link
@statwonk

statwonk Aug 27, 2015

@kevinushey curious what you have in store here? Is there another function I should use? RcppRoll looks very useful, thanks!

This comment has been minimized.

Copy link
@kevinushey

kevinushey Aug 27, 2015

Author Owner

The main reason why I deprecated this function:

  1. It looked like most users were just interested in the simpler roll_*() functions,

  2. I was hoping that I could provide a different means of making easy 'roll' functions, but within C++,

  3. The interface of the generated function no longer fits the same interface of the other directly exported functions (e.g. supporting fill, partial, align and so on)

That said, if you find this useful still it might be worth un-deprecating (since it still works, it's just less featureful than the other roll methods)


## error checks
if( !is.null(const_vars) ) {
if( !is.list(const_vars) || is.list(const_vars) && is.null( names( const_vars ) ) ) {
if (!is.null(const_vars)) {
if (!is.list(const_vars) ||
is.list(const_vars) && is.null(names(const_vars))) {
stop("'const_vars' must be a named list")
}
}

if( length( combine ) > 1 ||
!(combine %in% c("+", "-", "*", "/", "&", "|", "^", "<<", ">>") ) ) {
if (length(combine) > 1 ||
!(combine %in% c("+", "-", "*", "/", "&", "|", "^", "<<", ">>"))) {
stop("combine must be one of '+', '-', '*', '/', '&', '|', '^', '<<', '>>'")
}

funky_regex <- "([^a-zA-Z_])(x)(?=[^x])|(\\Ax)|(x\\z)"
if( length( grep( funky_regex, fun, perl=TRUE ) ) < 1 ) {
if (length(grep(funky_regex, fun, perl = TRUE)) < 1) {
stop("'fun' must be in terms of a variable 'x'")
}

## random name if null
if( is.null(name) ) {
name <- paste( sep="", collapse="", c("z",
sample( c( letters, LETTERS, 0:9), size=20, replace=TRUE )
) )
if (is.null(name)) {
random_string <- sample(c(letters, LETTERS, 0:9), 20, TRUE)
name <- paste(sep = "", collapse = "", c("z", random_string))
}

## environment for cppSource generated files
cpp_env <- new.env()

outFile <- paste( sep="", tempfile(), ".cpp" )
conn <- file( outFile, open="w" )
on.exit( close(conn) )
outFile <- paste(sep = "", tempfile(), ".cpp")
conn <- file(outFile, open = "w")
on.exit(close(conn))

w <- function(...) {
cat( paste0(..., "\n"), file=conn)
cat(paste0(..., "\n"), file = conn)
}

w1 <- function(...) {
cat( paste0("\t", ..., "\n"), file=conn)
cat(paste0("\t", ..., "\n"), file = conn)
}

w2 <- function(...) {
cat( paste0("\t\t", ..., "\n"), file=conn)
cat(paste0("\t\t", ..., "\n"), file = conn)
}

w3 <- function(...) {
cat( paste0("\t\t\t", ..., "\n"), file=conn)
cat(paste0("\t\t\t", ..., "\n"), file = conn)
}

w4 <- function(...) {
cat( paste0("\t\t\t\t", ..., "\n"), file=conn)
cat(paste0("\t\t\t\t", ..., "\n"), file = conn)
}

## depends
if( is.null(depends) ) {
if (is.null(depends)) {
w("// [[Rcpp::depends(RcppArmadillo)]]")
} else {
w("// [[Rcpp::depends(RcppArmadillo, ",
paste( depends, collapse=", " ),
paste(depends, collapse = ", "),
")")
}

w("#include <RcppArmadillo.h>")
if( !is.null(includes) ) {
for( include in includes ) {
w( paste0("#include ", include ) )
if (!is.null(includes)) {
for (include in includes) {
w(paste0("#include ", include))
w()
}
}
Expand All @@ -191,48 +191,57 @@ rollit <- function( fun="x",

## wrap the function provided by the user

if( inline) w("inline")
if (inline) w("inline")
w("double ", name, "(NV& x, NV& weights, const int& n, const int& N, const int& ind) {")
if( combine %in% c("+", "-") ) {
if (combine %in% c("+", "-")) {
w1("double out_ = 0;")
} else {
w1("double out_ = 1;")
}

## constant variables
## be sure to parse any functions of x within the constant variables
if( !is.null(const_vars) ) {
for( i in seq_along(const_vars) ) {
tmp <- gsub( funky_regex, "\\1\\2\\3\\4\\5[ seq(ind, ind+n-1) ]", const_vars[i], perl=TRUE )
if (!is.null(const_vars)) {
for(i in seq_along(const_vars)) {
tmp <-
gsub(funky_regex, "\\1\\2\\3\\4\\5[ seq(ind, ind+n-1) ]", const_vars[i], perl =
TRUE)
w1("const double ", names(const_vars)[i], " = ", tmp, ";")
}
}


## funky parser
(parsed_fun <- gsub( funky_regex, "\\1\\2\\3\\4\\5[i+ind]", fun, perl=TRUE ))
(parsed_fun <-
gsub(funky_regex, "\\1\\2\\3\\4\\5[i+ind]", fun, perl = TRUE))

## apply function as vector
if( vector ) {
w1("out_ = ", gsub( funky_regex, "\\1\\2\\3\\4\\5[ seq(ind, ind+n-1) ] * weights", fun, perl=TRUE ), ";")
} else { ## apply function elementwise
if (vector) {
w1(
"out_ = ", gsub(
funky_regex, "\\1\\2\\3\\4\\5[ seq(ind, ind+n-1) ] * weights", fun, perl =
TRUE
), ";"
)
} else {
## apply function elementwise
w1("for( int i=0; i < n; i++ ) {")
w2("if( weights[i] != 0 ) {")
w3("out_ ", combine, "= weights[i] * ", parsed_fun, ";")
w2("}")
w1("}")
}

if( !is.null( final_trans ) ) {
w1("out_ = ", gsub( funky_regex, "\\1out_", final_trans, perl=TRUE), ";" )
if (!is.null(final_trans)) {
w1("out_ = ", gsub(funky_regex, "\\1out_", final_trans, perl = TRUE), ";")
}
w1("return out_;")
w("}")
w()

## numericvector call
w("// [[Rcpp::export]]")
w("NumericVector ", name, "_numeric( NumericVector x, int n, NumericVector weights ) {" )
w("NumericVector ", name, "_numeric( NumericVector x, int n, NumericVector weights ) {")
w1()
w1("int len = x.size();")
w1("int len_out = len - n + 1;")
Expand All @@ -253,7 +262,9 @@ rollit <- function( fun="x",
## function definition -- matrix

w("// [[Rcpp::export]]")
w("NumericMatrix ", name, "_matrix( NumericMatrix A, int n, bool by_column, NumericVector weights ) {")
w(
"NumericMatrix ", name, "_matrix( NumericMatrix A, int n, bool by_column, NumericVector weights ) {"
)
w1()
w1("int nRow = A.nrow();")
w1("int nCol = A.ncol();")
Expand Down Expand Up @@ -299,49 +310,49 @@ rollit <- function( fun="x",

cat("C++ source file written to", outFile, ".\n")
cat("Compiling...\n")
sourceCpp( outFile, env=cpp_env, ... )
sourceCpp(outFile, env = cpp_env, ...)
cat("Done!\n")

return( function(x, n, by.column=TRUE, weights=rep(1,n), normalize=FALSE ) {

force( combine )
force( outFile )
return(function(x, n, by.column = TRUE, weights = rep(1,n), normalize =
FALSE) {
force(combine)
force(outFile)

if( length(weights) != n ) {
if (length(weights) != n) {
stop("length of weights must equal n")
}

if( normalize ) {
if (normalize) {
weights <- weights * length(weights) / sum(weights)
}

if( is.matrix(x) ) {
if( n > nrow(x) ) {
if (is.matrix(x)) {
if (n > nrow(x)) {
stop("n cannot be greater than nrow(x)")
}
call <- call( paste( sep="", name, "_matrix" ),
x,
as.integer(n),
as.logical(by.column),
as.numeric(weights)
)
return( eval( call, envir=cpp_env ) )
call <- call(
paste(sep = "", name, "_matrix"),
x,
as.integer(n),
as.logical(by.column),
as.numeric(weights)
)
return(eval(call, envir = cpp_env))
}

if( is.vector(x) ) {
if( n > length(x) ) {
if (is.vector(x)) {
if (n > length(x)) {
stop("n cannot be greater than length(x)")
}
call <- call( paste( sep="", name, "_numeric" ),
x,
as.integer(n),
as.numeric(weights)
)
return( as.numeric( eval( call, envir=cpp_env ) ) )
call <- call(paste(sep = "", name, "_numeric"),
x,
as.integer(n),
as.numeric(weights))
return(as.numeric(eval(call, envir = cpp_env)))
}

stop("the x supplied is neither a vector nor a matrix")

} )
})

}
9 changes: 8 additions & 1 deletion R/rollit_generated.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

##' RcppRoll
##'
##' The following functions are provided directly by \code{RcppRoll}.
##' Efficient windowed / rolling operations. Each function
##' here applies an operation over a moving window of
##' size \code{n}, with (customizable) weights specified
##' through \code{weights}.
##'
##' The functions postfixed with \code{l} and \code{r}
##' are convenience wrappers that supply \strong{l}eft
##' and \strong{r}ight alignment of the windowed operations.
##'
##' @name RcppRoll-exports
##' @param x A numeric vector or a numeric matrix.
Expand Down
Loading

0 comments on commit e504ca1

Please sign in to comment.