LCOV - code coverage report
Current view: top level - lepton - Operation.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 530 556 95.3 %
Date: 2024-10-11 08:09:49 Functions: 280 290 96.6 %

          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             : #ifndef __PLUMED_lepton_Operation_h
      34             : #define __PLUMED_lepton_Operation_h
      35             : 
      36             : /* -------------------------------------------------------------------------- *
      37             :  *                                   lepton                                   *
      38             :  * -------------------------------------------------------------------------- *
      39             :  * This is part of the lepton expression parser originating from              *
      40             :  * Simbios, the NIH National Center for Physics-Based Simulation of           *
      41             :  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
      42             :  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
      43             :  *                                                                            *
      44             :  * Portions copyright (c) 2009-2019 Stanford University and the Authors.      *
      45             :  * Authors: Peter Eastman                                                     *
      46             :  * Contributors:                                                              *
      47             :  *                                                                            *
      48             :  * Permission is hereby granted, free of charge, to any person obtaining a    *
      49             :  * copy of this software and associated documentation files (the "Software"), *
      50             :  * to deal in the Software without restriction, including without limitation  *
      51             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
      52             :  * and/or sell copies of the Software, and to permit persons to whom the      *
      53             :  * Software is furnished to do so, subject to the following conditions:       *
      54             :  *                                                                            *
      55             :  * The above copyright notice and this permission notice shall be included in *
      56             :  * all copies or substantial portions of the Software.                        *
      57             :  *                                                                            *
      58             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
      59             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
      60             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
      61             :  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
      62             :  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
      63             :  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
      64             :  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
      65             :  * -------------------------------------------------------------------------- */
      66             : 
      67             : #include "windowsIncludes.h"
      68             : #include "CustomFunction.h"
      69             : #include "Exception.h"
      70             : #include <cmath>
      71             : #include <map>
      72             : #include <string>
      73             : #include <vector>
      74             : #include <sstream>
      75             : #include <algorithm>
      76             : #include <limits>
      77             : 
      78             : namespace PLMD {
      79             : namespace lepton {
      80             : 
      81             : class ExpressionTreeNode;
      82             : 
      83             : /**
      84             :  * An Operation represents a single step in the evaluation of an expression, such as a function,
      85             :  * an operator, or a constant value.  Each Operation takes some number of values as arguments
      86             :  * and produces a single value.
      87             :  *
      88             :  * This is an abstract class with subclasses for specific operations.
      89             :  */
      90             : 
      91             : class LEPTON_EXPORT Operation {
      92             : public:
      93             :     virtual ~Operation() {
      94             :     }
      95             :     /**
      96             :      * This enumeration lists all Operation subclasses.  This is provided so that switch statements
      97             :      * can be used when processing or analyzing parsed expressions.
      98             :      */
      99             :     enum Id {CONSTANT, VARIABLE, CUSTOM, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, NEGATE, SQRT, EXP, LOG,
     100             :              SIN, COS, SEC, CSC, TAN, COT, ASIN, ACOS, ATAN, ATAN2, SINH, COSH, TANH, ERF, ERFC, STEP, DELTA, NANDELTA, SQUARE, CUBE, RECIPROCAL,
     101             :              ADD_CONSTANT, MULTIPLY_CONSTANT, POWER_CONSTANT, MIN, MAX, ABS, FLOOR, CEIL, SELECT,
     102             :              ACOT, ASEC, ACSC, COTH, SECH, CSCH, ASINH, ACOSH, ATANH, ACOTH, ASECH, ACSCH};
     103             :     /**
     104             :      * Get the name of this Operation.
     105             :      */
     106             :     virtual std::string getName() const = 0;
     107             :     /**
     108             :      * Get this Operation's ID.
     109             :      */
     110             :     virtual Id getId() const = 0;
     111             :     /**
     112             :      * Get the number of arguments this operation expects.
     113             :      */
     114             :     virtual int getNumArguments() const = 0;
     115             :     /**
     116             :      * Create a clone of this Operation.
     117             :      */
     118             :     virtual Operation* clone() const = 0;
     119             :     /**
     120             :      * Perform the computation represented by this operation.
     121             :      *
     122             :      * @param args        the array of arguments
     123             :      * @param variables   a map containing the values of all variables
     124             :      * @return the result of performing the computation.
     125             :      */
     126             :     virtual double evaluate(double* args, const std::map<std::string, double>& variables) const = 0;
     127             :     /**
     128             :      * Return an ExpressionTreeNode which represents the analytic derivative of this Operation with respect to a variable.
     129             :      *
     130             :      * @param children     the child nodes
     131             :      * @param childDerivs  the derivatives of the child nodes with respect to the variable
     132             :      * @param variable     the variable with respect to which the derivate should be taken
     133             :      */
     134             :     virtual ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const = 0;
     135             :     /**
     136             :      * Get whether this operation should be displayed with infix notation.
     137             :      */
     138       15910 :     virtual bool isInfixOperator() const {
     139       15910 :         return false;
     140             :     }
     141             :     /**
     142             :      * Get whether this is a symmetric binary operation, such that exchanging its arguments
     143             :      * does not affect the result.
     144             :      */
     145       51753 :     virtual bool isSymmetric() const {
     146       51753 :         return false;
     147             :     }
     148      101645 :     virtual bool operator!=(const Operation& op) const {
     149      101645 :         return op.getId() != getId();
     150             :     }
     151      105248 :     virtual bool operator==(const Operation& op) const {
     152      105248 :         return !(*this != op);
     153             :     }
     154             :     class Constant;
     155             :     class Variable;
     156             :     class Custom;
     157             :     class Add;
     158             :     class Subtract;
     159             :     class Multiply;
     160             :     class Divide;
     161             :     class Power;
     162             :     class Negate;
     163             :     class Sqrt;
     164             :     class Exp;
     165             :     class Log;
     166             :     class Sin;
     167             :     class Cos;
     168             :     class Sec;
     169             :     class Csc;
     170             :     class Tan;
     171             :     class Cot;
     172             :     class Asin;
     173             :     class Acos;
     174             :     class Atan;
     175             :     class Atan2;
     176             :     class Sinh;
     177             :     class Cosh;
     178             :     class Tanh;
     179             :     class Erf;
     180             :     class Erfc;
     181             :     class Step;
     182             :     class Delta;
     183             :     class Nandelta;
     184             :     class Square;
     185             :     class Cube;
     186             :     class Reciprocal;
     187             :     class AddConstant;
     188             :     class MultiplyConstant;
     189             :     class PowerConstant;
     190             :     class Min;
     191             :     class Max;
     192             :     class Abs;
     193             :     class Floor;
     194             :     class Ceil;
     195             :     class Select;
     196             :     class Acot;
     197             :     class Asec;
     198             :     class Acsc;
     199             :     class Coth;
     200             :     class Sech;
     201             :     class Csch;
     202             :     class Asinh;
     203             :     class Acosh;
     204             :     class Atanh;
     205             :     class Acoth;
     206             :     class Asech;
     207             :     class Acsch;
     208             : };
     209             : 
     210             : class LEPTON_EXPORT Operation::Constant : public Operation {
     211             : public:
     212     2017858 :     Constant(double value) : value(value) {
     213             :     }
     214         227 :     std::string getName() const {
     215         227 :         std::stringstream name;
     216         227 :         name << value;
     217         227 :         return name.str();
     218         227 :     }
     219       27150 :     Id getId() const {
     220       27150 :         return CONSTANT;
     221             :     }
     222     2028986 :     int getNumArguments() const {
     223     2028986 :         return 0;
     224             :     }
     225     2145781 :     Operation* clone() const {
     226     2145781 :         return new Constant(value);
     227             :     }
     228     2018722 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     229     2018722 :         return value;
     230             :     }
     231             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     232             :     double getValue() const {
     233        6447 :         return value;
     234             :     }
     235       31324 :     bool operator!=(const Operation& op) const {
     236       31324 :         const Constant* o = dynamic_cast<const Constant*>(&op);
     237       31324 :         return (o == NULL || o->value != value);
     238             :     }
     239             : private:
     240             :     double value;
     241             : };
     242             : 
     243             : class LEPTON_EXPORT Operation::Variable : public Operation {
     244             : public:
     245      243625 :     Variable(const std::string& name) : name(name) {
     246      243625 :     }
     247        9018 :     std::string getName() const {
     248        9018 :         return name;
     249             :     }
     250       30572 :     Id getId() const {
     251       30572 :         return VARIABLE;
     252             :     }
     253        9120 :     int getNumArguments() const {
     254        9120 :         return 0;
     255             :     }
     256      240337 :     Operation* clone() const {
     257      480674 :         return new Variable(name);
     258             :     }
     259          20 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     260          20 :         std::map<std::string, double>::const_iterator iter = variables.find(name);
     261          20 :         if (iter == variables.end())
     262          24 :             throw Exception("No value specified for variable "+name);
     263           8 :         return iter->second;
     264             :     }
     265             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     266       45647 :     bool operator!=(const Operation& op) const {
     267       45647 :         const Variable* o = dynamic_cast<const Variable*>(&op);
     268       45647 :         return (o == NULL || o->name != name);
     269             :     }
     270             : private:
     271             :     std::string name;
     272             : };
     273             : 
     274             : class LEPTON_EXPORT Operation::Custom : public Operation {
     275             : public:
     276           0 :     Custom(const std::string& name, CustomFunction* function) : name(name), function(function), isDerivative(false), derivOrder(function->getNumArguments(), 0) {
     277           0 :     }
     278             :     Custom(const std::string& name, CustomFunction* function, const std::vector<int>& derivOrder) : name(name), function(function), isDerivative(false), derivOrder(derivOrder) {
     279             :         for (int order : derivOrder)
     280             :             if (order != 0)
     281             :                 isDerivative = true;
     282             :     }
     283           0 :     Custom(const Custom& base, int derivIndex) : name(base.name), function(base.function->clone()), isDerivative(true), derivOrder(base.derivOrder) {
     284           0 :         derivOrder[derivIndex]++;
     285           0 :     }
     286           0 :     ~Custom() {
     287           0 :         delete function;
     288           0 :     }
     289           0 :     std::string getName() const {
     290           0 :         return name;
     291             :     }
     292           0 :     Id getId() const {
     293           0 :         return CUSTOM;
     294             :     }
     295           0 :     int getNumArguments() const {
     296           0 :         return function->getNumArguments();
     297             :     }
     298           0 :     Operation* clone() const {
     299           0 :         Custom* clone = new Custom(name, function->clone());
     300           0 :         clone->isDerivative = isDerivative;
     301           0 :         clone->derivOrder = derivOrder;
     302           0 :         return clone;
     303             :     }
     304           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     305           0 :         if (isDerivative)
     306           0 :             return function->evaluateDerivative(args, &derivOrder[0]);
     307           0 :         return function->evaluate(args);
     308             :     }
     309             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     310             :     const std::vector<int>& getDerivOrder() const {
     311             :         return derivOrder;
     312             :     }
     313           0 :     bool operator!=(const Operation& op) const {
     314           0 :         const Custom* o = dynamic_cast<const Custom*>(&op);
     315           0 :         return (o == NULL || o->name != name || o->isDerivative != isDerivative || o->derivOrder != derivOrder);
     316             :     }
     317             : private:
     318             :     std::string name;
     319             :     CustomFunction* function;
     320             :     bool isDerivative;
     321             :     std::vector<int> derivOrder;
     322             : };
     323             : 
     324             : class LEPTON_EXPORT Operation::Add : public Operation {
     325             : public:
     326        1593 :     Add() {
     327             :     }
     328         614 :     std::string getName() const {
     329         614 :         return "+";
     330             :     }
     331       40244 :     Id getId() const {
     332       40244 :         return ADD;
     333             :     }
     334        7429 :     int getNumArguments() const {
     335        7429 :         return 2;
     336             :     }
     337       41274 :     Operation* clone() const {
     338       41274 :         return new Add();
     339             :     }
     340         413 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     341         413 :         return args[0]+args[1];
     342             :     }
     343             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     344         614 :     bool isInfixOperator() const {
     345         614 :         return true;
     346             :     }
     347        3592 :     bool isSymmetric() const {
     348        3592 :         return true;
     349             :     }
     350             : };
     351             : 
     352             : class LEPTON_EXPORT Operation::Subtract : public Operation {
     353             : public:
     354        1137 :     Subtract() {
     355             :     }
     356         431 :     std::string getName() const {
     357         431 :         return "-";
     358             :     }
     359       25483 :     Id getId() const {
     360       25483 :         return SUBTRACT;
     361             :     }
     362        6688 :     int getNumArguments() const {
     363        6688 :         return 2;
     364             :     }
     365       31562 :     Operation* clone() const {
     366       31562 :         return new Subtract();
     367             :     }
     368        1284 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     369        1284 :         return args[0]-args[1];
     370             :     }
     371             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     372         431 :     bool isInfixOperator() const {
     373         431 :         return true;
     374             :     }
     375             : };
     376             : 
     377             : class LEPTON_EXPORT Operation::Multiply : public Operation {
     378             : public:
     379        4727 :     Multiply() {
     380             :     }
     381         838 :     std::string getName() const {
     382         838 :         return "*";
     383             :     }
     384       83422 :     Id getId() const {
     385       83422 :         return MULTIPLY;
     386             :     }
     387       18860 :     int getNumArguments() const {
     388       18860 :         return 2;
     389             :     }
     390      115973 :     Operation* clone() const {
     391      115973 :         return new Multiply();
     392             :     }
     393        1441 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     394        1441 :         return args[0]*args[1];
     395             :     }
     396             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     397         838 :     bool isInfixOperator() const {
     398         838 :         return true;
     399             :     }
     400        6290 :     bool isSymmetric() const {
     401        6290 :         return true;
     402             :     }
     403             : };
     404             : 
     405             : class LEPTON_EXPORT Operation::Divide : public Operation {
     406             : public:
     407         554 :     Divide() {
     408             :     }
     409          50 :     std::string getName() const {
     410          50 :         return "/";
     411             :     }
     412        5521 :     Id getId() const {
     413        5521 :         return DIVIDE;
     414             :     }
     415        1721 :     int getNumArguments() const {
     416        1721 :         return 2;
     417             :     }
     418       11742 :     Operation* clone() const {
     419       11742 :         return new Divide();
     420             :     }
     421         668 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     422         668 :         return args[0]/args[1];
     423             :     }
     424             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     425          50 :     bool isInfixOperator() const {
     426          50 :         return true;
     427             :     }
     428             : };
     429             : 
     430             : class LEPTON_EXPORT Operation::Power : public Operation {
     431             : public:
     432         440 :     Power() {
     433             :     }
     434           4 :     std::string getName() const {
     435           4 :         return "^";
     436             :     }
     437        4509 :     Id getId() const {
     438        4509 :         return POWER;
     439             :     }
     440        1168 :     int getNumArguments() const {
     441        1168 :         return 2;
     442             :     }
     443        9169 :     Operation* clone() const {
     444        9169 :         return new Power();
     445             :     }
     446         204 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     447         204 :         return std::pow(args[0], args[1]);
     448             :     }
     449             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     450           4 :     bool isInfixOperator() const {
     451           4 :         return true;
     452             :     }
     453             : };
     454             : 
     455             : class LEPTON_EXPORT Operation::Negate : public Operation {
     456             : public:
     457         361 :     Negate() {
     458             :     }
     459          74 :     std::string getName() const {
     460          74 :         return "-";
     461             :     }
     462       12926 :     Id getId() const {
     463       12926 :         return NEGATE;
     464             :     }
     465        2360 :     int getNumArguments() const {
     466        2360 :         return 1;
     467             :     }
     468       23206 :     Operation* clone() const {
     469       23206 :         return new Negate();
     470             :     }
     471        1641 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     472        1641 :         return -args[0];
     473             :     }
     474             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     475             : };
     476             : 
     477             : class LEPTON_EXPORT Operation::Sqrt : public Operation {
     478             : public:
     479         122 :     Sqrt() {
     480             :     }
     481          83 :     std::string getName() const {
     482          83 :         return "sqrt";
     483             :     }
     484        4653 :     Id getId() const {
     485        4653 :         return SQRT;
     486             :     }
     487         797 :     int getNumArguments() const {
     488         797 :         return 1;
     489             :     }
     490        5491 :     Operation* clone() const {
     491        5491 :         return new Sqrt();
     492             :     }
     493        1111 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     494        1111 :         return std::sqrt(args[0]);
     495             :     }
     496             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     497             : };
     498             : 
     499             : class LEPTON_EXPORT Operation::Exp : public Operation {
     500             : public:
     501          34 :     Exp() {
     502             :     }
     503          28 :     std::string getName() const {
     504          28 :         return "exp";
     505             :     }
     506        1495 :     Id getId() const {
     507        1495 :         return EXP;
     508             :     }
     509         308 :     int getNumArguments() const {
     510         308 :         return 1;
     511             :     }
     512         924 :     Operation* clone() const {
     513         924 :         return new Exp();
     514             :     }
     515         405 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     516         405 :         return std::exp(args[0]);
     517             :     }
     518             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     519             : };
     520             : 
     521             : class LEPTON_EXPORT Operation::Log : public Operation {
     522             : public:
     523         116 :     Log() {
     524             :     }
     525           2 :     std::string getName() const {
     526           2 :         return "log";
     527             :     }
     528        1832 :     Id getId() const {
     529        1832 :         return LOG;
     530             :     }
     531         442 :     int getNumArguments() const {
     532         442 :         return 1;
     533             :     }
     534        3637 :     Operation* clone() const {
     535        3637 :         return new Log();
     536             :     }
     537         108 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     538         108 :         return std::log(args[0]);
     539             :     }
     540             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     541             : };
     542             : 
     543             : class LEPTON_EXPORT Operation::Sin : public Operation {
     544             : public:
     545         313 :     Sin() {
     546             :     }
     547         733 :     std::string getName() const {
     548         733 :         return "sin";
     549             :     }
     550       49089 :     Id getId() const {
     551       49089 :         return SIN;
     552             :     }
     553        3276 :     int getNumArguments() const {
     554        3276 :         return 1;
     555             :     }
     556       52623 :     Operation* clone() const {
     557       52623 :         return new Sin();
     558             :     }
     559         206 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     560         206 :         return std::sin(args[0]);
     561             :     }
     562             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     563             : };
     564             : 
     565             : class LEPTON_EXPORT Operation::Cos : public Operation {
     566             : public:
     567        1318 :     Cos() {
     568             :     }
     569        1117 :     std::string getName() const {
     570        1117 :         return "cos";
     571             :     }
     572       64840 :     Id getId() const {
     573       64840 :         return COS;
     574             :     }
     575        5825 :     int getNumArguments() const {
     576        5825 :         return 1;
     577             :     }
     578       76519 :     Operation* clone() const {
     579       76519 :         return new Cos();
     580             :     }
     581         204 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     582         204 :         return std::cos(args[0]);
     583             :     }
     584             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     585             : };
     586             : 
     587             : class LEPTON_EXPORT Operation::Sec : public Operation {
     588             : public:
     589           8 :     Sec() {
     590             :     }
     591           6 :     std::string getName() const {
     592           6 :         return "sec";
     593             :     }
     594         214 :     Id getId() const {
     595         214 :         return SEC;
     596             :     }
     597          54 :     int getNumArguments() const {
     598          54 :         return 1;
     599             :     }
     600         184 :     Operation* clone() const {
     601         184 :         return new Sec();
     602             :     }
     603         606 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     604         606 :         return 1.0/std::cos(args[0]);
     605             :     }
     606             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     607             : };
     608             : 
     609             : class LEPTON_EXPORT Operation::Csc : public Operation {
     610             : public:
     611           8 :     Csc() {
     612             :     }
     613           6 :     std::string getName() const {
     614           6 :         return "csc";
     615             :     }
     616         224 :     Id getId() const {
     617         224 :         return CSC;
     618             :     }
     619          54 :     int getNumArguments() const {
     620          54 :         return 1;
     621             :     }
     622         240 :     Operation* clone() const {
     623         240 :         return new Csc();
     624             :     }
     625         606 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     626         606 :         return 1.0/std::sin(args[0]);
     627             :     }
     628             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     629             : };
     630             : 
     631             : class LEPTON_EXPORT Operation::Tan : public Operation {
     632             : public:
     633           6 :     Tan() {
     634             :     }
     635           4 :     std::string getName() const {
     636           4 :         return "tan";
     637             :     }
     638         140 :     Id getId() const {
     639         140 :         return TAN;
     640             :     }
     641          36 :     int getNumArguments() const {
     642          36 :         return 1;
     643             :     }
     644         104 :     Operation* clone() const {
     645         104 :         return new Tan();
     646             :     }
     647         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     648         202 :         return std::tan(args[0]);
     649             :     }
     650             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     651             : };
     652             : 
     653             : class LEPTON_EXPORT Operation::Cot : public Operation {
     654             : public:
     655           6 :     Cot() {
     656             :     }
     657           4 :     std::string getName() const {
     658           4 :         return "cot";
     659             :     }
     660         146 :     Id getId() const {
     661         146 :         return COT;
     662             :     }
     663          36 :     int getNumArguments() const {
     664          36 :         return 1;
     665             :     }
     666         134 :     Operation* clone() const {
     667         134 :         return new Cot();
     668             :     }
     669         404 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     670         404 :         return 1.0/std::tan(args[0]);
     671             :     }
     672             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     673             : };
     674             : 
     675             : class LEPTON_EXPORT Operation::Asin : public Operation {
     676             : public:
     677          38 :     Asin() {
     678             :     }
     679           2 :     std::string getName() const {
     680           2 :         return "asin";
     681             :     }
     682          46 :     Id getId() const {
     683          46 :         return ASIN;
     684             :     }
     685          20 :     int getNumArguments() const {
     686          20 :         return 1;
     687             :     }
     688          34 :     Operation* clone() const {
     689          34 :         return new Asin();
     690             :     }
     691         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     692         101 :         return std::asin(args[0]);
     693             :     }
     694             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     695             : };
     696             : 
     697             : class LEPTON_EXPORT Operation::Acos : public Operation {
     698             : public:
     699          38 :     Acos() {
     700             :     }
     701           2 :     std::string getName() const {
     702           2 :         return "acos";
     703             :     }
     704          46 :     Id getId() const {
     705          46 :         return ACOS;
     706             :     }
     707          20 :     int getNumArguments() const {
     708          20 :         return 1;
     709             :     }
     710          34 :     Operation* clone() const {
     711          34 :         return new Acos();
     712             :     }
     713         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     714         101 :         return std::acos(args[0]);
     715             :     }
     716             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     717             : };
     718             : 
     719             : class LEPTON_EXPORT Operation::Atan : public Operation {
     720             : public:
     721          38 :     Atan() {
     722             :     }
     723           2 :     std::string getName() const {
     724           2 :         return "atan";
     725             :     }
     726          46 :     Id getId() const {
     727          46 :         return ATAN;
     728             :     }
     729          20 :     int getNumArguments() const {
     730          20 :         return 1;
     731             :     }
     732          34 :     Operation* clone() const {
     733          34 :         return new Atan();
     734             :     }
     735         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     736         101 :         return std::atan(args[0]);
     737             :     }
     738             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     739             : };
     740             : 
     741             : class LEPTON_EXPORT Operation::Atan2 : public Operation {
     742             : public:
     743         136 :     Atan2() {
     744             :     }
     745           8 :     std::string getName() const {
     746           8 :         return "atan2";
     747             :     }
     748         160 :     Id getId() const {
     749         160 :         return ATAN2;
     750             :     }
     751          88 :     int getNumArguments() const {
     752          88 :         return 2;
     753             :     }
     754         120 :     Operation* clone() const {
     755         120 :         return new Atan2();
     756             :     }
     757         404 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     758         404 :         return std::atan2(args[0], args[1]);
     759             :     }
     760             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     761             : };
     762             : 
     763             : class LEPTON_EXPORT Operation::Sinh : public Operation {
     764             : public:
     765           6 :     Sinh() {
     766             :     }
     767           4 :     std::string getName() const {
     768           4 :         return "sinh";
     769             :     }
     770          88 :     Id getId() const {
     771          88 :         return SINH;
     772             :     }
     773          36 :     int getNumArguments() const {
     774          36 :         return 1;
     775             :     }
     776          78 :     Operation* clone() const {
     777          78 :         return new Sinh();
     778             :     }
     779         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     780         202 :         return std::sinh(args[0]);
     781             :     }
     782             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     783             : };
     784             : 
     785             : class LEPTON_EXPORT Operation::Cosh : public Operation {
     786             : public:
     787           6 :     Cosh() {
     788             :     }
     789           4 :     std::string getName() const {
     790           4 :         return "cosh";
     791             :     }
     792          88 :     Id getId() const {
     793          88 :         return COSH;
     794             :     }
     795          36 :     int getNumArguments() const {
     796          36 :         return 1;
     797             :     }
     798          78 :     Operation* clone() const {
     799          78 :         return new Cosh();
     800             :     }
     801         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     802         202 :         return std::cosh(args[0]);
     803             :     }
     804             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     805             : };
     806             : 
     807             : class LEPTON_EXPORT Operation::Tanh : public Operation {
     808             : public:
     809           8 :     Tanh() {
     810             :     }
     811           6 :     std::string getName() const {
     812           6 :         return "tanh";
     813             :     }
     814         228 :     Id getId() const {
     815         228 :         return TANH;
     816             :     }
     817          54 :     int getNumArguments() const {
     818          54 :         return 1;
     819             :     }
     820         242 :     Operation* clone() const {
     821         242 :         return new Tanh();
     822             :     }
     823         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     824         303 :         return std::tanh(args[0]);
     825             :     }
     826             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     827             : };
     828             : 
     829             : class LEPTON_EXPORT Operation::Erf : public Operation {
     830             : public:
     831          34 :     Erf() {
     832             :     }
     833           2 :     std::string getName() const {
     834           2 :         return "erf";
     835             :     }
     836          40 :     Id getId() const {
     837          40 :         return ERF;
     838             :     }
     839          18 :     int getNumArguments() const {
     840          18 :         return 1;
     841             :     }
     842          30 :     Operation* clone() const {
     843          30 :         return new Erf();
     844             :     }
     845             :     double evaluate(double* args, const std::map<std::string, double>& variables) const;
     846             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     847             : };
     848             : 
     849             : class LEPTON_EXPORT Operation::Erfc : public Operation {
     850             : public:
     851          34 :     Erfc() {
     852             :     }
     853           2 :     std::string getName() const {
     854           2 :         return "erfc";
     855             :     }
     856          40 :     Id getId() const {
     857          40 :         return ERFC;
     858             :     }
     859          18 :     int getNumArguments() const {
     860          18 :         return 1;
     861             :     }
     862          30 :     Operation* clone() const {
     863          30 :         return new Erfc();
     864             :     }
     865             :     double evaluate(double* args, const std::map<std::string, double>& variables) const;
     866             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     867             : };
     868             : 
     869             : class LEPTON_EXPORT Operation::Step : public Operation {
     870             : public:
     871          39 :     Step() {
     872             :     }
     873          17 :     std::string getName() const {
     874          17 :         return "step";
     875             :     }
     876        4303 :     Id getId() const {
     877        4303 :         return STEP;
     878             :     }
     879         373 :     int getNumArguments() const {
     880         373 :         return 1;
     881             :     }
     882        2628 :     Operation* clone() const {
     883        2628 :         return new Step();
     884             :     }
     885         606 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     886         606 :         return (args[0] >= 0.0 ? 1.0 : 0.0);
     887             :     }
     888             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     889             : };
     890             : 
     891             : class LEPTON_EXPORT Operation::Delta : public Operation {
     892             : public:
     893          17 :     Delta() {
     894             :     }
     895           8 :     std::string getName() const {
     896           8 :         return "delta";
     897             :     }
     898        2395 :     Id getId() const {
     899        2395 :         return DELTA;
     900             :     }
     901         182 :     int getNumArguments() const {
     902         182 :         return 1;
     903             :     }
     904        1107 :     Operation* clone() const {
     905        1107 :         return new Delta();
     906             :     }
     907         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     908         202 :         return (args[0] == 0.0 ? 1.0/0.0 : 0.0);
     909             :     }
     910             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     911             : };
     912             : 
     913             : class LEPTON_EXPORT Operation::Nandelta : public Operation {
     914             : public:
     915           8 :     Nandelta() {
     916             :     }
     917           6 :     std::string getName() const {
     918           6 :         return "nandelta";
     919             :     }
     920         120 :     Id getId() const {
     921         120 :         return NANDELTA;
     922             :     }
     923          50 :     int getNumArguments() const {
     924          50 :         return 1;
     925             :     }
     926          90 :     Operation* clone() const {
     927          90 :         return new Nandelta();
     928             :     }
     929         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     930         303 :         return (args[0] == 0.0 ? std::numeric_limits<double>::quiet_NaN() : 0.0);
     931             :     }
     932             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     933             : };
     934             : 
     935             : class LEPTON_EXPORT Operation::Square : public Operation {
     936             : public:
     937         378 :     Square() {
     938             :     }
     939         374 :     std::string getName() const {
     940         374 :         return "square";
     941             :     }
     942       19443 :     Id getId() const {
     943       19443 :         return SQUARE;
     944             :     }
     945        2333 :     int getNumArguments() const {
     946        2333 :         return 1;
     947             :     }
     948       20360 :     Operation* clone() const {
     949       20360 :         return new Square();
     950             :     }
     951        3155 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     952        3155 :         return args[0]*args[0];
     953             :     }
     954             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     955             : };
     956             : 
     957             : class LEPTON_EXPORT Operation::Cube : public Operation {
     958             : public:
     959        1107 :     Cube() {
     960             :     }
     961          23 :     std::string getName() const {
     962          23 :         return "cube";
     963             :     }
     964        1405 :     Id getId() const {
     965        1405 :         return CUBE;
     966             :     }
     967         256 :     int getNumArguments() const {
     968         256 :         return 1;
     969             :     }
     970        1055 :     Operation* clone() const {
     971        1055 :         return new Cube();
     972             :     }
     973         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     974         202 :         return args[0]*args[0]*args[0];
     975             :     }
     976             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     977             : };
     978             : 
     979             : class LEPTON_EXPORT Operation::Reciprocal : public Operation {
     980             : public:
     981          93 :     Reciprocal() {
     982             :     }
     983          81 :     std::string getName() const {
     984          81 :         return "recip";
     985             :     }
     986        4059 :     Id getId() const {
     987        4059 :         return RECIPROCAL;
     988             :     }
     989         834 :     int getNumArguments() const {
     990         834 :         return 1;
     991             :     }
     992        4372 :     Operation* clone() const {
     993        4372 :         return new Reciprocal();
     994             :     }
     995        2121 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     996        2121 :         return 1.0/args[0];
     997             :     }
     998             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     999             : };
    1000             : 
    1001             : class LEPTON_EXPORT Operation::AddConstant : public Operation {
    1002             : public:
    1003         542 :     AddConstant(double value) : value(value) {
    1004             :     }
    1005         796 :     std::string getName() const {
    1006         796 :         std::stringstream name;
    1007         796 :         name << value << "+";
    1008         796 :         return name.str();
    1009         796 :     }
    1010       12010 :     Id getId() const {
    1011       12010 :         return ADD_CONSTANT;
    1012             :     }
    1013        3513 :     int getNumArguments() const {
    1014        3513 :         return 1;
    1015             :     }
    1016       37351 :     Operation* clone() const {
    1017       37351 :         return new AddConstant(value);
    1018             :     }
    1019        2907 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1020        2907 :         return args[0]+value;
    1021             :     }
    1022             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1023             :     double getValue() const {
    1024         850 :         return value;
    1025             :     }
    1026       10085 :     bool operator!=(const Operation& op) const {
    1027       10085 :         const AddConstant* o = dynamic_cast<const AddConstant*>(&op);
    1028       10085 :         return (o == NULL || o->value != value);
    1029             :     }
    1030             : private:
    1031             :     double value;
    1032             : };
    1033             : 
    1034             : class LEPTON_EXPORT Operation::MultiplyConstant : public Operation {
    1035             : public:
    1036        2135 :     MultiplyConstant(double value) : value(value) {
    1037             :     }
    1038        1412 :     std::string getName() const {
    1039        1412 :         std::stringstream name;
    1040        1412 :         name << value << "*";
    1041        1412 :         return name.str();
    1042        1412 :     }
    1043       54125 :     Id getId() const {
    1044       54125 :         return MULTIPLY_CONSTANT;
    1045             :     }
    1046       11256 :     int getNumArguments() const {
    1047       11256 :         return 1;
    1048             :     }
    1049       55327 :     Operation* clone() const {
    1050       55327 :         return new MultiplyConstant(value);
    1051             :     }
    1052        2626 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1053        2626 :         return args[0]*value;
    1054             :     }
    1055             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1056             :     double getValue() const {
    1057        3550 :         return value;
    1058             :     }
    1059       35217 :     bool operator!=(const Operation& op) const {
    1060       35217 :         const MultiplyConstant* o = dynamic_cast<const MultiplyConstant*>(&op);
    1061       35217 :         return (o == NULL || o->value != value);
    1062             :     }
    1063             : private:
    1064             :     double value;
    1065             : };
    1066             : 
    1067             : class LEPTON_EXPORT Operation::PowerConstant : public Operation {
    1068             : public:
    1069        2298 :     PowerConstant(double value) : value(value) {
    1070        2298 :         intValue = (int) value;
    1071          69 :         isIntPower = (intValue == value);
    1072             :     }
    1073          37 :     std::string getName() const {
    1074          37 :         std::stringstream name;
    1075          37 :         name << "^" << value;
    1076          37 :         return name.str();
    1077          37 :     }
    1078        2047 :     Id getId() const {
    1079        2047 :         return POWER_CONSTANT;
    1080             :     }
    1081         454 :     int getNumArguments() const {
    1082         454 :         return 1;
    1083             :     }
    1084        2229 :     Operation* clone() const {
    1085        2229 :         return new PowerConstant(value);
    1086             :     }
    1087    10691410 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1088    10691410 :         if (isIntPower) {
    1089             :             // Integer powers can be computed much more quickly by repeated multiplication.
    1090             :             
    1091    10687191 :             int exponent = intValue;
    1092    10687191 :             double base = args[0];
    1093    10687191 :             if (exponent < 0) {
    1094         804 :                 exponent = -exponent;
    1095         804 :                 base = 1.0/base;
    1096             :             }
    1097             :             double result = 1.0;
    1098    42750671 :             while (exponent != 0) {
    1099    32063480 :                 if ((exponent&1) == 1)
    1100    23423887 :                     result *= base;
    1101    32063480 :                 base *= base;
    1102    32063480 :                 exponent = exponent>>1;
    1103             :            }
    1104             :            return result;
    1105             :         }
    1106             :         else
    1107        4219 :         return std::pow(args[0], value);
    1108             :     }
    1109             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1110             :     double getValue() const {
    1111             :         return value;
    1112             :     }
    1113         572 :     bool operator!=(const Operation& op) const {
    1114         572 :         const PowerConstant* o = dynamic_cast<const PowerConstant*>(&op);
    1115         572 :         return (o == NULL || o->value != value);
    1116             :     }
    1117          74 :     bool isInfixOperator() const {
    1118          74 :         return true;
    1119             :     }
    1120             : private:
    1121             :     double value;
    1122             :     int intValue;
    1123             :     bool isIntPower;
    1124             : };
    1125             : 
    1126             : class LEPTON_EXPORT Operation::Min : public Operation {
    1127             : public:
    1128          68 :     Min() {
    1129             :     }
    1130           4 :     std::string getName() const {
    1131           4 :         return "min";
    1132             :     }
    1133          80 :     Id getId() const {
    1134          80 :         return MIN;
    1135             :     }
    1136          44 :     int getNumArguments() const {
    1137          44 :         return 2;
    1138             :     }
    1139          60 :     Operation* clone() const {
    1140          60 :         return new Min();
    1141             :     }
    1142         404 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1143             :         // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
    1144         404 :         return (std::min)(args[0], args[1]);
    1145             :     }
    1146             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1147             : };
    1148             : 
    1149             : class LEPTON_EXPORT Operation::Max : public Operation {
    1150             : public:
    1151          68 :     Max() {
    1152             :     }
    1153           4 :     std::string getName() const {
    1154           4 :         return "max";
    1155             :     }
    1156          80 :     Id getId() const {
    1157          80 :         return MAX;
    1158             :     }
    1159          44 :     int getNumArguments() const {
    1160          44 :         return 2;
    1161             :     }
    1162          60 :     Operation* clone() const {
    1163          60 :         return new Max();
    1164             :     }
    1165         404 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1166             :         // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
    1167         404 :         return (std::max)(args[0], args[1]);
    1168             :     }
    1169             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1170             : };
    1171             : 
    1172             : class LEPTON_EXPORT Operation::Abs : public Operation {
    1173             : public:
    1174          21 :     Abs() {
    1175             :     }
    1176          18 :     std::string getName() const {
    1177          18 :         return "abs";
    1178             :     }
    1179         846 :     Id getId() const {
    1180         846 :         return ABS;
    1181             :     }
    1182         160 :     int getNumArguments() const {
    1183         160 :         return 1;
    1184             :     }
    1185         976 :     Operation* clone() const {
    1186         976 :         return new Abs();
    1187             :     }
    1188         505 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1189         505 :         return std::abs(args[0]);
    1190             :     }
    1191             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1192             : };
    1193             : 
    1194             : class LEPTON_EXPORT Operation::Floor : public Operation {
    1195             : public:
    1196             : 
    1197          34 :     Floor() {
    1198             :     }
    1199           2 :     std::string getName() const {
    1200           2 :         return "floor";
    1201             :     }
    1202          40 :     Id getId() const {
    1203          40 :         return FLOOR;
    1204             :     }
    1205          18 :     int getNumArguments() const {
    1206          18 :         return 1;
    1207             :     }
    1208          30 :     Operation* clone() const {
    1209          30 :         return new Floor();
    1210             :     }
    1211         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1212         101 :         return std::floor(args[0]);
    1213             :     }
    1214             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1215             : };
    1216             : 
    1217             : class LEPTON_EXPORT Operation::Ceil : public Operation {
    1218             : public:
    1219          34 :     Ceil() {
    1220             :     }
    1221           2 :     std::string getName() const {
    1222           2 :         return "ceil";
    1223             :     }
    1224          40 :     Id getId() const {
    1225          40 :         return CEIL;
    1226             :     }
    1227          18 :     int getNumArguments() const {
    1228          18 :         return 1;
    1229             :     }
    1230          30 :     Operation* clone() const {
    1231          30 :         return new Ceil();
    1232             :     }
    1233         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1234         101 :         return std::ceil(args[0]);
    1235             :     }
    1236             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1237             : };
    1238             : 
    1239             : class LEPTON_EXPORT Operation::Select : public Operation {
    1240             : public:
    1241          36 :     Select() {
    1242             :     }
    1243          16 :     std::string getName() const {
    1244          16 :         return "select";
    1245             :     }
    1246         344 :     Id getId() const {
    1247         344 :         return SELECT;
    1248             :     }
    1249         188 :     int getNumArguments() const {
    1250         188 :         return 3;
    1251             :     }
    1252         272 :     Operation* clone() const {
    1253         272 :         return new Select();
    1254             :     }
    1255        1624 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1256        1624 :         return (args[0] != 0.0 ? args[1] : args[2]);
    1257             :     }
    1258             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1259             : };
    1260             : 
    1261             : #define LEPTON_CLASS_OPERATION(Name,name,NAME,nargs,impl) \
    1262             : class LEPTON_EXPORT Operation::Name : public Operation { \
    1263             : public: \
    1264             :     Name() { \
    1265             :     } \
    1266             :     std::string getName() const { \
    1267             :         return #name; \
    1268             :     } \
    1269             :     Id getId() const { \
    1270             :         return NAME; \
    1271             :     } \
    1272             :     int getNumArguments() const { \
    1273             :         return nargs; \
    1274             :     } \
    1275             :     Operation* clone() const { \
    1276             :         return new Name(); \
    1277             :     } \
    1278             :     double evaluate(double* args, const std::map<std::string, double>& variables) const { \
    1279             :         return impl; \
    1280             :     } \
    1281             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const; \
    1282             : }
    1283             : 
    1284         296 : LEPTON_CLASS_OPERATION(Acot,acot,ACOT,1,std::atan(1.0/args[0]));
    1285         296 : LEPTON_CLASS_OPERATION(Asec,asec,ASEC,1,std::acos(1.0/args[0]));
    1286         296 : LEPTON_CLASS_OPERATION(Acsc,acsc,ACSC,1,std::asin(1.0/args[0]));
    1287        1144 : LEPTON_CLASS_OPERATION(Coth,coth,ACOT,1,1.0/std::tanh(args[0]));
    1288         730 : LEPTON_CLASS_OPERATION(Sech,sech,SECH,1,1.0/std::cosh(args[0]));
    1289         730 : LEPTON_CLASS_OPERATION(Csch,csch,CSCH,1,1.0/std::sinh(args[0]));
    1290             : 
    1291         195 : LEPTON_CLASS_OPERATION(Asinh,asinh,ASINH,1,std::asinh(args[0]));
    1292         195 : LEPTON_CLASS_OPERATION(Acosh,acosh,ACOSH,1,std::acosh(args[0]));
    1293         195 : LEPTON_CLASS_OPERATION(Atanh,atanh,ATANH,1,std::atanh(args[0]));
    1294             : 
    1295         296 : LEPTON_CLASS_OPERATION(Acoth,acoth,ACOTH,1,0.5*std::log((args[0]+1.0)/(args[0]-1.0)));
    1296         296 : LEPTON_CLASS_OPERATION(Asech,asech,ASECH,1,std::log(std::sqrt(1.0/args[0]-1.0)*std::sqrt(1.0/args[0]+1.0)+1.0/args[0]));
    1297         296 : LEPTON_CLASS_OPERATION(Acsch,acsch,ACSCH,1,std::log(1.0/args[0]+std::sqrt(1.0/(args[0]*args[0])+1.0)));
    1298             : 
    1299             : } // namespace lepton
    1300             : } // namespace PLMD
    1301             : 
    1302             : #endif /*LEPTON_OPERATION_H_*/

Generated by: LCOV version 1.15