Skip to content

Commit 7258909

Browse files
committed
frollmax PR as potentially complete
1 parent 996bce9 commit 7258909

File tree

5 files changed

+18
-28
lines changed

5 files changed

+18
-28
lines changed

R/froll.R

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ partial2adaptive = function(x, n, align, adaptive) {
3737
if (!is.numeric(n))
3838
stopf("n must be an integer vector or a list of integer vectors")
3939
if (verbose)
40-
cat("partial2adaptive: froll partial=TRUE trimming 'n' and redirecting to adaptive=TRUE\n")
40+
catf("partial2adaptive: froll partial=TRUE trimming 'n' and redirecting to adaptive=TRUE\n")
4141
if (length(n)>1L) {
4242
lapply(n, len, align, FUN=trimn)
4343
} else {
@@ -53,7 +53,7 @@ partial2adaptive = function(x, n, align, adaptive) {
5353
if (length(n[[1L]]) != len)
5454
stopf("length of vectors in 'x' must match to length of adaptive window in 'n'")
5555
if (verbose)
56-
cat("partial2adaptive: froll adaptive=TRUE and partial=TRUE trimming 'n'\n")
56+
catf("partial2adaptive: froll adaptive=TRUE and partial=TRUE trimming 'n'\n")
5757
lapply(n, align, FUN=trimnadaptive)
5858
}
5959
}
@@ -73,7 +73,7 @@ froll = function(fun, x, n, fill=NA, algo, align=c("right","left","center"), na.
7373
verbose = getOption("datatable.verbose")
7474
rev2 = function(x) if (is.list(x)) lapply(x, rev) else rev(x)
7575
if (verbose)
76-
cat("froll: adaptive=TRUE && align='left' pre-processing for align='right'\n")
76+
catf("froll: adaptive=TRUE && align='left' pre-processing for align='right'\n")
7777
x = rev2(x)
7878
n = rev2(n)
7979
align = "right"
@@ -84,7 +84,7 @@ froll = function(fun, x, n, fill=NA, algo, align=c("right","left","center"), na.
8484
ans = .Call(CfrollapplyR, FUN, x, n, fill, align, adaptive, rho)
8585
if (leftadaptive) {
8686
if (verbose)
87-
cat("froll: adaptive=TRUE && align='left' post-processing from align='right'\n")
87+
catf("froll: adaptive=TRUE && align='left' post-processing from align='right'\n")
8888
ans = rev2(ans)
8989
}
9090
if (isTRUE(give.names) && is.list(ans)) {
@@ -122,8 +122,6 @@ frollmax = function(x, n, fill=NA, algo=c("fast","exact"), align=c("right","left
122122
}
123123

124124
frollapply = function(x, n, FUN, ..., fill=NA, align=c("right","left","center"), adaptive=FALSE, partial=FALSE, give.names=FALSE) {
125-
if (isTRUE(adaptive) && base::getRversion() < "3.4.0") ## support SET_GROWABLE_BIT
126-
stopf("frollapply adaptive=TRUE requires at least R 3.4.0"); # nocov
127125
FUN = match.fun(FUN)
128126
rho = new.env()
129127
froll(FUN=FUN, rho=rho, x=x, n=n, fill=fill, align=align, adaptive=adaptive, partial=partial, give.names=give.names)

man/froll.Rd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@
126126
}
127127
\section{\code{frollapply}}{
128128
\code{frollapply} computes rolling aggregate on arbitrary R functions. \code{adaptive} argument is not supported (to be changed). The input \code{x} (first argument) to the function \code{FUN} is coerced to \emph{numeric} beforehand(to be changed) and \code{FUN} has to return a scalar \emph{numeric} value (to be changed). Checks for that are made only during the first iteration when \code{FUN} is evaluated. Edge cases can be found in examples below. Any R function is supported, but it is not optimized using our own C implementation -- hence, for example, using \code{frollapply} to compute a rolling average is inefficient. It is also always single-threaded because there is no thread-safe API to R's C \code{eval}. Nevertheless we've seen the computation speed up vis-a-vis versions implemented in base R.
129-
Support for \code{adaptive=TRUE} in \code{frollapply} requires R 3.4.0 or higher.
130129
}
131130
\section{\code{zoo} package users notice}{
132131
Users coming from most popular package for rolling functions \code{zoo} might expect following differences in \code{data.table} implementation

src/data.table.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
#if R_VERSION < R_Version(4, 5, 0)
1717
# define isDataFrame(x) isFrame(x) // #6180
1818
#endif
19-
#if !defined(R_VERSION) || R_VERSION < R_Version(3, 4, 0)
20-
# define SET_GROWABLE_BIT(x) // frollapply adaptive #5441
21-
#endif
2219
#include <Rinternals.h>
2320
#define SEXPPTR_RO(x) ((const SEXP *)DATAPTR_RO(x)) // to avoid overhead of looped STRING_ELT and VECTOR_ELT
2421
#include <stdint.h> // for uint64_t rather than unsigned long long

src/froll.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,9 @@ void frollmaxExact(double *x, uint64_t nx, ans_t *ans, int k, double fill, bool
573573
ans->dbl_v[i] = w;
574574
}
575575
} else {
576-
bool *isnan = malloc(nx*sizeof(bool)); // isnan lookup - we use it to reduce ISNAN calls in nested loop
576+
bool *isnan = malloc(nx*sizeof(*isnan)); // isnan lookup - we use it to reduce ISNAN calls in nested loop
577577
if (!isnan) { // # nocov start
578578
ansSetMsg(ans, 3, "%s: Unable to allocate memory for isnan", __func__); // raise error
579-
free(isnan);
580579
return;
581580
} // # nocov end
582581
bool truehasnf = hasnf>0;

src/frolladaptive.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ void frolladaptivemeanFast(double *x, uint64_t nx, ans_t *ans, int *k, double fi
5353
double *cs = malloc(sizeof(*cs) * nx); // cumsum vector, same as double cs[nx] but no segfault
5454
if (!cs) { // # nocov start
5555
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cumsum", __func__); // raise error
56-
free(cs);
5756
return;
5857
} // # nocov end
5958
if (!truehasnf) {
@@ -82,22 +81,22 @@ void frolladaptivemeanFast(double *x, uint64_t nx, ans_t *ans, int *k, double fi
8281
}
8382
if (truehasnf) {
8483
uint64_t nc = 0, pinf = 0, ninf = 0; // running NA counter
85-
uint64_t *cn = malloc(nx*sizeof(uint64_t)); // cumulative NA counter, used the same way as cumsum, same as uint64_t cn[nx] but no segfault
84+
uint64_t *cn = malloc(nx*sizeof(*cn)); // cumulative NA counter, used the same way as cumsum, same as uint64_t cn[nx] but no segfault
8685
if (!cn) { // # nocov start
8786
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum NA counter", __func__); // raise error
88-
free(cs); free(cn);
87+
free(cs);
8988
return;
9089
} // # nocov end
91-
uint64_t *cpinf = malloc(nx*sizeof(uint64_t));
90+
uint64_t *cpinf = malloc(nx*sizeof(*cpinf));
9291
if (!cpinf) { // # nocov start
9392
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum Inf counter", __func__); // raise error
94-
free(cs); free(cn); free(cpinf);
93+
free(cs); free(cn);
9594
return;
9695
} // # nocov end
97-
uint64_t *cninf = malloc(nx*sizeof(uint64_t));
96+
uint64_t *cninf = malloc(nx*sizeof(*cninf));
9897
if (!cninf) { // # nocov start
9998
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum -Inf counter", __func__); // raise error
100-
free(cs); free(cn); free(cpinf); free(cninf);
99+
free(cs); free(cn); free(cpinf);
101100
return;
102101
} // # nocov end
103102
for (uint64_t i=0; i<nx; i++) { // loop over observations to calculate cumsum and cum NA counter
@@ -277,7 +276,6 @@ void frolladaptivesumFast(double *x, uint64_t nx, ans_t *ans, int *k, double fil
277276
double *cs = malloc(sizeof(*cs) * nx);
278277
if (!cs) { // # nocov start
279278
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cumsum", __func__); // raise error
280-
free(cs);
281279
return;
282280
} // # nocov end
283281
if (!truehasnf) {
@@ -306,22 +304,22 @@ void frolladaptivesumFast(double *x, uint64_t nx, ans_t *ans, int *k, double fil
306304
}
307305
if (truehasnf) {
308306
uint64_t nc = 0, pinf = 0, ninf = 0; // running NA counter
309-
uint64_t *cn = malloc(nx*sizeof(uint64_t)); // cumulative NA counter, used the same way as cumsum, same as uint64_t cn[nx] but no segfault
307+
uint64_t *cn = malloc(nx*sizeof(*cn)); // cumulative NA counter, used the same way as cumsum, same as uint64_t cn[nx] but no segfault
310308
if (!cn) { // # nocov start
311309
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum NA counter", __func__); // raise error
312-
free(cs); free(cn);
310+
free(cs);
313311
return;
314312
} // # nocov end
315-
uint64_t *cpinf = malloc(nx*sizeof(uint64_t));
313+
uint64_t *cpinf = malloc(nx*sizeof(*cpinf));
316314
if (!cpinf) { // # nocov start
317315
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum Inf counter", __func__); // raise error
318-
free(cs); free(cn); free(cpinf);
316+
free(cs); free(cn);
319317
return;
320318
} // # nocov end
321-
uint64_t *cninf = malloc(nx*sizeof(uint64_t));
319+
uint64_t *cninf = malloc(nx*sizeof(*cninf));
322320
if (!cninf) { // # nocov start
323321
ansSetMsg(ans, 3, "%s: Unable to allocate memory for cum -Inf counter", __func__); // raise error
324-
free(cs); free(cn); free(cpinf); free(cninf);
322+
free(cs); free(cn); free(cpinf);
325323
return;
326324
} // # nocov end
327325
for (uint64_t i=0; i<nx; i++) { // loop over observations to calculate cumsum and cum NA counter
@@ -492,10 +490,9 @@ void frolladaptivemaxExact(double *x, uint64_t nx, ans_t *ans, int *k, double fi
492490
}
493491
}
494492
} else {
495-
bool *isnan = malloc(nx*sizeof(bool)); // isnan lookup - we use it to reduce ISNAN calls in nested loop
493+
bool *isnan = malloc(nx*sizeof(*isnan)); // isnan lookup - we use it to reduce ISNAN calls in nested loop
496494
if (!isnan) { // # nocov start
497495
ansSetMsg(ans, 3, "%s: Unable to allocate memory for isnan", __func__); // raise error
498-
free(isnan);
499496
return;
500497
} // # nocov end
501498
bool truehasnf = hasnf>0;

0 commit comments

Comments
 (0)