// (C) Copyright Nick Thompson, John Maddock 2023. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Module build check for boost::math::tools::evaluate_polynomial_estrin. It // consumes the exported Estrin polynomial evaluator through `import boost.math;` // and confirms all three overloads (general container, std::array, explicit // scratch space) resolve from a module consumer. Estrin evaluates // p(z) = c[0] + c[1] z + c[2] z^2 + ... with coefficients in ascending order. // The assertions use only mathematically-certain values: integer coefficients // and integer arguments keep every intermediate exactly representable, so the // results are exact. #ifndef BOOST_MATH_BUILD_MODULE #include #else import boost.math; #endif #include "math_unit_test.hpp" #ifndef BOOST_MATH_BUILD_MODULE #include #include #endif using boost::math::tools::evaluate_polynomial_estrin; // General RandomAccessContainer overload (allocates its own scratch vector). template void test_vector_overload() { // p(z) = 2 + 3 z + 4 z^2. std::vector coeffs {Real(2), Real(3), Real(4)}; CHECK_ULP_CLOSE(Real(2), evaluate_polynomial_estrin(coeffs, Real(0)), 0); // p(0) = c0 CHECK_ULP_CLOSE(Real(9), evaluate_polynomial_estrin(coeffs, Real(1)), 0); // p(1) = sum(coeffs) CHECK_ULP_CLOSE(Real(24), evaluate_polynomial_estrin(coeffs, Real(2)), 0); // 2 + 6 + 16 CHECK_ULP_CLOSE(Real(3), evaluate_polynomial_estrin(coeffs, Real(-1)), 0); // 2 - 3 + 4 // A single coefficient is the constant polynomial p(z) = c0 for all z. std::vector constant {Real(7)}; CHECK_ULP_CLOSE(Real(7), evaluate_polynomial_estrin(constant, Real(0)), 0); CHECK_ULP_CLOSE(Real(7), evaluate_polynomial_estrin(constant, Real(5)), 0); // No coefficients evaluates to zero for any argument. std::vector empty; CHECK_EQUAL(Real(0), evaluate_polynomial_estrin(empty, Real(3))); } // std::array overload: same value, no heap allocation for the scratch space. template void test_array_overload() { // p(z) = 1 + 2 z + 3 z^2 + 4 z^3. std::array coeffs {Real(1), Real(2), Real(3), Real(4)}; CHECK_ULP_CLOSE(Real(1), evaluate_polynomial_estrin(coeffs, Real(0)), 0); // p(0) = c0 CHECK_ULP_CLOSE(Real(10), evaluate_polynomial_estrin(coeffs, Real(1)), 0); // 1 + 2 + 3 + 4 CHECK_ULP_CLOSE(Real(49), evaluate_polynomial_estrin(coeffs, Real(2)), 0); // 1 + 4 + 12 + 32 } // Explicit scratch-space overload: the caller supplies working storage of at // least (n + 1) / 2 elements whose value type matches the argument. template void test_scratch_overload() { // p(z) = 5 + z^3. std::vector coeffs {Real(5), Real(0), Real(0), Real(1)}; std::vector scratch(2); CHECK_ULP_CLOSE(Real(5), evaluate_polynomial_estrin(coeffs, scratch, Real(0)), 0); // p(0) = 5 CHECK_ULP_CLOSE(Real(6), evaluate_polynomial_estrin(coeffs, scratch, Real(1)), 0); // 5 + 1 CHECK_ULP_CLOSE(Real(13), evaluate_polynomial_estrin(coeffs, scratch, Real(2)), 0); // 5 + 8 } int main() { test_vector_overload(); test_vector_overload(); test_array_overload(); test_array_overload(); test_scratch_overload(); test_scratch_overload(); return boost::math::test::report_errors(); }