@@ -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 }
0 commit comments