--- title: "09 - Rolling Functions with Missing Values" output: litedown::html_format: options: toc: true number_sections: true vignette: > %\VignetteIndexEntry{09 - Rolling Functions with Missing Values} %\VignetteEngine{litedown::vignette} %\VignetteEncoding{UTF-8} editor: markdown: wrap: sentence bibliography: ["references.bib"] --- ## Notes * These functions ignore `NA` values for now. Adjustments for handling `NA` values are covered in a separate vignette. * R already provides efficient versions of the functions covered here. This is just to illustrate how to use C++ code. ## Cumulative sum The following function expands the previous `cumsum_cpp()` function to handle missing values. ```cpp [[cpp4r::register]] doubles cumsum2_cpp(doubles x, bool na_rm = false) { int n = x.size(); writable::doubles out(n); out[0] = x[0]; if (na_rm == true) { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = y1 + 0.0; } else { if (ISNAN(y1)) { out[i] = 0.0 + y2; } else { out[i] = y1 + y2; } } } } else { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = NA_REAL; } else { if (ISNAN(y1)) { out[i] = NA_REAL; } else { out[i] = y1 + y2; } } } } return out; } ``` Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes. ## Cumulative product The following function expands the previous `cumprod_cpp()` function to handle missing values. ```cpp [[cpp4r::register]] doubles cumprod2_cpp(doubles x, bool na_rm = false) { int n = x.size(); writable::doubles out(n); out[0] = x[0]; if (na_rm == true) { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = y1 * 1.0; } else { if (ISNAN(y1)) { out[i] = 1.0 * y2; } else { out[i] = y1 * y2; } } } } else { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = NA_REAL; } else { if (ISNAN(y1)) { out[i] = NA_REAL; } else { out[i] = y1 * y2; } } } } return out; } ``` Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes. ## Cumulative minimum The next function calculates the cumulative minimum of the elements of a vector. ```cpp [[cpp4r::register]] doubles cummin_cpp(doubles x, bool na_rm = false) { int n = x.size(); writable::doubles out(n); out[0] = x[0]; if (na_rm == true) { for (int i = 1; i < n; ++i) { double y1 = x[i - 1], y2 = x[i]; if (ISNAN(y1)) { out[i] = y2; } else { out[i] = std::min(y1, y2); } } } else { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = NA_REAL; } else { if (ISNAN(y1)) { out[i] = NA_REAL; } else { out[i] = std::min(y1, y2); } } } } return out; } ``` Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes. ## Cumulative maximum The next function calculates the cumulative maximum of the elements of a vector. ```cpp [[cpp4r::register]] doubles cummax_cpp(doubles x, bool na_rm = false) { int n = x.size(); writable::doubles out(n); out[0] = x[0]; if (na_rm == true) { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y1)) { out[i] = y2; } else { out[i] = std::max(y1, y2); } } } else { for (int i = 1; i < n; ++i) { double y1 = out[i - 1], y2 = x[i]; if (ISNAN(y2)) { out[i] = NA_REAL; } else { if (ISNAN(y1)) { out[i] = NA_REAL; } else { out[i] = std::max(y1, y2); } } } } return out; } ``` Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes.