Operation.h 33 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
#ifndef LEPTON_OPERATION_H_
#define LEPTON_OPERATION_H_

/* -------------------------------------------------------------------------- *
 *                                   Lepton                                   *
 * -------------------------------------------------------------------------- *
 * This is part of the Lepton expression parser originating from              *
 * Simbios, the NIH National Center for Physics-Based Simulation of           *
 * Biological Structures at Stanford, funded under the NIH Roadmap for        *
 * Medical Research, grant U54 GM072970. See https://simtk.org.               *
 *                                                                            *
12
 * Portions copyright (c) 2009-2013 Stanford University and the Authors.      *
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 * Authors: Peter Eastman                                                     *
 * Contributors:                                                              *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
 * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
 * -------------------------------------------------------------------------- */

#include "windowsIncludes.h"
Peter Eastman's avatar
Peter Eastman committed
36
#include "CustomFunction.h"
37
#include "Exception.h"
38
39
40
41
42
43
44
45
#include <cmath>
#include <map>
#include <string>
#include <vector>
#include <sstream>

namespace Lepton {

46
47
class ExpressionTreeNode;

48
49
50
51
52
53
54
55
/**
 * An Operation represents a single step in the evaluation of an expression, such as a function,
 * an operator, or a constant value.  Each Operation takes some number of values as arguments
 * and produces a single value.
 *
 * This is an abstract class with subclasses for specific operations.
 */

56
57
class LEPTON_EXPORT Operation {
public:
Peter Eastman's avatar
Peter Eastman committed
58
59
    virtual ~Operation() {
    }
60
61
62
63
    /**
     * This enumeration lists all Operation subclasses.  This is provided so that switch statements
     * can be used when processing or analyzing parsed expressions.
     */
64
    enum Id {CONSTANT, VARIABLE, CUSTOM, ADD, SUBTRACT, MULTIPLY, DIVIDE, POWER, NEGATE, SQRT, EXP, LOG,
65
             SIN, COS, SEC, CSC, TAN, COT, ASIN, ACOS, ATAN, SINH, COSH, TANH, ERF, ERFC, STEP, DELTA, SQUARE, CUBE, RECIPROCAL,
66
             ADD_CONSTANT, MULTIPLY_CONSTANT, POWER_CONSTANT, MIN, MAX, ABS};
67
68
69
    /**
     * Get the name of this Operation.
     */
70
    virtual std::string getName() const = 0;
71
72
73
    /**
     * Get this Operation's ID.
     */
74
    virtual Id getId() const = 0;
75
76
77
    /**
     * Get the number of arguments this operation expects.
     */
78
    virtual int getNumArguments() const = 0;
79
80
81
    /**
     * Create a clone of this Operation.
     */
82
    virtual Operation* clone() const = 0;
83
84
85
86
87
88
89
    /**
     * Perform the computation represented by this operation.
     *
     * @param args        the array of arguments
     * @param variables   a map containing the values of all variables
     * @return the result of performing the computation.
     */
90
    virtual double evaluate(double* args, const std::map<std::string, double>& variables) const = 0;
91
92
93
94
95
96
97
98
    /**
     * Return an ExpressionTreeNode which represents the analytic derivative of this Operation with respect to a variable.
     *
     * @param children     the child nodes
     * @param childDerivs  the derivatives of the child nodes with respect to the variable
     * @param variable     the variable with respect to which the derivate should be taken
     */
    virtual ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const = 0;
99
100
101
102
103
104
    /**
     * Get whether this operation should be displayed with infix notation.
     */
    virtual bool isInfixOperator() const {
        return false;
    }
105
106
107
108
109
110
111
    /**
     * Get whether this is a symmetric binary operation, such that exchanging its arguments
     * does not affect the result.
     */
    virtual bool isSymmetric() const {
        return false;
    }
112
113
114
115
116
117
    virtual bool operator!=(const Operation& op) const {
        return op.getId() != getId();
    }
    virtual bool operator==(const Operation& op) const {
        return !(*this != op);
    }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
    class Constant;
    class Variable;
    class Custom;
    class Add;
    class Subtract;
    class Multiply;
    class Divide;
    class Power;
    class Negate;
    class Sqrt;
    class Exp;
    class Log;
    class Sin;
    class Cos;
    class Sec;
    class Csc;
    class Tan;
    class Cot;
    class Asin;
    class Acos;
    class Atan;
139
140
141
    class Sinh;
    class Cosh;
    class Tanh;
142
143
    class Erf;
    class Erfc;
144
    class Step;
145
    class Delta;
146
147
148
    class Square;
    class Cube;
    class Reciprocal;
149
150
151
    class AddConstant;
    class MultiplyConstant;
    class PowerConstant;
152
153
154
    class Min;
    class Max;
    class Abs;
155
156
};

157
class LEPTON_EXPORT Operation::Constant : public Operation {
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
public:
    Constant(double value) : value(value) {
    }
    std::string getName() const {
        std::stringstream name;
        name << value;
        return name.str();
    }
    Id getId() const {
        return CONSTANT;
    }
    int getNumArguments() const {
        return 0;
    }
    Operation* clone() const {
        return new Constant(value);
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return value;
    }
178
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
179
180
181
    double getValue() const {
        return value;
    }
182
183
184
185
    bool operator!=(const Operation& op) const {
        const Constant* o = dynamic_cast<const Constant*>(&op);
        return (o == NULL || o->value != value);
    }
186
187
188
189
private:
    double value;
};

190
class LEPTON_EXPORT Operation::Variable : public Operation {
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
public:
    Variable(const std::string& name) : name(name) {
    }
    std::string getName() const {
        return name;
    }
    Id getId() const {
        return VARIABLE;
    }
    int getNumArguments() const {
        return 0;
    }
    Operation* clone() const {
        return new Variable(name);
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        std::map<std::string, double>::const_iterator iter = variables.find(name);
        if (iter == variables.end())
209
            throw Exception("No value specified for variable "+name);
210
211
        return iter->second;
    }
212
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
213
214
215
216
    bool operator!=(const Operation& op) const {
        const Variable* o = dynamic_cast<const Variable*>(&op);
        return (o == NULL || o->name != name);
    }
217
218
219
220
private:
    std::string name;
};

221
class LEPTON_EXPORT Operation::Custom : public Operation {
222
public:
Peter Eastman's avatar
Peter Eastman committed
223
224
225
226
227
228
229
    Custom(const std::string& name, CustomFunction* function) : name(name), function(function), isDerivative(false), derivOrder(function->getNumArguments(), 0) {
    }
    Custom(const Custom& base, int derivIndex) : name(base.name), function(base.function->clone()), isDerivative(true), derivOrder(base.derivOrder) {
        derivOrder[derivIndex]++;
    }
    ~Custom() {
        delete function;
230
231
232
233
234
235
236
237
    }
    std::string getName() const {
        return name;
    }
    Id getId() const {
        return CUSTOM;
    }
    int getNumArguments() const {
Peter Eastman's avatar
Peter Eastman committed
238
        return function->getNumArguments();
239
240
    }
    Operation* clone() const {
Peter Eastman's avatar
Peter Eastman committed
241
242
243
244
        Custom* clone = new Custom(name, function->clone());
        clone->isDerivative = isDerivative;
        clone->derivOrder = derivOrder;
        return clone;
245
246
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
Peter Eastman's avatar
Peter Eastman committed
247
248
249
        if (isDerivative)
            return function->evaluateDerivative(args, &derivOrder[0]);
        return function->evaluate(args);
250
    }
251
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
252
253
254
    const std::vector<int>& getDerivOrder() const {
        return derivOrder;
    }
255
256
257
258
    bool operator!=(const Operation& op) const {
        const Custom* o = dynamic_cast<const Custom*>(&op);
        return (o == NULL || o->name != name || o->isDerivative != isDerivative || o->derivOrder != derivOrder);
    }
259
260
private:
    std::string name;
Peter Eastman's avatar
Peter Eastman committed
261
262
263
    CustomFunction* function;
    bool isDerivative;
    std::vector<int> derivOrder;
264
265
};

266
class LEPTON_EXPORT Operation::Add : public Operation {
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
public:
    Add() {
    }
    std::string getName() const {
        return "+";
    }
    Id getId() const {
        return ADD;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Add();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]+args[1];
    }
285
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
286
287
288
    bool isInfixOperator() const {
        return true;
    }
289
290
291
    bool isSymmetric() const {
        return true;
    }
292
293
};

294
class LEPTON_EXPORT Operation::Subtract : public Operation {
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
public:
    Subtract() {
    }
    std::string getName() const {
        return "-";
    }
    Id getId() const {
        return SUBTRACT;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Subtract();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]-args[1];
    }
313
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
314
315
316
    bool isInfixOperator() const {
        return true;
    }
317
318
};

319
class LEPTON_EXPORT Operation::Multiply : public Operation {
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
public:
    Multiply() {
    }
    std::string getName() const {
        return "*";
    }
    Id getId() const {
        return MULTIPLY;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Multiply();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]*args[1];
    }
338
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
339
340
341
    bool isInfixOperator() const {
        return true;
    }
342
343
344
    bool isSymmetric() const {
        return true;
    }
345
346
};

347
class LEPTON_EXPORT Operation::Divide : public Operation {
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
public:
    Divide() {
    }
    std::string getName() const {
        return "/";
    }
    Id getId() const {
        return DIVIDE;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Divide();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]/args[1];
    }
366
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
367
368
369
    bool isInfixOperator() const {
        return true;
    }
370
371
};

372
class LEPTON_EXPORT Operation::Power : public Operation {
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
public:
    Power() {
    }
    std::string getName() const {
        return "^";
    }
    Id getId() const {
        return POWER;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Power();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::pow(args[0], args[1]);
    }
391
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
392
393
394
    bool isInfixOperator() const {
        return true;
    }
395
396
};

397
class LEPTON_EXPORT Operation::Negate : public Operation {
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
public:
    Negate() {
    }
    std::string getName() const {
        return "-";
    }
    Id getId() const {
        return NEGATE;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Negate();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return -args[0];
    }
416
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
417
418
};

419
class LEPTON_EXPORT Operation::Sqrt : public Operation {
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
public:
    Sqrt() {
    }
    std::string getName() const {
        return "sqrt";
    }
    Id getId() const {
        return SQRT;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Sqrt();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::sqrt(args[0]);
    }
438
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
439
440
};

441
class LEPTON_EXPORT Operation::Exp : public Operation {
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
public:
    Exp() {
    }
    std::string getName() const {
        return "exp";
    }
    Id getId() const {
        return EXP;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Exp();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::exp(args[0]);
    }
460
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
461
462
};

463
class LEPTON_EXPORT Operation::Log : public Operation {
464
465
466
467
468
469
470
public:
    Log() {
    }
    std::string getName() const {
        return "log";
    }
    Id getId() const {
Peter Eastman's avatar
Bug fix  
Peter Eastman committed
471
        return LOG;
472
473
474
475
476
477
478
479
480
481
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Log();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::log(args[0]);
    }
482
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
483
484
};

485
class LEPTON_EXPORT Operation::Sin : public Operation {
486
487
488
489
490
491
492
public:
    Sin() {
    }
    std::string getName() const {
        return "sin";
    }
    Id getId() const {
Peter Eastman's avatar
Bug fix  
Peter Eastman committed
493
        return SIN;
494
495
496
497
498
499
500
501
502
503
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Sin();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::sin(args[0]);
    }
504
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
505
506
};

507
class LEPTON_EXPORT Operation::Cos : public Operation {
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
public:
    Cos() {
    }
    std::string getName() const {
        return "cos";
    }
    Id getId() const {
        return COS;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Cos();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::cos(args[0]);
    }
526
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
527
528
};

529
class LEPTON_EXPORT Operation::Sec : public Operation {
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
public:
    Sec() {
    }
    std::string getName() const {
        return "sec";
    }
    Id getId() const {
        return SEC;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Sec();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return 1.0/std::cos(args[0]);
    }
548
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
549
550
};

551
class LEPTON_EXPORT Operation::Csc : public Operation {
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
public:
    Csc() {
    }
    std::string getName() const {
        return "csc";
    }
    Id getId() const {
        return CSC;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Csc();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return 1.0/std::sin(args[0]);
    }
570
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
571
572
};

573
class LEPTON_EXPORT Operation::Tan : public Operation {
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
public:
    Tan() {
    }
    std::string getName() const {
        return "tan";
    }
    Id getId() const {
        return TAN;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Tan();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::tan(args[0]);
    }
592
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
593
594
};

595
class LEPTON_EXPORT Operation::Cot : public Operation {
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
public:
    Cot() {
    }
    std::string getName() const {
        return "cot";
    }
    Id getId() const {
        return COT;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Cot();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return 1.0/std::tan(args[0]);
    }
614
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
615
616
};

617
class LEPTON_EXPORT Operation::Asin : public Operation {
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
public:
    Asin() {
    }
    std::string getName() const {
        return "asin";
    }
    Id getId() const {
        return ASIN;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Asin();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::asin(args[0]);
    }
636
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
637
638
};

639
class LEPTON_EXPORT Operation::Acos : public Operation {
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
public:
    Acos() {
    }
    std::string getName() const {
        return "acos";
    }
    Id getId() const {
        return ACOS;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Acos();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::acos(args[0]);
    }
658
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
659
660
};

661
class LEPTON_EXPORT Operation::Atan : public Operation {
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
public:
    Atan() {
    }
    std::string getName() const {
        return "atan";
    }
    Id getId() const {
        return ATAN;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Atan();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::atan(args[0]);
    }
680
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
681
682
};

683
class LEPTON_EXPORT Operation::Sinh : public Operation {
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
public:
    Sinh() {
    }
    std::string getName() const {
        return "sinh";
    }
    Id getId() const {
        return SINH;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Sinh();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::sinh(args[0]);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

705
class LEPTON_EXPORT Operation::Cosh : public Operation {
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
public:
    Cosh() {
    }
    std::string getName() const {
        return "cosh";
    }
    Id getId() const {
        return COSH;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Cosh();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::cosh(args[0]);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

727
class LEPTON_EXPORT Operation::Tanh : public Operation {
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
public:
    Tanh() {
    }
    std::string getName() const {
        return "tanh";
    }
    Id getId() const {
        return TANH;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Tanh();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::tanh(args[0]);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
747
748
};

749
class LEPTON_EXPORT Operation::Erf : public Operation {
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
public:
    Erf() {
    }
    std::string getName() const {
        return "erf";
    }
    Id getId() const {
        return ERF;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Erf();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const;
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

769
class LEPTON_EXPORT Operation::Erfc : public Operation {
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
public:
    Erfc() {
    }
    std::string getName() const {
        return "erfc";
    }
    Id getId() const {
        return ERFC;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Erfc();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const;
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

789
class LEPTON_EXPORT Operation::Step : public Operation {
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
public:
    Step() {
    }
    std::string getName() const {
        return "step";
    }
    Id getId() const {
        return STEP;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Step();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return (args[0] >= 0.0 ? 1.0 : 0.0);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
809
810
};

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
class LEPTON_EXPORT Operation::Delta : public Operation {
public:
    Delta() {
    }
    std::string getName() const {
        return "delta";
    }
    Id getId() const {
        return DELTA;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Delta();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return (args[0] == 0.0 ? 1.0 : 0.0);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

833
class LEPTON_EXPORT Operation::Square : public Operation {
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
public:
    Square() {
    }
    std::string getName() const {
        return "square";
    }
    Id getId() const {
        return SQUARE;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Square();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]*args[0];
    }
852
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
853
854
};

855
class LEPTON_EXPORT Operation::Cube : public Operation {
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
public:
    Cube() {
    }
    std::string getName() const {
        return "cube";
    }
    Id getId() const {
        return CUBE;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Cube();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return args[0]*args[0]*args[0];
    }
874
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
875
876
};

877
class LEPTON_EXPORT Operation::Reciprocal : public Operation {
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
public:
    Reciprocal() {
    }
    std::string getName() const {
        return "recip";
    }
    Id getId() const {
        return RECIPROCAL;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Reciprocal();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return 1.0/args[0];
    }
896
897
898
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

899
class LEPTON_EXPORT Operation::AddConstant : public Operation {
900
public:
901
    AddConstant(double value) : value(value) {
902
903
    }
    std::string getName() const {
904
905
906
        std::stringstream name;
        name << value << "+";
        return name.str();
907
908
    }
    Id getId() const {
909
        return ADD_CONSTANT;
910
911
912
913
914
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
915
        return new AddConstant(value);
916
917
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
918
        return args[0]+value;
919
920
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
921
922
923
    double getValue() const {
        return value;
    }
924
925
926
927
    bool operator!=(const Operation& op) const {
        const AddConstant* o = dynamic_cast<const AddConstant*>(&op);
        return (o == NULL || o->value != value);
    }
928
929
private:
    double value;
930
931
};

932
class LEPTON_EXPORT Operation::MultiplyConstant : public Operation {
933
public:
934
    MultiplyConstant(double value) : value(value) {
935
936
    }
    std::string getName() const {
937
938
939
        std::stringstream name;
        name << value << "*";
        return name.str();
940
941
    }
    Id getId() const {
942
        return MULTIPLY_CONSTANT;
943
944
945
946
947
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
948
        return new MultiplyConstant(value);
949
950
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
951
        return args[0]*value;
952
953
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
954
955
956
    double getValue() const {
        return value;
    }
957
958
959
960
    bool operator!=(const Operation& op) const {
        const MultiplyConstant* o = dynamic_cast<const MultiplyConstant*>(&op);
        return (o == NULL || o->value != value);
    }
961
962
963
964
private:
    double value;
};

965
class LEPTON_EXPORT Operation::PowerConstant : public Operation {
966
967
public:
    PowerConstant(double value) : value(value) {
968
969
        intValue = (int) value;
        isIntPower = (intValue == value);
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
    }
    std::string getName() const {
        std::stringstream name;
        name << "^" << value;
        return name.str();
    }
    Id getId() const {
        return POWER_CONSTANT;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new PowerConstant(value);
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
        if (isIntPower) {
            // Integer powers can be computed much more quickly by repeated multiplication.
            
            int exponent = intValue;
            double base = args[0];
            if (exponent < 0) {
                exponent = -exponent;
                base = 1.0/base;
            }
            double result = 1.0;
            while (exponent != 0) {
                if ((exponent&1) == 1)
                    result *= base;
                base *= base;
                exponent = exponent>>1;
           }
           return result;
        }
        else
            return std::pow(args[0], value);
1006
1007
1008
1009
1010
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
    double getValue() const {
        return value;
    }
1011
1012
1013
1014
    bool operator!=(const Operation& op) const {
        const PowerConstant* o = dynamic_cast<const PowerConstant*>(&op);
        return (o == NULL || o->value != value);
    }
1015
1016
1017
    bool isInfixOperator() const {
        return true;
    }
1018
1019
private:
    double value;
1020
1021
    int intValue;
    bool isIntPower;
1022
1023
};

1024
class LEPTON_EXPORT Operation::Min : public Operation {
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
public:
    Min() {
    }
    std::string getName() const {
        return "min";
    }
    Id getId() const {
        return MIN;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Min();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
1041
1042
        // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
        return (std::min)(args[0], args[1]);
1043
1044
1045
1046
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

1047
class LEPTON_EXPORT Operation::Max : public Operation {
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
public:
    Max() {
    }
    std::string getName() const {
        return "max";
    }
    Id getId() const {
        return MAX;
    }
    int getNumArguments() const {
        return 2;
    }
    Operation* clone() const {
        return new Max();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
1064
1065
        // parens around (std::min) are workaround for horrible microsoft max/min macro trouble
        return (std::max)(args[0], args[1]);
1066
1067
1068
1069
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

1070
class LEPTON_EXPORT Operation::Abs : public Operation {
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
public:
    Abs() {
    }
    std::string getName() const {
        return "abs";
    }
    Id getId() const {
        return ABS;
    }
    int getNumArguments() const {
        return 1;
    }
    Operation* clone() const {
        return new Abs();
    }
    double evaluate(double* args, const std::map<std::string, double>& variables) const {
        return std::abs(args[0]);
    }
    ExpressionTreeNode differentiate(const std::vector<ExpressionTreeNode>& children, const std::vector<ExpressionTreeNode>& childDerivs, const std::string& variable) const;
};

1092
1093
1094
} // namespace Lepton

#endif /*LEPTON_OPERATION_H_*/