LCOV - code coverage report
Current view: top level - lepton - Operation.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 274 316 86.7 %
Date: 2026-11-05 10:19:06 Functions: 53 57 93.0 %

          Line data    Source code
       1             : 
       2             : /* -------------------------------------------------------------------------- *
       3             :  *                                   lepton                                   *
       4             :  * -------------------------------------------------------------------------- *
       5             :  * This is part of the lepton expression parser.                              *
       6             :  * See https://openmm.org/development.                                        *
       7             :  *                                                                            *
       8             :  * Portions copyright (c) 2009-2021 Stanford University and the Authors.      *
       9             :  * Authors: Peter Eastman                                                     *
      10             :  * Contributors:                                                              *
      11             :  *                                                                            *
      12             :  * Permission is hereby granted, free of charge, to any person obtaining a    *
      13             :  * copy of this software and associated documentation files (the "Software"), *
      14             :  * to deal in the Software without restriction, including without limitation  *
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
      16             :  * and/or sell copies of the Software, and to permit persons to whom the      *
      17             :  * Software is furnished to do so, subject to the following conditions:       *
      18             :  *                                                                            *
      19             :  * The above copyright notice and this permission notice shall be included in *
      20             :  * all copies or substantial portions of the Software.                        *
      21             :  *                                                                            *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
      23             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
      25             :  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
      26             :  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
      27             :  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
      28             :  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
      29             :  * -------------------------------------------------------------------------- */
      30             : 
      31             : #include "Operation.h"
      32             : #include "ExpressionTreeNode.h"
      33             : #include "MSVC_erfc.h"
      34             : 
      35             : namespace PLMD {
      36             : using namespace lepton;
      37             : using namespace std;
      38             : 
      39       38930 : static bool isZero(const ExpressionTreeNode& node) {
      40       38930 :     if (node.getOperation().getId() != Operation::CONSTANT)
      41             :         return false;
      42       26057 :     return dynamic_cast<const Operation::Constant&>(node.getOperation()).getValue() == 0.0;
      43             : }
      44             : 
      45         222 : double Operation::Erf::evaluate(double* args, const map<string, double>& variables) const {
      46         222 :     return erf(args[0]);
      47             : }
      48             : 
      49         204 : double Operation::Erfc::evaluate(double* args, const map<string, double>& variables) const {
      50         204 :     return erfc(args[0]);
      51             : }
      52             : 
      53        6849 : ExpressionTreeNode Operation::Constant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      54        6849 :     return ExpressionTreeNode(new Operation::Constant(0.0));
      55             : }
      56             : 
      57       10881 : ExpressionTreeNode Operation::Variable::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      58       10881 :     if (variable == name)
      59        5636 :         return ExpressionTreeNode(new Operation::Constant(1.0));
      60        5245 :     return ExpressionTreeNode(new Operation::Constant(0.0));
      61             : }
      62             : 
      63           0 : ExpressionTreeNode Operation::Custom::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      64           0 :     if (function->getNumArguments() == 0)
      65           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
      66           0 :     ExpressionTreeNode result;
      67             :     bool foundTerm = false;
      68           0 :     for (int i = 0; i < getNumArguments(); i++) {
      69           0 :         if (!isZero(childDerivs[i])) {
      70           0 :             if (foundTerm)
      71           0 :                 result = ExpressionTreeNode(new Operation::Add(),
      72             :                                             result,
      73           0 :                                             ExpressionTreeNode(new Operation::Multiply(), ExpressionTreeNode(new Operation::Custom(*this, i), children), childDerivs[i]));
      74             :             else {
      75           0 :                 result = ExpressionTreeNode(new Operation::Multiply(), ExpressionTreeNode(new Operation::Custom(*this, i), children), childDerivs[i]);
      76             :                 foundTerm = true;
      77             :             }
      78             :         }
      79             :     }
      80           0 :     if (foundTerm)
      81           0 :         return result;
      82           0 :     return ExpressionTreeNode(new Operation::Constant(0.0));
      83           0 : }
      84             : 
      85        3902 : ExpressionTreeNode Operation::Add::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      86        3902 :     if (isZero(childDerivs[0]))
      87        1002 :         return childDerivs[1];
      88        2900 :     if (isZero(childDerivs[1]))
      89         872 :         return childDerivs[0];
      90        2028 :     return ExpressionTreeNode(new Operation::Add(), childDerivs[0], childDerivs[1]);
      91             : }
      92             : 
      93        2268 : ExpressionTreeNode Operation::Subtract::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      94        2268 :     if (isZero(childDerivs[0])) {
      95        1387 :         if (isZero(childDerivs[1]))
      96        1042 :             return ExpressionTreeNode(new Operation::Constant(0.0));
      97         345 :         return ExpressionTreeNode(new Operation::Negate(), childDerivs[1]);
      98             :     }
      99         881 :     if (isZero(childDerivs[1]))
     100         668 :         return childDerivs[0];
     101         213 :     return ExpressionTreeNode(new Operation::Subtract(), childDerivs[0], childDerivs[1]);
     102             : }
     103             : 
     104        8291 : ExpressionTreeNode Operation::Multiply::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     105        8291 :     if (isZero(childDerivs[0])) {
     106        5436 :         if (isZero(childDerivs[1]))
     107        2368 :             return ExpressionTreeNode(new Operation::Constant(0.0));
     108        3068 :         return ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]);
     109             :     }
     110        2855 :     if (isZero(childDerivs[1]))
     111        1113 :         return ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
     112        1742 :     return ExpressionTreeNode(new Operation::Add(),
     113        3484 :                               ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]),
     114        5226 :                               ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]));
     115             : }
     116             : 
     117        3184 : ExpressionTreeNode Operation::Divide::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     118        3184 :     ExpressionTreeNode subexp;
     119        3184 :     if (isZero(childDerivs[0])) {
     120        1124 :         if (isZero(childDerivs[1]))
     121         257 :             return ExpressionTreeNode(new Operation::Constant(0.0));
     122         867 :         subexp = ExpressionTreeNode(new Operation::Negate(), ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
     123             :     }
     124        2060 :     else if (isZero(childDerivs[1]))
     125        1938 :         subexp = ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
     126             :     else
     127         244 :         subexp = ExpressionTreeNode(new Operation::Subtract(),
     128         244 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
     129         366 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
     130        2927 :     return ExpressionTreeNode(new Operation::Divide(), subexp, ExpressionTreeNode(new Operation::Square(), children[1]));
     131        3184 : }
     132             : 
     133        1624 : ExpressionTreeNode Operation::Power::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     134        1624 :     return ExpressionTreeNode(new Operation::Add(),
     135        3248 :                               ExpressionTreeNode(new Operation::Multiply(),
     136        3248 :                                                  ExpressionTreeNode(new Operation::Multiply(),
     137             :                                                                     children[1],
     138        3248 :                                                                     ExpressionTreeNode(new Operation::Power(),
     139        3248 :                                                                                        children[0], ExpressionTreeNode(new Operation::AddConstant(-1.0), children[1]))),
     140             :                                                  childDerivs[0]),
     141        3248 :                               ExpressionTreeNode(new Operation::Multiply(),
     142        3248 :                                                  ExpressionTreeNode(new Operation::Multiply(),
     143        3248 :                                                                     ExpressionTreeNode(new Operation::Log(), children[0]),
     144        3248 :                                                                     ExpressionTreeNode(new Operation::Power(), children[0], children[1])),
     145        3248 :                                                  childDerivs[1]));
     146             : }
     147             : 
     148        2085 : ExpressionTreeNode Operation::Negate::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     149        2085 :     if (isZero(childDerivs[0]))
     150        1069 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     151        1016 :     return ExpressionTreeNode(new Operation::Negate(), childDerivs[0]);
     152             : }
     153             : 
     154         468 : ExpressionTreeNode Operation::Sqrt::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     155         468 :     if (isZero(childDerivs[0]))
     156          56 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     157         412 :     return ExpressionTreeNode(new Operation::Multiply(),
     158         824 :                               ExpressionTreeNode(new Operation::MultiplyConstant(0.5),
     159         824 :                                                  ExpressionTreeNode(new Operation::Reciprocal(),
     160         824 :                                                                     ExpressionTreeNode(new Operation::Sqrt(), children[0]))),
     161         412 :                               childDerivs[0]);
     162             : }
     163             : 
     164        1300 : ExpressionTreeNode Operation::Exp::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     165        1300 :     if (isZero(childDerivs[0]))
     166         121 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     167        1179 :     return ExpressionTreeNode(new Operation::Multiply(),
     168        2358 :                               ExpressionTreeNode(new Operation::Exp(), children[0]),
     169        1179 :                               childDerivs[0]);
     170             : }
     171             : 
     172         191 : ExpressionTreeNode Operation::Log::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     173         191 :     if (isZero(childDerivs[0]))
     174          25 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     175         166 :     return ExpressionTreeNode(new Operation::Multiply(),
     176         332 :                               ExpressionTreeNode(new Operation::Reciprocal(), children[0]),
     177         166 :                               childDerivs[0]);
     178             : }
     179             : 
     180         148 : ExpressionTreeNode Operation::Sin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     181         148 :     if (isZero(childDerivs[0]))
     182          37 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     183         111 :     return ExpressionTreeNode(new Operation::Multiply(),
     184         222 :                               ExpressionTreeNode(new Operation::Cos(), children[0]),
     185         111 :                               childDerivs[0]);
     186             : }
     187             : 
     188         343 : ExpressionTreeNode Operation::Cos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     189         343 :     if (isZero(childDerivs[0]))
     190          70 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     191         273 :     return ExpressionTreeNode(new Operation::Multiply(),
     192         546 :                               ExpressionTreeNode(new Operation::Negate(),
     193         546 :                                                  ExpressionTreeNode(new Operation::Sin(), children[0])),
     194         273 :                               childDerivs[0]);
     195             : }
     196             : 
     197           2 : ExpressionTreeNode Operation::Sec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     198           2 :     if (isZero(childDerivs[0]))
     199           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     200           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     201           4 :                               ExpressionTreeNode(new Operation::Multiply(),
     202           4 :                                                  ExpressionTreeNode(new Operation::Sec(), children[0]),
     203           4 :                                                  ExpressionTreeNode(new Operation::Tan(), children[0])),
     204           2 :                               childDerivs[0]);
     205             : }
     206             : 
     207           2 : ExpressionTreeNode Operation::Csc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     208           2 :     if (isZero(childDerivs[0]))
     209           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     210           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     211           4 :                               ExpressionTreeNode(new Operation::Negate(),
     212           4 :                                                  ExpressionTreeNode(new Operation::Multiply(),
     213           4 :                                                                     ExpressionTreeNode(new Operation::Csc(), children[0]),
     214           4 :                                                                     ExpressionTreeNode(new Operation::Cot(), children[0]))),
     215           2 :                               childDerivs[0]);
     216             : }
     217             : 
     218           2 : ExpressionTreeNode Operation::Tan::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     219           2 :     if (isZero(childDerivs[0]))
     220           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     221           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     222           4 :                               ExpressionTreeNode(new Operation::Square(),
     223           4 :                                                  ExpressionTreeNode(new Operation::Sec(), children[0])),
     224           2 :                               childDerivs[0]);
     225             : }
     226             : 
     227           2 : ExpressionTreeNode Operation::Cot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     228           2 :     if (isZero(childDerivs[0]))
     229           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     230           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     231           4 :                               ExpressionTreeNode(new Operation::Negate(),
     232           4 :                                                  ExpressionTreeNode(new Operation::Square(),
     233           4 :                                                                     ExpressionTreeNode(new Operation::Csc(), children[0]))),
     234           2 :                               childDerivs[0]);
     235             : }
     236             : 
     237           2 : ExpressionTreeNode Operation::Asin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     238           2 :     if (isZero(childDerivs[0]))
     239           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     240           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     241           4 :                               ExpressionTreeNode(new Operation::Reciprocal(),
     242           4 :                                                  ExpressionTreeNode(new Operation::Sqrt(),
     243           4 :                                                                     ExpressionTreeNode(new Operation::Subtract(),
     244           4 :                                                                                        ExpressionTreeNode(new Operation::Constant(1.0)),
     245           4 :                                                                                        ExpressionTreeNode(new Operation::Square(), children[0])))),
     246           2 :                               childDerivs[0]);
     247             : }
     248             : 
     249          23 : ExpressionTreeNode Operation::Acos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     250          23 :     if (isZero(childDerivs[0]))
     251           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     252          23 :     return ExpressionTreeNode(new Operation::Multiply(),
     253          46 :                               ExpressionTreeNode(new Operation::Negate(),
     254          46 :                                                  ExpressionTreeNode(new Operation::Reciprocal(),
     255          46 :                                                                     ExpressionTreeNode(new Operation::Sqrt(),
     256          46 :                                                                                        ExpressionTreeNode(new Operation::Subtract(),
     257          46 :                                                                                                           ExpressionTreeNode(new Operation::Constant(1.0)),
     258          46 :                                                                                                           ExpressionTreeNode(new Operation::Square(), children[0]))))),
     259          23 :                               childDerivs[0]);
     260             : }
     261             : 
     262           2 : ExpressionTreeNode Operation::Atan::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     263           2 :     if (isZero(childDerivs[0]))
     264           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     265           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     266           4 :                               ExpressionTreeNode(new Operation::Reciprocal(),
     267           4 :                                                  ExpressionTreeNode(new Operation::AddConstant(1.0),
     268           4 :                                                                     ExpressionTreeNode(new Operation::Square(), children[0]))),
     269           2 :                               childDerivs[0]);
     270             : }
     271             : 
     272          54 : ExpressionTreeNode Operation::Atan2::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     273          54 :     return ExpressionTreeNode(new Operation::Divide(),
     274         108 :                               ExpressionTreeNode(new Operation::Subtract(),
     275         108 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
     276         108 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1])),
     277         108 :                               ExpressionTreeNode(new Operation::Add(),
     278         108 :                                                  ExpressionTreeNode(new Operation::Square(), children[0]),
     279         162 :                                                  ExpressionTreeNode(new Operation::Square(), children[1])));
     280             : }
     281             : 
     282          28 : ExpressionTreeNode Operation::Sinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     283          28 :     if (isZero(childDerivs[0]))
     284          13 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     285          15 :     return ExpressionTreeNode(new Operation::Multiply(),
     286          30 :                               ExpressionTreeNode(new Operation::Cosh(),
     287             :                                                  children[0]),
     288          15 :                               childDerivs[0]);
     289             : }
     290             : 
     291           2 : ExpressionTreeNode Operation::Cosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     292           2 :     if (isZero(childDerivs[0]))
     293           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     294           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     295           4 :                               ExpressionTreeNode(new Operation::Sinh(),
     296             :                                                  children[0]),
     297           2 :                               childDerivs[0]);
     298             : }
     299             : 
     300          18 : ExpressionTreeNode Operation::Tanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     301          18 :     if (isZero(childDerivs[0]))
     302           6 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     303          12 :     return ExpressionTreeNode(new Operation::Multiply(),
     304          24 :                               ExpressionTreeNode(new Operation::Subtract(),
     305          24 :                                                  ExpressionTreeNode(new Operation::Constant(1.0)),
     306          24 :                                                  ExpressionTreeNode(new Operation::Square(),
     307          24 :                                                                     ExpressionTreeNode(new Operation::Tanh(), children[0]))),
     308          12 :                               childDerivs[0]);
     309             : }
     310             : 
     311           3 : ExpressionTreeNode Operation::Erf::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     312           3 :     if (isZero(childDerivs[0]))
     313           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     314           3 :     return ExpressionTreeNode(new Operation::Multiply(),
     315           6 :                               ExpressionTreeNode(new Operation::Multiply(),
     316           6 :                                                  ExpressionTreeNode(new Operation::Constant(2.0/sqrt(M_PI))),
     317           6 :                                                  ExpressionTreeNode(new Operation::Exp(),
     318           6 :                                                                     ExpressionTreeNode(new Operation::Negate(),
     319           6 :                                                                                        ExpressionTreeNode(new Operation::Square(), children[0])))),
     320           3 :                               childDerivs[0]);
     321             : }
     322             : 
     323           2 : ExpressionTreeNode Operation::Erfc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     324           2 :     if (isZero(childDerivs[0]))
     325           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     326           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     327           4 :                               ExpressionTreeNode(new Operation::Multiply(),
     328           4 :                                                  ExpressionTreeNode(new Operation::Constant(-2.0/sqrt(M_PI))),
     329           4 :                                                  ExpressionTreeNode(new Operation::Exp(),
     330           4 :                                                                     ExpressionTreeNode(new Operation::Negate(),
     331           4 :                                                                                        ExpressionTreeNode(new Operation::Square(), children[0])))),
     332           2 :                               childDerivs[0]);
     333             : }
     334             : 
     335         265 : ExpressionTreeNode Operation::Step::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     336         265 :     return ExpressionTreeNode(new Operation::Delta(),children[0]);
     337             : }
     338             : 
     339           3 : ExpressionTreeNode Operation::Delta::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     340           3 :     return ExpressionTreeNode(new Operation::Nandelta(), children[0]);
     341             : }
     342             : 
     343           3 : ExpressionTreeNode Operation::Nandelta::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     344           3 :     return ExpressionTreeNode(new Operation::Nandelta(), children[0]);
     345             : }
     346             : 
     347           2 : ExpressionTreeNode Operation::Square::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     348           2 :     if (isZero(childDerivs[0]))
     349           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     350           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     351           4 :                               ExpressionTreeNode(new Operation::MultiplyConstant(2.0),
     352             :                                                  children[0]),
     353           2 :                               childDerivs[0]);
     354             : }
     355             : 
     356           2 : ExpressionTreeNode Operation::Cube::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     357           2 :     if (isZero(childDerivs[0]))
     358           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     359           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     360           4 :                               ExpressionTreeNode(new Operation::MultiplyConstant(3.0),
     361           4 :                                                  ExpressionTreeNode(new Operation::Square(), children[0])),
     362           2 :                               childDerivs[0]);
     363             : }
     364             : 
     365           2 : ExpressionTreeNode Operation::Reciprocal::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     366           2 :     if (isZero(childDerivs[0]))
     367           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     368           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     369           4 :                               ExpressionTreeNode(new Operation::Negate(),
     370           4 :                                                  ExpressionTreeNode(new Operation::Reciprocal(),
     371           4 :                                                                     ExpressionTreeNode(new Operation::Square(), children[0]))),
     372           2 :                               childDerivs[0]);
     373             : }
     374             : 
     375           0 : ExpressionTreeNode Operation::AddConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     376           0 :     return childDerivs[0];
     377             : }
     378             : 
     379           0 : ExpressionTreeNode Operation::MultiplyConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     380           0 :     if (isZero(childDerivs[0]))
     381           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     382           0 :     return ExpressionTreeNode(new Operation::MultiplyConstant(value),
     383           0 :                               childDerivs[0]);
     384             : }
     385             : 
     386           0 : ExpressionTreeNode Operation::PowerConstant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     387           0 :     if (isZero(childDerivs[0]))
     388           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     389           0 :     return ExpressionTreeNode(new Operation::Multiply(),
     390           0 :                               ExpressionTreeNode(new Operation::MultiplyConstant(value),
     391           0 :                                                  ExpressionTreeNode(new Operation::PowerConstant(value-1),
     392             :                                                                     children[0])),
     393           0 :                               childDerivs[0]);
     394             : }
     395             : 
     396           4 : ExpressionTreeNode Operation::Min::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     397           4 :     ExpressionTreeNode step(new Operation::Step(),
     398           8 :                             ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
     399          20 :     return ExpressionTreeNode(new Operation::Select(), {step, childDerivs[1], childDerivs[0]});
     400           8 : }
     401             : 
     402           4 : ExpressionTreeNode Operation::Max::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     403           4 :     ExpressionTreeNode step(new Operation::Step(),
     404           8 :                             ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
     405          20 :     return ExpressionTreeNode(new Operation::Select(), {step, childDerivs[0], childDerivs[1]});
     406           8 : }
     407             : 
     408          13 : ExpressionTreeNode Operation::Abs::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     409          13 :     if (isZero(childDerivs[0]))
     410           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     411          13 :     ExpressionTreeNode step(new Operation::Step(), children[0]);
     412          13 :     return ExpressionTreeNode(new Operation::Multiply(),
     413             :                               childDerivs[0],
     414          26 :                               ExpressionTreeNode(new Operation::AddConstant(-1),
     415          39 :                                                  ExpressionTreeNode(new Operation::MultiplyConstant(2), step)));
     416          13 : }
     417             : 
     418           2 : ExpressionTreeNode Operation::Floor::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     419           2 :     return ExpressionTreeNode(new Operation::Constant(0.0));
     420             : }
     421             : 
     422           2 : ExpressionTreeNode Operation::Ceil::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     423           2 :     return ExpressionTreeNode(new Operation::Constant(0.0));
     424             : }
     425             : 
     426          34 : ExpressionTreeNode Operation::Select::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     427          34 :     vector<ExpressionTreeNode> derivChildren;
     428          34 :     derivChildren.push_back(children[0]);
     429          34 :     derivChildren.push_back(childDerivs[1]);
     430          34 :     derivChildren.push_back(childDerivs[2]);
     431          68 :     return ExpressionTreeNode(new Operation::Select(), derivChildren);
     432          34 : }
     433             : 
     434             : #define LEPTON_CONST(x) ExpressionTreeNode(new Operation::Constant(x))
     435             : #define LEPTON_OP1(name,x) ExpressionTreeNode(new Operation::name(),x)
     436             : #define LEPTON_OP2(name,x,y) ExpressionTreeNode(new Operation::name(),x,y)
     437             : #define LEPTON_ADD_CONST(x,y) ExpressionTreeNode(new Operation::AddConstant(x),y)
     438             : 
     439           3 : ExpressionTreeNode Operation::Acot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     440             :     return
     441           3 :       LEPTON_OP2(Multiply,
     442             :         LEPTON_OP1(Negate,
     443             :           LEPTON_OP1(Reciprocal,
     444             :             LEPTON_ADD_CONST(1.0,
     445             :               LEPTON_OP1(Square,children[0])
     446             :             )
     447             :           )
     448             :         ),
     449             :         childDerivs[0]
     450             :       );
     451             : }
     452             : 
     453           2 : ExpressionTreeNode Operation::Asec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     454             :     return
     455           2 :       LEPTON_OP2(Multiply,
     456             :         LEPTON_OP1(Reciprocal,
     457             :           LEPTON_OP2(Multiply,
     458             :             LEPTON_OP1(Abs,children[0]),
     459             :             LEPTON_OP1(Sqrt,
     460             :               LEPTON_OP2(Subtract,
     461             :                 LEPTON_OP1(Square,children[0]),
     462             :                 LEPTON_CONST(1.0)
     463             :               )
     464             :             )
     465             :           )
     466             :         ),
     467             :         childDerivs[0]
     468             :       );
     469             : }
     470             : 
     471           2 : ExpressionTreeNode Operation::Acsc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     472             :     return
     473           2 :     LEPTON_OP2(Multiply,
     474             :       LEPTON_OP1(Negate,
     475             :         LEPTON_OP1(Reciprocal,
     476             :           LEPTON_OP2(Multiply,
     477             :             LEPTON_OP1(Abs,children[0]),
     478             :             LEPTON_OP1(Sqrt,
     479             :               LEPTON_OP2(Subtract,
     480             :                 LEPTON_OP1(Square,children[0]),
     481             :                 LEPTON_CONST(1.0)
     482             :               )
     483             :             )
     484             :           )
     485             :         )
     486             :       ),
     487             :       childDerivs[0]
     488             :     );
     489             : }
     490             : 
     491           2 : ExpressionTreeNode Operation::Coth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     492             :     return
     493           2 :     LEPTON_OP2(Multiply,
     494             :       LEPTON_OP2(Subtract,
     495             :         LEPTON_CONST(1.0),
     496             :         LEPTON_OP1(Square,
     497             :           LEPTON_OP1(Coth,children[0])
     498             :         )
     499             :       ),
     500             :       childDerivs[0]
     501             :     );
     502             : }
     503             : 
     504           3 : ExpressionTreeNode Operation::Sech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     505             :     return
     506           3 :     LEPTON_OP2(Multiply,
     507             :       LEPTON_OP1(Negate,
     508             :         LEPTON_OP2(Multiply,
     509             :           LEPTON_OP1(Tanh,children[0]),
     510             :           LEPTON_OP1(Sech,children[0])
     511             :         )
     512             :       ),
     513             :       childDerivs[0]
     514             :     );
     515             : }
     516             : 
     517           2 : ExpressionTreeNode Operation::Csch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     518             :     return
     519           2 :     LEPTON_OP2(Multiply,
     520             :       LEPTON_OP1(Negate,
     521             :         LEPTON_OP2(Multiply,
     522             :           LEPTON_OP1(Coth,children[0]),
     523             :           LEPTON_OP1(Csch,children[0])
     524             :         )
     525             :       ),
     526             :       childDerivs[0]
     527             :     );
     528             : }
     529             : 
     530           2 : ExpressionTreeNode Operation::Acosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     531             :     return
     532           2 :     LEPTON_OP2(Multiply,
     533             :       LEPTON_OP1(Reciprocal,
     534             :         LEPTON_OP1(Sqrt,
     535             :           LEPTON_OP2(Subtract,
     536             :             LEPTON_OP1(Square,children[0]),
     537             :             LEPTON_CONST(1.0)
     538             :           )
     539             :         )
     540             :       ),
     541             :       childDerivs[0]
     542             :     );
     543             : }
     544             : 
     545           2 : ExpressionTreeNode Operation::Atanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     546             :     return
     547           2 :     LEPTON_OP2(Multiply,
     548             :       LEPTON_OP1(Reciprocal,
     549             :         LEPTON_OP2(Subtract,
     550             :           LEPTON_CONST(1.0),
     551             :           LEPTON_OP1(Square,children[0])
     552             :         )
     553             :       ),
     554             :       childDerivs[0]
     555             :     );
     556             : }
     557             : 
     558           2 : ExpressionTreeNode Operation::Asinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     559             :     return
     560           2 :     LEPTON_OP2(Multiply,
     561             :       LEPTON_OP1(Reciprocal,
     562             :         LEPTON_OP1(Sqrt,
     563             :           LEPTON_ADD_CONST(1.0,
     564             :             LEPTON_OP1(Square,children[0])
     565             :           )
     566             :         )
     567             :       ),
     568             :       childDerivs[0]
     569             :     );
     570             : }
     571             : 
     572           2 : ExpressionTreeNode Operation::Acoth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     573             :     return
     574           2 :     LEPTON_OP2(Multiply,
     575             :       LEPTON_OP1(Reciprocal,
     576             :         LEPTON_OP2(Subtract,
     577             :           LEPTON_CONST(1.0),
     578             :           LEPTON_OP1(Square,children[0])
     579             :         )
     580             :       ),
     581             :       childDerivs[0]
     582             :     );
     583             : }
     584             : 
     585           2 : ExpressionTreeNode Operation::Asech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     586             :     return
     587           2 :     LEPTON_OP2(Multiply,
     588             :       LEPTON_OP1(Negate,
     589             :         LEPTON_OP1(Reciprocal,
     590             :           LEPTON_OP2(Multiply,
     591             :             children[0],
     592             :             LEPTON_OP2(Multiply,
     593             :               LEPTON_ADD_CONST(1.0,
     594             :                 children[0]
     595             :               ),
     596             :               LEPTON_OP1(Sqrt,
     597             :                 LEPTON_OP2(Divide,
     598             :                   LEPTON_OP2(Subtract,
     599             :                     LEPTON_CONST(1.0),
     600             :                     children[0]
     601             :                   ),
     602             :                   LEPTON_ADD_CONST(1.0,
     603             :                     children[0]
     604             :                   )
     605             :                 )
     606             :               )
     607             :             )
     608             :           )
     609             :         )
     610             :       ),
     611             :       childDerivs[0]
     612             :     );
     613             : }
     614             : 
     615           2 : ExpressionTreeNode Operation::Acsch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     616             :     return
     617           2 :     LEPTON_OP2(Multiply,
     618             :       LEPTON_OP1(Negate,
     619             :         LEPTON_OP1(Reciprocal,
     620             :           LEPTON_OP2(Multiply,
     621             :             LEPTON_OP1(Square,children[0]),
     622             :             LEPTON_OP1(Sqrt,
     623             :               LEPTON_ADD_CONST(1.0,
     624             :                 LEPTON_OP1(Reciprocal,
     625             :                   LEPTON_OP1(Square,children[0])
     626             :                 )
     627             :               )
     628             :             )
     629             :           )
     630             :         )
     631             :       ),
     632             :       childDerivs[0]
     633             :     );
     634             : }
     635             : 
     636             : }

Generated by: LCOV version 1.16