Skip to content

Commit 347e848

Browse files
committed
handle zeros in frollprod fast
1 parent cec82e9 commit 347e848

File tree

1 file changed

+63
-14
lines changed

1 file changed

+63
-14
lines changed

src/froll.c

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,11 @@ void frollminExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
888888
#undef PROD_WINDOW_STEP_FRONT
889889
#define PROD_WINDOW_STEP_FRONT \
890890
if (R_FINITE(x[i])) { \
891-
w *= x[i]; \
891+
if (x[i] == 0.0) { \
892+
zerc++; \
893+
} else { \
894+
w *= x[i]; \
895+
} \
892896
} else if (ISNAN(x[i])) { \
893897
nc++; \
894898
} else if (x[i]==R_PosInf) { \
@@ -899,7 +903,11 @@ void frollminExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
899903
#undef PROD_WINDOW_STEP_BACK
900904
#define PROD_WINDOW_STEP_BACK \
901905
if (R_FINITE(x[i-k])) { \
902-
w /= x[i-k]; \
906+
if (x[i-k] == 0.0) { \
907+
zerc--; \
908+
} else { \
909+
w /= x[i-k]; \
910+
} \
903911
} else if (ISNAN(x[i-k])) { \
904912
nc--; \
905913
} else if (x[i-k]==R_PosInf) { \
@@ -911,18 +919,34 @@ void frollminExact(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
911919
#define PROD_WINDOW_STEP_VALUE \
912920
if (nc == 0) { \
913921
if (pinf == 0 && ninf == 0) { \
914-
ans->dbl_v[i] = (double) w; \
922+
if (zerc) { \
923+
ans->dbl_v[i] = 0.0; \
924+
} else { \
925+
ans->dbl_v[i] = (double) w; \
926+
} \
915927
} else { \
916-
ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
928+
if (zerc) { \
929+
ans->dbl_v[i] = R_NaN; \
930+
} else { \
931+
ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
932+
} \
917933
} \
918934
} else if (nc == k) { \
919935
ans->dbl_v[i] = narm ? 1.0 : NA_REAL; \
920936
} else { \
921937
if (narm) { \
922938
if (pinf == 0 && ninf == 0) { \
923-
ans->dbl_v[i] = (double) w; \
939+
if (zerc) { \
940+
ans->dbl_v[i] = 0.0; \
941+
} else { \
942+
ans->dbl_v[i] = (double) w; \
943+
} \
924944
} else { \
925-
ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
945+
if (zerc) { \
946+
ans->dbl_v[i] = R_NaN; \
947+
} else { \
948+
ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
949+
} \
926950
} \
927951
} else { \
928952
ans->dbl_v[i] = NA_REAL; \
@@ -944,34 +968,59 @@ void frollprodFast(const double *x, uint64_t nx, ans_t *ans, int k, double fill,
944968
return;
945969
}
946970
long double w = 1.0;
971+
int zerc = 0;
947972
bool truehasnf = hasnf>0;
948973
if (!truehasnf) {
949974
int i;
950975
for (i=0; i<k-1; i++) { // #loop_counter_not_local_scope_ok
951-
w *= x[i];
976+
if (x[i] == 0.0) {
977+
zerc++;
978+
} else {
979+
w *= x[i];
980+
}
952981
ans->dbl_v[i] = fill;
953982
}
954-
w *= x[i];
955-
ans->dbl_v[i] = (double) w;
983+
if (x[i] == 0.0) {
984+
zerc++;
985+
} else {
986+
w *= x[i];
987+
}
988+
if (zerc) {
989+
ans->dbl_v[i] = 0.0;
990+
} else {
991+
ans->dbl_v[i] = (double) w;
992+
}
956993
if (R_FINITE((double) w)) {
957994
for (uint64_t i=k; i<nx; i++) {
958-
w /= x[i-k];
959-
w *= x[i];
960-
ans->dbl_v[i] = (double) w;
995+
if (x[i-k] == 0.0) {
996+
zerc--;
997+
} else {
998+
w /= x[i-k];
999+
}
1000+
if (x[i] == 0.0) {
1001+
zerc++;
1002+
} else {
1003+
w *= x[i];
1004+
}
1005+
if (zerc) {
1006+
ans->dbl_v[i] = 0.0;
1007+
} else {
1008+
ans->dbl_v[i] = (double) w;
1009+
}
9611010
}
9621011
if (!R_FINITE((double) w)) {
9631012
if (hasnf==-1)
9641013
ansSetMsg(ans, 2, "%s: has.nf=FALSE used but non-finite values are present in input, use default has.nf=NA to avoid this warning", __func__);
9651014
if (verbose)
9661015
ansSetMsg(ans, 0, "%s: non-finite values are present in input, re-running with extra care for NFs\n", __func__);
967-
w = 1.0; truehasnf = true;
1016+
w = 1.0; zerc = 0; truehasnf = true;
9681017
}
9691018
} else {
9701019
if (hasnf==-1)
9711020
ansSetMsg(ans, 2, "%s: has.nf=FALSE used but non-finite values are present in input, use default has.nf=NA to avoid this warning", __func__);
9721021
if (verbose)
9731022
ansSetMsg(ans, 0, "%s: non-finite values are present in input, skip non-finite inaware attempt and run with extra care for NFs straighaway\n", __func__);
974-
w = 1.0; truehasnf = true;
1023+
w = 1.0; zerc = 0; truehasnf = true;
9751024
}
9761025
}
9771026
if (truehasnf) {

0 commit comments

Comments
 (0)