LCOV - code coverage report
Current view: top level - lepton - Operation.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 272 315 86.3 %
Date: 2024-10-18 14:00:27 Functions: 53 57 93.0 %

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

Generated by: LCOV version 1.16