Rcpp Version 0.9.10
ifelseLooped.r
Go to the documentation of this file.
00001 #!/usr/bin/r
00002 ##
00003 ## This example goes back to the following StackOverflow questions:
00004 ##   http://stackoverflow.com/questions/7153586/can-i-vectorize-a-calculation-which-depends-on-previous-elements
00005 ## and provides a nice example of how to accelerate path-dependent
00006 ## loops which are harder to vectorise.  It lead to the following blog
00007 ## post:
00008 ##   http://dirk.eddelbuettel.com/blog/2011/08/23#rcpp_for_path_dependent_loops
00009 ##
00010 ## Thanks to Josh Ulrich for provided a first nice (R-based) answer on
00011 ## StackOverflow and for also catching a small oversight in my posted answer.
00012 ##
00013 ## Dirk Eddelbuettel, 23 Aug 2011
00014 ##
00015 ## Copyrighted but of course GPL'ed
00016 
00017 
00018 library(inline)
00019 library(rbenchmark)
00020 library(compiler)
00021 
00022 fun1 <- function(z) {
00023   for(i in 2:NROW(z)) {
00024     z[i] <- ifelse(z[i-1]==1, 1, 0)
00025   }
00026   z
00027 }
00028 fun1c <- cmpfun(fun1)
00029 
00030 
00031 fun2 <- function(z) {
00032   for(i in 2:NROW(z)) {
00033     z[i] <- if(z[i-1]==1) 1 else 0
00034   }
00035   z
00036 }
00037 fun2c <- cmpfun(fun2)
00038 
00039 
00040 funRcpp <- cxxfunction(signature(zs="numeric"), plugin="Rcpp", body="
00041   Rcpp::NumericVector z = Rcpp::NumericVector(zs);
00042   int n = z.size();
00043   for (int i=1; i<n; i++) {
00044     z[i] = (z[i-1]==1.0 ? 1.0 : 0.0);
00045   }
00046   return(z);
00047 ")
00048 
00049 
00050 z <- rep(c(1,1,0,0,0,0), 100)
00051 ## test all others against fun1 and make sure all are identical
00052 all(sapply(list(fun2(z),fun1c(z),fun2c(z),funRcpp(z)), identical, fun1(z)))
00053 
00054 res <- benchmark(fun1(z), fun2(z),
00055                  fun1c(z), fun2c(z),
00056                  funRcpp(z),
00057                  columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"),
00058                  order="relative",
00059                  replications=1000)
00060 print(res)
00061 
00062 z <- c(1,1,0,0,0,0)
00063 res2 <- benchmark(fun1(z), fun2(z),
00064                  fun1c(z), fun2c(z),
00065                  funRcpp(z),
00066                  columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"),
00067                  order="relative",
00068                  replications=10000)
00069 print(res2)
00070 
00071 
00072 if (FALSE) {                            # quick test to see if Int vectors are faster: appears not
00073     funRcppI <- cxxfunction(signature(zs="integer"), plugin="Rcpp", body="
00074         Rcpp::IntegerVector z = Rcpp::IntegerVector(zs);
00075         int n = z.size();
00076         for (int i=1; i<n; i++) {
00077             z[i] = (z[i-1]==1.0 ? 1.0 : 0.0);
00078         }
00079         return(z);
00080     ")
00081 
00082     z <- rep(c(1L,1L,0L,0L,0L,0L), 100)
00083     identical(fun1(z),fun2(z),fun1c(z),fun2c(z),funRcppI(z))
00084 
00085     res3 <- benchmark(fun1(z), fun2(z),
00086                       fun1c(z), fun2c(z),
00087                       funRcppI(z),
00088                       columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"),
00089                       order="relative",
00090                       replications=1000)
00091     print(res3)
00092 
00093     z <- c(1L,1L,0L,0L,0L,0L)
00094     res4 <- benchmark(fun1(z), fun2(z),
00095                       fun1c(z), fun2c(z),
00096                       funRcppI(z),
00097                       columns=c("test", "replications", "elapsed", "relative", "user.self", "sys.self"),
00098                       order="relative",
00099                       replications=10000)
00100     print(res4)
00101 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines