@@ -1071,390 +1071,3 @@ void frollprodExact(double *x, uint64_t nx, ans_t *ans, int k, double fill, bool
10711071 }
10721072 }
10731073}
1074-
1075- static inline void wmin (const double * restrict x , uint64_t o , int k , double * restrict w , uint64_t * iw , bool narm ) {
1076- if (narm ) {
1077- for (int i = 0 ; i < k ; i ++ ) {
1078- if (x [o + i - k + 1 ] <= w [0 ]) { // this never true if all x NAs and narm=TRUE
1079- iw [0 ] = o + i - k + 1 ;
1080- w [0 ] = x [iw [0 ]];
1081- }
1082- }
1083- } else {
1084- double ww = R_PosInf ;
1085- uint64_t iww = 0 ;
1086- for (int i = 0 ; i < k ; i ++ ) {
1087- uint64_t ii = o + i - k + 1 ;
1088- if (ISNAN (x [ii ])) {
1089- if (ISNA (x [ii ])) {
1090- error ("internal error: frollmin reached untested branch of code, for now use frollmin algo='exact', please provide reproducible example of your frollmin usage to data.table github issue tracker\n" ); // # nocov
1091- //iww = ii; ww = NA_REAL;
1092- } else if (ISNA (ww )) {
1093- error ("internal error: frollmin reached untested branch of code, for now use frollmin algo='exact', please provide reproducible example of your frollmin usage to data.table github issue tracker\n" ); // # nocov
1094- // do nothing because w > x[i]: NA > NaN
1095- } else { // no NA in window so NaN >= than any non-NA
1096- iww = ii ; ww = R_NaN ;
1097- }
1098- } else if (ISNAN (ww )) {
1099- // w still within the window and is NA or NaN, x[i] is not NA - already checked above, therefore to nothing
1100- } else if (x [ii ] <= ww ) {
1101- iww = ii ; ww = x [iww ];
1102- }
1103- }
1104- iw [0 ] = iww ;
1105- w [0 ] = ww ;
1106- }
1107- }
1108- /* fast rolling min - fast
1109- * see rolling max fast details
1110- */
1111- void frollminFast (double * x , uint64_t nx , ans_t * ans , int k , double fill , bool narm , int hasnf , bool verbose ) {
1112- if (verbose )
1113- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: running for input length %" PRIu64 ", window %d, hasnf %d, narm %d\n" ), "frollminFast" , (uint64_t )nx , k , hasnf , (int )narm );
1114- if (k == 0 ) {
1115- if (verbose )
1116- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: window width of size 0, returning all +Inf vector\n" ), __func__ );
1117- for (uint64_t i = 0 ; i < nx ; i ++ ) {
1118- ans -> dbl_v [i ] = R_PosInf ;
1119- }
1120- return ;
1121- }
1122- double w = R_PosInf ; // window min
1123- uint64_t cmin = 0 ; // counter of nested loops for verbose
1124- uint64_t iw = 0 ; // index of window min
1125- uint64_t i ;
1126- if (narm || hasnf == -1 ) {
1127- for (i = 0 ; i < k - 1 ; i ++ ) { // #loop_counter_not_local_scope_ok
1128- if (x [i ] <= w ) { // <= rather than < because we track most recent minimum using iw
1129- iw = i ; w = x [iw ];
1130- }
1131- ans -> dbl_v [i ] = fill ;
1132- }
1133- for (i = k - 1 ; i < nx ; i ++ ) {
1134- if (iw + k <= i ) { // min left current window // note that it is still <= same as in max
1135- iw = i - k ; w = R_PosInf ;
1136- wmin (x , i , k , & w , & iw , true); cmin ++ ;
1137- } else if (x [i ] <= w ) {
1138- iw = i ; w = x [iw ];
1139- }
1140- ans -> dbl_v [i ] = w ;
1141- }
1142- } else {
1143- bool truehasnf = hasnf > 0 ;
1144- for (i = 0 ; i < k - 1 ; i ++ ) { // up to first full window only #loop_counter_not_local_scope_ok
1145- if (ISNAN (x [i ])) {
1146- truehasnf = true;
1147- if (ISNA (x [i ])) {
1148- iw = i ; w = NA_REAL ;
1149- } else if (ISNA (w )) {
1150- // do nothing because w > x[i]: NA > NaN
1151- } else {
1152- iw = i ; w = R_NaN ;
1153- }
1154- } else if (x [i ] <= w ) {
1155- iw = i ; w = x [iw ];
1156- }
1157- ans -> dbl_v [i ] = fill ;
1158- }
1159- if (!truehasnf ) { // maybe no NAs
1160- for (; i < nx ; i ++ ) {
1161- if (ISNAN (x [i ])) { // Inf properly propagates
1162- if (verbose )
1163- ansSetMsg (ans , 0 , "%s: non-finite values are present in input, continue with extra care for NFs\n" , __func__ );
1164- truehasnf = true;
1165- break ; // does not increment, w stays as from previous iteration
1166- }
1167- if (iw + k <= i ) { // min left current window // note that it is still <= same as in max
1168- iw = i - k ; w = R_PosInf ;
1169- wmin (x , i , k , & w , & iw , true); cmin ++ ;
1170- } else if (x [i ] <= w ) {
1171- iw = i ; w = x [iw ];
1172- }
1173- ans -> dbl_v [i ] = w ;
1174- }
1175- }
1176- if (truehasnf ) {
1177- for (; i < nx ; i ++ ) { // this loop continues from where "maybe no NAs" loop left
1178- if (ISNAN (x [i ])) {
1179- if (ISNA (x [i ])) {
1180- iw = i ; w = NA_REAL ;
1181- } else if (ISNA (w )) {
1182- // do nothing because w > x[i]: NA > NaN
1183- } else { // no NA in window so NaN >= than any non-NA
1184- iw = i ; w = R_NaN ;
1185- }
1186- } else if (iw + k <= i ) { // min left current window // note that it is still <= same as in max
1187- iw = i - k ; w = R_PosInf ;
1188- wmin (x , i , k , & w , & iw , false); cmin ++ ;
1189- } else if (ISNAN (w )) {
1190- // w still within the window and is NA or NaN, x[i] is not NA - already checked above, therefore do nothing
1191- } else if (x [i ] <= w ) {
1192- iw = i ; w = x [iw ];
1193- }
1194- ans -> dbl_v [i ] = w ;
1195- }
1196- }
1197- }
1198- if (verbose )
1199- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: nested window min calculation called %" PRIu64 " times\n" ), __func__ , cmin );
1200- }
1201- /* fast rolling min - exact
1202- * see rolling max exact details
1203- */
1204- void frollminExact (double * x , uint64_t nx , ans_t * ans , int k , double fill , bool narm , int hasnf , bool verbose ) {
1205- if (verbose )
1206- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: running in parallel for input length %" PRIu64 ", window %d, hasnf %d, narm %d\n" ), "frollminExact" , (uint64_t )nx , k , hasnf , (int )narm );
1207- if (k == 0 ) {
1208- if (verbose )
1209- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: window width of size 0, returning all +Inf vector\n" ), __func__ );
1210- for (uint64_t i = 0 ; i < nx ; i ++ ) {
1211- ans -> dbl_v [i ] = R_PosInf ;
1212- }
1213- return ;
1214- }
1215- for (int i = 0 ; i < k - 1 ; i ++ ) {
1216- ans -> dbl_v [i ] = fill ;
1217- }
1218- if (narm || hasnf == -1 ) { // ignore NAs as > does not propagate
1219- #pragma omp parallel for num_threads(getDTthreads(nx, true))
1220- for (uint64_t i = k - 1 ; i < nx ; i ++ ) {
1221- double w = R_PosInf ;
1222- for (int j = - k + 1 ; j <=0 ; j ++ ) {
1223- if (x [i + j ] < w )
1224- w = x [i + j ];
1225- }
1226- ans -> dbl_v [i ] = w ;
1227- }
1228- } else {
1229- bool * isnan = malloc (nx * sizeof (bool )); // isnan lookup - we use it to reduce ISNAN calls in nested loop
1230- if (!isnan ) { // # nocov start
1231- ansSetMsg (ans , 3 , "%s: Unable to allocate memory for isnan" , __func__ ); // raise error
1232- free (isnan );
1233- return ;
1234- } // # nocov end
1235- bool truehasnf = hasnf > 0 ;
1236- for (uint64_t i = 0 ; i < nx ; i ++ ) { // no openmp as this should be very fast
1237- if (ISNAN (x [i ])) {
1238- truehasnf = true;
1239- isnan [i ] = true;
1240- } else {
1241- isnan [i ] = false;
1242- }
1243- }
1244- if (!truehasnf ) { // not found any NAs
1245- #pragma omp parallel for num_threads(getDTthreads(nx, true))
1246- for (uint64_t i = k - 1 ; i < nx ; i ++ ) {
1247- double w = R_PosInf ;
1248- for (int j = - k + 1 ; j <=0 ; j ++ ) {
1249- if (x [i + j ] < w )
1250- w = x [i + j ];
1251- }
1252- ans -> dbl_v [i ] = w ;
1253- }
1254- } else { // there are some NAs
1255- #pragma omp parallel for num_threads(getDTthreads(nx, true))
1256- for (uint64_t i = k - 1 ; i < nx ; i ++ ) {
1257- double w = R_PosInf ;
1258- if (isnan [i ] && ISNA (x [i ])) {
1259- w = NA_REAL ;
1260- } else {
1261- for (int j = - k + 1 ; j <=0 ; j ++ ) {
1262- if (isnan [i + j ]) {
1263- if (ISNA (x [i + j ])) {
1264- w = NA_REAL ;
1265- break ; // break because NA > NaN
1266- } else {
1267- w = R_NaN ; // continue nested loop in case there is NA there
1268- }
1269- } else if (x [i + j ] < w )
1270- w = x [i + j ];
1271- }
1272- }
1273- ans -> dbl_v [i ] = w ;
1274- }
1275- }
1276- }
1277- }
1278-
1279- /* fast rolling prod - fast
1280- * same as mean fast
1281- */
1282- void frollprodFast (double * x , uint64_t nx , ans_t * ans , int k , double fill , bool narm , int hasnf , bool verbose ) {
1283- if (verbose )
1284- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: running for input length %" PRIu64 ", window %d, hasnf %d, narm %d\n" ), "frollprodFast" , (uint64_t )nx , k , hasnf , (int )narm );
1285- if (k == 0 ) {
1286- if (verbose )
1287- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: window width of size 0, returning all 1 vector\n" ), __func__ );
1288- for (uint64_t i = 0 ; i < nx ; i ++ ) {
1289- ans -> dbl_v [i ] = 1.0 ;
1290- }
1291- return ;
1292- }
1293- long double w = 1.0 ;
1294- bool truehasnf = hasnf > 0 ;
1295- if (!truehasnf ) {
1296- int i ;
1297- for (i = 0 ; i < k - 1 ; i ++ ) { // #loop_counter_not_local_scope_ok
1298- w *= x [i ];
1299- ans -> dbl_v [i ] = fill ;
1300- }
1301- w *= x [i ];
1302- ans -> dbl_v [i ] = (double ) w ;
1303- if (R_FINITE ((double ) w )) {
1304- for (uint64_t i = k ; i < nx ; i ++ ) {
1305- w /= x [i - k ];
1306- w *= x [i ];
1307- ans -> dbl_v [i ] = (double ) w ;
1308- }
1309- if (!R_FINITE ((double ) w )) {
1310- if (hasnf == -1 )
1311- 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__ );
1312- if (verbose )
1313- ansSetMsg (ans , 0 , "%s: non-finite values are present in input, re-running with extra care for NFs\n" , __func__ );
1314- w = 1.0 ; truehasnf = true;
1315- }
1316- } else {
1317- if (hasnf == -1 )
1318- 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__ );
1319- if (verbose )
1320- 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__ );
1321- w = 1.0 ; truehasnf = true;
1322- }
1323- }
1324- if (truehasnf ) {
1325- int nc = 0 , pinf = 0 , ninf = 0 ; // NA counter within sliding window
1326- int i ; // iterator declared here because it is being used after for loop
1327-
1328- #undef PROD_WINDOW_STEP_FRONT
1329- #define PROD_WINDOW_STEP_FRONT \
1330- if (R_FINITE(x[i])) { \
1331- w *= x[i]; \
1332- } else if (ISNAN(x[i])) { \
1333- nc++; \
1334- } else if (x[i]==R_PosInf) { \
1335- pinf++; \
1336- } else if (x[i]==R_NegInf) { \
1337- ninf++; \
1338- }
1339- #undef PROD_WINDOW_STEP_BACK
1340- #define PROD_WINDOW_STEP_BACK \
1341- if (R_FINITE(x[i-k])) { \
1342- w /= x[i-k]; \
1343- } else if (ISNAN(x[i-k])) { \
1344- nc--; \
1345- } else if (x[i-k]==R_PosInf) { \
1346- pinf--; \
1347- } else if (x[i-k]==R_NegInf) { \
1348- ninf--; \
1349- }
1350- #undef PROD_WINDOW_STEP_VALUE
1351- #define PROD_WINDOW_STEP_VALUE \
1352- if (nc == 0) { \
1353- if (pinf == 0 && ninf == 0) { \
1354- ans->dbl_v[i] = (double) w; \
1355- } else { \
1356- ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
1357- } \
1358- } else if (nc == k) { \
1359- ans->dbl_v[i] = narm ? 1.0 : NA_REAL; \
1360- } else { \
1361- if (narm) { \
1362- if (pinf == 0 && ninf == 0) { \
1363- ans->dbl_v[i] = (double) w; \
1364- } else { \
1365- ans->dbl_v[i] = (ninf+(w<0))%2 ? R_NegInf : R_PosInf; \
1366- } \
1367- } else { \
1368- ans->dbl_v[i] = NA_REAL; \
1369- } \
1370- }
1371-
1372- for (i = 0 ; i < k - 1 ; i ++ ) { // loop over leading observation, all partial window only; #loop_counter_not_local_scope_ok
1373- PROD_WINDOW_STEP_FRONT
1374- ans -> dbl_v [i ] = fill ; // partial window fill all
1375- }
1376- PROD_WINDOW_STEP_FRONT // i==k-1
1377- PROD_WINDOW_STEP_VALUE
1378- for (uint64_t i = k ; i < nx ; i ++ ) { // loop over obs, complete window, all remaining after partial window
1379- PROD_WINDOW_STEP_BACK
1380- PROD_WINDOW_STEP_FRONT
1381- PROD_WINDOW_STEP_VALUE
1382- }
1383- }
1384- }
1385- /* fast rolling prod - exact
1386- * same as mean exact
1387- */
1388- void frollprodExact (double * x , uint64_t nx , ans_t * ans , int k , double fill , bool narm , int hasnf , bool verbose ) {
1389- if (verbose )
1390- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: running in parallel for input length %" PRIu64 ", window %d, hasnf %d, narm %d\n" ), "frollprodExact" , (uint64_t )nx , k , hasnf , (int )narm );
1391- if (k == 0 ) {
1392- if (verbose )
1393- snprintf (end (ans -> message [0 ]), 500 , _ ("%s: window width of size 0, returning all 1 vector\n" ), __func__ );
1394- for (uint64_t i = 0 ; i < nx ; i ++ ) {
1395- ans -> dbl_v [i ] = 1.0 ;
1396- }
1397- return ;
1398- }
1399- for (int i = 0 ; i < k - 1 ; i ++ ) {
1400- ans -> dbl_v [i ] = fill ;
1401- }
1402- bool truehasnf = hasnf > 0 ;
1403- if (!truehasnf || !narm ) {
1404- #pragma omp parallel for num_threads(getDTthreads(nx, true))
1405- for (uint64_t i = k - 1 ; i < nx ; i ++ ) {
1406- if (narm && truehasnf ) {
1407- continue ;
1408- }
1409- long double w = 1.0 ;
1410- for (int j = - k + 1 ; j <=0 ; j ++ ) {
1411- w *= x [i + j ];
1412- }
1413- if (R_FINITE ((double ) w )) {
1414- ans -> dbl_v [i ] = (double ) w ;
1415- } else if (ISNAN ((double ) w )) {
1416- if (!narm ) {
1417- ans -> dbl_v [i ] = (double ) w ;
1418- }
1419- truehasnf = true;
1420- } else {
1421- ans -> dbl_v [i ] = (double ) w ;
1422- }
1423- }
1424- if (truehasnf ) {
1425- if (hasnf == -1 )
1426- 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__ );
1427- if (verbose ) {
1428- if (narm )
1429- ansSetMsg (ans , 0 , "%s: non-finite values are present in input, re-running with extra care for NFs\n" , __func__ );
1430- else
1431- ansSetMsg (ans , 0 , "%s: non-finite values are present in input, na.rm=FALSE and algo='exact' propagates NFs properply, no need to re-run\n" , __func__ );
1432- }
1433- }
1434- }
1435- if (truehasnf && narm ) {
1436- #pragma omp parallel for num_threads(getDTthreads(nx, true))
1437- for (uint64_t i = k - 1 ; i < nx ; i ++ ) {
1438- long double w = 1.0 ;
1439- int nc = 0 ;
1440- for (int j = - k + 1 ; j <=0 ; j ++ ) {
1441- if (ISNAN (x [i + j ])) {
1442- nc ++ ;
1443- } else {
1444- w *= x [i + j ];
1445- }
1446- }
1447- if (w > DBL_MAX ) { // in contrast to mean, here we can overflow long double more than DBL_MAX
1448- ans -> dbl_v [i ] = R_PosInf ;
1449- } else if (w < - DBL_MAX ) {
1450- ans -> dbl_v [i ] = R_NegInf ;
1451- } else {
1452- if (nc < k ) {
1453- ans -> dbl_v [i ] = (double ) w ;
1454- } else {
1455- ans -> dbl_v [i ] = 1.0 ;
1456- }
1457- }
1458- }
1459- }
1460- }
0 commit comments