Isis 3.0 Programmer Reference
Back | Home
InlineCalculator.cpp
Go to the documentation of this file.
1 
24 #include "InlineCalculator.h"
25 
26 // std library
27 #include <cmath>
28 
29 // Qt library
30 #include <QMap>
31 #include <QString>
32 #include <QStringList>
33 #include <QVariant>
34 #include <QVector>
35 
36 // boost library
37 #include <boost/foreach.hpp>
38 
39 // naif library
40 #include <SpiceUsr.h>
41 #include <SpiceZfc.h>
42 #include <SpiceZmc.h>
43 
44 // other ISIS
45 #include "IException.h"
46 #include "InlineInfixToPostfix.h"
47 #include "IString.h"
48 #include "NaifStatus.h"
49 
50 using namespace std;
51 
52 namespace Isis {
53 
58  InlineCalculator::InlineCalculator() : Calculator() {
59  initialize();
60  }
61 
62 
69  InlineCalculator::InlineCalculator(const QString &equation) : Calculator() {
70  initialize();
71  compile(equation);
72  }
73 
74 
79  destruct();
80  }
81 
82 
90  int InlineCalculator::size() const {
91  return (m_functions.size());
92  }
93 
94 
102  QString InlineCalculator::equation() const {
103  return (m_equation);
104  }
105 
106 
123  bool InlineCalculator::compile(const QString &equation) {
124  // Transform equation to postfix order
125 
126  QString tokenOps = toPostfix(equation);
127  tokenOps = tokenOps.simplified();
128 
129  int nerrors = 0;
130  QString error = "Errors parsing inline equation[" + equation + "].";
131  IException errList(IException::User, error, _FILEINFO_);
132 
133  Clear(); // Clear the stack
135  m_functions.clear(); // Clear function list
136 
137  QStringList tokenList = tokenOps.split(" ");
138  while ( !tokenList.isEmpty() ) {
139  QString token = tokenList.takeFirst();
140  if ( !token.isEmpty() ) {
141 
142  // See if the function already exists. Note that scalars and variables
143  // that are already present can safely be reused. New occuring ones are
144  // created fresh!
145  FxTypePtr fx = find(token);
146  if ( 0 != fx ) {
147  m_functions.push_back(fx);
148  }
149  // New scalars and variables will create new unique function objects if
150  // they do not already exist (they would be found above then)
151  else if ( isScalar(token) ) {
152  fx = addFunction(new ParameterFx(token, &InlineCalculator::scalar, this));
153  m_functions.push_back(fx);
154  }
155  else if ( isVariable(token) ) {
156  // Will also get line, sample, band, etc...
157  fx = addFunction(new ParameterFx(token, &InlineCalculator::variable, this));
158  m_functions.push_back(fx);
159  }
160  else {
161  // Parameter not recognized during compile. All unknown tokens are
162  // assumed to be variables until run time when they are searched for
163  // in the current state of the resource pool.
164  try {
165  if ( !orphanTokenHandler(token) ) {
166  error = "Equation element (" + token + ") invalid - token not recognized.";
167  errList.append(IException(IException::User, error, _FILEINFO_));
168  nerrors++;
169  }
170  }
171  // Catch all failures from orphaned tokens
172  catch (IException &e) {
173  errList.append(e);
174  nerrors++;
175  }
176  }
177  }
178  }
179 
180  // Might want to make this optional here
181  if (nerrors > 0) {
182  throw errList;
183  }
184  return (nerrors == 0);
185  }
186 
187 
205  QVector<double> value;
206  try {
207  pushVariables(variablePool);
208  value = evaluate();
209  popVariables();
210  }
211  catch (IException &ie) {
212  popVariables();
214  "Calculation with variable pool failed.",
215  _FILEINFO_);
216  }
217  return (value);
218  }
219 
220 
236 
237  BOOST_FOREACH (FxTypePtr function, m_functions) {
238  function->execute();
239  }
240 
241  if (StackSize() != 1) {
242  QString msg = "Too many operands in the equation [" + m_equation + "].";
244  }
245 
246  return (Pop(true));
247  }
248 
249 
258  QString InlineCalculator::toPostfix(const QString &equation) const {
259  InlineInfixToPostfix parser;
260  return (parser.convert(equation));
261  }
262 
263 
272  bool InlineCalculator::isScalar(const QString &scalar) {
273  if (scalar.isEmpty()) return (false);
274  try {
275  toDouble(scalar);
276  return (true);
277  }
278  catch (IException &e) {
279  return (false);
280  }
281  }
282 
283 
292  bool InlineCalculator::isVariable(const QString &str) {
293  if (str.isEmpty()) {
294  return (false);
295  }
296  if (!isScalar(str)) {
297  return (true);
298  }
299  return (false);
300  }
301 
302 
311  void InlineCalculator::scalar(const QVariant &scalar) {
312  Push(toDouble(scalar.toString()));
313  }
314 
315 
326  void InlineCalculator::variable(const QVariant &variable) {
327  CalculatorVariablePool *variablePool = variables();
328  QString key = variable.toString();
329  if (variablePool->exists(key)) {
330  QVector<double> values = variablePool->value(key);
331  Push(values);
332  return;
333  }
334 
335  // Error!
336  QString error = "Could not find variable [" + key + "] in variable pool.";
337  throw IException(IException::User, error, _FILEINFO_);
338  }
339 
340 
352  double floatModulusOperator(double a, double b) {
353  return (fmod(a, b));
354  }
355 
356 
363  QVector<double> y = Pop();
364  QVector<double> x = Pop();
365  QVector<double> result;
366  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
368  Push(result);
369  return;
370  }
371 
372 
378  QVector<double> degree = Pop();
379  QVector<double> result;
380  BOOST_FOREACH(double d, degree) {
381  result.push_back(d * rpd_c());
382  }
383  Push(result);
384  return;
385  }
386 
387 
394  QVector<double> result;
395  BOOST_FOREACH(double r, radians) {
396  result.push_back(r * dpr_c());
397  }
398  Push(result);
399  return;
400  }
401 
402 
407  Push(pi_c());
408  return;
409  }
410 
411 
416  Push(E);
417  return;
418  }
419 
420 
430  bool InlineCalculator::fxExists(const QString &fxname) const {
431  return (m_fxPool.contains(fxname));
432  }
433 
434 
448  FxTypePtr func = find(function->name());
449  if (!func) {
450  m_fxPool.insert(function->name(), function);
451  }
452  else {
453  QString msg = "Function operator [" + function->name() +
454  "] exists! Cannot replace existing functions in the pool :-(";
456  }
457  return (function);
458  }
459 
460 
481  bool InlineCalculator::orphanTokenHandler(const QString &token) {
482  return (false);
483  }
484 
485 
493  m_variablePoolList.push_back(variablePool);
494  return;
495  }
496 
497 
506  if ( !m_variablePoolList.isEmpty() ) {
507  return (m_variablePoolList.back());
508  }
510  "Request for nonexistent variable pool.",
511  _FILEINFO_);
512  }
513 
514 
519  Clear();
520  if ( !m_variablePoolList.isEmpty() ) {
521  m_variablePoolList.pop_back();
522  }
523  return;
524  }
525 
526 
538  FxPoolType::iterator fx = m_fxPool.find(fxname);
539  if ( m_fxPool.end() == fx ) return NULL;
540  return (*fx);
541  }
542 
543 
548  // Set up calculator function lookup list
549  addFunction(new VoidFx("^", &Calculator::Exponent, this));
550  addFunction(new VoidFx("/", &Calculator::Divide, this));
551  addFunction(new VoidFx("*", &Calculator::Multiply, this));
552  addFunction(new VoidFx("<<", &Calculator::LeftShift, this));
553  addFunction(new VoidFx(">>", &Calculator::RightShift, this));
554  addFunction(new VoidFx("+", &Calculator::Add, this));
555  addFunction(new VoidFx("-", &Calculator::Subtract, this));
556  addFunction(new VoidFx(">", &Calculator::GreaterThan, this));
557  addFunction(new VoidFx("<", &Calculator::LessThan, this));
560  addFunction(new VoidFx("==", &Calculator::Equal, this));
561  addFunction(new VoidFx("!=", &Calculator::NotEqual, this));
562 
563  // These are not part of the Calculator class because InfixToPostfix didn't
564  // add/recognize them in the tokenizer. See InlineInfixToPostfix class which
565  // is part of this calculator.
566  addFunction(new VoidFx("&", &Calculator::And, this));
567  addFunction(new VoidFx("and", &Calculator::And, this));
568  addFunction(new VoidFx("|", &Calculator::Or, this));
569  addFunction(new VoidFx("or", &Calculator::Or, this));
571  addFunction(new VoidFx("mod", &Calculator::Modulus, this));
573 
574  addFunction(new VoidFx("--", &Calculator::Negative, this));
575  addFunction(new VoidFx("neg", &Calculator::Negative, this));
576 
577  addFunction(new VoidFx("min", &Calculator::MinimumPixel, this));
578  addFunction(new VoidFx("max", &Calculator::MaximumPixel, this));
579  addFunction(new VoidFx("abs", &Calculator::AbsoluteValue, this));
580  addFunction(new VoidFx("sqrt", &Calculator::SquareRoot, this));
581  addFunction(new VoidFx("log", &Calculator::Log, this));
582  addFunction(new VoidFx("ln", &Calculator::Log, this));
583  addFunction(new VoidFx("log10", &Calculator::Log10, this));
584  addFunction(new InlineVoidFx("pi", &InlineCalculator::pi, this));
585 
586  addFunction(new VoidFx("sin", &Calculator::Sine, this));
587  addFunction(new VoidFx("cos", &Calculator::Cosine, this));
588  addFunction(new VoidFx("tan", &Calculator::Tangent, this));
589  addFunction(new VoidFx("sec", &Calculator::Secant, this));
590  addFunction(new VoidFx("csc", &Calculator::Cosecant, this));
591  addFunction(new VoidFx("cot", &Calculator::Cotangent, this));
592  addFunction(new VoidFx("asin", &Calculator::Arcsine, this));
593  addFunction(new VoidFx("acos", &Calculator::Arccosine, this));
594  addFunction(new VoidFx("atan", &Calculator::Arctangent, this));
595  addFunction(new VoidFx("atan2", &Calculator::Arctangent2, this));
596 
600 
601  // Add new functions available for inlining
602  // m_variablePoolList = defaultVariables();
603 
604  return;
605  }
606 
607 
613  BOOST_FOREACH (FxTypePtr function, m_fxPool) {
614  delete function;
615  }
616 
617  m_fxPool.clear();
618  m_functions.clear();
619  return;
620  }
621 
622 
627  }
628 
629 
634  }
635 
636 
643  bool CalculatorVariablePool::exists(const QString &variable) const {
644  return (true);
645  }
646 
647 
659  const int &index) const {
660  QString mess = "No implementation in Calculator variable pool to provide "
661  " value for variable [" + variable + "].";
663  }
664 
665 
678  void CalculatorVariablePool::add(const QString &key, QVector<double> &values) {
679  QString mess = "No implementation in Calculator variable pool to add "
680  " value for variable [" + key + "].";
682  }
683 
684 
690  FxBinder::FxBinder(const QString &name) : m_name(name) {
691  }
692 
693 
698  }
699 
700 
706  QString FxBinder::name() const {
707  return (m_name);
708  }
709 
710 
716  dispatch();
717  }
718 
719 
725  dispatch();
726  }
727 
728 
735  QVariant FxBinder::args() {
736  return (QVariant(m_name));
737  }
738 
739 
748  InlineVoidFx::InlineVoidFx(const QString &name, calcOp function,
749  InlineCalculator *calculator) : FxBinder(name),
750  m_func(function),
751  m_calc(calculator) {
752  }
753 
754 
759  }
760 
761 
768  }
769 
770 
782  ParameterFx::ParameterFx(const QString &name, calcOp function,
783  InlineCalculator *calculator) : FxBinder(name),
784  m_func(function),
785  m_calc(calculator){
786  }
787 
788 
793  }
794 
795 
803  }
804 
805 
814  VoidFx::VoidFx(const QString &name, calcOp function,
815  InlineCalculator *calculator) : FxBinder(name),
816  m_func(function),
817  m_calc(calculator) {
818  }
819 
820 
825  }
826 
827 
834  }
835 } // namespace Isis
void LessThanOrEqual()
Pop two elements off the stack and compare them to see where one is less than or equal to the other...
Definition: Calculator.cpp:660
void And()
Pop two elements, AND them, then push the result on the stack.
Definition: Calculator.cpp:692
void Divide()
Pops two, divides them, then pushes the quotient on the stack.
Definition: Calculator.cpp:367
QList< CalculatorVariablePool * > m_variablePoolList
The list of variable pool pointers.
virtual QString toPostfix(const QString &equation) const
Converts the given string from infix to postfix format.
void Multiply()
Pops two elements, multiplies them, then pushes the product on the stack.
Definition: Calculator.cpp:330
void floatModulus()
Pops the top two vectors off the current stack and performs the floatModulusOperator() on the corresp...
void NotEqual()
Pop two elements off the stack and compare them to see where one is not equal to the other...
Definition: Calculator.cpp:675
void GreaterThan()
Pop two elements off the stack and compare them to see where one is greater than the other...
Definition: Calculator.cpp:600
void LeftShift()
Pop the top element, then perform a left shift with zero fill.
Definition: Calculator.cpp:454
CalculatorVariablePool()
Constructs a CalculatorVariablePool object.
void Arctangent()
Pops one element and push the arctangent.
Definition: Calculator.cpp:800
void variable(const QVariant &variable)
Pushes the given value onto the stack as a variable.
void Arctangent2()
Pops two elements and push the arctangent.
Definition: Calculator.cpp:840
virtual void add(const QString &key, QVector< double > &values)
Add a parameter to the variable pool.
const double E(2.7182818284590452354)
Sets some basic constants for use in ISIS programming.
QString m_name
Name of function.
void dispatch()
Calls the function corresponding to this object using its stored InlineCalculator, InlineCalculator operator, and arguments.
This is a simple class to model a Calculator Variable Pool.
virtual ~FxBinder()
Destroys the FxBinder object.
void MinimumPixel()
Pop two elements, then push the minimum on a pixel by pixel basis back on the stack.
Definition: Calculator.cpp:570
FxBinder(const QString &name)
Constructs a function binder given a name.
A parser for converting equation strings to postfix.
void degrees()
Pops the top vector off the current stack and converts from radians to degrees.
void Or()
Pop two elements, OR them, then push the result on the stack.
Definition: Calculator.cpp:706
QString convert(const QString &infix)
This method converts infix to postfix.
void Arccosine()
Pops one element and push the arccosine.
Definition: Calculator.cpp:790
void LessThan()
Pop two elements off the stack and compare them to see where one is less than the other...
Definition: Calculator.cpp:615
InlineCalculator * m_calc
The Calculator used to evaluate this function.
void Modulus()
Pops two elements, mods them, then pushes the result on the stack.
Definition: Calculator.cpp:379
virtual ~InlineCalculator()
Destroys the InlineCalculator object.
void GreaterThanOrEqual()
Pop two elements off the stack and compare them to see where one is greater than or equal to the othe...
Definition: Calculator.cpp:645
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception&#39;s causational exc...
Definition: IException.cpp:425
void Cotangent()
Pops one element and push the cotangent.
Definition: Calculator.cpp:770
bool fxExists(const QString &fxname) const
Determines whether the given function name exists in the current function pool.
QVector< double > Pop(bool keepSpecials=false)
Pop an element off the stack.
Definition: Calculator.cpp:958
Provides a calculator for inline equations.
virtual bool orphanTokenHandler(const QString &token)
Default token handler if it is undefined during parsing/compilation.
FxPoolType m_fxPool
The map between function names and equation lists.
int size() const
Accesses the number of functions, operators, variables, and scalars to be executed.
bool isScalar(const QString &scalar)
Determines whether the given string contains a scalar value (i.e.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:154
void Negative()
Pops an element, negates it, then pushes the result.
Definition: Calculator.cpp:320
void Log()
Pop an element, compute its log, then push the result on the stack.
Definition: Calculator.cpp:432
InlineVoidFx(const QString &name, calcOp function, InlineCalculator *calculator)
Constructs an InlineVoid function from the given name, InlineCalculator operator, and InlineCalculato...
InlineCalculator * m_calc
The InlineCalculator used to evaluate this function.
virtual ~InlineVoidFx()
Destroys the InlineVoidFx object.
void Arcsine()
Pops one element and push the arcsine.
Definition: Calculator.cpp:780
QVector< double > evaluate()
Evaluate compiled equation with existing variable pool.
bool compile(const QString &equation)
Compiles the given equation for evaluation.
void PerformOperation(QVector< double > &results, QVector< double >::iterator arg1Start, QVector< double >::iterator arg1End, double operation(double))
Performs the mathematical operations on each argument.
double floatModulusOperator(double a, double b)
Determines the remainder of the quotient a/b whose sign is the same as that of a. ...
void SquareRoot()
Pop an element, compute its square root, then push the root on the stack.
Definition: Calculator.cpp:410
InlineCalculator * m_calc
The InlineCalculator used to evaluate this function.
void Add()
Pops two elements, adds them, then pushes the sum on the stack.
Definition: Calculator.cpp:343
bool isVariable(const QString &str)
Determines whether the given string is a variable.
void popVariables()
Removes the last variable pool in the current variable pool list.
QString equation() const
Accesses the string representation of the current equation, in postfix format.
virtual QVector< double > value(const QString &variable, const int &index=0) const
Return vector of doubles for Calculator functions.
int StackSize()
Returns the current stack size.
Definition: Calculator.cpp:883
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
This is the parent class to the various function classes.
void Subtract()
Pops two elements, subtracts them, then pushes the difference on the stack.
Definition: Calculator.cpp:355
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:134
void Equal()
Pop two elements off the stack and compare them to see where one is equal to the other, then push the results on the stack.
Definition: Calculator.cpp:630
FxEqList m_functions
The list of pointers to function equations for the calculator.
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:126
virtual ~ParameterFx()
Destroys the ParameterFx object.
This class is used to bind function names with corresponding Calculator functions that do not take pa...
calcOp m_func
The InlineCalculator operator that takes parameters.
void destruct()
Discard of all the function pool and class resources.
void operator()()
Executes the function.
void initialize()
Adds the recognized functions to the function pool.
#define CALL_MEMBER_FN(object, ptrToMember)
Macro for calling member functions.
void Push(double scalar)
Push a scalar onto the stack.
Definition: Calculator.cpp:902
calcOp m_func
The Calculator operator that takes no parameters.
void pushVariables(CalculatorVariablePool *variablePool)
Push the given variable pool onto the current variable pool list.
void pi()
Pushes the PI constant onto the current stack.
void radians()
Pops the top vector off the current stack and converts from degrees to radians.
virtual void Clear()
Clear out the stack.
void AbsoluteValue()
Pop an element, compute its absolute value, then push the result on the stack.
Definition: Calculator.cpp:420
FxTypePtr find(const QString &fxname)
Gets a pointer to the function from the current pool that corresponds to the given function name...
ParameterFx(const QString &name, calcOp function, InlineCalculator *calculator)
Constructs a Parameter function from the given name (containing the appropriate parameters), InlineCalculator operator, and InlineCalculator.
calcOp m_func
The InlineCalculator operator that takes no parameters.
void MaximumPixel()
Pop two elements, then push the maximum on a pixel by pixel basis back on the stack.
Definition: Calculator.cpp:585
QString name() const
The name assigned to this function binder.
void Secant()
Pops one element and push the secant.
Definition: Calculator.cpp:760
This class is used to bind function names with corresponding InlineCalculator functions that do not t...
void Sine()
Pops one element and push the sine.
Definition: Calculator.cpp:720
virtual bool exists(const QString &variable) const
Returns true so the real error can be reported.
void RightShift()
Pop the top element, then perform a right shift with zero fill.
Definition: Calculator.cpp:493
virtual QVariant args()
Accesses the arguments for this function.
void Tangent()
Pops one element and push the tangent.
Definition: Calculator.cpp:740
virtual ~VoidFx()
Destroys the VoidFx object.
void execute()
Executes the function.
void dispatch()
Calls the function corresponding to this object using its stored Calculator and Calculator operator...
Isis exception class.
Definition: IException.h:99
VoidFx(const QString &name, calcOp function, InlineCalculator *calculator)
Constructs a Void function from the given name, Calculator operator, and Calculator.
InlineCalculator()
Constructs an InlineCalculator object by initializing the operator lookup list.
QString m_equation
The equation to be evaluated.
void Cosecant()
Pops one element and push the cosecant.
Definition: Calculator.cpp:750
void eConstant()
Pushes the Euler constant (e) onto the current stack.
virtual void dispatch()=0
This method defines how to execute this function.
FxTypePtr addFunction(FxTypePtr function)
Adds a function to the function pool.
void Log10()
Pop an element, compute its base 10 log, then push the result on the stack.
Definition: Calculator.cpp:442
void Exponent()
Pops two elements, computes the power then pushes the result on the stack The exponent has to be a sc...
Definition: Calculator.cpp:395
~CalculatorVariablePool()
Destroys the CalculatorVariablePool object.
void Cosine()
Pops one element and push the cosine.
Definition: Calculator.cpp:730
void scalar(const QVariant &scalar)
Pushes the given value onto the stack as a scalar.
void dispatch()
Calls the function corresponding to this object using its stored InlineCalculator and InlineCalculato...
This class is used to bind function names with corresponding Calculator functions that take a paramet...
Calculator for arrays.
Definition: Calculator.h:66
CalculatorVariablePool * variables()
Accesses the last variable pool in the current pool list.

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:20:34