1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkExprTkFunctionParser.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkExprTkFunctionParser.h"
16 #include "vtkObjectFactory.h"
17 
18 #include <algorithm>
19 #include <cctype>
20 #include <random>
21 #include <regex>
22 
23 // exprtk macros
24 #define exprtk_disable_string_capabilities
25 #define exprtk_disable_rtl_io_file
26 #define exprtk_disable_caseinsensitivity
27 #include "vtk_exprtk.h"
28 #include "vtksys/SystemTools.hxx"
29 
30 using ExprTkResultType = exprtk::results_context<double>::type_store_t::store_type;
31 
32 /**
33  * Implementation of vtkExprTkTools
34  */
35 struct vtkExprTkTools
36 {
37   exprtk::symbol_table<double> SymbolTable;
38   exprtk::expression<double> Expression;
39   exprtk::parser<double> Parser;
40 };
41 
42 /**
43  * Implementation of the magnitude function
44  */
45 template <typename T>
46 class mag : public exprtk::igeneric_function<T>
47 {
48 public:
49   typedef typename exprtk::igeneric_function<T> igfun_t;
50   typedef typename igfun_t::parameter_list_t parameter_list_t;
51   typedef typename igfun_t::generic_type generic_type;
52   typedef typename generic_type::scalar_view scalar_t;
53   typedef typename generic_type::vector_view vector_t;
54 
55   using exprtk::igeneric_function<T>::operator();
56 
mag()57   mag()
58     : exprtk::igeneric_function<T>("V|VTT")
59   /*
60      Overloads:
61      0. V   - x(vector)
62      1. VTT - x(vector), r0, r1
63   */
64   {
65   }
66 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)67   inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) override
68   {
69     const vector_t x(parameters[0]);
70 
71     std::size_t r0 = 0;
72     std::size_t r1 = x.size() - 1;
73 
74     if ((1 == ps_index) &&
75       !exprtk::rtl::vecops::helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
76     {
77       return std::numeric_limits<T>::quiet_NaN();
78     }
79     else if (exprtk::rtl::vecops::helper::invalid_range(x, r0, r1))
80     {
81       return std::numeric_limits<T>::quiet_NaN();
82     }
83 
84     T result = T(0);
85 
86     for (std::size_t i = r0; i <= r1; ++i)
87     {
88       result += (x[i] * x[i]);
89     }
90     result = std::sqrt(result);
91 
92     return result;
93   }
94 };
95 
96 /**
97  * Implementation of the x element of cross product function
98  */
99 template <typename T>
100 class crossX : public exprtk::igeneric_function<T>
101 {
102 public:
103   typedef typename exprtk::igeneric_function<T> igfun_t;
104   typedef typename igfun_t::parameter_list_t parameter_list_t;
105   typedef typename igfun_t::generic_type generic_type;
106   typedef typename generic_type::scalar_view scalar_t;
107   typedef typename generic_type::vector_view vector_t;
108 
109   using exprtk::igeneric_function<T>::operator();
110 
crossX()111   crossX()
112     : exprtk::igeneric_function<T>("VV|VVTT")
113   /*
114      Overloads:
115      0. VV   - x(vector), y(vector)
116      1. VVTT - x(vector), y(vector), r0, r1
117   */
118   {
119   }
120 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)121   inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) override
122   {
123     const vector_t x(parameters[0]);
124     const vector_t y(parameters[1]);
125 
126     std::size_t r0 = 0;
127     std::size_t r1 = std::min(x.size(), y.size()) - 1;
128 
129     if ((1 == ps_index) &&
130       !exprtk::rtl::vecops::helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
131     {
132       return std::numeric_limits<T>::quiet_NaN();
133     }
134     else if (exprtk::rtl::vecops::helper::invalid_range(y, r0, r1))
135     {
136       return std::numeric_limits<T>::quiet_NaN();
137     }
138 
139     T result = x[1] * y[2] - x[2] * y[1];
140 
141     return result;
142   }
143 };
144 
145 /**
146  * Implementation of the y element of cross product function
147  */
148 template <typename T>
149 class crossY : public exprtk::igeneric_function<T>
150 {
151 public:
152   typedef typename exprtk::igeneric_function<T> igfun_t;
153   typedef typename igfun_t::parameter_list_t parameter_list_t;
154   typedef typename igfun_t::generic_type generic_type;
155   typedef typename generic_type::scalar_view scalar_t;
156   typedef typename generic_type::vector_view vector_t;
157 
158   using exprtk::igeneric_function<T>::operator();
159 
crossY()160   crossY()
161     : exprtk::igeneric_function<T>("VV|VVTT")
162   /*
163      Overloads:
164      0. VV   - x(vector), y(vector)
165      1. VVTT - x(vector), y(vector), r0, r1
166   */
167   {
168   }
169 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)170   inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) override
171   {
172     const vector_t x(parameters[0]);
173     const vector_t y(parameters[1]);
174 
175     std::size_t r0 = 0;
176     std::size_t r1 = std::min(x.size(), y.size()) - 1;
177 
178     if ((1 == ps_index) &&
179       !exprtk::rtl::vecops::helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
180     {
181       return std::numeric_limits<T>::quiet_NaN();
182     }
183     else if (exprtk::rtl::vecops::helper::invalid_range(y, r0, r1))
184     {
185       return std::numeric_limits<T>::quiet_NaN();
186     }
187 
188     T result = x[2] * y[0] - x[0] * y[2];
189 
190     return result;
191   }
192 };
193 
194 /**
195  * Implementation of the z element of cross product function
196  */
197 template <typename T>
198 class crossZ : public exprtk::igeneric_function<T>
199 {
200 public:
201   typedef typename exprtk::igeneric_function<T> igfun_t;
202   typedef typename igfun_t::parameter_list_t parameter_list_t;
203   typedef typename igfun_t::generic_type generic_type;
204   typedef typename generic_type::scalar_view scalar_t;
205   typedef typename generic_type::vector_view vector_t;
206 
207   using exprtk::igeneric_function<T>::operator();
208 
crossZ()209   crossZ()
210     : exprtk::igeneric_function<T>("VV|VVTT")
211   /*
212      Overloads:
213      0. VV   - x(vector), y(vector)
214      1. VVTT - x(vector), y(vector), r0, r1
215   */
216   {
217   }
218 
operator ()(const std::size_t & ps_index,parameter_list_t parameters)219   inline T operator()(const std::size_t& ps_index, parameter_list_t parameters) override
220   {
221     const vector_t x(parameters[0]);
222     const vector_t y(parameters[1]);
223 
224     std::size_t r0 = 0;
225     std::size_t r1 = std::min(x.size(), y.size()) - 1;
226 
227     if ((1 == ps_index) &&
228       !exprtk::rtl::vecops::helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
229     {
230       return std::numeric_limits<T>::quiet_NaN();
231     }
232     else if (exprtk::rtl::vecops::helper::invalid_range(y, r0, r1))
233     {
234       return std::numeric_limits<T>::quiet_NaN();
235     }
236 
237     T result = x[0] * y[1] - x[1] * y[0];
238 
239     return result;
240   }
241 };
242 
243 namespace
244 {
245 /**
246  * Implementation of sign function.
247  */
sign(double v)248 inline double sign(double v)
249 {
250   if (v == 0.)
251   {
252     return 0.;
253   }
254   else if (std::signbit(v))
255   {
256     return -1.;
257   }
258   else
259   {
260     return 1.;
261   }
262 }
263 
264 // compile-time declaration of needed function/variables/vectors/packages
265 // these are useful to minimize the construction cost, especially when
266 // multiple instances of this class are instantiated
267 exprtk::rtl::vecops::package<double> vectorOperationsPackage;
268 std::vector<double> iHat = { 1, 0, 0 };
269 std::vector<double> jHat = { 0, 1, 0 };
270 std::vector<double> kHat = { 0, 0, 1 };
271 mag<double> magnitude;
272 crossX<double> crossXProduct;
273 crossY<double> crossYProduct;
274 crossZ<double> crossZProduct;
275 
276 // the value that is returned as a result if there is an error
277 double vtkParserErrorResult = std::numeric_limits<double>::quiet_NaN();
278 double vtkParserVectorErrorResult[3] = { vtkParserErrorResult, vtkParserErrorResult,
279   vtkParserErrorResult };
280 
281 //------------------------------------------------------------------------------
RemoveSpacesFrom(std::string str)282 std::string RemoveSpacesFrom(std::string str)
283 {
284   str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
285   return str;
286 }
287 
288 //------------------------------------------------------------------------------
HasEnding(const std::string & fullString,const std::string & ending)289 bool HasEnding(const std::string& fullString, const std::string& ending)
290 {
291   if (fullString.size() >= ending.size())
292   {
293     return (fullString.compare(fullString.size() - ending.size(), ending.size(), ending) == 0);
294   }
295   else
296   {
297     return false;
298   }
299 }
300 
301 //------------------------------------------------------------------------------
GenerateRandomAlphabeticString(unsigned int len)302 std::string GenerateRandomAlphabeticString(unsigned int len)
303 {
304   static constexpr auto chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
305                                 "abcdefghijklmnopqrstuvwxyz";
306   auto rng = std::default_random_engine(std::random_device{}());
307   auto dist = std::uniform_int_distribution<int>(0, static_cast<int>(std::strlen(chars) - 1));
308   auto result = std::string(len, '\0');
309   std::generate_n(begin(result), len, [&]() { return chars[dist(rng)]; });
310 
311   return result;
312 }
313 
314 //------------------------------------------------------------------------------
GenerateUniqueVariableName(const std::vector<std::string> & variableNames,const std::string & variableName)315 std::string GenerateUniqueVariableName(
316   const std::vector<std::string>& variableNames, const std::string& variableName)
317 {
318   std::string sanitizedName = vtkExprTkFunctionParser::SanitizeName(variableName.c_str());
319   do
320   {
321     sanitizedName += GenerateRandomAlphabeticString(5);
322   } while (
323     std::find(variableNames.begin(), variableNames.end(), sanitizedName) != variableNames.end());
324 
325   return sanitizedName;
326 }
327 }
328 
329 vtkStandardNewMacro(vtkExprTkFunctionParser);
330 
331 //------------------------------------------------------------------------------
vtkExprTkFunctionParser()332 vtkExprTkFunctionParser::vtkExprTkFunctionParser()
333 {
334   this->EvaluateMTime.Modified();
335   this->VariableMTime.Modified();
336   this->ParseMTime.Modified();
337   this->FunctionMTime.Modified();
338 
339   this->ReplaceInvalidValues = 0;
340   this->ReplacementValue = 0.0;
341 
342   this->ExprTkTools = new vtkExprTkTools;
343   // add vector support
344   this->ExprTkTools->SymbolTable.add_package(vectorOperationsPackage);
345   // add unit vectors
346   this->ExprTkTools->SymbolTable.add_vector("iHat", iHat);
347   this->ExprTkTools->SymbolTable.add_vector("jHat", jHat);
348   this->ExprTkTools->SymbolTable.add_vector("kHat", kHat);
349   // add ln and sign
350   this->ExprTkTools->SymbolTable.add_function("ln", std::log);
351   this->ExprTkTools->SymbolTable.add_function("sign", sign);
352   // add magnitude function
353   this->ExprTkTools->SymbolTable.add_function("mag", magnitude);
354   // add functions which are used to implement cross product
355   this->ExprTkTools->SymbolTable.add_function("crossX", crossXProduct);
356   this->ExprTkTools->SymbolTable.add_function("crossY", crossYProduct);
357   this->ExprTkTools->SymbolTable.add_function("crossZ", crossZProduct);
358   // register symbol table
359   this->ExprTkTools->Expression.register_symbol_table(this->ExprTkTools->SymbolTable);
360   // enable the collection of variables, which will be used in UpdateNeededVariables
361   this->ExprTkTools->Parser.dec().collect_variables() = true;
362 }
363 
364 //------------------------------------------------------------------------------
~vtkExprTkFunctionParser()365 vtkExprTkFunctionParser::~vtkExprTkFunctionParser()
366 {
367   this->RemoveAllVariables();
368   delete this->ExprTkTools;
369 }
370 
371 //------------------------------------------------------------------------------
SetFunction(const char * function)372 void vtkExprTkFunctionParser::SetFunction(const char* function)
373 {
374   // check if we have already set the same function string
375   if (!this->Function.empty() && function && this->Function == function)
376   {
377     return;
378   }
379 
380   if (function)
381   {
382     this->Function = function;
383     this->FunctionWithUsedVariableNames = this->Function;
384   }
385   else
386   {
387     this->Function = std::string();
388     this->FunctionWithUsedVariableNames = std::string();
389   }
390 
391   this->FunctionMTime.Modified();
392   this->ScalarVariableNeeded.clear();
393   this->VectorVariableNeeded.clear();
394   this->Modified();
395 }
396 
397 //------------------------------------------------------------------------------
Parse(ParseMode mode)398 int vtkExprTkFunctionParser::Parse(ParseMode mode)
399 {
400   if (this->Function.empty())
401   {
402     vtkErrorMacro("Parse: no function has been set");
403     return 0;
404   }
405 
406   // During the parsing of the first mode, perform the necessary changes in the function
407   if (mode == ParseMode::DetectReturnType)
408   {
409     // Before parsing, replace the original variable names in the function
410     // with the valid ones if needed.
411     for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); ++i)
412     {
413       if (this->OriginalScalarVariableNames[i] != this->UsedScalarVariableNames[i])
414       {
415         vtksys::SystemTools::ReplaceString(this->FunctionWithUsedVariableNames,
416           this->OriginalScalarVariableNames[i], this->UsedScalarVariableNames[i]);
417       }
418     }
419     for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); ++i)
420     {
421       if (this->OriginalVectorVariableNames[i] != this->UsedVectorVariableNames[i])
422       {
423         vtksys::SystemTools::ReplaceString(this->FunctionWithUsedVariableNames,
424           this->OriginalVectorVariableNames[i], this->UsedVectorVariableNames[i]);
425       }
426     }
427 
428     // remove spaces to perform replacement for norm and cross
429     this->FunctionWithUsedVariableNames = RemoveSpacesFrom(this->FunctionWithUsedVariableNames);
430 
431     // check for usage of old dot format product, e.g. (v1.v2) instead of dot(v1,v2)
432     if (this->CheckOldFormatOfDotProductUsage())
433     {
434       std::string oldDotUsageError =
435         "Warn: 0000 Type: [Old Usage] Msg: "
436         "Possible usage of old format of dot product v1.v2. Please use dot(v1,v2)."
437         "\tExpression: " +
438         this->Function + '\n';
439       vtkWarningMacro(<< oldDotUsageError);
440     }
441 
442     // fix cross occurrences with something that ExprTk can understand
443     this->FunctionWithUsedVariableNames =
444       FixVectorReturningFunctionOccurrences(VectorReturningFunction::Cross);
445 
446     // fix norm occurrences with something that ExprTk can understand
447     this->FunctionWithUsedVariableNames =
448       FixVectorReturningFunctionOccurrences(VectorReturningFunction::Norm);
449   }
450 
451   if (mode == ParseMode::DetectReturnType)
452   {
453     // ExprTK, in order to extract vector and scalar results, and identify the result type,
454     // it requires to "return results" instead of just evaluating an expression
455     this->ExpressionString = "return [" + this->FunctionWithUsedVariableNames + "];";
456   }
457   else
458   {
459     // Since we know now the return type, we can assign the result to a result scalar/vector
460     std::string resultName = GenerateRandomAlphabeticString(10);
461     if (this->ResultType == ExprTkResultType::e_scalar)
462     {
463       this->ExprTkTools->SymbolTable.add_variable(resultName, this->Result[0]);
464       this->ExpressionString = resultName + " := " + this->FunctionWithUsedVariableNames + ";";
465     }
466     else
467     {
468       this->ExprTkTools->SymbolTable.add_vector(
469         resultName, this->Result.GetData(), this->Result.GetSize());
470       this->ExpressionString = resultName + " := [" + this->FunctionWithUsedVariableNames + "];";
471     }
472   }
473 
474   bool parsingResult =
475     this->ExprTkTools->Parser.compile(this->ExpressionString, this->ExprTkTools->Expression);
476   // check parsing result
477   if (!parsingResult)
478   {
479     // print error only once
480     if (mode == ParseMode::DetectReturnType)
481     {
482       std::stringstream parsingErrorStream;
483       // save error
484       for (std::size_t i = 0; i < this->ExprTkTools->Parser.error_count(); ++i)
485       {
486         auto error = this->ExprTkTools->Parser.get_error(i);
487         parsingErrorStream << "Err: " << i << " Type: [" << exprtk::parser_error::to_str(error.mode)
488                            << "] Msg: " << error.diagnostic << "\tExpression: " << this->Function
489                            << "\n";
490       }
491       vtkErrorMacro(<< parsingErrorStream.str());
492     }
493 
494     return 0;
495   }
496 
497   if (mode == ParseMode::DetectReturnType)
498   {
499     // Collect meta-data about variables that are needed for evaluation of the
500     // function.
501     this->UpdateNeededVariables();
502   }
503   this->ParseMTime.Modified();
504   return 1;
505 }
506 
FixVectorReturningFunctionOccurrences(VectorReturningFunction vectorReturningFunction)507 std::string vtkExprTkFunctionParser::FixVectorReturningFunctionOccurrences(
508   VectorReturningFunction vectorReturningFunction)
509 {
510   std::string desiredFunction;
511   std::string functionWithoutParenthesis;
512   if (vectorReturningFunction == VectorReturningFunction::Cross)
513   {
514     desiredFunction = "cross(";
515     functionWithoutParenthesis = "cross";
516   }
517   else
518   {
519     desiredFunction = "norm(";
520     functionWithoutParenthesis = "norm";
521   }
522 
523   // collect all the variables that end with the desired function, e.g. mycross, m1cross
524   std::vector<std::string> variableNamesContainingFunction;
525   for (const auto& scalarVariable : this->UsedScalarVariableNames)
526   {
527     if (HasEnding(scalarVariable, functionWithoutParenthesis))
528     {
529       variableNamesContainingFunction.push_back(scalarVariable);
530     }
531   }
532   for (const auto& vectorVariable : this->UsedVectorVariableNames)
533   {
534     if (HasEnding(vectorVariable, functionWithoutParenthesis))
535     {
536       variableNamesContainingFunction.push_back(vectorVariable);
537     }
538   }
539   // sort vector by size to ensure that the largest variables names will be checked first
540   std::sort(variableNamesContainingFunction.begin(), variableNamesContainingFunction.end(),
541     [](const std::string& s1, const std::string& s2) -> bool { return s1.size() > s2.size(); });
542 
543   static const std::string allowedChars = "01234565789.,()+-*/%^|&=<>!";
544   std::string::size_type pos = 0;
545   std::string function = this->FunctionWithUsedVariableNames;
546   while ((pos = function.find(desiredFunction, pos)) != std::string::npos)
547   {
548     // if we are not in the beginning
549     if (static_cast<int>(pos) - 1 != -1)
550     {
551       // check the found occurrence if it's part of a variable
552       // this check is required because the previous character could be a number
553       // and that is part of a variable name which includes cross, such m1cross
554       bool foundVariableOccurrence = false;
555       for (const auto& variable : variableNamesContainingFunction)
556       {
557         // check the size of the variable vs the function
558         if (variable.size() >= functionWithoutParenthesis.size())
559         {
560           const int sizeDifference =
561             static_cast<int>(variable.size() - functionWithoutParenthesis.size());
562           // check pos to not exceed the beginning
563           if (static_cast<int>(pos) - sizeDifference >= 0)
564           {
565             // check if occurrence match variable
566             if (function.substr(pos - sizeDifference, variable.size()) == variable)
567             {
568               foundVariableOccurrence = true;
569               break;
570             }
571           }
572         }
573       }
574       // skip the found occurrence if it's part of a variable
575       if (foundVariableOccurrence)
576       {
577         pos += desiredFunction.size();
578         continue;
579       }
580 
581       // check if a character that is allowed is found
582       bool allowedCharFound = false;
583       for (char allowedChar : allowedChars)
584       {
585         if (function[pos - 1] == allowedChar)
586         {
587           allowedCharFound = true;
588           break;
589         }
590       }
591 
592       // skip the found occurrence if no allowed character has been found
593       if (!allowedCharFound)
594       {
595         pos += desiredFunction.size();
596         continue;
597       }
598     }
599 
600     pos += desiredFunction.size();
601 
602     // match the number of parenthesis
603     int leftParenthesis = 1; // 1 because we have already detected one
604     int rightParenthesis = 0;
605     std::stringstream interior;
606     for (size_t i = pos; i < function.size(); ++i)
607     {
608       if (function[i] == ')')
609       {
610         ++rightParenthesis;
611       }
612       if (function[i] == '(')
613       {
614         ++leftParenthesis;
615       }
616 
617       if (leftParenthesis == rightParenthesis)
618       {
619         break;
620       }
621       else
622       {
623         interior << function[i];
624       }
625     }
626     // if the number of left and right parenthesis is equal, then replace appropriately
627     if (rightParenthesis == leftParenthesis)
628     {
629       // go back to replace
630       pos -= desiredFunction.size();
631 
632       std::string replacement;
633       if (vectorReturningFunction == VectorReturningFunction::Cross)
634       {
635         // (iHat*crossX(v1,v2)+jHat*crossY(v1,v2)+kHat*crossZ(v1,v2))
636         replacement = "(iHat*crossX(" + interior.str() + ")" + "+jHat*crossY(" + interior.str() +
637           ")" + "+kHat*crossZ(" + interior.str() + "))";
638       }
639       else
640       {
641         // ((v)/mag(v))
642         replacement = "((" + interior.str() + ")/mag(" + interior.str() + "))";
643       }
644 
645       // perform replacement, +1 is for the right parenthesis
646       function.replace(pos, desiredFunction.size() + interior.str().size() + 1, replacement);
647     }
648     else
649     {
650       // ExprTk will catch it the parenthesis mismatch
651       // ExprTk will also catch all the cases that the interior is not valid
652       break;
653     }
654   }
655   return function;
656 }
657 
658 //------------------------------------------------------------------------------
CheckOldFormatOfDotProductUsage()659 bool vtkExprTkFunctionParser::CheckOldFormatOfDotProductUsage()
660 {
661   const std::string function = this->FunctionWithUsedVariableNames;
662   std::string::size_type pos = 0;
663   while ((pos = function.find('.', pos)) != std::string::npos)
664   {
665     // if we are not in the beginning
666     if (static_cast<int>(pos) - 1 != -1)
667     {
668       // check if left character is digit
669       bool leftCharacterIsDigit = false;
670       if (std::isdigit(function[pos - 1]))
671       {
672         leftCharacterIsDigit = true;
673       }
674 
675       // check if right character is digit
676       bool rightCharacterIsDigit = false;
677       // before that check, check if you can look at the right character
678       if (pos + 1 < function.size())
679       {
680         if (std::isdigit(function[pos + 1]))
681         {
682           rightCharacterIsDigit = true;
683         }
684       }
685 
686       // both left character and right character are not digits
687       // then this is a possible product usage
688       if (!leftCharacterIsDigit && !rightCharacterIsDigit)
689       {
690         return true;
691       }
692       else
693       {
694         ++pos;
695       }
696     }
697     else
698     {
699       // check if right character is number
700       bool rightCharacterIsNumber = false;
701       // before that check, check if you can look at the right character
702       if (pos + 1 < function.size())
703       {
704         if (std::isdigit(function[pos + 1]))
705         {
706           rightCharacterIsNumber = true;
707         }
708       }
709       // right character is not a number
710       // then this is a possible product usage
711       if (!rightCharacterIsNumber)
712       {
713         return true;
714       }
715       else
716       {
717         ++pos;
718       }
719     }
720   }
721   return false;
722 }
723 
724 //------------------------------------------------------------------------------
InvalidateFunction()725 void vtkExprTkFunctionParser::InvalidateFunction()
726 {
727   this->FunctionMTime.Modified();
728 }
729 
730 //------------------------------------------------------------------------------
Evaluate()731 bool vtkExprTkFunctionParser::Evaluate()
732 {
733   if (this->FunctionMTime.GetMTime() > this->ParseMTime.GetMTime())
734   {
735     // compile with mode 0 to identify return type
736     if (this->Parse(ParseMode::DetectReturnType) == 0)
737     {
738       return false;
739     }
740     // perform evaluation to identify the return type
741     this->ExprTkTools->Expression.value();
742     this->ResultType = this->ExprTkTools->Expression.results()[0].type;
743 
744     // compile with mode 1 to save results in the result array
745     if (this->Parse(ParseMode::SaveResultInVariable) == 0)
746     {
747       return false;
748     }
749   }
750   // perform evaluation
751   this->ExprTkTools->Expression.value();
752 
753   switch (this->ResultType)
754   {
755     case ExprTkResultType::e_scalar:
756       if (std::isnan(this->Result[0]) || std::isinf(this->Result[0]))
757       {
758         if (this->ReplaceInvalidValues)
759         {
760           this->Result[0] = this->ReplacementValue;
761         }
762         else
763         {
764           vtkErrorMacro("Invalid result because of mathematically wrong input.");
765           return false;
766         }
767       }
768       break;
769     case ExprTkResultType::e_vector:
770       for (int i = 0; i < 3; i++)
771       {
772         if (std::isnan(this->Result[i]) || std::isinf(this->Result[i]))
773         {
774           if (this->ReplaceInvalidValues)
775           {
776             this->Result[i] = this->ReplacementValue;
777           }
778           else
779           {
780             vtkErrorMacro("Invalid vector element result because of mathematically wrong input.");
781             return false;
782           }
783         }
784       }
785       break;
786     default:
787       vtkErrorMacro("Not supported result type.");
788       return false;
789   }
790 
791   this->EvaluateMTime.Modified();
792 
793   return true;
794 }
795 
796 //------------------------------------------------------------------------------
IsScalarResult()797 int vtkExprTkFunctionParser::IsScalarResult()
798 {
799   if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
800     this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
801   {
802     if (this->Evaluate() == false)
803       return 0;
804   }
805   return (this->ResultType == ExprTkResultType::e_scalar);
806 }
807 
808 //------------------------------------------------------------------------------
GetScalarResult()809 double vtkExprTkFunctionParser::GetScalarResult()
810 {
811   if (!(this->IsScalarResult()))
812   {
813     vtkErrorMacro("GetScalarResult: no valid scalar result");
814     return vtkParserErrorResult;
815   }
816   return this->Result[0];
817 }
818 
819 //------------------------------------------------------------------------------
IsVectorResult()820 int vtkExprTkFunctionParser::IsVectorResult()
821 {
822   if (this->VariableMTime.GetMTime() > this->EvaluateMTime.GetMTime() ||
823     this->FunctionMTime.GetMTime() > this->EvaluateMTime.GetMTime())
824   {
825     if (this->Evaluate() == false)
826       return 0;
827   }
828   return (this->ResultType == ExprTkResultType::e_vector);
829 }
830 
831 //------------------------------------------------------------------------------
GetVectorResult()832 double* vtkExprTkFunctionParser::GetVectorResult()
833 {
834   if (!(this->IsVectorResult()))
835   {
836     vtkErrorMacro("GetVectorResult: no valid vector result");
837     return vtkParserVectorErrorResult;
838   }
839   return this->Result.GetData();
840 }
841 
842 //------------------------------------------------------------------------------
GetScalarVariableName(int i)843 std::string vtkExprTkFunctionParser::GetScalarVariableName(int i)
844 {
845   if (i >= 0 && i < this->GetNumberOfScalarVariables())
846   {
847     return this->OriginalScalarVariableNames[i];
848   }
849   return std::string();
850 }
851 
852 //------------------------------------------------------------------------------
GetVectorVariableName(int i)853 std::string vtkExprTkFunctionParser::GetVectorVariableName(int i)
854 {
855   if (i >= 0 && i < this->GetNumberOfVectorVariables())
856   {
857     return this->OriginalVectorVariableNames[i];
858   }
859   return std::string();
860 }
861 
862 //------------------------------------------------------------------------------
SetScalarVariableValue(const std::string & inVariableName,double value)863 void vtkExprTkFunctionParser::SetScalarVariableValue(
864   const std::string& inVariableName, double value)
865 {
866   if (inVariableName.empty())
867   {
868     vtkErrorMacro("Variable name is empty");
869     return;
870   }
871   // check if variable name exists in vectors
872   for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); i++)
873   {
874     if (this->OriginalVectorVariableNames[i] == inVariableName)
875     {
876       vtkErrorMacro("Scalar variable name is already registered as a vector variable name");
877       return;
878     }
879   }
880   // check if variable already exists
881   for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); i++)
882   {
883     if (this->OriginalScalarVariableNames[i] == inVariableName)
884     {
885       if (*this->ScalarVariableValues[i] != value)
886       {
887         *this->ScalarVariableValues[i] = value;
888         this->VariableMTime.Modified();
889         this->Modified();
890       }
891       return;
892     }
893   }
894 
895   double* scalarValue = new double(value);
896   // if variable name is not sanitized, create a unique sanitized string and set it as variable name
897   std::string variableName = vtkExprTkFunctionParser::SanitizeName(inVariableName.c_str());
898   if (variableName != inVariableName)
899   {
900     variableName = GenerateUniqueVariableName(this->UsedScalarVariableNames, inVariableName);
901   }
902 
903   // check if variable is a registered keyword, e.g. sin().
904   bool additionResult = this->ExprTkTools->SymbolTable.add_variable(variableName, *scalarValue);
905   if (additionResult)
906   {
907     this->ScalarVariableValues.push_back(scalarValue);
908     this->OriginalScalarVariableNames.push_back(inVariableName);
909     this->UsedScalarVariableNames.push_back(variableName);
910 
911     this->VariableMTime.Modified();
912     this->Modified();
913   }
914   else
915   {
916     delete scalarValue;
917     vtkErrorMacro("Scalar variable `" << inVariableName << "` is a reserved keyword");
918   }
919 }
920 
921 //------------------------------------------------------------------------------
SetScalarVariableValue(int i,double value)922 void vtkExprTkFunctionParser::SetScalarVariableValue(int i, double value)
923 {
924   if (i < 0 || i >= this->GetNumberOfScalarVariables())
925   {
926     return;
927   }
928 
929   if (*this->ScalarVariableValues[i] != value)
930   {
931     *this->ScalarVariableValues[i] = value;
932     this->VariableMTime.Modified();
933   }
934   this->Modified();
935 }
936 
937 //------------------------------------------------------------------------------
GetScalarVariableValue(const std::string & inVariableName)938 double vtkExprTkFunctionParser::GetScalarVariableValue(const std::string& inVariableName)
939 {
940   for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); i++)
941   {
942     if (this->OriginalScalarVariableNames[i] == inVariableName)
943     {
944       return *this->ScalarVariableValues[i];
945     }
946   }
947   vtkErrorMacro(
948     "GetScalarVariableValue: scalar variable name " << inVariableName << " does not exist");
949   return vtkParserErrorResult;
950 }
951 
952 //------------------------------------------------------------------------------
GetScalarVariableValue(int i)953 double vtkExprTkFunctionParser::GetScalarVariableValue(int i)
954 {
955   if (i < 0 || i >= this->GetNumberOfScalarVariables())
956   {
957     vtkErrorMacro("GetScalarVariableValue: scalar variable number " << i << " does not exist");
958     return vtkParserErrorResult;
959   }
960 
961   return *this->ScalarVariableValues[i];
962 }
963 
964 //------------------------------------------------------------------------------
SetVectorVariableValue(const std::string & inVariableName,double xValue,double yValue,double zValue)965 void vtkExprTkFunctionParser::SetVectorVariableValue(
966   const std::string& inVariableName, double xValue, double yValue, double zValue)
967 {
968   if (inVariableName.empty())
969   {
970     vtkErrorMacro("Variable name is empty");
971     return;
972   }
973   // check if variable name exists in vectors
974   for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); i++)
975   {
976     if (this->OriginalScalarVariableNames[i] == inVariableName)
977     {
978       vtkErrorMacro("Vector variable name is already registered as a scalar variable name");
979       return;
980     }
981   }
982   // check if variable already exists
983   for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); i++)
984   {
985     if (this->OriginalVectorVariableNames[i] == inVariableName)
986     {
987       if ((*this->VectorVariableValues[i])[0] != xValue ||
988         (*this->VectorVariableValues[i])[1] != yValue ||
989         (*this->VectorVariableValues[i])[2] != zValue)
990       {
991         (*this->VectorVariableValues[i])[0] = xValue;
992         (*this->VectorVariableValues[i])[1] = yValue;
993         (*this->VectorVariableValues[i])[2] = zValue;
994         this->VariableMTime.Modified();
995         this->Modified();
996       }
997       return;
998     }
999   }
1000 
1001   vtkTuple<double, 3>* vector = new vtkTuple<double, 3>();
1002   (*vector)[0] = xValue;
1003   (*vector)[1] = yValue;
1004   (*vector)[2] = zValue;
1005 
1006   // if variable name is not sanitized, create a unique sanitized string and set it as variable name
1007   std::string variableName = vtkExprTkFunctionParser::SanitizeName(inVariableName.c_str());
1008   if (variableName != inVariableName)
1009   {
1010     variableName = GenerateUniqueVariableName(this->UsedVectorVariableNames, inVariableName);
1011   }
1012   // check if variable is a registered keyword, e.g. sin().
1013   bool additionResult =
1014     this->ExprTkTools->SymbolTable.add_vector(variableName, vector->GetData(), vector->GetSize());
1015   if (additionResult)
1016   {
1017     this->VectorVariableValues.push_back(vector);
1018     this->OriginalVectorVariableNames.push_back(inVariableName);
1019     this->UsedVectorVariableNames.push_back(variableName);
1020 
1021     this->VariableMTime.Modified();
1022     this->Modified();
1023   }
1024   else
1025   {
1026     delete vector;
1027     vtkErrorMacro("Vector variable `" << inVariableName << "` is a reserved keyword");
1028   }
1029 }
1030 
1031 //------------------------------------------------------------------------------
SetVectorVariableValue(int i,double xValue,double yValue,double zValue)1032 void vtkExprTkFunctionParser::SetVectorVariableValue(
1033   int i, double xValue, double yValue, double zValue)
1034 {
1035   if (i < 0 || i >= this->GetNumberOfVectorVariables())
1036   {
1037     return;
1038   }
1039   if ((*this->VectorVariableValues[i])[0] != xValue ||
1040     (*this->VectorVariableValues[i])[1] != yValue || (*this->VectorVariableValues[i])[2] != zValue)
1041   {
1042     (*this->VectorVariableValues[i])[0] = xValue;
1043     (*this->VectorVariableValues[i])[1] = yValue;
1044     (*this->VectorVariableValues[i])[2] = zValue;
1045     this->VariableMTime.Modified();
1046     this->Modified();
1047   }
1048 }
1049 
1050 //------------------------------------------------------------------------------
GetVectorVariableValue(const std::string & inVariableName)1051 double* vtkExprTkFunctionParser::GetVectorVariableValue(const std::string& inVariableName)
1052 {
1053   for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); i++)
1054   {
1055     if (this->OriginalVectorVariableNames[i] == inVariableName)
1056     {
1057       return this->VectorVariableValues[i]->GetData();
1058     }
1059   }
1060   vtkErrorMacro(
1061     "GetVectorVariableValue: vector variable name " << inVariableName << " does not exist");
1062   return vtkParserVectorErrorResult;
1063 }
1064 
1065 //------------------------------------------------------------------------------
GetVectorVariableValue(int i)1066 double* vtkExprTkFunctionParser::GetVectorVariableValue(int i)
1067 {
1068   if (i < 0 || i >= this->GetNumberOfVectorVariables())
1069   {
1070     vtkErrorMacro("GetVectorVariableValue: vector variable number " << i << " does not exist");
1071     return vtkParserVectorErrorResult;
1072   }
1073   return this->VectorVariableValues[i]->GetData();
1074 }
1075 
1076 //------------------------------------------------------------------------------
RemoveScalarVariables()1077 void vtkExprTkFunctionParser::RemoveScalarVariables()
1078 {
1079   this->ExprTkTools->SymbolTable.clear_variables();
1080   this->OriginalScalarVariableNames.clear();
1081   this->UsedScalarVariableNames.clear();
1082   for (size_t i = 0; i < this->ScalarVariableValues.size(); ++i)
1083   {
1084     delete this->ScalarVariableValues[i];
1085   }
1086   this->ScalarVariableValues.clear();
1087 }
1088 
1089 //------------------------------------------------------------------------------
RemoveVectorVariables()1090 void vtkExprTkFunctionParser::RemoveVectorVariables()
1091 {
1092   // we clear vector variables to avoid removing iHat,jHat, kHat
1093   for (size_t i = 0; i < this->UsedVectorVariableNames.size(); ++i)
1094   {
1095     this->ExprTkTools->SymbolTable.remove_vector(this->UsedVectorVariableNames[i]);
1096   }
1097   this->OriginalVectorVariableNames.clear();
1098   this->UsedVectorVariableNames.clear();
1099   for (size_t i = 0; i < this->VectorVariableValues.size(); ++i)
1100   {
1101     delete this->VectorVariableValues[i];
1102   }
1103   this->VectorVariableValues.clear();
1104 }
1105 
1106 //------------------------------------------------------------------------------
RemoveAllVariables()1107 void vtkExprTkFunctionParser::RemoveAllVariables()
1108 {
1109   this->RemoveScalarVariables();
1110   this->RemoveVectorVariables();
1111 }
1112 
1113 //------------------------------------------------------------------------------
GetMTime()1114 vtkMTimeType vtkExprTkFunctionParser::GetMTime()
1115 {
1116   vtkMTimeType mTime = this->Superclass::GetMTime();
1117 
1118   if (this->EvaluateMTime > mTime)
1119   {
1120     mTime = this->EvaluateMTime;
1121   }
1122   if (this->VariableMTime > mTime)
1123   {
1124     mTime = this->VariableMTime;
1125   }
1126   if (this->ParseMTime > mTime)
1127   {
1128     mTime = this->ParseMTime;
1129   }
1130   if (this->FunctionMTime > mTime)
1131   {
1132     mTime = this->FunctionMTime;
1133   }
1134 
1135   return mTime;
1136 }
1137 
1138 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1139 void vtkExprTkFunctionParser::PrintSelf(ostream& os, vtkIndent indent)
1140 {
1141   this->Superclass::PrintSelf(os, indent);
1142 
1143   os << indent << "Function: " << (this->GetFunction() ? this->GetFunction() : "(none)") << endl;
1144 
1145   os << indent << "FunctionWithUsedVariableNames: "
1146      << (!this->FunctionWithUsedVariableNames.empty() ? this->FunctionWithUsedVariableNames
1147                                                       : "(none)")
1148      << endl;
1149 
1150   os << indent << "ExpressionString: "
1151      << (!this->ExpressionString.empty() ? this->ExpressionString : "(none)") << endl;
1152 
1153   for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); i++)
1154   {
1155     os << indent << "  " << this->OriginalScalarVariableNames[i] << " / "
1156        << this->UsedScalarVariableNames[i] << ": " << (*this->ScalarVariableValues[i]) << endl;
1157   }
1158 
1159   for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); i++)
1160   {
1161     os << indent << "  " << this->OriginalVectorVariableNames[i] << " / "
1162        << this->UsedVectorVariableNames[i] << ": (" << (*this->VectorVariableValues[i])[0] << ", "
1163        << (*this->VectorVariableValues[i])[1] << ", " << (*this->VectorVariableValues[i])[2] << ")"
1164        << endl;
1165   }
1166 
1167   if (this->EvaluateMTime.GetMTime() > this->FunctionMTime.GetMTime() &&
1168     this->EvaluateMTime.GetMTime() > this->VariableMTime.GetMTime() &&
1169     this->ExprTkTools->Expression.results().count() > 0)
1170   {
1171     if (this->ResultType == ExprTkResultType::e_scalar)
1172     {
1173       os << indent << "ScalarResult: " << this->GetScalarResult() << endl;
1174       os << indent << "VectorResult: "
1175          << "(none)" << endl;
1176     }
1177     else
1178     {
1179       os << indent << "ScalarResult: "
1180          << "(none)" << endl;
1181       os << indent << "VectorResult: "
1182          << "(" << this->GetVectorResult()[0] << ", " << this->GetVectorResult()[1] << ", "
1183          << this->GetVectorResult()[2] << ")" << endl;
1184     }
1185   }
1186   else
1187   {
1188     os << indent << "ScalarResult: "
1189        << "(none)" << endl;
1190     os << indent << "VectorResult: "
1191        << "(none)" << endl;
1192   }
1193 
1194   os << indent << "Replace Invalid Values: " << (this->GetReplaceInvalidValues() ? "On" : "Off")
1195      << endl;
1196   os << indent << "Replacement Value: " << this->GetReplacementValue() << endl;
1197 }
1198 
1199 //------------------------------------------------------------------------------
UpdateNeededVariables()1200 void vtkExprTkFunctionParser::UpdateNeededVariables()
1201 {
1202   this->ScalarVariableNeeded.clear();
1203   this->ScalarVariableNeeded.resize(this->UsedScalarVariableNames.size(), false);
1204 
1205   this->VectorVariableNeeded.clear();
1206   this->VectorVariableNeeded.resize(this->UsedVectorVariableNames.size(), false);
1207 
1208   // store variables after parsing
1209   std::deque<exprtk::parser<double>::dependent_entity_collector::symbol_t> symbolList;
1210   this->ExprTkTools->Parser.dec().symbols(symbolList);
1211   // convert them to a set to remove duplicates
1212   std::set<std::string> variables;
1213   for (const auto& symbol : symbolList)
1214   {
1215     variables.insert(symbol.first);
1216   }
1217 
1218   for (auto& variable : variables)
1219   {
1220     // check if variable exists in scalars
1221     for (size_t j = 0; j < this->UsedScalarVariableNames.size(); ++j)
1222     {
1223       if (variable == this->UsedScalarVariableNames[j])
1224       {
1225         this->ScalarVariableNeeded[j] = true;
1226         break;
1227       }
1228     }
1229 
1230     // check if variable exists in vectors
1231     for (size_t j = 0; j < this->UsedVectorVariableNames.size(); ++j)
1232     {
1233       if (variable == this->UsedVectorVariableNames[j])
1234       {
1235         this->VectorVariableNeeded[j] = true;
1236         break;
1237       }
1238     }
1239   }
1240 }
1241 
1242 //------------------------------------------------------------------------------
SanitizeName(const char * name)1243 std::string vtkExprTkFunctionParser::SanitizeName(const char* name)
1244 {
1245   if (!name || name[0] == '\0')
1246   {
1247     return std::string();
1248   }
1249 
1250   std::ostringstream cname;
1251   for (size_t cc = 0; name[cc]; cc++)
1252   {
1253     if (isalnum(name[cc]) || name[cc] == '_')
1254     {
1255       cname << name[cc];
1256     }
1257   }
1258   // if first character is not an alphabet, add an 'a' to it.
1259   if (cname.str().empty() || isalpha(cname.str()[0]))
1260   {
1261     return cname.str();
1262   }
1263   else
1264   {
1265     return "a" + cname.str();
1266   }
1267 }
1268 
1269 //------------------------------------------------------------------------------
GetScalarVariableIndex(const std::string & inVariableName)1270 int vtkExprTkFunctionParser::GetScalarVariableIndex(const std::string& inVariableName)
1271 {
1272   for (size_t i = 0; i < this->OriginalScalarVariableNames.size(); ++i)
1273   {
1274     if (this->OriginalScalarVariableNames[i] == inVariableName)
1275     {
1276       return static_cast<int>(i);
1277     }
1278   }
1279   return -1;
1280 }
1281 
1282 //------------------------------------------------------------------------------
GetScalarVariableNeeded(int i)1283 bool vtkExprTkFunctionParser::GetScalarVariableNeeded(int i)
1284 {
1285   if (i < 0 || i >= static_cast<int>(this->ScalarVariableNeeded.size()))
1286   {
1287     return false;
1288   }
1289   return this->ScalarVariableNeeded[i];
1290 }
1291 
1292 //------------------------------------------------------------------------------
GetScalarVariableNeeded(const std::string & inVariableName)1293 bool vtkExprTkFunctionParser::GetScalarVariableNeeded(const std::string& inVariableName)
1294 {
1295   std::vector<std::string>::const_iterator iter =
1296     std::find(this->OriginalScalarVariableNames.begin(), this->OriginalScalarVariableNames.end(),
1297       inVariableName);
1298   if (iter != this->OriginalScalarVariableNames.end())
1299   {
1300     return this->GetScalarVariableNeeded(
1301       static_cast<int>(iter - this->OriginalScalarVariableNames.begin()));
1302   }
1303   else
1304   {
1305     vtkErrorMacro(
1306       "GetScalarVariableNeeded: scalar variable name " << inVariableName << " does not exist");
1307     return false;
1308   }
1309 }
1310 
1311 //------------------------------------------------------------------------------
GetVectorVariableIndex(const std::string & inVariableName)1312 int vtkExprTkFunctionParser::GetVectorVariableIndex(const std::string& inVariableName)
1313 {
1314   for (size_t i = 0; i < this->OriginalVectorVariableNames.size(); i++)
1315   {
1316     if (this->OriginalVectorVariableNames[i] == inVariableName)
1317     {
1318       return static_cast<int>(i);
1319     }
1320   }
1321   return -1;
1322 }
1323 
1324 //------------------------------------------------------------------------------
GetVectorVariableNeeded(int i)1325 bool vtkExprTkFunctionParser::GetVectorVariableNeeded(int i)
1326 {
1327   if (i < 0 || i >= static_cast<int>(this->VectorVariableNeeded.size()))
1328   {
1329     return false;
1330   }
1331   return this->VectorVariableNeeded[i];
1332 }
1333 
1334 //------------------------------------------------------------------------------
GetVectorVariableNeeded(const std::string & inVariableName)1335 bool vtkExprTkFunctionParser::GetVectorVariableNeeded(const std::string& inVariableName)
1336 {
1337   std::vector<std::string>::const_iterator iter =
1338     std::find(this->OriginalVectorVariableNames.begin(), this->OriginalVectorVariableNames.end(),
1339       inVariableName);
1340   if (iter != this->OriginalVectorVariableNames.end())
1341   {
1342     return this->GetVectorVariableNeeded(
1343       static_cast<int>(iter - this->OriginalVectorVariableNames.begin()));
1344   }
1345   else
1346   {
1347     vtkErrorMacro(
1348       "GetVectorVariableNeeded: scalar variable name " << inVariableName << " does not exist");
1349     return false;
1350   }
1351 }
1352