// Copyright Maksym Zhelyenzyakov 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_OPTIMIZATION_DETAIL_DIFFERENTIABLE_OPT_UTILITIES_HPP #define BOOST_MATH_OPTIMIZATION_DETAIL_DIFFERENTIABLE_OPT_UTILITIES_HPP #include #include #include #include #include namespace boost { namespace math { namespace optimization { namespace rdiff = boost::math::differentiation::reverse_mode; /** @brief> helper to get the underlying realtype from * update policy * */ template struct update_policy_real_type; template class UpdPol, typename RealType> struct update_policy_real_type> { using type = RealType; }; template using update_policy_real_type_t = typename update_policy_real_type::type>::type; /** @brief> get realtype from argument container * */ template struct argument_container_t { using type = typename argument_container_t::type>::type; }; template struct argument_container_t> { using type = ValueType; }; template struct argument_container_t, N>> { using type = RealType; }; template class Container, typename ValueType, typename... Args> struct argument_container_t> { using type = ValueType; }; template class Container, typename RealType, std::size_t N, typename... Args> struct argument_container_t, Args...>> { using type = RealType; }; /******************************************************************************/ /** @brief simple blas helpers */ template auto dot(const Container& x, const Container& y) -> typename Container::value_type { using T = typename Container::value_type; BOOST_MATH_ASSERT(x.size() == y.size()); return std::inner_product(x.begin(), x.end(), y.begin(), T(0)); } template auto norm_2(const Container& x) -> typename Container::value_type { return sqrt(dot(x, x)); } template auto norm_1(const Container& x) -> typename Container::value_type { using T = typename Container::value_type; T ret{ 0 }; for (auto& xi : x) { ret += abs(xi); } return ret; } template T norm_inf(const std::vector& x) { BOOST_ASSERT(!x.empty()); T max_val = std::abs(x[0]); const std::size_t n = x.size(); for (std::size_t i = 1; i < n; ++i) { const T abs_val = std::abs(x[i]); if (abs_val > max_val) max_val = abs_val; } return max_val; } /** @brief alpha*x (alpha is scalar, x is vector */ template void scale(Container& x, const RealType& alpha) { for (auto& xi : x) { xi *= alpha; } } /** @brief y += alpha * x */ template void axpy(RealType alpha, const ContainerX& x, ContainerY& y) { BOOST_MATH_ASSERT(x.size() == y.size()); const size_t n = x.size(); for (size_t i = 0; i < n; ++i) { y[i] += alpha * x[i]; } } /******************************************************************************/ template std::vector random_vector(size_t n) { /** @brief> generates a random std::vector of size n * using mt19937 algorithm */ static std::mt19937 rng{ std::random_device{}() }; static std::uniform_real_distribution dist(0.0, 1.0); std::vector result(n); std::generate(result.begin(), result.end(), [&] { return static_cast(dist(rng)); }); return result; } } // namespace optimization } // namespace math } // namespace boost #endif