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