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_*/
|