Try the following:
MakeNonNeg <- function(v) { size <- length(v) myOut <- as.numeric(v) if (size > 1L) { for (i in 1:(size-1L)) { if (myOut[i] >= 0) {next} myOut[i+1L] <- myOut[i]+myOut[i+1L] myOut[i] <- 0 } } myOut } MakeNonNeg(inVector) [1] 2 0 0 29 7
Below is a more exotic example:
set.seed(4242) BigVec <- sample(-40000:100000, 100000, replace = TRUE) gmp::sum.bigz(BigVec) Big Integer ('bigz') : [1] 2997861106 t3 <- MakeNonNeg(BigVec) gmp::sum.bigz(t3) Big Integer ('bigz') : [1] 2997861106 BigVec[1:20] [1] 98056 8680 -7814 53620 58390 90832 74970 -16392 52648 83779 -17229 38484 -36589 75156 71200 95968 -11599 57705 [19] 19209 -21596 t3[1:20] [1] 98056 8680 0 45806 58390 90832 74970 0 36256 83779 0 21255 0 38567 71200 95968 0 46106 19209 0
Here is my system info:
sessionInfo() R version 3.3.0 (2016-05-03) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 7 x64 (build 7601) Service Pack 1
Below are the timings for both functions with JIT disabled.
microbenchmark( makeNonNeg = MakeNonNeg(BigVec), zeroElement = zeroElement(BigVec), times=10) Unit: milliseconds expr min lq mean median uq max neval makeNonNeg 254.1255 255.8430 267.9527 258.6369 277.0222 303.6516 10 zeroElement 152.0358 164.7988 175.3191 166.4948 198.3855 209.8739 10
With JIT enabled, we get different results for makeNonNeg . However, the results for zeroElement do not change so much (I think that since Reduce is the main part of the function, and it is already encoded, there is not much room for improvement).
library(compiler) enableJIT(3) [1] 0 microbenchmark( makeNonNeg = MakeNonNeg(BigVec), zeroElement = zeroElement(BigVec), times=10) Unit: milliseconds expr min lq mean median uq max neval makeNonNeg 11.20514 11.55366 12.76953 11.84655 12.20554 20.60036 10 zeroElement 144.15123 149.33591 163.66421 157.34711 176.20139 198.57268 10
Thus, when JIT disabled, zeroElement about 50% faster, and when JIT turned on, makeNonNeg about 13 times faster.
Joseph Wood
source share