| 978 | */ |
| 979 | template<typename XAt, typename YAt> |
| 980 | inline void dsAccumulateBuckets( |
| 981 | std::size_t n, int w, ssfp_t xmin, ssfp_t scaleX, XAt xAt, YAt yAt, DownsampleWorkspace* ws) |
| 982 | { |
| 983 | auto getColFromX = [&](ssfp_t x) -> std::size_t { |
| 984 | auto c = static_cast<long>((x - xmin) * scaleX); |
| 985 | if (c < 0) |
| 986 | c = 0; |
| 987 | |
| 988 | else if (c >= w) |
| 989 | c = w - 1; |
| 990 | |
| 991 | return std::size_t(c); |
| 992 | }; |
| 993 | |
| 994 | for (std::size_t i = 0; i < n; ++i) { |
| 995 | const ssfp_t xv = xAt(i); |
| 996 | const ssfp_t yv = yAt(i); |
| 997 | if (!std::isfinite(xv) || !std::isfinite(yv)) |
| 998 | continue; |
| 999 | |
| 1000 | const std::size_t c = getColFromX(xv); |
| 1001 | |
| 1002 | if (ws->cnt[c] == 0) { |
| 1003 | ws->firstI[c] = ws->lastI[c] = i; |
| 1004 | ws->minI[c] = ws->maxI[c] = i; |
| 1005 | ws->minY[c] = ws->maxY[c] = yv; |
| 1006 | ws->cnt[c] = 1; |
| 1007 | continue; |
| 1008 | } |
| 1009 | |
| 1010 | if (yv < ws->minY[c]) { |
| 1011 | ws->minY[c] = yv; |
| 1012 | ws->minI[c] = i; |
| 1013 | } |
| 1014 | |
| 1015 | if (yv > ws->maxY[c]) { |
| 1016 | ws->maxY[c] = yv; |
| 1017 | ws->maxI[c] = i; |
| 1018 | } |
| 1019 | |
| 1020 | ws->lastI[c] = i; |
| 1021 | ++ws->cnt[c]; |
| 1022 | } |
| 1023 | } |
| 1024 | |
| 1025 | /** |
| 1026 | * @brief Emit time-ordered first/min/max/last points for a single column. |
no test coverage detected