Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #pragma once 6 : 7 : #include <algorithm> 8 : #include <tuple> 9 : 10 : #include "scipp/core/except.h" 11 : 12 : namespace scipp::core { 13 : 14 : /// Return params for computing bin index for linear edges (constant bin width). 15 22895631 : constexpr static auto linear_edge_params = [](const auto &edges) { 16 22895631 : auto len = scipp::size(edges) - 1; 17 22895631 : const auto offset = edges.front(); 18 22895631 : const auto nbin = len; 19 22895631 : const auto scale = static_cast<double>(nbin) / (edges.back() - edges.front()); 20 22895631 : return std::tuple{offset, nbin, scale}; 21 : }; 22 : 23 : namespace expect::histogram { 24 1334 : template <class T> void sorted_edges(const T &edges) { 25 1334 : if (!std::is_sorted(edges.begin(), edges.end())) 26 1 : throw except::BinEdgeError("Bin edges of histogram must be sorted."); 27 1333 : } 28 : } // namespace expect::histogram 29 : 30 : template <class Index, class T, class Edges, class Params> 31 30910276 : Index get_bin(const T &x, const Edges &edges, const Params ¶ms) { 32 : // Explicitly check for x outside edges here as otherwise we may run into an 33 : // integer overflow when converting the "bin" computation result to `Index`. 34 30910276 : if (x < edges.front() || x >= edges.back()) 35 109985 : return -1; 36 30800291 : const auto [offset, nbin, scale] = params; 37 30800291 : Index bin = (x - offset) * scale; 38 30800291 : bin = std::clamp(bin, Index(0), Index(nbin - 1)); 39 30800291 : if (x < edges[bin]) { 40 88 : return bin - 1; 41 30800203 : } else if (x >= edges[bin + 1]) { 42 2220 : return bin + 1; 43 : } else { 44 30797983 : return bin; 45 : } 46 : } 47 : 48 : } // namespace scipp::core