forked from tidyverse/dplyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwindow.cpp
133 lines (119 loc) · 2.95 KB
/
window.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "pch.h"
#include <dplyr/main.h>
//' Cumulativate versions of any, all, and mean
//'
//' dplyr provides `cumall()`, `cumany()`, and `cummean()` to complete R's set
//' of cumulative functions.
//'
//' @section Cumulative logical functions:
//'
//' These are particularly useful in conjunction with `filter()`:
//'
//' * `cumall(x)`: all cases until the first `FALSE`.
//' * `cumall(!x)`: all cases until the first `TRUE`.
//' * `cumany(x)`: all cases after the first `TRUE`.
//' * `cumany(!x)`: all cases after the first `FALSE`.
//'
//' @param x For `cumall()` and `cumany()`, a logical vector; for
//' `cummean()` an integer or numeric vector.
//' @return A vector the same length as `x`.
//' @export
//' @examples
//' # `cummean()` returns a numeric/integer vector of the same length
//' # as the input vector.
//' x <- c(1, 3, 5, 2, 2)
//' cummean(x)
//' cumsum(x) / seq_along(x)
//'
//' # `cumall()` and `cumany()` return logicals
//' cumall(x < 5)
//' cumany(x == 3)
//'
//' # `cumall()` vs. `cumany()`
//' df <- data.frame(
//' date = as.Date("2020-01-01") + 0:6,
//' balance = c(100, 50, 25, -25, -50, 30, 120)
//' )
//' # all rows after first overdraft
//' df %>% filter(cumany(balance < 0))
//' # all rows until first overdraft
//' df %>% filter(cumall(!(balance < 0)))
// [[Rcpp::export(rng = false)]]
Rcpp::LogicalVector cumall(Rcpp::LogicalVector x) {
int n = x.length();
Rcpp::LogicalVector out(n, TRUE);
int* p_x = x.begin();
int* p_out = out.begin();
// nothing to do as long as x[i] is TRUE
int i = 0 ;
for (; i < n; i++, ++p_x, ++p_out) {
if (*p_x != TRUE) {
break;
}
}
if (i == n) {
return out;
}
// set to NA as long as x[i] is NA or TRUE
for (; i < n; i++, ++p_x, ++p_out) {
if (*p_x == FALSE) {
break;
}
*p_out = NA_LOGICAL;
}
if (i == n) {
return out;
}
// then if we are here, the rest is FALSE
for (; i < n; i++, ++p_out) {
*p_out = FALSE;
}
return out;
}
//' @export
//' @rdname cumall
// [[Rcpp::export(rng = false)]]
Rcpp::LogicalVector cumany(Rcpp::LogicalVector x) {
int n = x.length();
Rcpp::LogicalVector out(n, FALSE);
int* p_x = x.begin();
int* p_out = out.begin();
// nothing to do as long as x[i] is FALSE
int i = 0 ;
for (; i < n; i++, ++p_x, ++p_out) {
if (*p_x != FALSE) {
break;
}
}
if (i == n) {
return out;
}
// set to NA as long as x[i] is NA or FALSE
for (; i < n; i++, ++p_x, ++p_out) {
if (*p_x == TRUE) {
break;
}
*p_out = NA_LOGICAL;
}
if (i == n) {
return out;
}
// then if we are here, the rest is TRUE
for (; i < n; i++, ++p_out) {
*p_out = TRUE;
}
return out;
}
//' @export
//' @rdname cumall
// [[Rcpp::export(rng = false)]]
Rcpp::NumericVector cummean(Rcpp::NumericVector x) {
int n = x.length();
Rcpp::NumericVector out(Rcpp::no_init(n));
double sum = out[0] = x[0];
for (int i = 1; i < n; i++) {
sum += x[i];
out[i] = sum / (i + 1.0);
}
return out;
}