Skip to content

Commit 2475352

Browse files
committed
handle var < 0 spotted by Ben
1 parent a0b6a3a commit 2475352

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

inst/tests/froll.Rraw

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,11 @@ test(6001.727, frollvar(adaptive=TRUE, c(1:2,NA), c(2,0,2), algo="exact"), c(NA_
14391439
test(6001.728, frollvar(adaptive=TRUE, c(1:2,NA), c(2,0,2), algo="exact", na.rm=TRUE), c(NA_real_,NA_real_,NA_real_))
14401440
test(6001.729, frollvar(adaptive=TRUE, c(1:2,NA), c(2,0,2), algo="exact", na.rm=TRUE, partial=TRUE), c(NA_real_,NA_real_,NA_real_))
14411441
test(6001.730, frollvar(adaptive=TRUE, c(1:2,NA), c(2,0,2), fill=99, algo="exact", na.rm=TRUE), c(99,NA,NA))
1442+
y = c(1e8+2.980232e-8, 1e8, 1e8, 1e8) # CLAMP0 test
1443+
test(6001.731, frollvar(y, 3)[4L], 0)
1444+
test(6001.732, frollsd(y, 3)[4L], 0)
1445+
test(6001.733, frollvar(y, c(3,3,3,3), adaptive=TRUE)[4L], 0)
1446+
test(6001.734, frollsd(y, c(3,3,3,3), adaptive=TRUE)[4L], 0)
14421447
test(6001.781, frollapply(FUN=var, 1:3, 0), c(NA_real_,NA_real_,NA_real_))
14431448
test(6001.782, frollapply(FUN=var, 1:3, 0, fill=99), c(NA_real_,NA_real_,NA_real_))
14441449
test(6001.783, frollapply(FUN=var, c(1:2,NA), 0), c(NA_real_,NA_real_,NA_real_))

src/froll.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,8 @@ void frollprodExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill
11371137
}
11381138
}
11391139

1140+
#define CLAMP0(x) (((x) < 0) ? 0 : (x))
1141+
11401142
/* fast rolling var - fast
11411143
Welford's online algorithm
11421144
numerically stable
@@ -1169,7 +1171,8 @@ void frollvarFast(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
11691171
long double delta = x[i] - wmean; // i==k-1
11701172
wmean += delta / (i + 1);
11711173
m2 += delta * (x[i] - wmean);
1172-
ans->dbl_v[i] = (double)(m2 / k0);
1174+
double ans_i = m2 / k0;
1175+
ans->dbl_v[i] = CLAMP0(ans_i);
11731176
if (R_FINITE((double) m2)) {
11741177
for (uint64_t i=k; i<nx; i++) {
11751178
double x_out = x[i-k];
@@ -1180,7 +1183,8 @@ void frollvarFast(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
11801183
long double delta_in = x_in - wmean;
11811184
wmean += delta_in / k;
11821185
m2 += delta_in * (x_in - wmean);
1183-
ans->dbl_v[i] = (double)(m2 / k0);
1186+
double ans_i = m2 / k0;
1187+
ans->dbl_v[i] = CLAMP0(ans_i);
11841188
}
11851189
if (!R_FINITE((double) m2)) {
11861190
if (hasnf==-1)
@@ -1235,7 +1239,7 @@ void frollvarExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
12351239
if (!R_FINITE((double) wsum)) {
12361240
if (ISNAN((double) wsum)) {
12371241
if (!narm) {
1238-
ans->dbl_v[i] = (double) wsum;
1242+
ans->dbl_v[i] = (double) wsum; // propagate NAs
12391243
}
12401244
truehasnf = true;
12411245
} else {
@@ -1249,7 +1253,8 @@ void frollvarExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
12491253
xi = x[i+j] - wmean;
12501254
wsumxi += (xi * xi);
12511255
}
1252-
ans->dbl_v[i] = (double) (wsumxi / (k - 1));
1256+
double ans_i = wsumxi / (k - 1);
1257+
ans->dbl_v[i] = CLAMP0(ans_i);
12531258
}
12541259
}
12551260
if (truehasnf) {
@@ -1284,7 +1289,8 @@ void frollvarExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
12841289
xi = x[i+j] - wmean;
12851290
wsumxi += (xi * xi);
12861291
}
1287-
ans->dbl_v[i] = (double) (wsumxi / (k - 1));
1292+
double ans_i = wsumxi / (k - 1);
1293+
ans->dbl_v[i] = CLAMP0(ans_i);
12881294
} else if (nc < (k - 1)) { // var(scalar) is also NA thats why k-1 so at least 2 numbers must be there
12891295
long double wmean = wsum / (k - nc);
12901296
long double xi = 0.0;
@@ -1295,7 +1301,8 @@ void frollvarExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
12951301
wsumxi += (xi * xi);
12961302
}
12971303
}
1298-
ans->dbl_v[i] = (double) (wsumxi / (k - nc - 1));
1304+
double ans_i = wsumxi / (k - nc - 1);
1305+
ans->dbl_v[i] = CLAMP0(ans_i);
12991306
} else {
13001307
ans->dbl_v[i] = NA_REAL;
13011308
}

src/frolladaptive.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,8 @@ void frolladaptiveprodExact(const double *x, uint64_t nx, ans_t *ans, const int
737737
}
738738
}
739739

740+
#define CLAMP0(x) (((x) < 0) ? 0 : (x))
741+
740742
/* fast rolling adaptive var - exact
741743
*/
742744
void frolladaptivevarExact(const double *x, uint64_t nx, ans_t *ans, const int *k, double fill, bool narm, int hasnf, bool verbose) {
@@ -761,7 +763,7 @@ void frolladaptivevarExact(const double *x, uint64_t nx, ans_t *ans, const int *
761763
if (!R_FINITE((double) wsum)) {
762764
if (ISNAN((double) wsum)) {
763765
if (!narm) {
764-
ans->dbl_v[i] = (double) wsum;
766+
ans->dbl_v[i] = (double) wsum; // propagate NAs
765767
}
766768
truehasnf = true;
767769
} else {
@@ -775,7 +777,8 @@ void frolladaptivevarExact(const double *x, uint64_t nx, ans_t *ans, const int *
775777
xi = x[i+j] - wmean;
776778
wsumxi += (xi * xi);
777779
}
778-
ans->dbl_v[i] = (double) (wsumxi / (k[i] - 1));
780+
double ans_i = (wsumxi / (k[i] - 1));
781+
ans->dbl_v[i] = CLAMP0(ans_i);
779782
}
780783
}
781784
}

0 commit comments

Comments
 (0)