Back to home page

EIC code displayed by LXR

 
 

    


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

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_STL_OVERLOADS
0006 #define REVERSE_MODE_AUTODIFF_STL_OVERLOADS
0007 /* stl support : expressions */
0008 
0009 #ifdef BOOST_MATH_REVERSE_MODE_ET_ON
0010 #include <boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_et.hpp>
0011 #else
0012 #include <boost/math/differentiation/detail/reverse_mode_autodiff_basic_ops_no_et.hpp>
0013 #endif
0014 
0015 #include <boost/math/differentiation/detail/reverse_mode_autodiff_expression_template_base.hpp>
0016 #include <boost/math/special_functions/round.hpp>
0017 #include <boost/math/special_functions/trunc.hpp>
0018 #include <cmath>
0019 #include <complex>
0020 namespace boost {
0021 namespace math {
0022 namespace differentiation {
0023 namespace reverse_mode {
0024 template<typename RealType, size_t DerivativeOrder, typename ARG>
0025 struct fabs_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, fabs_expr<RealType,DerivativeOrder, ARG>>
0026 {
0027     /** @brief
0028     * |x|
0029     * d/dx |x| = 1 if x > 0
0030     *          -1 if x <= 0
0031     *
0032     * the choice is arbitrary and for optimization it is most likely
0033     * more correct to chose this convention over d/dx = 0  at x = 0
0034     * to avoid vanishing gradients
0035     * */
0036     using inner_t = rvar_t<RealType, DerivativeOrder - 1>;
0037 
0038     explicit fabs_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0039         : abstract_unary_expression<RealType,
0040                                     DerivativeOrder,
0041                                     ARG,
0042                                     fabs_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0043 
0044     inner_t evaluate() const
0045     {
0046         BOOST_MATH_STD_USING
0047         return fabs(this->arg.evaluate());
0048     }
0049     static const inner_t derivative(const inner_t &argv,
0050                                     const inner_t & /*v*/,
0051                                     const RealType & /*constant*/)
0052     {
0053         return argv > 0.0 ? inner_t{static_cast<RealType>(1.0)}
0054                           : inner_t{static_cast<RealType>(-1.0)};
0055     }
0056 };
0057 
0058 template<typename RealType, size_t DerivativeOrder, typename ARG>
0059 struct ceil_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, ceil_expr<RealType,DerivativeOrder, ARG>>
0060 {
0061     /** @brief ceil(1.11) = 2.0
0062     *
0063     * d/dx ceil(x) = 0.0 for all x
0064     *
0065     * we avoid problematic points at x = 1,2,3...
0066     * as with optimization its most likely intented
0067     * this function's derivative is 0.0;
0068     * */
0069     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0070 
0071     explicit ceil_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0072         : abstract_unary_expression<RealType,
0073                                     DerivativeOrder,
0074                                     ARG,
0075                                     ceil_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0076 
0077     inner_t evaluate() const
0078     {
0079         BOOST_MATH_STD_USING
0080         return ceil(this->arg.evaluate());
0081     }
0082     static const inner_t derivative(const inner_t & /*argv*/,
0083                                     const inner_t & /*v*/,
0084                                     const RealType & /*constant*/)
0085     {
0086         return inner_t{0.0};
0087     }
0088 };
0089 
0090 template<typename RealType, size_t DerivativeOrder, typename ARG>
0091 struct floor_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, floor_expr<RealType,DerivativeOrder, ARG>>
0092 {
0093     /** @brief floor(1.11) = 1.0, floor(-1.11) = 2
0094     *
0095     * d/dx floor(x) = 0.0 for all x
0096     *
0097     * we avoid problematic points at x = 1,2,3...
0098     * as with optimization its most likely intented
0099     * this function's derivative is 0.0;
0100     * */
0101     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0102 
0103     explicit floor_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0104                         const RealType                                   &v)
0105         : abstract_unary_expression<RealType,
0106                                     DerivativeOrder,
0107                                     ARG,
0108                                     floor_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0109 
0110     inner_t evaluate() const
0111     {
0112         BOOST_MATH_STD_USING
0113         return floor(this->arg.evaluate());
0114     }
0115     static const inner_t derivative(const inner_t & /*argv*/,
0116                                     const inner_t & /*v*/,
0117                                     const RealType & /*constant*/)
0118     {
0119         return inner_t{0.0};
0120     }
0121 };
0122 
0123 template<typename RealType, size_t DerivativeOrder, typename ARG>
0124 struct trunc_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, trunc_expr<RealType,DerivativeOrder, ARG>>
0125 {
0126     /** @brief trunc(1.11) = 1.0, trunc(-1.11) = -1.0
0127     *
0128     * d/dx trunc(x) = 0.0 for all x
0129     *
0130     * we avoid problematic points at x = 1,2,3...
0131     * as with optimization its most likely intented
0132     * this function's derivative is 0.0;
0133     * */
0134     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0135 
0136     explicit trunc_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0137                         const RealType                                   &v)
0138         : abstract_unary_expression<RealType,
0139                                     DerivativeOrder,
0140                                     ARG,
0141                                     trunc_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0142 
0143     inner_t evaluate() const
0144     {
0145         BOOST_MATH_STD_USING
0146         return trunc(this->arg.evaluate());
0147     }
0148     static const inner_t derivative(const inner_t & /*argv*/,
0149                                     const inner_t & /*v*/,
0150                                     const RealType & /*constant*/)
0151     {
0152         return inner_t{0.0};
0153     }
0154 };
0155 
0156 template<typename RealType, size_t DerivativeOrder, typename ARG>
0157 struct exp_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, exp_expr<RealType,DerivativeOrder, ARG>>
0158 {
0159     /** @brief exp(x)
0160     *
0161     * d/dx exp(x) = exp(x)
0162     *
0163     * */
0164     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0165 
0166     explicit exp_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0167         : abstract_unary_expression<RealType,
0168                                     DerivativeOrder,
0169                                     ARG,
0170                                     exp_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0171 
0172     inner_t evaluate() const
0173     {
0174         BOOST_MATH_STD_USING
0175         return exp(this->arg.evaluate());
0176     }
0177     static const inner_t derivative(const inner_t &argv,
0178                                     const inner_t & /*v*/,
0179                                     const RealType & /*constant*/)
0180     {
0181         BOOST_MATH_STD_USING
0182         return exp(argv);
0183     }
0184 };
0185 
0186 template<typename RealType, size_t DerivativeOrder, typename LHS, typename RHS>
0187 struct pow_expr
0188     : public abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, pow_expr<RealType, DerivativeOrder, LHS, RHS>>
0189 {
0190     /** @brief pow(x,y)
0191      *  d/dx pow(x,y) = y pow (x, y-1)
0192      *  d/dy pow(x,y) = pow(x,y) log(x)
0193     * */
0194     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0195     // Explicitly define constructor to forward to base class
0196     explicit pow_expr(const expression<RealType, DerivativeOrder, LHS> &left_hand_expr,
0197                       const expression<RealType, DerivativeOrder, RHS> &right_hand_expr)
0198         : abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, pow_expr<RealType, DerivativeOrder, LHS, RHS>>(
0199               left_hand_expr, right_hand_expr)
0200     {}
0201 
0202     inner_t evaluate() const
0203     {
0204         BOOST_MATH_STD_USING
0205         return pow(this->lhs.evaluate(), this->rhs.evaluate());
0206     };
0207     static const inner_t left_derivative(const inner_t &l, const inner_t &r, const inner_t & /*v*/)
0208     {
0209         BOOST_MATH_STD_USING
0210         return r * pow(l, r - static_cast<RealType>(1.0));
0211     };
0212     static const inner_t right_derivative(const inner_t &l, const inner_t &r, const inner_t & /*v*/)
0213     {
0214         BOOST_MATH_STD_USING
0215         return pow(l, r) * log(l);
0216     };
0217 };
0218 
0219 template<typename RealType, size_t DerivativeOrder, typename ARG>
0220 struct expr_pow_float_expr
0221     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, expr_pow_float_expr<RealType,DerivativeOrder, ARG>>
0222 {
0223     /** @brief pow(rvar,float)
0224       */
0225     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0226 
0227     explicit expr_pow_float_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0228                                  const RealType                                   &v)
0229         : abstract_unary_expression<RealType,
0230                                     DerivativeOrder,
0231                                     ARG,
0232                                     expr_pow_float_expr<RealType, DerivativeOrder, ARG>>(arg_expr,
0233                                                                                          v){};
0234 
0235     inner_t evaluate() const
0236     {
0237         BOOST_MATH_STD_USING
0238         return pow(this->arg.evaluate(), this->constant);
0239     }
0240     static const inner_t derivative(const inner_t &argv, const inner_t & /*v*/, const RealType &constant)
0241     {
0242         BOOST_MATH_STD_USING
0243         return inner_t{constant} * pow(argv, inner_t{constant - 1});
0244     }
0245 };
0246 
0247 template<typename RealType, size_t DerivativeOrder, typename ARG>
0248 struct float_pow_expr_expr
0249     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, float_pow_expr_expr<RealType,DerivativeOrder, ARG>>
0250 {
0251     /** @brief pow(float, rvar)
0252       * */
0253     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0254 
0255     explicit float_pow_expr_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0256                                  const RealType                                   &v)
0257         : abstract_unary_expression<RealType,
0258                                     DerivativeOrder,
0259                                     ARG,
0260                                     float_pow_expr_expr<RealType, DerivativeOrder, ARG>>(arg_expr,
0261                                                                                          v){};
0262 
0263     inner_t evaluate() const
0264     {
0265         BOOST_MATH_STD_USING
0266         return pow(this->constant, this->arg.evaluate());
0267     }
0268     static const inner_t derivative(const inner_t &argv, const inner_t & /*v*/, const RealType &constant)
0269     {
0270         BOOST_MATH_STD_USING
0271         return pow(constant, argv) * log(constant);
0272     }
0273 };
0274 
0275 template<typename RealType, size_t DerivativeOrder, typename ARG>
0276 struct sqrt_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, sqrt_expr<RealType,DerivativeOrder, ARG>>
0277 {
0278     /** @brief  sqrt(x)
0279      *  d/dx sqrt(x) = 1/(2 sqrt(x))
0280     * */
0281     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0282 
0283     explicit sqrt_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0284         : abstract_unary_expression<RealType,
0285                                     DerivativeOrder,
0286                                     ARG,
0287                                     sqrt_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0288 
0289     inner_t evaluate() const
0290     {
0291         BOOST_MATH_STD_USING
0292         return sqrt(this->arg.evaluate());
0293     }
0294     static const inner_t derivative(const inner_t &argv,
0295                                     const inner_t & /*v*/,
0296                                     const RealType & /*constant*/)
0297     {
0298         BOOST_MATH_STD_USING
0299         return static_cast<RealType>(1.0) / (static_cast<RealType>(2.0) * sqrt(argv));
0300     }
0301 };
0302 
0303 template<typename RealType, size_t DerivativeOrder, typename ARG>
0304 struct log_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, log_expr<RealType,DerivativeOrder, ARG>>
0305 {
0306     /** @brief log(x)
0307      *  d/dx log(x) = 1/x
0308       * */
0309     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0310 
0311     explicit log_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0312         : abstract_unary_expression<RealType,
0313                                     DerivativeOrder,
0314                                     ARG,
0315                                     log_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0316 
0317     inner_t evaluate() const
0318     {
0319         BOOST_MATH_STD_USING
0320         return log(this->arg.evaluate());
0321     }
0322     static const inner_t derivative(const inner_t &argv,
0323                                     const inner_t & /*v*/,
0324                                     const RealType & /*constant*/)
0325     {
0326         return static_cast<RealType>(1.0) / argv;
0327     }
0328 };
0329 
0330 template<typename RealType, size_t DerivativeOrder, typename ARG>
0331 struct cos_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, cos_expr<RealType,DerivativeOrder, ARG>>
0332 {
0333     /** @brief cos(x)
0334      *  d/dx cos(x) = -sin(x)
0335       * */
0336     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0337 
0338     explicit cos_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0339         : abstract_unary_expression<RealType,
0340                                     DerivativeOrder,
0341                                     ARG,
0342                                     cos_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0343 
0344     inner_t evaluate() const
0345     {
0346         BOOST_MATH_STD_USING
0347         return cos(this->arg.evaluate());
0348     }
0349     static const inner_t derivative(const inner_t &argv,
0350                                     const inner_t & /*v*/,
0351                                     const RealType & /*constant*/)
0352     {
0353         BOOST_MATH_STD_USING
0354         return -sin(argv);
0355     }
0356 };
0357 
0358 template<typename RealType, size_t DerivativeOrder, typename ARG>
0359 struct sin_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, sin_expr<RealType,DerivativeOrder, ARG>>
0360 {
0361     /** @brief sin(x)
0362      *  d/dx sin(x) = cos(x)
0363       * */
0364     using arg_type   = ARG;
0365     using value_type = RealType;
0366     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0367 
0368     explicit sin_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0369         : abstract_unary_expression<RealType,
0370                                     DerivativeOrder,
0371                                     ARG,
0372                                     sin_expr<RealType, DerivativeOrder, ARG>>(arg_expr, v){};
0373 
0374     inner_t evaluate() const
0375     {
0376         BOOST_MATH_STD_USING
0377         return sin(this->arg.evaluate());
0378     }
0379     static const inner_t derivative(const inner_t &argv,
0380                                     const inner_t & /*v*/,
0381                                     const RealType & /*constant*/)
0382     {
0383         BOOST_MATH_STD_USING
0384         return cos(argv);
0385     }
0386 };
0387 
0388 template<typename RealType, size_t DerivativeOrder, typename ARG>
0389 struct tan_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, tan_expr<RealType,DerivativeOrder, ARG>>
0390 {
0391     /** @brief tan(x)
0392      *  d/dx tan(x) = 1/cos^2(x)
0393       * */
0394     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0395 
0396     explicit tan_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0397         : abstract_unary_expression<RealType, DerivativeOrder, ARG, tan_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0398 
0399     inner_t evaluate() const
0400     {
0401         BOOST_MATH_STD_USING
0402         return tan(this->arg.evaluate());
0403     }
0404     static const inner_t derivative(const inner_t &argv,
0405                                     const inner_t & /*v*/,
0406                                     const RealType & /*constant*/)
0407     {
0408         BOOST_MATH_STD_USING
0409         return static_cast<RealType>(1.0) / (cos(argv) * cos(argv));
0410     }
0411 };
0412 
0413 template<typename RealType, size_t DerivativeOrder, typename ARG>
0414 struct acos_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, acos_expr<RealType,DerivativeOrder, ARG>>
0415 {
0416     /** @brief acos(x)
0417      *  d/dx acos(x) = -1/sqrt(1-x^2)
0418       * */
0419     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0420 
0421     explicit acos_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0422         : abstract_unary_expression<RealType, DerivativeOrder, ARG, acos_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0423 
0424     inner_t evaluate() const
0425     {
0426         BOOST_MATH_STD_USING
0427         return acos(this->arg.evaluate());
0428     }
0429     static const inner_t derivative(const inner_t &argv,
0430                                     const inner_t & /*v*/,
0431                                     const RealType & /*constant*/)
0432     {
0433         BOOST_MATH_STD_USING
0434         return static_cast<RealType>(-1.0) / sqrt(static_cast<RealType>(1.0) - argv * argv);
0435     }
0436 };
0437 
0438 template<typename RealType, size_t DerivativeOrder, typename ARG>
0439 struct asin_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, asin_expr<RealType,DerivativeOrder, ARG>>
0440 {
0441     /** @brief asin(x)
0442      *  d/dx asin =  1/sqrt(1-x^2)
0443       * */
0444     using arg_type   = ARG;
0445     using value_type = RealType;
0446     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0447 
0448     explicit asin_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0449         : abstract_unary_expression<RealType, DerivativeOrder, ARG, asin_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0450 
0451     inner_t evaluate() const
0452     {
0453         BOOST_MATH_STD_USING
0454         return asin(this->arg.evaluate());
0455     }
0456     static const inner_t derivative(const inner_t &argv,
0457                                     const inner_t & /*v*/,
0458                                     const RealType & /*constant*/)
0459     {
0460         BOOST_MATH_STD_USING
0461         return static_cast<RealType>(1.0) / sqrt(static_cast<RealType>(1.0) - argv * argv);
0462     }
0463 };
0464 
0465 template<typename RealType, size_t DerivativeOrder, typename ARG>
0466 struct atan_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, atan_expr<RealType,DerivativeOrder, ARG>>
0467 {
0468     /** @brief atan(x)
0469      *  d/dx atan(x) = 1/x^2+1
0470       * */
0471     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0472 
0473     explicit atan_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0474         : abstract_unary_expression<RealType, DerivativeOrder, ARG, atan_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0475 
0476     inner_t evaluate() const
0477     {
0478         BOOST_MATH_STD_USING
0479         return atan(this->arg.evaluate());
0480     }
0481     static const inner_t derivative(const inner_t &argv,
0482                                     const inner_t & /*v*/,
0483                                     const RealType & /*constant*/)
0484     {
0485         BOOST_MATH_STD_USING
0486         return static_cast<RealType>(1.0) / (static_cast<RealType>(1.0) + argv * argv);
0487     }
0488 };
0489 template<typename RealType, size_t DerivativeOrder, typename LHS, typename RHS>
0490 struct atan2_expr
0491     : public abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, atan2_expr<RealType, DerivativeOrder, LHS, RHS>>
0492 {
0493     /** @brief atan2(x,y)
0494     * */
0495     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0496     // Explicitly define constructor to forward to base class
0497     explicit atan2_expr(const expression<RealType, DerivativeOrder, LHS> &left_hand_expr,
0498                         const expression<RealType, DerivativeOrder, RHS> &right_hand_expr)
0499         : abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, atan2_expr<RealType, DerivativeOrder, LHS, RHS>>(
0500               left_hand_expr, right_hand_expr)
0501     {}
0502 
0503     inner_t evaluate() const
0504     {
0505         BOOST_MATH_STD_USING
0506         return atan2(this->lhs.evaluate(), this->rhs.evaluate());
0507     };
0508     static const inner_t left_derivative(const inner_t &l, const inner_t &r, const inner_t & /*v*/)
0509     {
0510         return r / (l * l + r * r);
0511     };
0512     static const inner_t right_derivative(const inner_t &l, const inner_t &r, const inner_t & /*v*/)
0513     {
0514         return -l / (l * l + r * r);
0515     };
0516 };
0517 
0518 template<typename RealType, size_t DerivativeOrder, typename ARG>
0519 struct atan2_left_float_expr
0520     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, atan2_left_float_expr<RealType,DerivativeOrder, ARG>>
0521 {
0522     /** @brief atan2(float,rvar) 
0523       * */
0524     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0525 
0526     explicit atan2_left_float_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0527         : abstract_unary_expression<RealType, DerivativeOrder, ARG, atan2_left_float_expr<RealType,DerivativeOrder, ARG>>(arg_expr,
0528                                                                                          v){};
0529 
0530     inner_t evaluate() const
0531     {
0532         BOOST_MATH_STD_USING
0533         return atan2(this->constant, this->arg.evaluate());
0534     }
0535     static const inner_t derivative(const inner_t &argv, const inner_t & /*v*/, const RealType &constant)
0536     {
0537         return -constant / (constant * constant + argv * argv);
0538     }
0539 };
0540 
0541 template<typename RealType, size_t DerivativeOrder, typename ARG>
0542 struct atan2_right_float_expr
0543     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, atan2_right_float_expr<RealType,DerivativeOrder, ARG>>
0544 {
0545     /** @brief atan2(rvar,float) 
0546       * */
0547     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0548 
0549     explicit atan2_right_float_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0550         : abstract_unary_expression<RealType, DerivativeOrder, ARG, atan2_right_float_expr<RealType,DerivativeOrder, ARG>>(arg_expr,
0551                                                                                           v){};
0552 
0553     inner_t evaluate() const
0554     {
0555         BOOST_MATH_STD_USING
0556         return atan2(this->arg.evaluate(), this->constant);
0557     }
0558     static const inner_t derivative(const inner_t &argv, const inner_t & /*v*/, const RealType &constant)
0559     {
0560         return constant / (constant * constant + argv * argv);
0561     }
0562 };
0563 
0564 template<typename RealType, size_t DerivativeOrder, typename ARG>
0565 struct round_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, round_expr<RealType,DerivativeOrder, ARG>>
0566 {
0567     /** @brief round(x)
0568      *  d/dx round = 0
0569       * */
0570     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0571 
0572     explicit round_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0573         : abstract_unary_expression<RealType, DerivativeOrder, ARG, round_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0574 
0575     inner_t evaluate() const
0576     {
0577         BOOST_MATH_STD_USING
0578         return round(this->arg.evaluate());
0579     }
0580     static const inner_t derivative(const inner_t & /*argv*/,
0581                                     const inner_t & /*v*/,
0582                                     const RealType & /*constant*/)
0583     {
0584         return inner_t{0.0};
0585     }
0586 };
0587 
0588 template<typename RealType, size_t DerivativeOrder, typename ARG>
0589 struct sinh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, sinh_expr<RealType,DerivativeOrder, ARG>>
0590 {
0591     /** @brief sinh(x)
0592      *  d/dx sinh(x) = cosh
0593       * */
0594     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0595 
0596     explicit sinh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0597         : abstract_unary_expression<RealType, DerivativeOrder, ARG, sinh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0598 
0599     inner_t evaluate() const
0600     {
0601         BOOST_MATH_STD_USING
0602         return sinh(this->arg.evaluate());
0603     }
0604     static const inner_t derivative(const inner_t &argv,
0605                                     const inner_t & /*v*/,
0606                                     const RealType & /*constant*/)
0607     {
0608         BOOST_MATH_STD_USING
0609         return cosh(argv);
0610     }
0611 };
0612 
0613 template<typename RealType, size_t DerivativeOrder, typename ARG>
0614 struct cosh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, cosh_expr<RealType,DerivativeOrder, ARG>>
0615 {
0616     /** @brief cosh(x)
0617      *  d/dx cosh(x) = sinh
0618       * */
0619     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0620 
0621     explicit cosh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0622         : abstract_unary_expression<RealType, DerivativeOrder, ARG, cosh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0623 
0624     inner_t evaluate() const
0625     {
0626         BOOST_MATH_STD_USING
0627         return cosh(this->arg.evaluate());
0628     }
0629     static const inner_t derivative(const inner_t &argv,
0630                                     const inner_t & /*v*/,
0631                                     const RealType & /*constant*/)
0632     {
0633         BOOST_MATH_STD_USING
0634         return sinh(argv);
0635     }
0636 };
0637 template<typename RealType, size_t DerivativeOrder, typename ARG>
0638 struct tanh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, tanh_expr<RealType,DerivativeOrder, ARG>>
0639 {
0640     /** @brief tanh(x)
0641      *  d/dx tanh(x) = 1/cosh^2
0642       * */
0643     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0644 
0645     explicit tanh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0646         : abstract_unary_expression<RealType, DerivativeOrder, ARG, tanh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0647 
0648     inner_t evaluate() const
0649     {
0650         BOOST_MATH_STD_USING
0651         return tanh(this->arg.evaluate());
0652     }
0653     static const inner_t derivative(const inner_t &argv,
0654                                     const inner_t & /*v*/,
0655                                     const RealType & /*constant*/)
0656     {
0657         BOOST_MATH_STD_USING
0658         return static_cast<RealType>(1.0) / (cosh(argv) * cosh(argv));
0659     }
0660 };
0661 
0662 template<typename RealType, size_t DerivativeOrder, typename ARG>
0663 struct log10_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, log10_expr<RealType,DerivativeOrder, ARG>>
0664 {
0665     /** @brief log10(x)
0666      *  d/dx log10(x) = 1/(x * log(10))
0667       * */
0668     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0669 
0670     explicit log10_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0671         : abstract_unary_expression<RealType, DerivativeOrder, ARG, log10_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0672 
0673     inner_t evaluate() const
0674     {
0675         BOOST_MATH_STD_USING
0676         return log10(this->arg.evaluate());
0677     }
0678     static const inner_t derivative(const inner_t &argv,
0679                                     const inner_t & /*v*/,
0680                                     const RealType & /*constant*/)
0681     {
0682         BOOST_MATH_STD_USING
0683         return static_cast<RealType>(1.0) / (argv * log(static_cast<RealType>(10.0)));
0684     }
0685 };
0686 
0687 template<typename RealType, size_t DerivativeOrder, typename ARG>
0688 struct acosh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, acosh_expr<RealType,DerivativeOrder, ARG>>
0689 {
0690     /** @brief acosh(x)
0691      *  d/dx acosh(x) = 1/(sqrt(x-1)sqrt(x+1)
0692       * */
0693     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0694 
0695     explicit acosh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0696         : abstract_unary_expression<RealType, DerivativeOrder, ARG, acosh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0697 
0698     inner_t evaluate() const
0699     {
0700         BOOST_MATH_STD_USING
0701         return acosh(this->arg.evaluate());
0702     }
0703     static const inner_t derivative(const inner_t &argv,
0704                                     const inner_t & /*v*/,
0705                                     const RealType & /*constant*/)
0706     {
0707         BOOST_MATH_STD_USING
0708         return static_cast<RealType>(1.0)
0709                / (sqrt(argv - static_cast<RealType>(1.0)) * sqrt(argv + static_cast<RealType>(1.0)));
0710     }
0711 };
0712 
0713 template<typename RealType, size_t DerivativeOrder, typename ARG>
0714 struct asinh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, asinh_expr<RealType,DerivativeOrder, ARG>>
0715 {
0716     /** @brief asinh(x)
0717      *  d/dx asinh(x) = 1/(sqrt(1+x^2))
0718       * */
0719     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0720 
0721     explicit asinh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0722         : abstract_unary_expression<RealType, DerivativeOrder, ARG, asinh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0723 
0724     inner_t evaluate() const
0725     {
0726         BOOST_MATH_STD_USING
0727         return asinh(this->arg.evaluate());
0728     }
0729     static const inner_t derivative(const inner_t &argv,
0730                                     const inner_t & /*v*/,
0731                                     const RealType & /*constant*/)
0732     {
0733         BOOST_MATH_STD_USING
0734         return static_cast<RealType>(1.0) / (sqrt(static_cast<RealType>(1.0) + argv * argv));
0735     }
0736 };
0737 
0738 template<typename RealType, size_t DerivativeOrder, typename ARG>
0739 struct atanh_expr : public abstract_unary_expression<RealType, DerivativeOrder, ARG, atanh_expr<RealType,DerivativeOrder, ARG>>
0740 {
0741     /** @brief atanh(x)
0742      *  d/dx atanh(x) = 1/(1-x^2)
0743       * */
0744     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0745 
0746     explicit atanh_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0747         : abstract_unary_expression<RealType, DerivativeOrder, ARG, atanh_expr<RealType,DerivativeOrder, ARG>>(arg_expr, v){};
0748 
0749     inner_t evaluate() const
0750     {
0751         BOOST_MATH_STD_USING
0752         return atanh(this->arg.evaluate());
0753     }
0754     static const inner_t derivative(const inner_t &argv,
0755                                     const inner_t & /*v*/,
0756                                     const RealType & /*constant*/)
0757     {
0758         BOOST_MATH_STD_USING
0759         return static_cast<RealType>(1.0) / (static_cast<RealType>(1.0) - argv * argv);
0760     }
0761 };
0762 template<typename RealType, size_t DerivativeOrder, typename LHS, typename RHS>
0763 struct fmod_expr
0764     : public abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, fmod_expr<RealType, DerivativeOrder, LHS, RHS>>
0765 {
0766     /** @brief 
0767     * */
0768     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0769     // Explicitly define constructor to forward to base class
0770     explicit fmod_expr(const expression<RealType, DerivativeOrder, LHS> &left_hand_expr,
0771                        const expression<RealType, DerivativeOrder, RHS> &right_hand_expr)
0772         : abstract_binary_expression<RealType, DerivativeOrder, LHS, RHS, fmod_expr<RealType, DerivativeOrder, LHS, RHS>>(
0773               left_hand_expr, right_hand_expr)
0774     {}
0775 
0776     inner_t evaluate() const
0777     {
0778         BOOST_MATH_STD_USING
0779         return fmod(this->lhs.evaluate(), this->rhs.evaluate());
0780     };
0781     static const inner_t left_derivative(const inner_t & /*l*/,
0782                                          const inner_t & /*r*/,
0783                                          const inner_t & /*v*/)
0784     {
0785         return inner_t{1.0};
0786     };
0787     static const inner_t right_derivative(const inner_t &l, const inner_t &r, const inner_t & /*v*/)
0788     {
0789         BOOST_MATH_STD_USING
0790         return static_cast<RealType>(-1.0) * trunc(l / r);
0791     };
0792 };
0793 
0794 template<typename RealType, size_t DerivativeOrder, typename ARG>
0795 struct fmod_left_float_expr
0796     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, fmod_left_float_expr<RealType,DerivativeOrder, ARG>>
0797 {
0798     /** @brief 
0799       * */
0800     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0801 
0802     explicit fmod_left_float_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr, const RealType &v)
0803         : abstract_unary_expression<RealType, DerivativeOrder, ARG, fmod_left_float_expr<RealType,DerivativeOrder, ARG>>(arg_expr,
0804                                                                                         v){};
0805 
0806     inner_t evaluate() const
0807     {
0808         BOOST_MATH_STD_USING
0809         return fmod(this->constant, this->arg.evaluate());
0810     }
0811     static const inner_t derivative(const inner_t &argv, const inner_t & /*v*/, const RealType &constant)
0812     {
0813         BOOST_MATH_STD_USING
0814         return static_cast<RealType>(-1.0) * trunc(constant / argv);
0815     }
0816 };
0817 
0818 template<typename RealType, size_t DerivativeOrder, typename ARG>
0819 struct fmod_right_float_expr
0820     : public abstract_unary_expression<RealType, DerivativeOrder, ARG, fmod_right_float_expr<RealType,DerivativeOrder, ARG>>
0821 {
0822     /** @brief
0823       * */
0824     using inner_t    = rvar_t<RealType, DerivativeOrder - 1>;
0825 
0826     explicit fmod_right_float_expr(const expression<RealType, DerivativeOrder, ARG> &arg_expr,
0827                                    const RealType                                   &v)
0828         : abstract_unary_expression<RealType,
0829                                     DerivativeOrder,
0830                                     ARG,
0831                                     fmod_right_float_expr<RealType, DerivativeOrder, ARG>>(arg_expr,
0832                                                                                            v){};
0833 
0834     inner_t evaluate() const
0835     {
0836         BOOST_MATH_STD_USING
0837         return fmod(this->arg.evaluate(), this->constant);
0838     }
0839     static const inner_t derivative(const inner_t & /*argv*/,
0840                                     const inner_t & /*v*/,
0841                                     const RealType & /*constant*/)
0842     {
0843         return inner_t{1.0};
0844     }
0845 };
0846 /**************************************************************************************************/
0847 
0848 } // namespace reverse_mode
0849 } // namespace differentiation
0850 } // namespace math
0851 } // namespace boost
0852 #endif