/// @file grotto/piecewise.hpp /// @brief Horner evaluation of a cubic and a bound-selected piece. /// @details `eval_horner` evaluates one polynomial. `piecewise_eval` selects /// the piece whose upper bound is the first entry of `bounds` /// strictly greater than `x`. /// @author Ryan Henry /// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors) /// @license Released under a GNU General Public v2.0 (GPLv2) license; /// see [LICENSE.md](@ref license) for details. #ifndef LIBDPF_INCLUDE_GROTTO_PIECEWISE_HPP__ #define LIBDPF_INCLUDE_GROTTO_PIECEWISE_HPP__ #include #include #include #include "hedley/hedley.h" namespace grotto { namespace polynomials { template using poly_constant = std::array; template using poly_linear = std::array; template using poly_quadratic = std::array; template using poly_cubic = std::array; template HEDLEY_PURE HEDLEY_NO_THROW constexpr auto eval_horner(const poly_constant & f, T x) noexcept { return f[0]; } template HEDLEY_PURE HEDLEY_NO_THROW constexpr auto eval_horner(const poly_linear & f, T x) noexcept { return f[1] * x + f[0]; } template HEDLEY_PURE HEDLEY_NO_THROW constexpr auto eval_horner(const poly_quadratic & f, T x) noexcept { return (f[2] * x + f[1]) * x + f[0]; } template HEDLEY_PURE HEDLEY_NO_THROW constexpr auto eval_horner(const poly_cubic & f, T x) noexcept { return ((f[3] * x + f[2]) * x + f[1]) * x + f[0]; } template HEDLEY_PURE HEDLEY_NO_THROW auto piecewise_eval(const std::array, N1> & polys, const std::array & bounds, T x) noexcept { auto it = std::upper_bound(std::cbegin(bounds), std::cend(bounds), x, [](const T & lhs, const T & rhs){ return lhs < rhs; }); auto i = std::distance(std::cbegin(bounds), it); return eval_horner(polys[i], x); } } // namespace polynomials } // namespace grotto #endif // LIBDPF_INCLUDE_GROTTO_PIECEWISE_HPP__