NimbleSM
NimbleSM is a solid mechanics simulation code for dynamic systems
Loading...
Searching...
No Matches
nimble_expression_parser.h
Go to the documentation of this file.
1/*
2//@HEADER
3// ************************************************************************
4//
5// NimbleSM
6// Copyright 2018
7// National Technology & Engineering Solutions of Sandia, LLC (NTESS)
8//
9// Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government
10// retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY EXPRESS OR IMPLIED
28// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
30// NO EVENT SHALL NTESS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact David Littlewood (djlittl@sandia.gov)
39//
40// ************************************************************************
41//@HEADER
42*/
43
44#ifndef NIMBLE_EXPRESSION_PARSER_H
45#define NIMBLE_EXPRESSION_PARSER_H
46
47#include <cmath>
48#include <cstdlib>
49#include <cstring>
50#include <stdexcept>
51#include <typeinfo>
52
53#ifdef NIMBLE_HAVE_DARMA
54// darma wraps headers for std containers
55#include <darma.h>
56#else
57#include <map>
58#include <string>
59#endif
60
62
64{ // Used by the MemoryManager class
66};
67
69{
70 // Keeps track of all objects created using the ``New'' method
71 // When the MemoryManager is deleted, everything it manages is deleted too
72 public:
73 const static unsigned int BlockSize = 62;
84 template <typename T, typename... In>
85 T*
86 New(In... inputs)
87 {
88 T* pointer = new T(inputs...);
89 unsigned long insert_location = first->count;
90 if (insert_location < BlockSize) {
91 first->count = insert_location + 1;
92 first->Pointers[insert_location] = pointer;
93 } else {
94 first = new MemoryBlock(first);
95 first->count = 1;
96 first->Pointers[0] = pointer;
97 }
98 return pointer;
99 }
101 { // Deletes everything allocated with MemoryManager::New
102 MemoryBlock* current = first;
103 MemoryBlock* next = current->next;
104 DeletableObjectBaseClass** scan = current->Pointers;
105 unsigned int count = current->count;
106 for (unsigned int i = 0; i < count; ++i) { delete *scan++; }
107 delete current;
108 current = next;
109 while (current) {
110 scan = current->Pointers;
111 next = current->next;
112 for (unsigned int i = 0; i < BlockSize; ++i) { delete *scan++; }
113 delete current;
114 current = next;
115 }
116 }
117};
118
119template <typename T>
121{ // Acts as the ``evaluation'' function (overloaded in derived classes)
122 virtual operator T() const = 0;
123 // Provides a way for derived classes to optimize calculation for faster
124 // evaluation
125 virtual Evaluatable*
127 {
128 return this;
129 }
130};
131
132template <typename T>
134{ // Stores a constant; when evaluated returns the constant.
136 operator T() const { return value; }
139};
140
141template <typename T>
143{ // Stores a pointer; when evaluated returns the value stared at the reference
145 operator T() const { return *value; }
148};
149
150// This macro produces a structure which calls f(x) on the input and returns the
151// result
152#define MakeGenericFunction(GenericFunction, f) \
153 template <typename Out, typename In> \
154 struct GenericFunction : Evaluatable<Out> \
155 { \
156 struct ReferenceCase : Evaluatable<Out> \
157 { \
158 In* input1; \
159 operator Out() const { return f(*input1); } \
160 ReferenceCase(In* in1) : input1(in1) {} \
161 }; \
162 Evaluatable<In>* input1; \
163 operator Out() const { return f(*input1); } \
164 GenericFunction(Evaluatable<In>* in1) : input1(in1) {} \
165 Evaluatable<Out>* \
166 optimize(MemoryManager& m) \
167 { \
168 Evaluatable<In>* in1 = this->input1->optimize(m); \
169 if (GenericConstant<In>* constant = dynamic_cast<GenericConstant<In>*>(in1)) { \
170 return m.New<GenericConstant<Out>>(f(*in1)); \
171 } else if (GenericReference<In>* reference = dynamic_cast<GenericReference<In>*>(in1)) { \
172 return m.New<ReferenceCase>(reference->value); \
173 } \
174 this->input1 = in1; \
175 return this; \
176 } \
177 };
178
179#define MakeGenericOperator(name, operation) \
180 template <typename Out, typename In1, typename In2> \
181 struct name : Evaluatable<Out> \
182 { \
183 template <typename In1_t, typename In2_t> \
184 struct ReferenceCase : Evaluatable<Out> \
185 { \
186 In1_t* input1; \
187 In2_t* input2; \
188 operator Out() const { return (*input1)operation(*input2); } \
189 ReferenceCase(In1_t* in1, In2_t* in2) : input1(in1), input2(in2) {} \
190 }; \
191 template <typename In2_type> \
192 struct ConstCase1 : Evaluatable<Out> \
193 { \
194 In1 input1; \
195 In2_type* input2; \
196 operator Out() const { return input1 operation(*input2); } \
197 ConstCase1(In1 in1, In2_type* in2) : input1(in1), input2(in2) {} \
198 }; \
199 template <typename In1_type> \
200 struct ConstCase2 : Evaluatable<Out> \
201 { \
202 In1_type* input1; \
203 In2 input2; \
204 operator Out() const { return (*input1)operation input2; } \
205 ConstCase2(In1_type* in1, In2 in2) : input1(in1), input2(in2) {} \
206 }; \
207 Evaluatable<In1>* input1; \
208 Evaluatable<In2>* input2; \
209 operator Out() const { return (*input1)operation(*input2); } \
210 name(Evaluatable<In1>* in1, Evaluatable<In2>* in2) : input1(in1), input2(in2) {} \
211 Evaluatable<Out>* \
212 optimize(MemoryManager& m) \
213 { \
214 Evaluatable<In1>* input1 = this->input1->optimize(m); \
215 Evaluatable<In2>* input2 = this->input2->optimize(m); \
216 if (auto const1 = dynamic_cast<GenericConstant<In1>*>(input1)) { \
217 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
218 return m.New<GenericConstant<Out>>((*input1)operation(*input2)); \
219 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
220 return m.New<ConstCase1<In2>>(const1->value, ref2->value); \
221 else \
222 return m.New<ConstCase1<Evaluatable<In2>>>(const1->value, input2); \
223 } else if (auto ref1 = dynamic_cast<GenericReference<In1>*>(input1)) { \
224 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
225 return m.New<ConstCase2<In1>>(ref1->value, const2->value); \
226 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
227 return m.New<ReferenceCase<In1, In2>>(ref1->value, ref2->value); \
228 else \
229 return m.New<ReferenceCase<In1, Evaluatable<In2>>>(ref1->value, input2); \
230 } else if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
231 return m.New<ConstCase2<Evaluatable<In1>>>(input1, const2->value); \
232 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
233 return m.New<ReferenceCase<Evaluatable<In1>, In2>>(input1, ref2->value); \
234 this->input1 = input1; \
235 this->input2 = input2; \
236 return this; \
237 } \
238 };
239
240#define MakeGenericTwoInputFunc(name, f) \
241 template <typename Out, typename In1, typename In2> \
242 struct name : Evaluatable<Out> \
243 { \
244 template <typename In1_t, typename In2_t> \
245 struct ReferenceCase : Evaluatable<Out> \
246 { \
247 In1_t* input1; \
248 In2_t* input2; \
249 operator Out() const { return f(*input1, *input2); } \
250 ReferenceCase(In1_t* in1, In2_t* in2) : input1(in1), input2(in2) {} \
251 }; \
252 template <typename In2_type> \
253 struct ConstCase1 : Evaluatable<Out> \
254 { \
255 In1 input1; \
256 In2_type* input2; \
257 operator Out() const { return f(input1, *input2); } \
258 ConstCase1(In1 in1, In2_type* in2) : input1(in1), input2(in2) {} \
259 }; \
260 template <typename In1_type> \
261 struct ConstCase2 : Evaluatable<Out> \
262 { \
263 In1_type* input1; \
264 In2 input2; \
265 operator Out() const { return f(*input1, input2); } \
266 ConstCase2(In1_type* in1, In2 in2) : input1(in1), input2(in2) {} \
267 }; \
268 Evaluatable<In1>* input1; \
269 Evaluatable<In2>* input2; \
270 operator Out() const { return f(*input1, *input2); } \
271 name(Evaluatable<In1>* in1, Evaluatable<In2>* in2) : input1(in1), input2(in2) {} \
272 Evaluatable<Out>* \
273 optimize(MemoryManager& m) \
274 { \
275 Evaluatable<In1>* input1 = this->input1->optimize(m); \
276 Evaluatable<In2>* input2 = this->input2->optimize(m); \
277 if (auto const1 = dynamic_cast<GenericConstant<In1>*>(input1)) { \
278 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
279 return m.New<GenericConstant<Out>>(f(*input1, *input2)); \
280 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
281 return m.New<ConstCase1<In2>>(const1->value, ref2->value); \
282 else \
283 return m.New<ConstCase1<Evaluatable<In2>>>(const1->value, input2); \
284 } else if (auto ref1 = dynamic_cast<GenericReference<In1>*>(input1)) { \
285 if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
286 return m.New<ConstCase2<In1>>(ref1->value, const2->value); \
287 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
288 return m.New<ReferenceCase<In1, In2>>(ref1->value, ref2->value); \
289 else \
290 return m.New<ReferenceCase<In1, Evaluatable<In2>>>(ref1->value, input2); \
291 } else if (auto const2 = dynamic_cast<GenericConstant<In2>*>(input2)) \
292 return m.New<ConstCase2<Evaluatable<In1>>>(input1, const2->value); \
293 else if (auto ref2 = dynamic_cast<GenericReference<In2>*>(input2)) \
294 return m.New<ReferenceCase<Evaluatable<In1>, In2>>(input1, ref2->value); \
295 this->input1 = input1; \
296 this->input2 = input2; \
297 return this; \
298 } \
299 };
300
301MakeGenericFunction(GenericSin, std::sin) MakeGenericFunction(GenericCos, std::cos) MakeGenericFunction(
302 GenericTan,
303 std::tan) MakeGenericFunction(GenericErf, std::erf) MakeGenericFunction(GenericExp, std::exp)
304 MakeGenericFunction(GenericLog, std::log) MakeGenericFunction(GenericAbs, std::abs)
305 MakeGenericFunction(GenericASin, std::asin) MakeGenericFunction(GenericACos, std::acos)
306 MakeGenericFunction(GenericATan, std::atan) MakeGenericFunction(GenericSqrt, std::sqrt)
307 MakeGenericFunction(GenericCbrt, std::cbrt) MakeGenericFunction(GenericErfc, std::erfc)
308 MakeGenericFunction(GenericCeil, std::ceil) MakeGenericFunction(GenericRound, std::round)
309 MakeGenericFunction(GenericFloor, std::floor) MakeGenericFunction(GenericLog10, std::log10)
310 MakeGenericFunction(GenericNeg, -) MakeGenericFunction(GenericNot, !)
311
312 MakeGenericOperator(GenericAdd, +) MakeGenericOperator(GenericMultiply, *)
313 MakeGenericOperator(GenericDivide, /) MakeGenericOperator(GenericSubtract, -)
315 GenericGreaterOrEqual,
316 >=) MakeGenericOperator(GenericLess, <)
317 MakeGenericOperator(GenericLessOrEqual, <=)
318 MakeGenericOperator(GenericEqual, ==)
319 MakeGenericOperator(GenericInequal, !=)
320 MakeGenericOperator(GenericAnd, &&)
321 MakeGenericOperator(GenericXor, xor)
322 MakeGenericOperator(GenericOr, ||)
323 MakeGenericTwoInputFunc(GenericPow, std::pow)
324 MakeGenericTwoInputFunc(GenericMod, std::fmod)
325
326 template <typename Out>
327 struct Conditional : Evaluatable<Out>
328{
332 operator Out() const { return (*condition) ? (*IfTrue) : (*IfFalse); }
333 Conditional(Evaluatable<bool>* condition, Evaluatable<Out>* WhenTrue, Evaluatable<Out>* WhenFalse)
334 : condition(condition), IfTrue(WhenTrue), IfFalse(WhenFalse)
335 {
336 }
339 {
340 Evaluatable<bool>* condition = this->condition->optimize(m);
341 Evaluatable<Out>* IfTrue = this->IfTrue->optimize(m);
342 Evaluatable<Out>* IfFalse = this->IfFalse->optimize(m);
343 if (auto ConstCondition = dynamic_cast<GenericConstant<bool>*>(condition)) {
344 if (ConstCondition->value) {
345 return IfTrue;
346 } else
347 return IfFalse;
348 }
349 this->condition = condition;
350 this->IfTrue = IfTrue;
351 this->IfFalse = IfFalse;
352 return this;
353 }
354};
355
358typedef GenericAdd<double, double, double> DoubleAdd;
359typedef GenericSubtract<double, double, double> DoubleSubtract;
360typedef GenericMultiply<double, double, double> DoubleMultiply;
361typedef GenericDivide<double, double, double> DoubleDivide;
362typedef GenericPow<double, double, double> DoublePow;
363typedef GenericMod<double, double, double> DoubleMod;
364typedef GenericPow<double, double, int> DoubleToIntegerPow;
367typedef Conditional<double> RealValuedConditional;
368
369struct Reader
370{
371 const char* first;
372 unsigned int length;
373 unsigned int pos = 0;
374 Reader(const char* lit, unsigned int len) : first(lit), length(len) {}
375 Reader(const std::string& s) : Reader(s.c_str(), s.size()) {}
376 Reader(const char* lit) : first(lit), length(std::strlen(lit)) {}
377 Reader(const char* start, const char* end) : first(start), length(end - start) {}
378 Reader(const Reader& r) : first(r.first), length(r.length) {}
379
380 Reader
381 sub(const char* start, const char* end)
382 {
383 return Reader(start, end - start);
384 }
385
386 Reader
387 sub(unsigned int start, unsigned int end)
388 {
389 return Reader(first + start, first + end);
390 }
391
392 Reader
393 sub(const char* start, unsigned int len)
394 {
395 return Reader(start, len);
396 }
397
398 int
399 Next(char open, char close)
400 {
401 const char* f = this->first;
402 if (f[pos] == open) {
403 int depth = 1;
404 while (depth != 0 && pos < length) {
405 char c = f[++pos];
406 if (c == open)
407 depth++;
408 else if (c == close)
409 depth--;
410 }
411 return depth;
412 } else
413 pos++;
414 return 0;
415 }
416 int
417 Prev(char open, char close)
418 {
419 const char* f = this->first;
420 if (f[pos] == close) {
421 int depth = 1;
422 while (depth != 0 && pos > 0) {
423 char c = f[--pos];
424 if (c == close)
425 depth++;
426 else if (c == open)
427 depth--;
428 }
429 return depth;
430 } else
431 pos--;
432 return 0;
433 }
434
435 bool
437 {
438 pos = 0;
439 const char* f = first;
440 int max_pos = length - 1;
441 while (pos < max_pos && f[pos] != c) Next('(', ')');
442 if (f[pos] == c)
443 return true;
444 else
445 return false;
446 }
447
448 bool
449 operator<<(char c)
450 {
451 pos = length - 1;
452 const char* f = first;
453 while (pos > 0 && f[pos] != c) Prev('(', ')');
454 if (f[pos] == c) return true;
455 return false;
456 }
457
458 bool
459 operator==(std::string& s)
460 {
461 return operator==(s.c_str());
462 }
463 bool
464 operator==(const char* lit)
465 {
466 const char* scan = first;
467 const char* last = scan + length;
468 while (scan < last && *lit != '\0') {
469 if (*scan == *lit) {
470 scan++;
471 lit++;
472 } else
473 return false;
474 }
475 return scan == last && *lit == '\0'; // Ensures that all the characters matched.
476 }
477 inline operator char() { return first[pos]; }
478 char
479 operator[](unsigned int i)
480 {
481 return first[i];
482 }
483 inline std::string
485 {
486 return std::string(first, length);
487 }
488 inline bool
490 {
491 return length == 0;
492 }
493};
494
495bool
496IsCMathFunc(Reader r);
497
499GetCMathFunc(Reader r, RealValuedExpression* input, MemoryManager& m);
500
501bool
502IsDigit(char c);
503
504bool
505IsInteger(Reader r);
506
507bool
508IsNumber(Reader r);
509
510void
511ConvertStringToLowercase(std::string& s);
512
513void
514RemoveWhitespace(Reader& text);
515
516void
517RemoveRedundantParenthesis(Reader& text);
518
519void
520ApplyNecessaryFormatting(Reader& text);
521
523{
524 public:
525 // When the EquationContext is annihilated, the MemoryManager object will
526 // annihilate everything allocated under mem.New
528 std::map<std::string, RealValuedExpression*> variables;
529 void
530 AddVarible(std::string name, double& ref)
531 {
532 variables[name] = mem.New<GenericReference<double>>(&ref);
533 }
535 ParseEquation(std::string s)
536 {
538 Reader reader = Reader(s);
539 return ParseEquation(reader);
540 }
541
542 private:
546 ParseDoubleConstant(Reader r)
547 {
548 if (r == "e") return mem.New<DoubleConstant>(M_E);
549 if (r == "pi") return mem.New<DoubleConstant>(M_PI);
550 if (r == "tau") return mem.New<DoubleConstant>(M_PI * 2);
551 if (IsNumber(r)) {
552 // DJL, fix for clang compiler
553 // return mem.New<DoubleConstant>(strtod(r.first, NULL));
554 std::string temp_string = r.MakeString();
555 double floating_point_value = std::stod(temp_string);
556 return mem.New<DoubleConstant>(floating_point_value);
557 }
558 return 0;
559 }
561 ParseFunction(Reader r)
562 {
563 char c = *r.first;
564 if (IsDigit(c) || c == '(' || c == '-' || r.length < 3) return 0;
565 while (c = r.first[r.pos], c != '(' && c != ' ' && r.pos < r.length) {
566 if (c != '*' && c != '/' && c != '^' && c != '+' && c != '=' && c != '<' && c != '~' && c != '>')
567 r.pos++;
568 else
569 return 0;
570 }
571 if (r >> '(') {
572 int p = r.pos;
573 int depth = r.Next('(', ')');
574 if (depth > 0) throw std::invalid_argument("Mismatched parethesis in " + r.MakeString());
575 if (r.pos < r.length - 1) return 0;
576 Reader func_name = r.sub(r.first, p);
577 if (IsCMathFunc(func_name)) {
578 RealValuedExpression* exp = ParseEquation(r.sub(p, r.length));
579 return GetCMathFunc(func_name, exp, mem);
580 }
581 }
582 return 0;
583 }
585 ParseOperation(Reader r)
586 {
587 if (r >> '?') {
588 int p1 = r.pos;
589 int depth = r.Next('?', ':');
590 if (depth > 0) throw std::invalid_argument("Couldn't find matching : for ternary operator in " + r.MakeString());
591 if (r.pos != r.length) {
592 return mem.New<RealValuedConditional>(
593 ParseBooleanExpression(r.sub(r.first, p1)),
594 ParseEquation(r.sub(p1 + 1, r.pos)),
595 ParseEquation(r.sub(r.pos + 1, r.length)));
596 }
597 }
598 if (r << '%')
599 return mem.New<DoubleMod>(ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
600
601 if (r << '+')
602 return mem.New<DoubleAdd>(ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
603
604 if (r << '-') {
605 // We need to ensure that we found a minus sign and not a value negation
606 while (r.pos > 0 && (r.first[r.pos] == '-' || r.first[r.pos] == ' ')) r.pos--;
607 if (r.pos > 0 || r.first[r.pos] != '-') {
608 char c = r.first[r.pos];
609 if (c != '*' && c != '/' && c != '^' && c != 'e' && c != '=' && c != '<' && c != '~' && c != '>') {
610 while (r.first[r.pos] != '-') r.pos++; // Moves it back to the last minus sign
611 return mem.New<DoubleSubtract>(
612 ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
613 }
614 }
615 }
616
617 if (r << '*')
618 return mem.New<DoubleMultiply>(ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
619
620 if (r << '/')
621 return mem.New<DoubleDivide>(ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
622
623 if (r >> '^') {
624 RealValuedExpression* base = ParseEquation(r.sub(r.first, r.pos));
625 Reader power_text = r.sub(r.pos + 1, r.length);
626 ApplyNecessaryFormatting(power_text);
627 if (IsInteger(power_text))
628 return mem.New<DoubleToIntegerPow>(base, mem.New<GenericConstant<int>>(strtol(power_text.first, NULL, 10)));
629 else
630 return mem.New<DoublePow>(base, ParseEquation(power_text));
631 }
632
633 if (*r.first == '-') { return mem.New<GenericNeg<double, double>>(ParseEquation(r.sub(1, r.length))); }
634
635 return 0;
636 }
637
639 ParseBooleanExpression(Reader r)
640 {
642 if (r == "true") return mem.New<BooleanConstant>(true);
643 if (r == "false") return mem.New<BooleanConstant>(false);
644
645 if (r << '|')
646 return mem.New<GenericOr<bool, bool, bool>>(
647 ParseBooleanExpression(r.sub(r.first, r.pos)), ParseBooleanExpression(r.sub(r.pos + 1, r.length)));
648
649 if (r << '^')
650 return mem.New<GenericXor<bool, bool, bool>>(
651 ParseBooleanExpression(r.sub(r.first, r.pos)), ParseBooleanExpression(r.sub(r.pos + 1, r.length)));
652
653 if (r << '&')
654 return mem.New<GenericAnd<bool, bool, bool>>(
655 ParseBooleanExpression(r.sub(r.first, r.pos)), ParseBooleanExpression(r.sub(r.pos + 1, r.length)));
656
657 if (r << '!') return mem.New<GenericNot<bool, bool>>(ParseBooleanExpression(r.sub(r.first + 1, r.length)));
658
659 if (r << '>') {
660 if (r.first[r.pos + 1] == '=')
661 return mem.New<GenericGreaterOrEqual<bool, double, double>>(
662 ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 2, r.length)));
663 else
664 return mem.New<GenericGreater<bool, double, double>>(
665 ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
666 }
667
668 if (r << '<') {
669 if (r.first[r.pos + 1] == '=')
670 return mem.New<GenericLessOrEqual<bool, double, double>>(
671 ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 2, r.length)));
672 else
673 return mem.New<GenericLess<bool, double, double>>(
674 ParseEquation(r.sub(r.first, r.pos)), ParseEquation(r.sub(r.pos + 1, r.length)));
675 }
676
677 /*if(r << '~') {
678 if(r.first[r.pos + 1] == '=') return
679 mem.New<DoubleComparison>(ApproxEqual, ParseEquation(r.sub(r.pos + 2,
680 r.length)), ParseEquation(r.sub(r.first, r.pos))); else return
681 mem.New<DoubleComparison>(ApproxEqual, ParseEquation(r.sub(r.pos + 1,
682 r.length)), ParseEquation(r.sub(r.first, r.pos)));
683 }*/
684
685 if (r << '=') {
686 if (r.first[r.pos - 1] == '=')
687 return mem.New<GenericEqual<bool, double, double>>(
688 ParseEquation(r.sub(r.pos + 1, r.length)), ParseEquation(r.sub(r.first, r.pos - 1)));
689 }
690 throw std::invalid_argument("Unable to parse \"" + r.MakeString() + "\" as boolean");
691 }
692};
693
694// To make a copy of a BoundaryConditionFunctor, create a new one directly from
695// the string that was originally used to parse it (i.e,
696// BoundaryConditionFunctor.equation)
698{
699 double x = 0, y = 0, z = 0, t = 0;
701 // The Computable Expression Object
703 std::string equation;
704 BoundaryConditionFunctor() : context(0) {} // Sets context to nil
706 {
707 if (equation == "") {
708 // Acts as default constructor if given an empty string
709 context = 0;
710 return;
711 }
712 try {
713 context = new EquationContext();
714 // Usage: context->AddVarible(name, reference);
715 context->AddVarible("x", x); // Passes a reference to x
716 context->AddVarible("y", y); // Passes a reference to y
717 context->AddVarible("z", z); // Passes a reference to z
718 context->AddVarible("t", t); // Passes a reference to t
719 // Creates the Computable Expression Object
720 expression = context->ParseEquation(equation);
721 // Optimizes the Computable Expression Object
722 expression = expression->optimize(context->mem);
723 this->equation = equation; // Stores a copy of the equation
724 } catch (std::invalid_argument arg) {
725 if (context) delete context;
726 context = 0;
727 throw arg;
728 }
729 }
733 {
734 return *this = other.equation;
735 }
737 operator=(const std::string& equation)
738 {
739 EquationContext* old_context = context;
740 try {
741 context = new EquationContext();
742 context->AddVarible("x", x);
743 context->AddVarible("y", y);
744 context->AddVarible("z", z);
745 context->AddVarible("t", t);
746 expression = context->ParseEquation(equation);
747 expression = expression->optimize(context->mem);
748 this->equation = equation;
749 if (old_context) delete old_context;
750 return *this;
751 } catch (std::invalid_argument arg) {
752 if (context) delete context;
753 context = old_context;
754 throw arg;
755 }
756 }
757 inline double
759 {
760 if (!expression) {
761 throw std::invalid_argument(
762 "Error in BoundaryConditionFunctor::eva(), expression pointer is "
763 "null.");
764 }
765 return *expression;
766 }
767 inline double
768 eval(double x, double y, double z, double t)
769 {
770 this->x = x;
771 this->y = y;
772 this->z = z;
773 this->t = t;
774 if (!expression) {
775 throw std::invalid_argument(
776 "Error in BoundaryConditionFunctor::eva(), expression pointer is "
777 "null.");
778 }
779 return *expression;
780 }
781 inline double
782 operator()(double x, double y, double z, double t)
783 {
784 this->x = x;
785 this->y = y;
786 this->z = z;
787 this->t = t;
788 if (!expression) {
789 throw std::invalid_argument(
790 "Error in BoundaryConditionFunctor::eva(), expression pointer is "
791 "null.");
792 }
793 return *expression; // Evaluates the Computable Expression Object
794 }
796 {
797 if (context) delete context;
798 // RealValuedExpression* expression is managed by the EquationContext,
799 // And will be destroyed when "context" is deleted.
800 }
801};
802} // namespace ExpressionParsing
803
804#endif
Definition nimble_expression_parser.h:523
RealValuedExpression * ParseEquation(std::string s)
Definition nimble_expression_parser.h:535
std::map< std::string, RealValuedExpression * > variables
Definition nimble_expression_parser.h:528
void AddVarible(std::string name, double &ref)
Definition nimble_expression_parser.h:530
MemoryManager mem
Definition nimble_expression_parser.h:527
Definition nimble_expression_parser.h:69
~MemoryManager()
Definition nimble_expression_parser.h:100
T * New(In... inputs)
Definition nimble_expression_parser.h:86
MemoryManager()
Definition nimble_expression_parser.h:83
MemoryBlock * first
Definition nimble_expression_parser.h:82
static const unsigned int BlockSize
Definition nimble_expression_parser.h:73
Definition nimble_expression_parser.h:61
GenericMod< double, double, double > DoubleMod
Definition nimble_expression_parser.h:363
RealValuedExpression * GetCMathFunc(Reader r, RealValuedExpression *input, MemoryManager &m)
Definition nimble_expression_parser.cc:57
Conditional< double > RealValuedConditional
Definition nimble_expression_parser.h:367
this condition
Definition nimble_expression_parser.h:349
GenericPow< double, double, double > DoublePow
Definition nimble_expression_parser.h:362
GenericSubtract< double, double, double > DoubleSubtract
Definition nimble_expression_parser.h:359
void ApplyNecessaryFormatting(Reader &text)
Definition nimble_expression_parser.cc:166
bool IsDigit(char c)
Definition nimble_expression_parser.cc:83
void RemoveWhitespace(Reader &text)
Definition nimble_expression_parser.cc:136
GenericMultiply< double, double, double > DoubleMultiply
Definition nimble_expression_parser.h:360
GenericPow< double, double, int > DoubleToIntegerPow
Definition nimble_expression_parser.h:364
std::cos std::erf std::log std::asin std::atan std::cbrt std::ceil std::floor MakeGenericOperator(GenericMultiply, *) MakeGenericOperator(GenericDivide
bool IsCMathFunc(Reader r)
Definition nimble_expression_parser.cc:47
std::cos std::erf std::log std::asin std::atan std::cbrt std::ceil std::floor<) MakeGenericOperator(GenericLessOrEqual,<=) MakeGenericOperator(GenericEqual,==) MakeGenericOperator(GenericInequal, !=) MakeGenericOperator(GenericAnd, &&) MakeGenericOperator(GenericXor, xor) MakeGenericOperator(GenericOr,||) MakeGenericTwoInputFunc(GenericPow, std::pow) MakeGenericTwoInputFunc(GenericMod, std::fmod) template< typename Out > struct Conditional :Evaluatable< Out > { Evaluatable< bool > *condition;Evaluatable< Out > *IfTrue;Evaluatable< Out > *IfFalse;operator Out() const { return(*condition) ?(*IfTrue) :(*IfFalse);} Conditional(Evaluatable< bool > *condition, Evaluatable< Out > *WhenTrue, Evaluatable< Out > *WhenFalse) :condition(condition), IfTrue(WhenTrue), IfFalse(WhenFalse) { } Evaluatable< Out > *optimize(MemoryManager &m) { Evaluatable< bool > *condition=this-> condition optimize(m)
void RemoveRedundantParenthesis(Reader &text)
Definition nimble_expression_parser.cc:149
void ConvertStringToLowercase(std::string &s)
Definition nimble_expression_parser.cc:126
GenericAdd< double, double, double > DoubleAdd
Definition nimble_expression_parser.h:358
Evaluatable< Out > * IfFalse
Definition nimble_expression_parser.h:342
Evaluatable< Out > * IfTrue
Definition nimble_expression_parser.h:341
GenericConstant< double > DoubleConstant
Definition nimble_expression_parser.h:357
MakeGenericFunction(GenericSin, std::sin) MakeGenericFunction(GenericCos
Evaluatable< double > RealValuedExpression
Definition nimble_expression_parser.h:356
bool IsNumber(Reader r)
Definition nimble_expression_parser.cc:101
GenericDivide< double, double, double > DoubleDivide
Definition nimble_expression_parser.h:361
bool IsInteger(Reader r)
Definition nimble_expression_parser.cc:89
Evaluatable< bool > BooleanExpression
Definition nimble_expression_parser.h:365
GenericConstant< bool > BooleanConstant
Definition nimble_expression_parser.h:366
#define MakeGenericFunction(GenericFunction, f)
Definition nimble_expression_parser.h:152
#define MakeGenericTwoInputFunc(name, f)
Definition nimble_expression_parser.h:240
Definition nimble_expression_parser.h:698
EquationContext * context
Definition nimble_expression_parser.h:700
BoundaryConditionFunctor & operator=(const BoundaryConditionFunctor &other)
Definition nimble_expression_parser.h:732
double operator()(double x, double y, double z, double t)
Definition nimble_expression_parser.h:782
double eval()
Definition nimble_expression_parser.h:758
~BoundaryConditionFunctor()
Definition nimble_expression_parser.h:795
RealValuedExpression * expression
Definition nimble_expression_parser.h:702
BoundaryConditionFunctor & operator=(const std::string &equation)
Definition nimble_expression_parser.h:737
BoundaryConditionFunctor()
Definition nimble_expression_parser.h:704
BoundaryConditionFunctor(const BoundaryConditionFunctor &other)
Definition nimble_expression_parser.h:730
std::string equation
Definition nimble_expression_parser.h:703
double eval(double x, double y, double z, double t)
Definition nimble_expression_parser.h:768
double t
Definition nimble_expression_parser.h:699
double x
Definition nimble_expression_parser.h:699
BoundaryConditionFunctor(const std::string &equation)
Definition nimble_expression_parser.h:705
double y
Definition nimble_expression_parser.h:699
double z
Definition nimble_expression_parser.h:699
Definition nimble_expression_parser.h:64
virtual ~DeletableObjectBaseClass()
Definition nimble_expression_parser.h:65
Definition nimble_expression_parser.h:121
virtual Evaluatable * optimize(MemoryManager &m)
Definition nimble_expression_parser.h:126
Definition nimble_expression_parser.h:134
double value
Definition nimble_expression_parser.h:135
GenericConstant()
Definition nimble_expression_parser.h:137
GenericConstant(T value)
Definition nimble_expression_parser.h:138
Definition nimble_expression_parser.h:143
GenericReference(T *value)
Definition nimble_expression_parser.h:147
GenericReference()
Definition nimble_expression_parser.h:146
T * value
Definition nimble_expression_parser.h:144
Definition nimble_expression_parser.h:75
DeletableObjectBaseClass * Pointers[BlockSize]
Definition nimble_expression_parser.h:76
MemoryBlock()
Definition nimble_expression_parser.h:79
MemoryBlock * next
Definition nimble_expression_parser.h:78
size_t count
Definition nimble_expression_parser.h:77
MemoryBlock(MemoryBlock *next)
Definition nimble_expression_parser.h:80
Definition nimble_expression_parser.h:370
const char * first
Definition nimble_expression_parser.h:371
char operator[](unsigned int i)
Definition nimble_expression_parser.h:479
bool IsEmpty()
Definition nimble_expression_parser.h:489
bool operator==(std::string &s)
Definition nimble_expression_parser.h:459
Reader(const Reader &r)
Definition nimble_expression_parser.h:378
std::string MakeString()
Definition nimble_expression_parser.h:484
Reader(const char *lit)
Definition nimble_expression_parser.h:376
Reader sub(const char *start, const char *end)
Definition nimble_expression_parser.h:381
bool operator>>(char c)
Definition nimble_expression_parser.h:436
Reader(const char *start, const char *end)
Definition nimble_expression_parser.h:377
Reader sub(unsigned int start, unsigned int end)
Definition nimble_expression_parser.h:387
Reader(const char *lit, unsigned int len)
Definition nimble_expression_parser.h:374
int Next(char open, char close)
Definition nimble_expression_parser.h:399
Reader sub(const char *start, unsigned int len)
Definition nimble_expression_parser.h:393
Reader(const std::string &s)
Definition nimble_expression_parser.h:375
bool operator==(const char *lit)
Definition nimble_expression_parser.h:464
int Prev(char open, char close)
Definition nimble_expression_parser.h:417
bool operator<<(char c)
Definition nimble_expression_parser.h:449
unsigned int length
Definition nimble_expression_parser.h:372
unsigned int pos
Definition nimble_expression_parser.h:373