Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:48:09

0001 //           Copyright Maksym Zhelyenzyakov 2025-2026.
0002 // Distributed under the Boost Software License, Version 1.0.
0003 //      (See accompanying file LICENSE_1_0.txt or copy at
0004 //           https://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef REVERSE_MODE_AUTODIFF_ERF_OVERLOADS_HPP
0006 #define REVERSE_MODE_AUTODIFF_ERF_OVERLOADS_HPP
0007 
0008 #include <boost/math/constants/constants.hpp>
0009 #include <boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp>
0010 
0011 #ifdef BOOST_MATH_REVERSE_MODE_ET_ON
0012 #include <boost/math/differentiation/detail/reverse_mode_autodiff_stl_et.hpp>
0013 #else
0014 #include <boost/math/differentiation/detail/reverse_mode_autodiff_stl_no_et.hpp>
0015 #endif
0016 
0017 #include <boost/math/differentiation/detail/reverse_mode_autodiff_utilities.hpp>
0018 #include <boost/math/special_functions/erf.hpp>
0019 
0020 namespace boost {
0021 namespace math {
0022 namespace differentiation {
0023 namespace reverse_mode {
0024 
0025 template<typename RealType, size_t DerivativeOrder, typename ARG>
0026 struct erf_expr;
0027 
0028 template<typename RealType, size_t DerivativeOrder, typename ARG>
0029 struct erfc_expr;
0030 
0031 template<typename RealType, size_t DerivativeOrder, typename ARG>
0032 struct erf_inv_expr;
0033 
0034 template<typename RealType, size_t DerivativeOrder, typename ARG>
0035 struct erfc_inv_expr;
0036 
0037 template<typename RealType, size_t DerivativeOrder, typename ARG>
0038 erf_expr<RealType, DerivativeOrder, ARG> erf(const expression<RealType, DerivativeOrder, ARG> &arg)
0039 {
0040     return erf_expr<RealType, DerivativeOrder, ARG>(arg, 0.0);
0041 }
0042 
0043 template<typename RealType, size_t DerivativeOrder, typename ARG>
0044 erfc_expr<RealType, DerivativeOrder, ARG> erfc(const expression<RealType, DerivativeOrder, ARG> &arg)
0045 {
0046     return erfc_expr<RealType, DerivativeOrder, ARG>(arg, 0.0);
0047 }
0048 
0049 template<typename RealType, size_t DerivativeOrder, typename ARG>
0050 erf_inv_expr<RealType, DerivativeOrder, ARG> erf_inv(
0051     const expression<RealType, DerivativeOrder, ARG> &arg)
0052 {
0053     return erf_inv_expr<RealType, DerivativeOrder, ARG>(arg, 0.0);
0054 }
0055 
0056 template<typename RealType, size_t DerivativeOrder, typename ARG>
0057 erfc_inv_expr<RealType, DerivativeOrder, ARG> erfc_inv(
0058     const expression<RealType, DerivativeOrder, ARG> &arg)
0059 {
0060     return erfc_inv_expr<RealType, DerivativeOrder, ARG>(arg, 0.0);
0061 }
0062 
0063 template<typename RealType, size_t DerivativeOrder, typename ARG>
0064 struct erf_expr : public abstract_unary_expression<RealType,
0065                                                    DerivativeOrder,
0066                                                    ARG,
0067                                                    erf_expr<RealType, DerivativeOrder, ARG>>
0068 {
0069     /** @brief erf(x)
0070     *
0071     * d/dx erf(x) = 2*exp(x^2)/sqrt(pi)
0072     *
0073     * */
0074     using inner_t = rvar_t<RealType, DerivativeOrder - 1>;
0075 
0076     explicit erf_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType v)
0077         : abstract_unary_expression<RealType,
0078                                     DerivativeOrder,
0079                                     ARG,
0080                                     erf_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0081 
0082     inner_t evaluate() const
0083     {
0084         return detail::if_functional_dispatch<(DerivativeOrder > 1)>(
0085             [this](auto &&x) { return reverse_mode::erf(std::forward<decltype(x)>(x)); },
0086             [this](auto &&x) { return boost::math::erf(std::forward<decltype(x)>(x)); },
0087             this->arg.evaluate());
0088     }
0089     static const inner_t derivative(const inner_t &argv,
0090                                     const inner_t & /*v*/,
0091                                     const RealType & /*constant*/)
0092     {
0093         BOOST_MATH_STD_USING
0094         return static_cast<RealType>(2.0) * exp(-argv * argv) / sqrt(constants::pi<RealType>());
0095     }
0096 };
0097 
0098 template<typename RealType, size_t DerivativeOrder, typename ARG>
0099 struct erfc_expr : public abstract_unary_expression<RealType,
0100                                                     DerivativeOrder,
0101                                                     ARG,
0102                                                     erfc_expr<RealType, DerivativeOrder, ARG>>
0103 {
0104     /** @brief erfc(x)
0105     *
0106     * d/dx erf(x) = -2*exp(x^2)/sqrt(pi)
0107     *
0108     * */
0109 
0110     using inner_t = rvar_t<RealType, DerivativeOrder - 1>;
0111 
0112     explicit erfc_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType v)
0113         : abstract_unary_expression<RealType,
0114                                     DerivativeOrder,
0115                                     ARG,
0116                                     erfc_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0117 
0118     inner_t evaluate() const
0119     {
0120         return detail::if_functional_dispatch<((DerivativeOrder > 1))>(
0121             [this](auto &&x) { return reverse_mode::erfc(std::forward<decltype(x)>(x)); },
0122             [this](auto &&x) { return boost::math::erfc(std::forward<decltype(x)>(x)); },
0123             this->arg.evaluate());
0124     }
0125     static const inner_t derivative(const inner_t &argv,
0126                                     const inner_t & /*v*/,
0127                                     const RealType & /*constant*/)
0128     {
0129         BOOST_MATH_STD_USING
0130         return static_cast<RealType>(-2.0) * exp(-argv * argv) / sqrt(constants::pi<RealType>());
0131     }
0132 };
0133 
0134 template<typename RealType, size_t DerivativeOrder, typename ARG>
0135 struct erf_inv_expr : public abstract_unary_expression<RealType,
0136                                                        DerivativeOrder,
0137                                                        ARG,
0138                                                        erf_inv_expr<RealType, DerivativeOrder, ARG>>
0139 {
0140     /** @brief erf(x)
0141     *
0142     * d/dx erf(x) = 2*exp(x^2)/sqrt(pi)
0143     *
0144     * */
0145 
0146     using inner_t = rvar_t<RealType, DerivativeOrder - 1>;
0147 
0148     explicit erf_inv_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0149                           const RealType                                    v)
0150         : abstract_unary_expression<RealType,
0151                                     DerivativeOrder,
0152                                     ARG,
0153                                     erf_inv_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0154 
0155     inner_t evaluate() const
0156     {
0157         return detail::if_functional_dispatch<((DerivativeOrder > 1))>(
0158             [this](auto &&x) { return reverse_mode::erf_inv(std::forward<decltype(x)>(x)); },
0159             [this](auto &&x) { return boost::math::erf_inv(std::forward<decltype(x)>(x)); },
0160             this->arg.evaluate());
0161     }
0162     static const inner_t derivative(const inner_t &argv,
0163                                     const inner_t & /*v*/,
0164                                     const RealType & /*constant*/)
0165     {
0166         BOOST_MATH_STD_USING
0167         return detail::if_functional_dispatch<((DerivativeOrder > 1))>(
0168             [](auto &&x) {
0169                 return static_cast<RealType>(0.5) * sqrt(constants::pi<RealType>())
0170                        * reverse_mode::exp(
0171                            reverse_mode::pow(reverse_mode::erf_inv(x), static_cast<RealType>(2.0)));
0172             },
0173             [](auto &&x) {
0174                 return static_cast<RealType>(0.5) * sqrt(constants::pi<RealType>())
0175                        * exp(pow(boost::math::erf_inv(x), static_cast<RealType>(2.0)));
0176             },
0177             argv);
0178     }
0179 };
0180 
0181 template<typename RealType, size_t DerivativeOrder, typename ARG>
0182 struct erfc_inv_expr
0183     : public abstract_unary_expression<RealType,
0184                                        DerivativeOrder,
0185                                        ARG,
0186                                        erfc_inv_expr<RealType, DerivativeOrder, ARG>>
0187 {
0188     /** @brief erfc(x)
0189     *
0190     * d/dx erf(x) = -2*exp(x^2)/sqrt(pi)
0191     *
0192     * */
0193 
0194     using inner_t = rvar_t<RealType, DerivativeOrder - 1>;
0195 
0196     explicit erfc_inv_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0197                            const RealType                                    v)
0198         : abstract_unary_expression<RealType,
0199                                     DerivativeOrder,
0200                                     ARG,
0201                                     erfc_inv_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0202 
0203     inner_t evaluate() const
0204     {
0205         return detail::if_functional_dispatch<((DerivativeOrder > 1))>(
0206             [this](auto &&x) { return reverse_mode::erfc_inv(std::forward<decltype(x)>(x)); },
0207             [this](auto &&x) { return boost::math::erfc_inv(std::forward<decltype(x)>(x)); },
0208             this->arg.evaluate());
0209     }
0210     static const inner_t derivative(const inner_t &argv,
0211                                     const inner_t & /*v*/,
0212                                     const RealType & /*constant*/)
0213     {
0214         BOOST_MATH_STD_USING
0215         return detail::if_functional_dispatch<((DerivativeOrder > 1))>(
0216             [](auto &&x) {
0217                 return static_cast<RealType>(-0.5) * sqrt(constants::pi<RealType>())
0218                        * reverse_mode::exp(reverse_mode::pow(reverse_mode::erfc_inv(x),
0219                                                              static_cast<RealType>(2.0)));
0220             },
0221             [](auto &&x) {
0222                 return static_cast<RealType>(-0.5) * sqrt(constants::pi<RealType>())
0223                        * exp(pow(boost::math::erfc_inv(x), static_cast<RealType>(2.0)));
0224             },
0225             argv);
0226     }
0227 };
0228 
0229 } // namespace reverse_mode
0230 } // namespace differentiation
0231 } // namespace math
0232 } // namespace boost
0233 
0234 #endif // REVERSE_MODE_AUTODIFF_ERF_OVERLOADS_HPP