LCOV - code coverage report
Current view: top level - lepton - Operation.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 477 580 82.2 %
Date: 2021-11-18 15:22:59 Functions: 295 396 74.5 %

          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-2015 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, 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, ATAN2};
     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       14462 :     virtual bool isInfixOperator() const {
     139       14462 :         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       47724 :     virtual bool isSymmetric() const {
     146       47724 :         return false;
     147             :     }
     148       56134 :     virtual bool operator!=(const Operation& op) const {
     149       56134 :         return op.getId() != getId();
     150             :     }
     151           0 :     virtual bool operator==(const Operation& op) const {
     152           0 :         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 Sinh;
     176             :     class Cosh;
     177             :     class Tanh;
     178             :     class Erf;
     179             :     class Erfc;
     180             :     class Step;
     181             :     class Delta;
     182             :     class Nandelta;
     183             :     class Square;
     184             :     class Cube;
     185             :     class Reciprocal;
     186             :     class AddConstant;
     187             :     class MultiplyConstant;
     188             :     class PowerConstant;
     189             :     class Min;
     190             :     class Max;
     191             :     class Abs;
     192             :     class Floor;
     193             :     class Ceil;
     194             :     class Select;
     195             :     class Acot;
     196             :     class Asec;
     197             :     class Acsc;
     198             :     class Coth;
     199             :     class Sech;
     200             :     class Csch;
     201             :     class Asinh;
     202             :     class Acosh;
     203             :     class Atanh;
     204             :     class Acoth;
     205             :     class Asech;
     206             :     class Acsch;
     207             :     class Atan2;
     208             : };
     209             : 
     210      363317 : class LEPTON_EXPORT Operation::Constant : public Operation {
     211             : public:
     212      363317 :     Constant(double value) : value(value) {
     213             :     }
     214          77 :     std::string getName() const {
     215         154 :         std::stringstream name;
     216          77 :         name << value;
     217          77 :         return name.str();
     218             :     }
     219       45505 :     Id getId() const {
     220       45505 :         return CONSTANT;
     221             :     }
     222       40191 :     int getNumArguments() const {
     223       40191 :         return 0;
     224             :     }
     225      344124 :     Operation* clone() const {
     226      688248 :         return new Constant(value);
     227             :     }
     228       47055 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     229       47055 :         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        6748 :         return value;
     234             :     }
     235         783 :     bool operator!=(const Operation& op) const {
     236         783 :         const Constant* o = dynamic_cast<const Constant*>(&op);
     237         783 :         return (o == NULL || o->value != value);
     238             :     }
     239             : private:
     240             :     double value;
     241             : };
     242             : 
     243      834588 : class LEPTON_EXPORT Operation::Variable : public Operation {
     244             : public:
     245      417294 :     Variable(const std::string& name) : name(name) {
     246             :     }
     247        9564 :     std::string getName() const {
     248        9564 :         return name;
     249             :     }
     250       46464 :     Id getId() const {
     251       46464 :         return VARIABLE;
     252             :     }
     253       20639 :     int getNumArguments() const {
     254       20639 :         return 0;
     255             :     }
     256      414404 :     Operation* clone() const {
     257      828808 :         return new Variable(name);
     258             :     }
     259           3 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     260           3 :         std::map<std::string, double>::const_iterator iter = variables.find(name);
     261           3 :         if (iter == variables.end())
     262           0 :             throw Exception("No value specified for variable "+name);
     263           3 :         return iter->second;
     264             :     }
     265             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     266       20216 :     bool operator!=(const Operation& op) const {
     267       20216 :         const Variable* o = dynamic_cast<const Variable*>(&op);
     268       39362 :         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           0 :     Custom(const Custom& base, int derivIndex) : name(base.name), function(base.function->clone()), isDerivative(true), derivOrder(base.derivOrder) {
     279           0 :         derivOrder[derivIndex]++;
     280           0 :     }
     281           0 :     ~Custom() {
     282           0 :         delete function;
     283           0 :     }
     284           0 :     std::string getName() const {
     285           0 :         return name;
     286             :     }
     287           0 :     Id getId() const {
     288           0 :         return CUSTOM;
     289             :     }
     290           0 :     int getNumArguments() const {
     291           0 :         return function->getNumArguments();
     292             :     }
     293           0 :     Operation* clone() const {
     294           0 :         Custom* clone = new Custom(name, function->clone());
     295           0 :         clone->isDerivative = isDerivative;
     296           0 :         clone->derivOrder = derivOrder;
     297           0 :         return clone;
     298             :     }
     299           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     300           0 :         if (isDerivative)
     301           0 :             return function->evaluateDerivative(args, &derivOrder[0]);
     302           0 :         return function->evaluate(args);
     303             :     }
     304             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     305             :     const std::vector<int>& getDerivOrder() const {
     306             :         return derivOrder;
     307             :     }
     308           0 :     bool operator!=(const Operation& op) const {
     309           0 :         const Custom* o = dynamic_cast<const Custom*>(&op);
     310           0 :         return (o == NULL || o->name != name || o->isDerivative != isDerivative || o->derivOrder != derivOrder);
     311             :     }
     312             : private:
     313             :     std::string name;
     314             :     CustomFunction* function;
     315             :     bool isDerivative;
     316             :     std::vector<int> derivOrder;
     317             : };
     318             : 
     319      102546 : class LEPTON_EXPORT Operation::Add : public Operation {
     320             : public:
     321      102546 :     Add() {
     322             :     }
     323         606 :     std::string getName() const {
     324         606 :         return "+";
     325             :     }
     326       31560 :     Id getId() const {
     327       31560 :         return ADD;
     328             :     }
     329       12031 :     int getNumArguments() const {
     330       12031 :         return 2;
     331             :     }
     332       99627 :     Operation* clone() const {
     333      199254 :         return new Add();
     334             :     }
     335      760482 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     336      760482 :         return args[0]+args[1];
     337             :     }
     338             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     339         606 :     bool isInfixOperator() const {
     340         606 :         return true;
     341             :     }
     342        3293 :     bool isSymmetric() const {
     343        3293 :         return true;
     344             :     }
     345             : };
     346             : 
     347       64598 : class LEPTON_EXPORT Operation::Subtract : public Operation {
     348             : public:
     349       64598 :     Subtract() {
     350             :     }
     351         410 :     std::string getName() const {
     352         410 :         return "-";
     353             :     }
     354       14640 :     Id getId() const {
     355       14640 :         return SUBTRACT;
     356             :     }
     357        7045 :     int getNumArguments() const {
     358        7045 :         return 2;
     359             :     }
     360       63111 :     Operation* clone() const {
     361      126222 :         return new Subtract();
     362             :     }
     363       85655 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     364       85655 :         return args[0]-args[1];
     365             :     }
     366             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     367         410 :     bool isInfixOperator() const {
     368         410 :         return true;
     369             :     }
     370             : };
     371             : 
     372      236584 : class LEPTON_EXPORT Operation::Multiply : public Operation {
     373             : public:
     374      236584 :     Multiply() {
     375             :     }
     376         823 :     std::string getName() const {
     377         823 :         return "*";
     378             :     }
     379       55743 :     Id getId() const {
     380       55743 :         return MULTIPLY;
     381             :     }
     382       23371 :     int getNumArguments() const {
     383       23371 :         return 2;
     384             :     }
     385      230068 :     Operation* clone() const {
     386      460136 :         return new Multiply();
     387             :     }
     388      810050 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     389      810050 :         return args[0]*args[1];
     390             :     }
     391             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     392         823 :     bool isInfixOperator() const {
     393         823 :         return true;
     394             :     }
     395        5404 :     bool isSymmetric() const {
     396        5404 :         return true;
     397             :     }
     398             : };
     399             : 
     400       33641 : class LEPTON_EXPORT Operation::Divide : public Operation {
     401             : public:
     402       33641 :     Divide() {
     403             :     }
     404          43 :     std::string getName() const {
     405          43 :         return "/";
     406             :     }
     407        4248 :     Id getId() const {
     408        4248 :         return DIVIDE;
     409             :     }
     410        2779 :     int getNumArguments() const {
     411        2779 :         return 2;
     412             :     }
     413       32982 :     Operation* clone() const {
     414       65964 :         return new Divide();
     415             :     }
     416     4792064 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     417     4792064 :         return args[0]/args[1];
     418             :     }
     419             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     420          43 :     bool isInfixOperator() const {
     421          43 :         return true;
     422             :     }
     423             : };
     424             : 
     425       14579 : class LEPTON_EXPORT Operation::Power : public Operation {
     426             : public:
     427       14579 :     Power() {
     428             :     }
     429           0 :     std::string getName() const {
     430           0 :         return "^";
     431             :     }
     432        1742 :     Id getId() const {
     433        1742 :         return POWER;
     434             :     }
     435        1098 :     int getNumArguments() const {
     436        1098 :         return 2;
     437             :     }
     438       14209 :     Operation* clone() const {
     439       28418 :         return new Power();
     440             :     }
     441           2 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     442           2 :         return std::pow(args[0], args[1]);
     443             :     }
     444             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     445           0 :     bool isInfixOperator() const {
     446           0 :         return true;
     447             :     }
     448             : };
     449             : 
     450       39205 : class LEPTON_EXPORT Operation::Negate : public Operation {
     451             : public:
     452       39205 :     Negate() {
     453             :     }
     454          54 :     std::string getName() const {
     455          54 :         return "-";
     456             :     }
     457        8423 :     Id getId() const {
     458        8423 :         return NEGATE;
     459             :     }
     460        3523 :     int getNumArguments() const {
     461        3523 :         return 1;
     462             :     }
     463       38453 :     Operation* clone() const {
     464       76906 :         return new Negate();
     465             :     }
     466     7750931 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     467     7750931 :         return -args[0];
     468             :     }
     469             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     470             : };
     471             : 
     472        7975 : class LEPTON_EXPORT Operation::Sqrt : public Operation {
     473             : public:
     474        7975 :     Sqrt() {
     475             :     }
     476          99 :     std::string getName() const {
     477          99 :         return "sqrt";
     478             :     }
     479        4062 :     Id getId() const {
     480        4062 :         return SQRT;
     481             :     }
     482         805 :     int getNumArguments() const {
     483         805 :         return 1;
     484             :     }
     485        7872 :     Operation* clone() const {
     486       15744 :         return new Sqrt();
     487             :     }
     488       11073 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     489       11073 :         return std::sqrt(args[0]);
     490             :     }
     491             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     492             : };
     493             : 
     494         963 : class LEPTON_EXPORT Operation::Exp : public Operation {
     495             : public:
     496         963 :     Exp() {
     497             :     }
     498          23 :     std::string getName() const {
     499          23 :         return "exp";
     500             :     }
     501         959 :     Id getId() const {
     502         959 :         return EXP;
     503             :     }
     504         211 :     int getNumArguments() const {
     505         211 :         return 1;
     506             :     }
     507         936 :     Operation* clone() const {
     508        1872 :         return new Exp();
     509             :     }
     510     2558965 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     511     2558965 :         return std::exp(args[0]);
     512             :     }
     513             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     514             : };
     515             : 
     516        4713 : class LEPTON_EXPORT Operation::Log : public Operation {
     517             : public:
     518        4713 :     Log() {
     519             :     }
     520           1 :     std::string getName() const {
     521           1 :         return "log";
     522             :     }
     523        1261 :     Id getId() const {
     524        1261 :         return LOG;
     525             :     }
     526         384 :     int getNumArguments() const {
     527         384 :         return 1;
     528             :     }
     529        4617 :     Operation* clone() const {
     530        9234 :         return new Log();
     531             :     }
     532         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     533         101 :         return std::log(args[0]);
     534             :     }
     535             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     536             : };
     537             : 
     538       80016 : class LEPTON_EXPORT Operation::Sin : public Operation {
     539             : public:
     540       80016 :     Sin() {
     541             :     }
     542         731 :     std::string getName() const {
     543         731 :         return "sin";
     544             :     }
     545       36821 :     Id getId() const {
     546       36821 :         return SIN;
     547             :     }
     548        6061 :     int getNumArguments() const {
     549        6061 :         return 1;
     550             :     }
     551       79277 :     Operation* clone() const {
     552      158554 :         return new Sin();
     553             :     }
     554      285240 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     555      285240 :         return std::sin(args[0]);
     556             :     }
     557             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     558             : };
     559             : 
     560      121767 : class LEPTON_EXPORT Operation::Cos : public Operation {
     561             : public:
     562      121767 :     Cos() {
     563             :     }
     564        1115 :     std::string getName() const {
     565        1115 :         return "cos";
     566             :     }
     567       52819 :     Id getId() const {
     568       52819 :         return COS;
     569             :     }
     570       10196 :     int getNumArguments() const {
     571       10196 :         return 1;
     572             :     }
     573      120453 :     Operation* clone() const {
     574      240906 :         return new Cos();
     575             :     }
     576      526746 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     577      526746 :         return std::cos(args[0]);
     578             :     }
     579             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     580             : };
     581             : 
     582         111 : class LEPTON_EXPORT Operation::Sec : public Operation {
     583             : public:
     584         111 :     Sec() {
     585             :     }
     586           3 :     std::string getName() const {
     587           3 :         return "sec";
     588             :     }
     589          75 :     Id getId() const {
     590          75 :         return SEC;
     591             :     }
     592          24 :     int getNumArguments() const {
     593          24 :         return 1;
     594             :     }
     595         107 :     Operation* clone() const {
     596         214 :         return new Sec();
     597             :     }
     598         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     599         303 :         return 1.0/std::cos(args[0]);
     600             :     }
     601             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     602             : };
     603             : 
     604         147 : class LEPTON_EXPORT Operation::Csc : public Operation {
     605             : public:
     606         147 :     Csc() {
     607             :     }
     608           3 :     std::string getName() const {
     609           3 :         return "csc";
     610             :     }
     611          80 :     Id getId() const {
     612          80 :         return CSC;
     613             :     }
     614          24 :     int getNumArguments() const {
     615          24 :         return 1;
     616             :     }
     617         143 :     Operation* clone() const {
     618         286 :         return new Csc();
     619             :     }
     620         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     621         303 :         return 1.0/std::sin(args[0]);
     622             :     }
     623             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     624             : };
     625             : 
     626          64 : class LEPTON_EXPORT Operation::Tan : public Operation {
     627             : public:
     628          64 :     Tan() {
     629             :     }
     630           2 :     std::string getName() const {
     631           2 :         return "tan";
     632             :     }
     633          52 :     Id getId() const {
     634          52 :         return TAN;
     635             :     }
     636          16 :     int getNumArguments() const {
     637          16 :         return 1;
     638             :     }
     639          61 :     Operation* clone() const {
     640         122 :         return new Tan();
     641             :     }
     642         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     643         202 :         return std::tan(args[0]);
     644             :     }
     645             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     646             : };
     647             : 
     648          83 : class LEPTON_EXPORT Operation::Cot : public Operation {
     649             : public:
     650          83 :     Cot() {
     651             :     }
     652           2 :     std::string getName() const {
     653           2 :         return "cot";
     654             :     }
     655          55 :     Id getId() const {
     656          55 :         return COT;
     657             :     }
     658          16 :     int getNumArguments() const {
     659          16 :         return 1;
     660             :     }
     661          80 :     Operation* clone() const {
     662         160 :         return new Cot();
     663             :     }
     664         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     665         202 :         return 1.0/std::tan(args[0]);
     666             :     }
     667             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     668             : };
     669             : 
     670          22 : class LEPTON_EXPORT Operation::Asin : public Operation {
     671             : public:
     672          22 :     Asin() {
     673             :     }
     674           1 :     std::string getName() const {
     675           1 :         return "asin";
     676             :     }
     677          15 :     Id getId() const {
     678          15 :         return ASIN;
     679             :     }
     680           9 :     int getNumArguments() const {
     681           9 :         return 1;
     682             :     }
     683          20 :     Operation* clone() const {
     684          40 :         return new Asin();
     685             :     }
     686         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     687         101 :         return std::asin(args[0]);
     688             :     }
     689             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     690             : };
     691             : 
     692          22 : class LEPTON_EXPORT Operation::Acos : public Operation {
     693             : public:
     694          22 :     Acos() {
     695             :     }
     696           1 :     std::string getName() const {
     697           1 :         return "acos";
     698             :     }
     699          15 :     Id getId() const {
     700          15 :         return ACOS;
     701             :     }
     702           9 :     int getNumArguments() const {
     703           9 :         return 1;
     704             :     }
     705          20 :     Operation* clone() const {
     706          40 :         return new Acos();
     707             :     }
     708         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     709         101 :         return std::acos(args[0]);
     710             :     }
     711             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     712             : };
     713             : 
     714          22 : class LEPTON_EXPORT Operation::Atan : public Operation {
     715             : public:
     716          22 :     Atan() {
     717             :     }
     718           1 :     std::string getName() const {
     719           1 :         return "atan";
     720             :     }
     721          15 :     Id getId() const {
     722          15 :         return ATAN;
     723             :     }
     724           9 :     int getNumArguments() const {
     725           9 :         return 1;
     726             :     }
     727          20 :     Operation* clone() const {
     728          40 :         return new Atan();
     729             :     }
     730         101 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     731         101 :         return std::atan(args[0]);
     732             :     }
     733             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     734             : };
     735             : 
     736          47 : class LEPTON_EXPORT Operation::Sinh : public Operation {
     737             : public:
     738          47 :     Sinh() {
     739             :     }
     740           2 :     std::string getName() const {
     741           2 :         return "sinh";
     742             :     }
     743          28 :     Id getId() const {
     744          28 :         return SINH;
     745             :     }
     746          16 :     int getNumArguments() const {
     747          16 :         return 1;
     748             :     }
     749          44 :     Operation* clone() const {
     750          88 :         return new Sinh();
     751             :     }
     752         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     753         202 :         return std::sinh(args[0]);
     754             :     }
     755             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     756             : };
     757             : 
     758          47 : class LEPTON_EXPORT Operation::Cosh : public Operation {
     759             : public:
     760          47 :     Cosh() {
     761             :     }
     762           2 :     std::string getName() const {
     763           2 :         return "cosh";
     764             :     }
     765          28 :     Id getId() const {
     766          28 :         return COSH;
     767             :     }
     768          16 :     int getNumArguments() const {
     769          16 :         return 1;
     770             :     }
     771          44 :     Operation* clone() const {
     772          88 :         return new Cosh();
     773             :     }
     774         202 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     775         202 :         return std::cosh(args[0]);
     776             :     }
     777             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     778             : };
     779             : 
     780         148 : class LEPTON_EXPORT Operation::Tanh : public Operation {
     781             : public:
     782         148 :     Tanh() {
     783             :     }
     784           3 :     std::string getName() const {
     785           3 :         return "tanh";
     786             :     }
     787          82 :     Id getId() const {
     788          82 :         return TANH;
     789             :     }
     790          24 :     int getNumArguments() const {
     791          24 :         return 1;
     792             :     }
     793         144 :     Operation* clone() const {
     794         288 :         return new Tanh();
     795             :     }
     796         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     797         303 :         return std::tanh(args[0]);
     798             :     }
     799             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     800             : };
     801             : 
     802          20 : class LEPTON_EXPORT Operation::Erf : public Operation {
     803             : public:
     804          20 :     Erf() {
     805             :     }
     806           1 :     std::string getName() const {
     807           1 :         return "erf";
     808             :     }
     809          12 :     Id getId() const {
     810          12 :         return ERF;
     811             :     }
     812           8 :     int getNumArguments() const {
     813           8 :         return 1;
     814             :     }
     815          18 :     Operation* clone() const {
     816          36 :         return new Erf();
     817             :     }
     818             :     double evaluate(double* args, const std::map<std::string, double>& variables) const;
     819             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     820             : };
     821             : 
     822           0 : class LEPTON_EXPORT Operation::Erfc : public Operation {
     823             : public:
     824           0 :     Erfc() {
     825             :     }
     826           0 :     std::string getName() const {
     827           0 :         return "erfc";
     828             :     }
     829           0 :     Id getId() const {
     830           0 :         return ERFC;
     831             :     }
     832           0 :     int getNumArguments() const {
     833           0 :         return 1;
     834             :     }
     835           0 :     Operation* clone() const {
     836           0 :         return new Erfc();
     837             :     }
     838             :     double evaluate(double* args, const std::map<std::string, double>& variables) const;
     839             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     840             : };
     841             : 
     842         558 : class LEPTON_EXPORT Operation::Step : public Operation {
     843             : public:
     844         558 :     Step() {
     845             :     }
     846           3 :     std::string getName() const {
     847           3 :         return "step";
     848             :     }
     849         305 :     Id getId() const {
     850         305 :         return STEP;
     851             :     }
     852          65 :     int getNumArguments() const {
     853          65 :         return 1;
     854             :     }
     855         550 :     Operation* clone() const {
     856        1100 :         return new Step();
     857             :     }
     858      682999 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     859      682999 :         return (args[0] >= 0.0 ? 1.0 : 0.0);
     860             :     }
     861             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     862             : };
     863             : 
     864         252 : class LEPTON_EXPORT Operation::Delta : public Operation {
     865             : public:
     866         252 :     Delta() {
     867             :     }
     868           2 :     std::string getName() const {
     869           2 :         return "delta";
     870             :     }
     871         227 :     Id getId() const {
     872         227 :         return DELTA;
     873             :     }
     874          39 :     int getNumArguments() const {
     875          39 :         return 1;
     876             :     }
     877         247 :     Operation* clone() const {
     878         494 :         return new Delta();
     879             :     }
     880      454128 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     881      454128 :         return (args[0] == 0.0 ? 1.0/0.0 : 0.0);
     882             :     }
     883             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     884             : };
     885             : 
     886          52 : class LEPTON_EXPORT Operation::Nandelta : public Operation {
     887             : public:
     888          52 :     Nandelta() {
     889             :     }
     890           3 :     std::string getName() const {
     891           3 :         return "nandelta";
     892             :     }
     893          36 :     Id getId() const {
     894          36 :         return NANDELTA;
     895             :     }
     896          22 :     int getNumArguments() const {
     897          22 :         return 1;
     898             :     }
     899          48 :     Operation* clone() const {
     900          96 :         return new Nandelta();
     901             :     }
     902         303 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     903         303 :         return (args[0] == 0.0 ? std::numeric_limits<double>::quiet_NaN() : 0.0);
     904             :     }
     905             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     906             : };
     907             : 
     908       33429 : class LEPTON_EXPORT Operation::Square : public Operation {
     909             : public:
     910       33429 :     Square() {
     911             :     }
     912         354 :     std::string getName() const {
     913         354 :         return "square";
     914             :     }
     915       15056 :     Id getId() const {
     916       15056 :         return SQUARE;
     917             :     }
     918        2629 :     int getNumArguments() const {
     919        2629 :         return 1;
     920             :     }
     921       32710 :     Operation* clone() const {
     922       65420 :         return new Square();
     923             :     }
     924     6156091 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     925     6156091 :         return args[0]*args[0];
     926             :     }
     927             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     928             : };
     929             : 
     930        1321 : class LEPTON_EXPORT Operation::Cube : public Operation {
     931             : public:
     932        1321 :     Cube() {
     933             :     }
     934          19 :     std::string getName() const {
     935          19 :         return "cube";
     936             :     }
     937         824 :     Id getId() const {
     938         824 :         return CUBE;
     939             :     }
     940         187 :     int getNumArguments() const {
     941         187 :         return 1;
     942             :     }
     943        1252 :     Operation* clone() const {
     944        2504 :         return new Cube();
     945             :     }
     946     2550349 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     947     2550349 :         return args[0]*args[0]*args[0];
     948             :     }
     949             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     950             : };
     951             : 
     952        4352 : class LEPTON_EXPORT Operation::Reciprocal : public Operation {
     953             : public:
     954        4352 :     Reciprocal() {
     955             :     }
     956          52 :     std::string getName() const {
     957          52 :         return "recip";
     958             :     }
     959        2381 :     Id getId() const {
     960        2381 :         return RECIPROCAL;
     961             :     }
     962         487 :     int getNumArguments() const {
     963         487 :         return 1;
     964             :     }
     965        4288 :     Operation* clone() const {
     966        8576 :         return new Reciprocal();
     967             :     }
     968     4793024 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     969     4793024 :         return 1.0/args[0];
     970             :     }
     971             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     972             : };
     973             : 
     974       46490 : class LEPTON_EXPORT Operation::AddConstant : public Operation {
     975             : public:
     976       46490 :     AddConstant(double value) : value(value) {
     977             :     }
     978         727 :     std::string getName() const {
     979        1454 :         std::stringstream name;
     980        1454 :         name << value << "+";
     981         727 :         return name.str();
     982             :     }
     983        7401 :     Id getId() const {
     984        7401 :         return ADD_CONSTANT;
     985             :     }
     986        4229 :     int getNumArguments() const {
     987        4229 :         return 1;
     988             :     }
     989       45436 :     Operation* clone() const {
     990       90872 :         return new AddConstant(value);
     991             :     }
     992    10153874 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
     993    10153874 :         return args[0]+value;
     994             :     }
     995             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
     996             :     double getValue() const {
     997             :         return value;
     998             :     }
     999        5785 :     bool operator!=(const Operation& op) const {
    1000        5785 :         const AddConstant* o = dynamic_cast<const AddConstant*>(&op);
    1001        5785 :         return (o == NULL || o->value != value);
    1002             :     }
    1003             : private:
    1004             :     double value;
    1005             : };
    1006             : 
    1007       62978 : class LEPTON_EXPORT Operation::MultiplyConstant : public Operation {
    1008             : public:
    1009       62978 :     MultiplyConstant(double value) : value(value) {
    1010             :     }
    1011        1332 :     std::string getName() const {
    1012        2664 :         std::stringstream name;
    1013        2664 :         name << value << "*";
    1014        1332 :         return name.str();
    1015             :     }
    1016       39145 :     Id getId() const {
    1017       39145 :         return MULTIPLY_CONSTANT;
    1018             :     }
    1019        7873 :     int getNumArguments() const {
    1020        7873 :         return 1;
    1021             :     }
    1022       60913 :     Operation* clone() const {
    1023      121826 :         return new MultiplyConstant(value);
    1024             :     }
    1025     7953728 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1026     7953728 :         return args[0]*value;
    1027             :     }
    1028             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1029             :     double getValue() const {
    1030         664 :         return value;
    1031             :     }
    1032       22412 :     bool operator!=(const Operation& op) const {
    1033       22412 :         const MultiplyConstant* o = dynamic_cast<const MultiplyConstant*>(&op);
    1034       22412 :         return (o == NULL || o->value != value);
    1035             :     }
    1036             : private:
    1037             :     double value;
    1038             : };
    1039             : 
    1040        2898 : class LEPTON_EXPORT Operation::PowerConstant : public Operation {
    1041             : public:
    1042        2898 :     PowerConstant(double value) : value(value) {
    1043        2898 :         intValue = (int) value;
    1044        2898 :         isIntPower = (intValue == value);
    1045             :     }
    1046          36 :     std::string getName() const {
    1047          72 :         std::stringstream name;
    1048          36 :         name << "^" << value;
    1049          36 :         return name.str();
    1050             :     }
    1051         985 :     Id getId() const {
    1052         985 :         return POWER_CONSTANT;
    1053             :     }
    1054         343 :     int getNumArguments() const {
    1055         343 :         return 1;
    1056             :     }
    1057        2804 :     Operation* clone() const {
    1058        5608 :         return new PowerConstant(value);
    1059             :     }
    1060    10698533 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1061    10698533 :         if (isIntPower) {
    1062             :             // Integer powers can be computed much more quickly by repeated multiplication.
    1063             :             
    1064    10694415 :             int exponent = intValue;
    1065    10694415 :             double base = args[0];
    1066    10694415 :             if (exponent < 0) {
    1067         804 :                 exponent = -exponent;
    1068         804 :                 base = 1.0/base;
    1069             :             }
    1070             :             double result = 1.0;
    1071    74865923 :             while (exponent != 0) {
    1072    32085754 :                 if ((exponent&1) == 1)
    1073    23435325 :                     result *= base;
    1074    32085754 :                 base *= base;
    1075    32085754 :                 exponent = exponent>>1;
    1076             :            }
    1077             :            return result;
    1078             :         }
    1079             :         else
    1080        4118 :         return std::pow(args[0], value);
    1081             :     }
    1082             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1083             :     double getValue() const {
    1084             :         return value;
    1085             :     }
    1086         505 :     bool operator!=(const Operation& op) const {
    1087         505 :         const PowerConstant* o = dynamic_cast<const PowerConstant*>(&op);
    1088         505 :         return (o == NULL || o->value != value);
    1089             :     }
    1090          72 :     bool isInfixOperator() const {
    1091          72 :         return true;
    1092             :     }
    1093             : private:
    1094             :     double value;
    1095             :     int intValue;
    1096             :     bool isIntPower;
    1097             : };
    1098             : 
    1099           0 : class LEPTON_EXPORT Operation::Min : public Operation {
    1100             : public:
    1101           0 :     Min() {
    1102             :     }
    1103           0 :     std::string getName() const {
    1104           0 :         return "min";
    1105             :     }
    1106           0 :     Id getId() const {
    1107           0 :         return MIN;
    1108             :     }
    1109           0 :     int getNumArguments() const {
    1110           0 :         return 2;
    1111             :     }
    1112           0 :     Operation* clone() const {
    1113           0 :         return new Min();
    1114             :     }
    1115           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1116             :         // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
    1117           0 :         return (std::min)(args[0], args[1]);
    1118             :     }
    1119             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1120             : };
    1121             : 
    1122           0 : class LEPTON_EXPORT Operation::Max : public Operation {
    1123             : public:
    1124           0 :     Max() {
    1125             :     }
    1126           0 :     std::string getName() const {
    1127           0 :         return "max";
    1128             :     }
    1129           0 :     Id getId() const {
    1130           0 :         return MAX;
    1131             :     }
    1132           0 :     int getNumArguments() const {
    1133           0 :         return 2;
    1134             :     }
    1135           0 :     Operation* clone() const {
    1136           0 :         return new Max();
    1137             :     }
    1138           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1139             :         // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
    1140           0 :         return (std::max)(args[0], args[1]);
    1141             :     }
    1142             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1143             : };
    1144             : 
    1145         973 : class LEPTON_EXPORT Operation::Abs : public Operation {
    1146             : public:
    1147         973 :     Abs() {
    1148             :     }
    1149          11 :     std::string getName() const {
    1150          11 :         return "abs";
    1151             :     }
    1152         450 :     Id getId() const {
    1153         450 :         return ABS;
    1154             :     }
    1155          89 :     int getNumArguments() const {
    1156          89 :         return 1;
    1157             :     }
    1158         960 :     Operation* clone() const {
    1159        1920 :         return new Abs();
    1160             :     }
    1161        8568 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1162       17136 :         return std::abs(args[0]);
    1163             :     }
    1164             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1165             : };
    1166             : 
    1167           0 : class LEPTON_EXPORT Operation::Floor : public Operation {
    1168             : public:
    1169             : 
    1170           0 :     Floor() {
    1171             :     }
    1172           0 :     std::string getName() const {
    1173           0 :         return "floor";
    1174             :     }
    1175           0 :     Id getId() const {
    1176           0 :         return FLOOR;
    1177             :     }
    1178           0 :     int getNumArguments() const {
    1179           0 :         return 1;
    1180             :     }
    1181           0 :     Operation* clone() const {
    1182           0 :         return new Floor();
    1183             :     }
    1184           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1185           0 :         return std::floor(args[0]);
    1186             :     }
    1187             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1188             : };
    1189             : 
    1190           0 : class LEPTON_EXPORT Operation::Ceil : public Operation {
    1191             : public:
    1192           0 :     Ceil() {
    1193             :     }
    1194           0 :     std::string getName() const {
    1195           0 :         return "ceil";
    1196             :     }
    1197           0 :     Id getId() const {
    1198           0 :         return CEIL;
    1199             :     }
    1200           0 :     int getNumArguments() const {
    1201           0 :         return 1;
    1202             :     }
    1203           0 :     Operation* clone() const {
    1204           0 :         return new Ceil();
    1205             :     }
    1206           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1207           0 :         return std::ceil(args[0]);
    1208             :     }
    1209             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1210             : };
    1211             : 
    1212           0 : class LEPTON_EXPORT Operation::Select : public Operation {
    1213             : public:
    1214           0 :     Select() {
    1215             :     }
    1216           0 :     std::string getName() const {
    1217           0 :         return "select";
    1218             :     }
    1219           0 :     Id getId() const {
    1220           0 :         return SELECT;
    1221             :     }
    1222           0 :     int getNumArguments() const {
    1223           0 :         return 3;
    1224             :     }
    1225           0 :     Operation* clone() const {
    1226           0 :         return new Select();
    1227             :     }
    1228           0 :     double evaluate(double* args, const std::map<std::string, double>& variables) const {
    1229           0 :         return (args[0] != 0.0 ? args[1] : args[2]);
    1230             :     }
    1231             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    1232             : };
    1233             : 
    1234             : #define LEPTON_CLASS_OPERATION(Name,name,NAME,nargs,impl) \
    1235             : class LEPTON_EXPORT Operation::Name : public Operation { \
    1236             : public: \
    1237             :     Name() { \
    1238             :     } \
    1239             :     std::string getName() const { \
    1240             :         return #name; \
    1241             :     } \
    1242             :     Id getId() const { \
    1243             :         return NAME; \
    1244             :     } \
    1245             :     int getNumArguments() const { \
    1246             :         return nargs; \
    1247             :     } \
    1248             :     Operation* clone() const { \
    1249             :         return new Name(); \
    1250             :     } \
    1251             :     double evaluate(double* args, const std::map<std::string, double>& variables) const { \
    1252             :         return impl; \
    1253             :     } \
    1254             :     ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const; \
    1255             : }
    1256             : 
    1257         162 : LEPTON_CLASS_OPERATION(Acot,acot,ACOT,1,std::atan(1.0/args[0]));
    1258         162 : LEPTON_CLASS_OPERATION(Asec,asec,ASEC,1,std::acos(1.0/args[0]));
    1259         162 : LEPTON_CLASS_OPERATION(Acsc,acsc,ACSC,1,std::asin(1.0/args[0]));
    1260         708 : LEPTON_CLASS_OPERATION(Coth,coth,ACOT,1,1.0/std::tanh(args[0]));
    1261         441 : LEPTON_CLASS_OPERATION(Sech,sech,SECH,1,1.0/std::cosh(args[0]));
    1262         441 : LEPTON_CLASS_OPERATION(Csch,csch,CSCH,1,1.0/std::sinh(args[0]));
    1263             : 
    1264         162 : LEPTON_CLASS_OPERATION(Asinh,asinh,ASINH,1,std::asinh(args[0]));
    1265         162 : LEPTON_CLASS_OPERATION(Acosh,acosh,ACOSH,1,std::acosh(args[0]));
    1266         162 : LEPTON_CLASS_OPERATION(Atanh,atanh,ATANH,1,std::atanh(args[0]));
    1267             : 
    1268         162 : LEPTON_CLASS_OPERATION(Acoth,acoth,ACOTH,1,0.5*std::log((args[0]+1.0)/(args[0]-1.0)));
    1269         162 : 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]));
    1270         162 : LEPTON_CLASS_OPERATION(Acsch,acsch,ACSCH,1,std::log(1.0/args[0]+std::sqrt(1.0/(args[0]*args[0])+1.0)));
    1271             : 
    1272         652 : LEPTON_CLASS_OPERATION(Atan2,atan2,ATAN2,2,std::atan2(args[0],args[1]));
    1273             : 
    1274             : } // namespace lepton
    1275             : } // namespace PLMD
    1276             : 
    1277             : #endif /*LEPTON_OPERATION_H_*/

Generated by: LCOV version 1.14