File indexing completed on 2026-08-17 08:48:09
0001
0002
0003
0004
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
0070
0071
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 & ,
0091 const RealType & )
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
0105
0106
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 & ,
0127 const RealType & )
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
0141
0142
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 & ,
0164 const RealType & )
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
0189
0190
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 & ,
0212 const RealType & )
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 }
0230 }
0231 }
0232 }
0233
0234 #endif