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-18 14:00:27 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       98954 :     virtual bool isInfixOperator() const {
     139       98954 :         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     1030714 :     virtual bool isSymmetric() const {
     146     1030714 :         return false;
     147             :     }
     148     8522745 :     virtual bool operator!=(const Operation& op) const {
     149     8522745 :         return op.getId() != getId();
     150             :     }
     151     8273372 :     virtual bool operator==(const Operation& op) const {
     152     8273372 :         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     2070326 :     Constant(double value) : value(value) {
     213             :     }
     214        1307 :     std::string getName() const {
     215        1307 :         std::stringstream name;
     216        1307 :         name << value;
     217        1307 :         return name.str();
     218        1307 :     }
     219      235493 :     Id getId() const {
     220      235493 :         return CONSTANT;
     221             :     }
     222     2159039 :     int getNumArguments() const {
     223     2159039 :         return 0;
     224             :     }
     225     4819946 :     Operation* clone() const {
     226     4819946 :         return new Constant(value);
     227             :     }
     228     2039421 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     229     2039421 :         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       57509 :         return value;
     234             :     }
     235     1378293 :     bool operator!=(const Operation& op) const {
     236     1378293 :         const Constant* o = dynamic_cast<const Constant*>(&op);
     237     1378293 :         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     3225653 :     Variable(const std::string& name) : name(name) {
     246     3225653 :     }
     247       97912 :     std::string getName() const {
     248       97912 :         return name;
     249             :     }
     250      509539 :     Id getId() const {
     251      509539 :         return VARIABLE;
     252             :     }
     253       99657 :     int getNumArguments() const {
     254       99657 :         return 0;
     255             :     }
     256     3204494 :     Operation* clone() const {
     257     6408988 :         return new Variable(name);
     258             :     }
     259          30 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     260          30 :         std::map<std::string, double>::const_iterator iter = variables.find(name);
     261          30 :         if (iter == variables.end())
     262          44 :             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      898008 :     bool operator!=(const Operation& op) const {
     267      898008 :         const Variable* o = dynamic_cast<const Variable*>(&op);
     268      898008 :         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        9202 :     Add() {
     327             :     }
     328        6137 :     std::string getName() const {
     329        6137 :         return "+";
     330             :     }
     331     4693891 :     Id getId() const {
     332     4693891 :         return ADD;
     333             :     }
     334       79378 :     int getNumArguments() const {
     335       79378 :         return 2;
     336             :     }
     337     1371244 :     Operation* clone() const {
     338     1371244 :         return new Add();
     339             :     }
     340         424 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     341         424 :         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        6137 :     bool isInfixOperator() const {
     345        6137 :         return true;
     346             :     }
     347      505512 :     bool isSymmetric() const {
     348      505512 :         return true;
     349             :     }
     350             : };
     351             : 
     352             : class LEPTON_EXPORT Operation::Subtract : public Operation {
     353             : public:
     354        4818 :     Subtract() {
     355             :     }
     356        1387 :     std::string getName() const {
     357        1387 :         return "-";
     358             :     }
     359     1762394 :     Id getId() const {
     360     1762394 :         return SUBTRACT;
     361             :     }
     362       37633 :     int getNumArguments() const {
     363       37633 :         return 2;
     364             :     }
     365      825569 :     Operation* clone() const {
     366      825569 :         return new Subtract();
     367             :     }
     368        1328 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     369        1328 :         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        1387 :     bool isInfixOperator() const {
     373        1387 :         return true;
     374             :     }
     375             : };
     376             : 
     377             : class LEPTON_EXPORT Operation::Multiply : public Operation {
     378             : public:
     379       27507 :     Multiply() {
     380             :     }
     381        3346 :     std::string getName() const {
     382        3346 :         return "*";
     383             :     }
     384     4234767 :     Id getId() const {
     385     4234767 :         return MULTIPLY;
     386             :     }
     387      126490 :     int getNumArguments() const {
     388      126490 :         return 2;
     389             :     }
     390     1564448 :     Operation* clone() const {
     391     1564448 :         return new Multiply();
     392             :     }
     393        3447 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     394        3447 :         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        3346 :     bool isInfixOperator() const {
     398        3346 :         return true;
     399             :     }
     400       65568 :     bool isSymmetric() const {
     401       65568 :         return true;
     402             :     }
     403             : };
     404             : 
     405             : class LEPTON_EXPORT Operation::Divide : public Operation {
     406             : public:
     407        8812 :     Divide() {
     408             :     }
     409        2990 :     std::string getName() const {
     410        2990 :         return "/";
     411             :     }
     412      707207 :     Id getId() const {
     413      707207 :         return DIVIDE;
     414             :     }
     415       61685 :     int getNumArguments() const {
     416       61685 :         return 2;
     417             :     }
     418      241491 :     Operation* clone() const {
     419      241491 :         return new Divide();
     420             :     }
     421         813 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     422         813 :         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        2990 :     bool isInfixOperator() const {
     426        2990 :         return true;
     427             :     }
     428             : };
     429             : 
     430             : class LEPTON_EXPORT Operation::Power : public Operation {
     431             : public:
     432        5564 :     Power() {
     433             :     }
     434           4 :     std::string getName() const {
     435           4 :         return "^";
     436             :     }
     437     1589975 :     Id getId() const {
     438     1589975 :         return POWER;
     439             :     }
     440       17617 :     int getNumArguments() const {
     441       17617 :         return 2;
     442             :     }
     443      560283 :     Operation* clone() const {
     444      560283 :         return new Power();
     445             :     }
     446         205 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     447         205 :         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        6072 :     Negate() {
     458             :     }
     459         772 :     std::string getName() const {
     460         772 :         return "-";
     461             :     }
     462      342739 :     Id getId() const {
     463      342739 :         return NEGATE;
     464             :     }
     465       32474 :     int getNumArguments() const {
     466       32474 :         return 1;
     467             :     }
     468      448490 :     Operation* clone() const {
     469      448490 :         return new Negate();
     470             :     }
     471        2811 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     472        2811 :         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        1063 :     Sqrt() {
     480             :     }
     481         732 :     std::string getName() const {
     482         732 :         return "sqrt";
     483             :     }
     484       54306 :     Id getId() const {
     485       54306 :         return SQRT;
     486             :     }
     487       10688 :     int getNumArguments() const {
     488       10688 :         return 1;
     489             :     }
     490       50179 :     Operation* clone() const {
     491       50179 :         return new Sqrt();
     492             :     }
     493        1116 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     494        1116 :         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        2986 :     Exp() {
     502             :     }
     503        2230 :     std::string getName() const {
     504        2230 :         return "exp";
     505             :     }
     506     1165561 :     Id getId() const {
     507     1165561 :         return EXP;
     508             :     }
     509       29973 :     int getNumArguments() const {
     510       29973 :         return 1;
     511             :     }
     512      354615 :     Operation* clone() const {
     513      354615 :         return new Exp();
     514             :     }
     515         406 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     516         406 :         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        1957 :     Log() {
     524             :     }
     525         370 :     std::string getName() const {
     526         370 :         return "log";
     527             :     }
     528      196293 :     Id getId() const {
     529      196293 :         return LOG;
     530             :     }
     531       11847 :     int getNumArguments() const {
     532       11847 :         return 1;
     533             :     }
     534      180809 :     Operation* clone() const {
     535      180809 :         return new Log();
     536             :     }
     537         109 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     538         109 :         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         488 :     Sin() {
     546             :     }
     547         900 :     std::string getName() const {
     548         900 :         return "sin";
     549             :     }
     550       93264 :     Id getId() const {
     551       93264 :         return SIN;
     552             :     }
     553        6610 :     int getNumArguments() const {
     554        6610 :         return 1;
     555             :     }
     556       80709 :     Operation* clone() const {
     557       80709 :         return new Sin();
     558             :     }
     559         207 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     560         207 :         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        1599 :     Cos() {
     568             :     }
     569        1342 :     std::string getName() const {
     570        1342 :         return "cos";
     571             :     }
     572      121365 :     Id getId() const {
     573      121365 :         return COS;
     574             :     }
     575       10578 :     int getNumArguments() const {
     576       10578 :         return 1;
     577             :     }
     578      122503 :     Operation* clone() const {
     579      122503 :         return new Cos();
     580             :     }
     581         205 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     582         205 :         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         340 :     Id getId() const {
     595         340 :         return SEC;
     596             :     }
     597          78 :     int getNumArguments() const {
     598          78 :         return 1;
     599             :     }
     600         256 :     Operation* clone() const {
     601         256 :         return new Sec();
     602             :     }
     603         608 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     604         608 :         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         362 :     Id getId() const {
     617         362 :         return CSC;
     618             :     }
     619          78 :     int getNumArguments() const {
     620          78 :         return 1;
     621             :     }
     622         336 :     Operation* clone() const {
     623         336 :         return new Csc();
     624             :     }
     625         608 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     626         608 :         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         224 :     Id getId() const {
     639         224 :         return TAN;
     640             :     }
     641          52 :     int getNumArguments() const {
     642          52 :         return 1;
     643             :     }
     644         146 :     Operation* clone() const {
     645         146 :         return new Tan();
     646             :     }
     647         203 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     648         203 :         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         236 :     Id getId() const {
     661         236 :         return COT;
     662             :     }
     663          52 :     int getNumArguments() const {
     664          52 :         return 1;
     665             :     }
     666         190 :     Operation* clone() const {
     667         190 :         return new Cot();
     668             :     }
     669         406 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     670         406 :         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          54 :     Asin() {
     678             :     }
     679           2 :     std::string getName() const {
     680           2 :         return "asin";
     681             :     }
     682          74 :     Id getId() const {
     683          74 :         return ASIN;
     684             :     }
     685          28 :     int getNumArguments() const {
     686          28 :         return 1;
     687             :     }
     688          50 :     Operation* clone() const {
     689          50 :         return new Asin();
     690             :     }
     691         102 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     692         102 :         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         183 :     Acos() {
     700             :     }
     701           7 :     std::string getName() const {
     702           7 :         return "acos";
     703             :     }
     704         324 :     Id getId() const {
     705         324 :         return ACOS;
     706             :     }
     707         105 :     int getNumArguments() const {
     708         105 :         return 1;
     709             :     }
     710         167 :     Operation* clone() const {
     711         167 :         return new Acos();
     712             :     }
     713         102 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     714         102 :         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          54 :     Atan() {
     722             :     }
     723           2 :     std::string getName() const {
     724           2 :         return "atan";
     725             :     }
     726          74 :     Id getId() const {
     727          74 :         return ATAN;
     728             :     }
     729          28 :     int getNumArguments() const {
     730          28 :         return 1;
     731             :     }
     732          50 :     Operation* clone() const {
     733          50 :         return new Atan();
     734             :     }
     735         102 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     736         102 :         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        1353 :     Atan2() {
     744             :     }
     745          30 :     std::string getName() const {
     746          30 :         return "atan2";
     747             :     }
     748        1878 :     Id getId() const {
     749        1878 :         return ATAN2;
     750             :     }
     751         633 :     int getNumArguments() const {
     752         633 :         return 2;
     753             :     }
     754        1270 :     Operation* clone() const {
     755        1270 :         return new Atan2();
     756             :     }
     757         408 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     758         408 :         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         144 :     Id getId() const {
     771         144 :         return SINH;
     772             :     }
     773          52 :     int getNumArguments() const {
     774          52 :         return 1;
     775             :     }
     776         110 :     Operation* clone() const {
     777         110 :         return new Sinh();
     778             :     }
     779         203 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     780         203 :         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         144 :     Id getId() const {
     793         144 :         return COSH;
     794             :     }
     795          52 :     int getNumArguments() const {
     796          52 :         return 1;
     797             :     }
     798         110 :     Operation* clone() const {
     799         110 :         return new Cosh();
     800             :     }
     801         203 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     802         203 :         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          23 :     Tanh() {
     810             :     }
     811          13 :     std::string getName() const {
     812          13 :         return "tanh";
     813             :     }
     814        1793 :     Id getId() const {
     815        1793 :         return TANH;
     816             :     }
     817         251 :     int getNumArguments() const {
     818         251 :         return 1;
     819             :     }
     820        2237 :     Operation* clone() const {
     821        2237 :         return new Tanh();
     822             :     }
     823         304 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     824         304 :         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          50 :     Erf() {
     832             :     }
     833           2 :     std::string getName() const {
     834           2 :         return "erf";
     835             :     }
     836          68 :     Id getId() const {
     837          68 :         return ERF;
     838             :     }
     839          26 :     int getNumArguments() const {
     840          26 :         return 1;
     841             :     }
     842          46 :     Operation* clone() const {
     843          46 :         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          50 :     Erfc() {
     852             :     }
     853           2 :     std::string getName() const {
     854           2 :         return "erfc";
     855             :     }
     856          68 :     Id getId() const {
     857          68 :         return ERFC;
     858             :     }
     859          26 :     int getNumArguments() const {
     860          26 :         return 1;
     861             :     }
     862          46 :     Operation* clone() const {
     863          46 :         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         393 :     Step() {
     872             :     }
     873         431 :     std::string getName() const {
     874         431 :         return "step";
     875             :     }
     876      163299 :     Id getId() const {
     877      163299 :         return STEP;
     878             :     }
     879        5084 :     int getNumArguments() const {
     880        5084 :         return 1;
     881             :     }
     882       48060 :     Operation* clone() const {
     883       48060 :         return new Step();
     884             :     }
     885         607 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     886         607 :         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         257 :     Delta() {
     894             :     }
     895         248 :     std::string getName() const {
     896         248 :         return "delta";
     897             :     }
     898      126045 :     Id getId() const {
     899      126045 :         return DELTA;
     900             :     }
     901        3899 :     int getNumArguments() const {
     902        3899 :         return 1;
     903             :     }
     904       25363 :     Operation* clone() const {
     905       25363 :         return new Delta();
     906             :     }
     907         203 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     908         203 :         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         204 :     Id getId() const {
     921         204 :         return NANDELTA;
     922             :     }
     923          74 :     int getNumArguments() const {
     924          74 :         return 1;
     925             :     }
     926         138 :     Operation* clone() const {
     927         138 :         return new Nandelta();
     928             :     }
     929         304 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     930         304 :         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        5378 :     Square() {
     938             :     }
     939        6521 :     std::string getName() const {
     940        6521 :         return "square";
     941             :     }
     942     2042212 :     Id getId() const {
     943     2042212 :         return SQUARE;
     944             :     }
     945       60400 :     int getNumArguments() const {
     946       60400 :         return 1;
     947             :     }
     948      841065 :     Operation* clone() const {
     949      841065 :         return new Square();
     950             :     }
     951        3707 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     952        3707 :         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        3024 :     Cube() {
     960             :     }
     961          51 :     std::string getName() const {
     962          51 :         return "cube";
     963             :     }
     964        5171 :     Id getId() const {
     965        5171 :         return CUBE;
     966             :     }
     967         689 :     int getNumArguments() const {
     968         689 :         return 1;
     969             :     }
     970        2879 :     Operation* clone() const {
     971        2879 :         return new Cube();
     972             :     }
     973         204 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     974         204 :         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         870 :     Reciprocal() {
     982             :     }
     983         738 :     std::string getName() const {
     984         738 :         return "recip";
     985             :     }
     986       43704 :     Id getId() const {
     987       43704 :         return RECIPROCAL;
     988             :     }
     989       10874 :     int getNumArguments() const {
     990       10874 :         return 1;
     991             :     }
     992       36189 :     Operation* clone() const {
     993       36189 :         return new Reciprocal();
     994             :     }
     995        2122 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     996        2122 :         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        3221 :     AddConstant(double value) : value(value) {
    1004             :     }
    1005        4440 :     std::string getName() const {
    1006        4440 :         std::stringstream name;
    1007        4440 :         name << value << "+";
    1008        4440 :         return name.str();
    1009        4440 :     }
    1010      420588 :     Id getId() const {
    1011      420588 :         return ADD_CONSTANT;
    1012             :     }
    1013       26804 :     int getNumArguments() const {
    1014       26804 :         return 1;
    1015             :     }
    1016      792892 :     Operation* clone() const {
    1017      792892 :         return new AddConstant(value);
    1018             :     }
    1019        2887 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1020        2887 :         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        7176 :         return value;
    1025             :     }
    1026      983418 :     bool operator!=(const Operation& op) const {
    1027      983418 :         const AddConstant* o = dynamic_cast<const AddConstant*>(&op);
    1028      983418 :         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       12414 :     MultiplyConstant(double value) : value(value) {
    1037             :     }
    1038        8359 :     std::string getName() const {
    1039        8359 :         std::stringstream name;
    1040        8359 :         name << value << "*";
    1041        8359 :         return name.str();
    1042        8359 :     }
    1043      946722 :     Id getId() const {
    1044      946722 :         return MULTIPLY_CONSTANT;
    1045             :     }
    1046       92138 :     int getNumArguments() const {
    1047       92138 :         return 1;
    1048             :     }
    1049      935939 :     Operation* clone() const {
    1050      935939 :         return new MultiplyConstant(value);
    1051             :     }
    1052        2634 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1053        2634 :         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       32210 :         return value;
    1058             :     }
    1059     2024697 :     bool operator!=(const Operation& op) const {
    1060     2024697 :         const MultiplyConstant* o = dynamic_cast<const MultiplyConstant*>(&op);
    1061     2024697 :         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        4093 :     PowerConstant(double value) : value(value) {
    1070        4093 :         intValue = (int) value;
    1071         115 :         isIntPower = (intValue == value);
    1072             :     }
    1073          69 :     std::string getName() const {
    1074          69 :         std::stringstream name;
    1075          69 :         name << "^" << value;
    1076          69 :         return name.str();
    1077          69 :     }
    1078        4021 :     Id getId() const {
    1079        4021 :         return POWER_CONSTANT;
    1080             :     }
    1081         761 :     int getNumArguments() const {
    1082         761 :         return 1;
    1083             :     }
    1084        3978 :     Operation* clone() const {
    1085        3978 :         return new PowerConstant(value);
    1086             :     }
    1087    11045323 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1088    11045323 :         if (isIntPower) {
    1089             :             // Integer powers can be computed much more quickly by repeated multiplication.
    1090             :             
    1091    11041104 :             int exponent = intValue;
    1092    11041104 :             double base = args[0];
    1093    11041104 :             if (exponent < 0) {
    1094         804 :                 exponent = -exponent;
    1095         804 :                 base = 1.0/base;
    1096             :             }
    1097             :             double result = 1.0;
    1098    44166323 :             while (exponent != 0) {
    1099    33125219 :                 if ((exponent&1) == 1)
    1100    23777800 :                     result *= base;
    1101    33125219 :                 base *= base;
    1102    33125219 :                 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        1277 :     bool operator!=(const Operation& op) const {
    1114        1277 :         const PowerConstant* o = dynamic_cast<const PowerConstant*>(&op);
    1115        1277 :         return (o == NULL || o->value != value);
    1116             :     }
    1117         138 :     bool isInfixOperator() const {
    1118         138 :         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         100 :     Min() {
    1129             :     }
    1130           4 :     std::string getName() const {
    1131           4 :         return "min";
    1132             :     }
    1133         136 :     Id getId() const {
    1134         136 :         return MIN;
    1135             :     }
    1136          68 :     int getNumArguments() const {
    1137          68 :         return 2;
    1138             :     }
    1139          92 :     Operation* clone() const {
    1140          92 :         return new Min();
    1141             :     }
    1142         408 :     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         408 :         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         100 :     Max() {
    1152             :     }
    1153           4 :     std::string getName() const {
    1154           4 :         return "max";
    1155             :     }
    1156         136 :     Id getId() const {
    1157         136 :         return MAX;
    1158             :     }
    1159          68 :     int getNumArguments() const {
    1160          68 :         return 2;
    1161             :     }
    1162          92 :     Operation* clone() const {
    1163          92 :         return new Max();
    1164             :     }
    1165         408 :     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         408 :         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        1092 :     Id getId() const {
    1180        1092 :         return ABS;
    1181             :     }
    1182         200 :     int getNumArguments() const {
    1183         200 :         return 1;
    1184             :     }
    1185        1152 :     Operation* clone() const {
    1186        1152 :         return new Abs();
    1187             :     }
    1188         507 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1189         507 :         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          50 :     Floor() {
    1198             :     }
    1199           2 :     std::string getName() const {
    1200           2 :         return "floor";
    1201             :     }
    1202          68 :     Id getId() const {
    1203          68 :         return FLOOR;
    1204             :     }
    1205          26 :     int getNumArguments() const {
    1206          26 :         return 1;
    1207             :     }
    1208          46 :     Operation* clone() const {
    1209          46 :         return new Floor();
    1210             :     }
    1211         102 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1212         102 :         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          50 :     Ceil() {
    1220             :     }
    1221           2 :     std::string getName() const {
    1222           2 :         return "ceil";
    1223             :     }
    1224          68 :     Id getId() const {
    1225          68 :         return CEIL;
    1226             :     }
    1227          26 :     int getNumArguments() const {
    1228          26 :         return 1;
    1229             :     }
    1230          46 :     Operation* clone() const {
    1231          46 :         return new Ceil();
    1232             :     }
    1233         102 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1234         102 :         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          44 :     Select() {
    1242             :     }
    1243          24 :     std::string getName() const {
    1244          24 :         return "select";
    1245             :     }
    1246         852 :     Id getId() const {
    1247         852 :         return SELECT;
    1248             :     }
    1249         424 :     int getNumArguments() const {
    1250         424 :         return 3;
    1251             :     }
    1252         592 :     Operation* clone() const {
    1253         592 :         return new Select();
    1254             :     }
    1255        2444 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1256        2444 :         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         350 : LEPTON_CLASS_OPERATION(Acot,acot,ACOT,1,std::atan(1.0/args[0]));
    1285         350 : LEPTON_CLASS_OPERATION(Asec,asec,ASEC,1,std::acos(1.0/args[0]));
    1286         350 : LEPTON_CLASS_OPERATION(Acsc,acsc,ACSC,1,std::asin(1.0/args[0]));
    1287        1410 : LEPTON_CLASS_OPERATION(Coth,coth,ACOT,1,1.0/std::tanh(args[0]));
    1288         894 : LEPTON_CLASS_OPERATION(Sech,sech,SECH,1,1.0/std::cosh(args[0]));
    1289         894 : LEPTON_CLASS_OPERATION(Csch,csch,CSCH,1,1.0/std::sinh(args[0]));
    1290             : 
    1291         248 : LEPTON_CLASS_OPERATION(Asinh,asinh,ASINH,1,std::asinh(args[0]));
    1292         248 : LEPTON_CLASS_OPERATION(Acosh,acosh,ACOSH,1,std::acosh(args[0]));
    1293         248 : LEPTON_CLASS_OPERATION(Atanh,atanh,ATANH,1,std::atanh(args[0]));
    1294             : 
    1295         350 : LEPTON_CLASS_OPERATION(Acoth,acoth,ACOTH,1,0.5*std::log((args[0]+1.0)/(args[0]-1.0)));
    1296         350 : 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         350 : 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.16