LCOV - code coverage report
Current view: top level - lepton - Operation.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 273 321 85.0 %
Date: 2024-10-11 08:09:49 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-2019 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        4761 : static bool isZero(const ExpressionTreeNode& node) {
      74        4761 :     if (node.getOperation().getId() != Operation::CONSTANT)
      75             :         return false;
      76        2790 :     return dynamic_cast<const Operation::Constant&>(node.getOperation()).getValue() == 0.0;
      77             : }
      78             : 
      79         202 : double Operation::Erf::evaluate(double* args, const map<string, double>& variables) const {
      80         202 :     return erf(args[0]);
      81             : }
      82             : 
      83         202 : double Operation::Erfc::evaluate(double* args, const map<string, double>& variables) const {
      84         202 :     return erfc(args[0]);
      85             : }
      86             : 
      87        1114 : ExpressionTreeNode Operation::Constant::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      88        1114 :     return ExpressionTreeNode(new Operation::Constant(0.0));
      89             : }
      90             : 
      91        1119 : ExpressionTreeNode Operation::Variable::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
      92        1119 :     if (variable == name)
      93         594 :         return ExpressionTreeNode(new Operation::Constant(1.0));
      94         525 :     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         577 : ExpressionTreeNode Operation::Add::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     120         577 :     if (isZero(childDerivs[0]))
     121         124 :         return childDerivs[1];
     122         453 :     if (isZero(childDerivs[1]))
     123         360 :         return childDerivs[0];
     124          93 :     return ExpressionTreeNode(new Operation::Add(), childDerivs[0], childDerivs[1]);
     125             : }
     126             : 
     127         340 : ExpressionTreeNode Operation::Subtract::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     128         340 :     if (isZero(childDerivs[0])) {
     129          75 :         if (isZero(childDerivs[1]))
     130          60 :             return ExpressionTreeNode(new Operation::Constant(0.0));
     131          15 :         return ExpressionTreeNode(new Operation::Negate(), childDerivs[1]);
     132             :     }
     133         265 :     if (isZero(childDerivs[1]))
     134          66 :         return childDerivs[0];
     135         199 :     return ExpressionTreeNode(new Operation::Subtract(), childDerivs[0], childDerivs[1]);
     136             : }
     137             : 
     138        1226 : ExpressionTreeNode Operation::Multiply::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     139        1226 :     if (isZero(childDerivs[0])) {
     140         902 :         if (isZero(childDerivs[1]))
     141         313 :             return ExpressionTreeNode(new Operation::Constant(0.0));
     142         589 :         return ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]);
     143             :     }
     144         324 :     if (isZero(childDerivs[1]))
     145          26 :         return ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
     146         298 :     return ExpressionTreeNode(new Operation::Add(),
     147         596 :                               ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]),
     148         894 :                               ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]));
     149             : }
     150             : 
     151         128 : ExpressionTreeNode Operation::Divide::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     152         128 :     ExpressionTreeNode subexp;
     153         128 :     if (isZero(childDerivs[0])) {
     154          99 :         if (isZero(childDerivs[1]))
     155          68 :             return ExpressionTreeNode(new Operation::Constant(0.0));
     156          31 :         subexp = ExpressionTreeNode(new Operation::Negate(), ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
     157             :     }
     158          29 :     else if (isZero(childDerivs[1]))
     159          16 :         subexp = ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]);
     160             :     else
     161          26 :         subexp = ExpressionTreeNode(new Operation::Subtract(),
     162          26 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
     163          39 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1]));
     164          60 :     return ExpressionTreeNode(new Operation::Divide(), subexp, ExpressionTreeNode(new Operation::Square(), children[1]));
     165         128 : }
     166             : 
     167         111 : ExpressionTreeNode Operation::Power::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     168         111 :     return ExpressionTreeNode(new Operation::Add(),
     169         222 :                               ExpressionTreeNode(new Operation::Multiply(),
     170         222 :                                                  ExpressionTreeNode(new Operation::Multiply(),
     171             :                                                                     children[1],
     172         222 :                                                                     ExpressionTreeNode(new Operation::Power(),
     173         222 :                                                                                        children[0], ExpressionTreeNode(new Operation::AddConstant(-1.0), children[1]))),
     174             :                                                  childDerivs[0]),
     175         222 :                               ExpressionTreeNode(new Operation::Multiply(),
     176         222 :                                                  ExpressionTreeNode(new Operation::Multiply(),
     177         222 :                                                                     ExpressionTreeNode(new Operation::Log(), children[0]),
     178         222 :                                                                     ExpressionTreeNode(new Operation::Power(), children[0], children[1])),
     179         222 :                                                  childDerivs[1]));
     180             : }
     181             : 
     182          11 : ExpressionTreeNode Operation::Negate::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     183          11 :     if (isZero(childDerivs[0]))
     184           3 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     185           8 :     return ExpressionTreeNode(new Operation::Negate(), childDerivs[0]);
     186             : }
     187             : 
     188          41 : ExpressionTreeNode Operation::Sqrt::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     189          41 :     if (isZero(childDerivs[0]))
     190           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     191          41 :     return ExpressionTreeNode(new Operation::Multiply(),
     192          82 :                               ExpressionTreeNode(new Operation::MultiplyConstant(0.5),
     193          82 :                                                  ExpressionTreeNode(new Operation::Reciprocal(),
     194          82 :                                                                     ExpressionTreeNode(new Operation::Sqrt(), children[0]))),
     195          41 :                               childDerivs[0]);
     196             : }
     197             : 
     198           3 : ExpressionTreeNode Operation::Exp::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     199           3 :     if (isZero(childDerivs[0]))
     200           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     201           3 :     return ExpressionTreeNode(new Operation::Multiply(),
     202           6 :                               ExpressionTreeNode(new Operation::Exp(), children[0]),
     203           3 :                               childDerivs[0]);
     204             : }
     205             : 
     206           2 : ExpressionTreeNode Operation::Log::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     207           2 :     if (isZero(childDerivs[0]))
     208           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     209           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     210           4 :                               ExpressionTreeNode(new Operation::Reciprocal(), children[0]),
     211           2 :                               childDerivs[0]);
     212             : }
     213             : 
     214          55 : ExpressionTreeNode Operation::Sin::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     215          55 :     if (isZero(childDerivs[0]))
     216           2 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     217          53 :     return ExpressionTreeNode(new Operation::Multiply(),
     218         106 :                               ExpressionTreeNode(new Operation::Cos(), children[0]),
     219          53 :                               childDerivs[0]);
     220             : }
     221             : 
     222         198 : ExpressionTreeNode Operation::Cos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     223         198 :     if (isZero(childDerivs[0]))
     224           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     225         198 :     return ExpressionTreeNode(new Operation::Multiply(),
     226         396 :                               ExpressionTreeNode(new Operation::Negate(),
     227         396 :                                                  ExpressionTreeNode(new Operation::Sin(), children[0])),
     228         198 :                               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           2 : ExpressionTreeNode Operation::Acos::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     284           2 :     if (isZero(childDerivs[0]))
     285           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     286           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     287           4 :                               ExpressionTreeNode(new Operation::Negate(),
     288           4 :                                                  ExpressionTreeNode(new Operation::Reciprocal(),
     289           4 :                                                                     ExpressionTreeNode(new Operation::Sqrt(),
     290           4 :                                                                                        ExpressionTreeNode(new Operation::Subtract(),
     291           4 :                                                                                                           ExpressionTreeNode(new Operation::Constant(1.0)),
     292           4 :                                                                                                           ExpressionTreeNode(new Operation::Square(), children[0]))))),
     293           2 :                               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           8 : ExpressionTreeNode Operation::Atan2::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     307           8 :     return ExpressionTreeNode(new Operation::Divide(),
     308          16 :                               ExpressionTreeNode(new Operation::Subtract(),
     309          16 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[1], childDerivs[0]),
     310          16 :                                                  ExpressionTreeNode(new Operation::Multiply(), children[0], childDerivs[1])),
     311          16 :                               ExpressionTreeNode(new Operation::Add(),
     312          16 :                                                  ExpressionTreeNode(new Operation::Square(), children[0]),
     313          24 :                                                  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           2 : ExpressionTreeNode Operation::Tanh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     335           2 :     if (isZero(childDerivs[0]))
     336           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     337           2 :     return ExpressionTreeNode(new Operation::Multiply(),
     338           4 :                               ExpressionTreeNode(new Operation::Subtract(),
     339           4 :                                                  ExpressionTreeNode(new Operation::Constant(1.0)),
     340           4 :                                                  ExpressionTreeNode(new Operation::Square(),
     341           4 :                                                                     ExpressionTreeNode(new Operation::Tanh(), children[0]))),
     342           2 :                               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          13 : ExpressionTreeNode Operation::Step::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     370          13 :     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           4 :     return ExpressionTreeNode(new Operation::Subtract(),
     434           8 :                               ExpressionTreeNode(new Operation::Multiply(), childDerivs[1], step),
     435           8 :                               ExpressionTreeNode(new Operation::Multiply(), childDerivs[0],
     436          16 :                                                  ExpressionTreeNode(new Operation::AddConstant(-1), step)));
     437           4 : }
     438             : 
     439           4 : ExpressionTreeNode Operation::Max::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     440           4 :     ExpressionTreeNode step(new Operation::Step(),
     441           8 :                             ExpressionTreeNode(new Operation::Subtract(), children[0], children[1]));
     442           4 :     return ExpressionTreeNode(new Operation::Subtract(),
     443           8 :                               ExpressionTreeNode(new Operation::Multiply(), childDerivs[0], step),
     444           8 :                               ExpressionTreeNode(new Operation::Multiply(), childDerivs[1],
     445          16 :                                                  ExpressionTreeNode(new Operation::AddConstant(-1), step)));
     446           4 : }
     447             : 
     448           3 : ExpressionTreeNode Operation::Abs::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     449           3 :     if (isZero(childDerivs[0]))
     450           0 :         return ExpressionTreeNode(new Operation::Constant(0.0));
     451           3 :     ExpressionTreeNode step(new Operation::Step(), children[0]);
     452           3 :     return ExpressionTreeNode(new Operation::Multiply(),
     453             :                               childDerivs[0],
     454           6 :                               ExpressionTreeNode(new Operation::AddConstant(-1),
     455           9 :                                                  ExpressionTreeNode(new Operation::MultiplyConstant(2), step)));
     456           3 : }
     457             : 
     458           2 : ExpressionTreeNode Operation::Floor::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     459           2 :     return ExpressionTreeNode(new Operation::Constant(0.0));
     460             : }
     461             : 
     462           2 : ExpressionTreeNode Operation::Ceil::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     463           2 :     return ExpressionTreeNode(new Operation::Constant(0.0));
     464             : }
     465             : 
     466          12 : ExpressionTreeNode Operation::Select::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     467             :     vector<ExpressionTreeNode> derivChildren;
     468          12 :     derivChildren.push_back(children[0]);
     469          12 :     derivChildren.push_back(childDerivs[1]);
     470          12 :     derivChildren.push_back(childDerivs[2]);
     471          24 :     return ExpressionTreeNode(new Operation::Select(), derivChildren);
     472          12 : }
     473             : 
     474             : #define LEPTON_CONST(x) ExpressionTreeNode(new Operation::Constant(x))
     475             : #define LEPTON_OP1(name,x) ExpressionTreeNode(new Operation::name(),x)
     476             : #define LEPTON_OP2(name,x,y) ExpressionTreeNode(new Operation::name(),x,y)
     477             : #define LEPTON_ADD_CONST(x,y) ExpressionTreeNode(new Operation::AddConstant(x),y)
     478             : 
     479           2 : ExpressionTreeNode Operation::Acot::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     480             :     return
     481           2 :       LEPTON_OP2(Multiply,
     482             :         LEPTON_OP1(Negate,
     483             :           LEPTON_OP1(Reciprocal,
     484             :             LEPTON_ADD_CONST(1.0,
     485             :               LEPTON_OP1(Square,children[0])
     486             :             )
     487             :           )
     488             :         ),
     489             :         childDerivs[0]
     490             :       );
     491             : }
     492             : 
     493           2 : ExpressionTreeNode Operation::Asec::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     494             :     return
     495           2 :       LEPTON_OP2(Multiply,
     496             :         LEPTON_OP1(Reciprocal,
     497             :           LEPTON_OP2(Multiply,
     498             :             LEPTON_OP1(Abs,children[0]),
     499             :             LEPTON_OP1(Sqrt,
     500             :               LEPTON_OP2(Subtract,
     501             :                 LEPTON_OP1(Square,children[0]),
     502             :                 LEPTON_CONST(1.0)
     503             :               )
     504             :             )
     505             :           )
     506             :         ),
     507             :         childDerivs[0]
     508             :       );
     509             : }
     510             : 
     511           2 : ExpressionTreeNode Operation::Acsc::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     512             :     return
     513           2 :     LEPTON_OP2(Multiply,
     514             :       LEPTON_OP1(Negate,
     515             :         LEPTON_OP1(Reciprocal,
     516             :           LEPTON_OP2(Multiply,
     517             :             LEPTON_OP1(Abs,children[0]),
     518             :             LEPTON_OP1(Sqrt,
     519             :               LEPTON_OP2(Subtract,
     520             :                 LEPTON_OP1(Square,children[0]),
     521             :                 LEPTON_CONST(1.0)
     522             :               )
     523             :             )
     524             :           )
     525             :         )
     526             :       ),
     527             :       childDerivs[0]
     528             :     );
     529             : }
     530             : 
     531           2 : ExpressionTreeNode Operation::Coth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     532             :     return
     533           2 :     LEPTON_OP2(Multiply,
     534             :       LEPTON_OP2(Subtract,
     535             :         LEPTON_CONST(1.0),
     536             :         LEPTON_OP1(Square,
     537             :           LEPTON_OP1(Coth,children[0])
     538             :         )
     539             :       ),
     540             :       childDerivs[0]
     541             :     );
     542             : }
     543             : 
     544           2 : ExpressionTreeNode Operation::Sech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     545             :     return
     546           2 :     LEPTON_OP2(Multiply,
     547             :       LEPTON_OP1(Negate,
     548             :         LEPTON_OP2(Multiply,
     549             :           LEPTON_OP1(Tanh,children[0]),
     550             :           LEPTON_OP1(Sech,children[0])
     551             :         )
     552             :       ),
     553             :       childDerivs[0]
     554             :     );
     555             : }
     556             : 
     557           2 : ExpressionTreeNode Operation::Csch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     558             :     return
     559           2 :     LEPTON_OP2(Multiply,
     560             :       LEPTON_OP1(Negate,
     561             :         LEPTON_OP2(Multiply,
     562             :           LEPTON_OP1(Coth,children[0]),
     563             :           LEPTON_OP1(Csch,children[0])
     564             :         )
     565             :       ),
     566             :       childDerivs[0]
     567             :     );
     568             : }
     569             : 
     570           2 : ExpressionTreeNode Operation::Acosh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     571             :     return
     572           2 :     LEPTON_OP2(Multiply,
     573             :       LEPTON_OP1(Reciprocal,
     574             :         LEPTON_OP1(Sqrt,
     575             :           LEPTON_OP2(Subtract,
     576             :             LEPTON_OP1(Square,children[0]),
     577             :             LEPTON_CONST(1.0)
     578             :           )
     579             :         )
     580             :       ),
     581             :       childDerivs[0]
     582             :     );
     583             : }
     584             : 
     585           2 : ExpressionTreeNode Operation::Atanh::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(Reciprocal,
     589             :         LEPTON_OP2(Subtract,
     590             :           LEPTON_CONST(1.0),
     591             :           LEPTON_OP1(Square,children[0])
     592             :         )
     593             :       ),
     594             :       childDerivs[0]
     595             :     );
     596             : }
     597             : 
     598           2 : ExpressionTreeNode Operation::Asinh::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     599             :     return
     600           2 :     LEPTON_OP2(Multiply,
     601             :       LEPTON_OP1(Reciprocal,
     602             :         LEPTON_OP1(Sqrt,
     603             :           LEPTON_ADD_CONST(1.0,
     604             :             LEPTON_OP1(Square,children[0])
     605             :           )
     606             :         )
     607             :       ),
     608             :       childDerivs[0]
     609             :     );
     610             : }
     611             : 
     612           2 : ExpressionTreeNode Operation::Acoth::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     613             :     return
     614           2 :     LEPTON_OP2(Multiply,
     615             :       LEPTON_OP1(Reciprocal,
     616             :         LEPTON_OP2(Subtract,
     617             :           LEPTON_CONST(1.0),
     618             :           LEPTON_OP1(Square,children[0])
     619             :         )
     620             :       ),
     621             :       childDerivs[0]
     622             :     );
     623             : }
     624             : 
     625           2 : ExpressionTreeNode Operation::Asech::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     626             :     return
     627           2 :     LEPTON_OP2(Multiply,
     628             :       LEPTON_OP1(Negate,
     629             :         LEPTON_OP1(Reciprocal,
     630             :           LEPTON_OP2(Multiply,
     631             :             children[0],
     632             :             LEPTON_OP2(Multiply,
     633             :               LEPTON_ADD_CONST(1.0,
     634             :                 children[0]
     635             :               ),
     636             :               LEPTON_OP1(Sqrt,
     637             :                 LEPTON_OP2(Divide,
     638             :                   LEPTON_OP2(Subtract,
     639             :                     LEPTON_CONST(1.0),
     640             :                     children[0]
     641             :                   ),
     642             :                   LEPTON_ADD_CONST(1.0,
     643             :                     children[0]
     644             :                   )
     645             :                 )
     646             :               )
     647             :             )
     648             :           )
     649             :         )
     650             :       ),
     651             :       childDerivs[0]
     652             :     );
     653             : }
     654             : 
     655           2 : ExpressionTreeNode Operation::Acsch::differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const {
     656             :     return
     657           2 :     LEPTON_OP2(Multiply,
     658             :       LEPTON_OP1(Negate,
     659             :         LEPTON_OP1(Reciprocal,
     660             :           LEPTON_OP2(Multiply,
     661             :             LEPTON_OP1(Square,children[0]),
     662             :             LEPTON_OP1(Sqrt,
     663             :               LEPTON_ADD_CONST(1.0,
     664             :                 LEPTON_OP1(Reciprocal,
     665             :                   LEPTON_OP1(Square,children[0])
     666             :                 )
     667             :               )
     668             :             )
     669             :           )
     670             :         )
     671             :       ),
     672             :       childDerivs[0]
     673             :     );
     674             : }
     675             : 
     676             : }

Generated by: LCOV version 1.15