Isis 3 Programmer Reference
Calculator.cpp
Go to the documentation of this file.
1 
23 #include <cmath>
24 
25 #include <QRegExp>
26 #include <QStack>
27 #include <QVector>
28 
29 #include "Calculator.h"
30 #include "InfixToPostfix.h"
31 #include "IException.h"
32 #include "SpecialPixel.h"
33 
34 using namespace std;
35 
36 namespace Isis {
46  Calculator::Calculator() {
48  p_valStack = NULL;
49 
50  p_valStack = new QStack< QVector<double> >();
51  }
52 
54  Calculator::~Calculator() {
55  if (p_valStack) {
56  delete p_valStack;
57  p_valStack = NULL;
58  }
59  }
60 
68  double NegateOperator(double a) {
69  return -1 * a;
70  }
71 
72 
81  double MultiplyOperator(double a, double b) {
82  return a * b;
83  }
84 
85 
94  double DivideOperator(double a, double b) {
95  return a / b;
96  }
97 
98 
107  double AddOperator(double a, double b) {
108  return a + b;
109  }
110 
111 
120  double SubtractOperator(double a, double b) {
121  return a - b;
122  }
123 
124 
133  double GreaterThanOperator(double a, double b) {
134  return a > b ? 1.0 : 0.0;
135  }
136 
137 
146  double LessThanOperator(double a, double b) {
147  return a < b ? 1.0 : 0.0;
148  }
149 
150 
159  double EqualOperator(double a, double b) {
160  return a == b ? 1.0 : 0.0;
161  }
162 
163 
172  double GreaterThanOrEqualOperator(double a, double b) {
173  return a >= b ? 1.0 : 0.0;
174  }
175 
176 
185  double LessThanOrEqualOperator(double a, double b) {
186  return a <= b ? 1.0 : 0.0;
187  }
188 
189 
198  double NotEqualOperator(double a, double b) {
199  return a != b ? 1.0 : 0.0;
200  }
201 
202 
210  double CosecantOperator(double a) {
211  return 1.0 / sin(a);
212  }
213 
214 
222  double SecantOperator(double a) {
223  return 1.0 / cos(a);
224  }
225 
233  double CotangentOperator(double a) {
234  return 1.0 / tan(a);
235  }
236 
237 
245  int Round(double a) {
246  return (a > 0) ? (int)(a + 0.5) : (int)(a - 0.5);
247  }
248 
249 
258  double BitwiseAndOperator(double a, double b) {
259  return (double)(Round(a)&Round(b));
260  }
261 
262 
271  double BitwiseOrOperator(double a, double b) {
272  return (double)(Round(a) | Round(b));
273  }
274 
275 
284  double ModulusOperator(double a, double b) {
285  return (double)(Round(a) % Round(b));
286  }
287 
296  double MaximumOperator(double a, double b) {
297 
298  if (std::isnan(a)) return (a);
299  if (std::isnan(b)) return (b);
300  return (a > b) ? a : b;
301  }
302 
311  double MinimumOperator(double a, double b) {
312  if (std::isnan(a)) return (a);
313  if (std::isnan(b)) return (b);
314  return (a < b) ? a : b;
315  }
316 
317 
318 
322  void Calculator::Negative() {
323  QVector<double> result = Pop();
324  PerformOperation(result, result.begin(), result.end(), NegateOperator);
325  Push(result);
326  }
327 
328 
332  void Calculator::Multiply() {
333  QVector<double> y = Pop();
334  QVector<double> x = Pop();
335  QVector<double> result;
336 
337  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), MultiplyOperator);
338  Push(result);
339  }
340 
341 
345  void Calculator::Add() {
346  QVector<double> y = Pop();
347  QVector<double> x = Pop();
348  QVector<double> result;
349  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), AddOperator);
350  Push(result);
351  }
352 
353 
357  void Calculator::Subtract() {
358  QVector<double> y = Pop();
359  QVector<double> x = Pop();
360  QVector<double> result;
361  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), SubtractOperator);
362  Push(result);
363  }
364 
365 
369  void Calculator::Divide() {
370  QVector<double> y = Pop();
371  QVector<double> x = Pop();
372  QVector<double> result;
373 
374  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), DivideOperator);
375  Push(result);
376  }
377 
381  void Calculator::Modulus() {
382  QVector<double> y = Pop();
383  QVector<double> x = Pop();
384  QVector<double> result;
385 
386  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), ModulusOperator);
387  Push(result);
388  }
389 
390 
397  void Calculator::Exponent() {
398  QVector<double> exponent = Pop();
399  QVector<double> x = Pop();
400  QVector<double> result;
401 
402  PerformOperation(result, x.begin(), x.end(), exponent.begin(), exponent.end(), pow);
403  Push(result);
404  }
405 
406 
412  void Calculator::SquareRoot() {
413  QVector<double> result = Pop();
414  PerformOperation(result, result.begin(), result.end(), sqrt);
415  Push(result);
416  }
417 
418 
422  void Calculator::AbsoluteValue() {
423  QVector<double> result = Pop();
424  PerformOperation(result, result.begin(), result.end(), fabs);
425  Push(result);
426  }
427 
428 
434  void Calculator::Log() {
435  QVector<double> result = Pop();
436  PerformOperation(result, result.begin(), result.end(), log);
437  Push(result);
438  }
439 
440 
444  void Calculator::Log10() {
445  QVector<double> result = Pop();
446  PerformOperation(result, result.begin(), result.end(), log10);
447  Push(result);
448  }
449 
450 
456  void Calculator::LeftShift() {
457  QVector<double> y = Pop();
458  if (y.size() != 1) {
459  IString msg = "When trying to do a left shift calculation, a non-scalar "
460  "shift value was encountered. Shifting requires scalars.";
461  throw IException(IException::Unknown, msg, _FILEINFO_);
462  }
463  else {
464  QVector<double> x = Pop();
465 
466  if ((int)y[0] > (int)x.size()) {
467  IString msg = "When trying to do a left shift calculation, a shift "
468  "value greater than the data size was encountered. "
469  "Shifting by this value would erase all of the data.";
470  throw IException(IException::Unknown, msg, _FILEINFO_);
471  }
472  else {
473  QVector<double> result;
474  int shift = (int)y[0];
475  result.resize(x.size());
476 
477  for (int i = 0; i < result.size(); i++) {
478  if (i + shift < x.size() && i + shift >= 0)
479  result[i] = x[i+shift];
480  else
481  result[i] = sqrt(-1.0); // create a NaN
482  }
483 
484  Push(result);
485  }
486  }
487  }
488 
489 
495  void Calculator::RightShift() {
496  QVector<double> y = Pop();
497  if (y.size() != 1) {
498  IString msg = "When trying to do a right shift calculation, a non-scalar "
499  "shift value was encountered. Shifting requires scalars.";
500  throw IException(IException::Unknown, msg, _FILEINFO_);
501  }
502  else {
503  QVector<double> x = Pop();
504 
505  if ((int)y[0] > (int)x.size()) {
506  IString msg = "When trying to do a right shift calculation, a shift "
507  "value greater than the data size was encountered. "
508  "Shifting by this value would erase all of the data.";
509  throw IException(IException::Unknown, msg, _FILEINFO_);
510  }
511  else {
512  QVector<double> result;
513  int shift = (int)y[0];
514  result.resize(x.size());
515 
516  for (int i = 0; i < (int)result.size(); i++) {
517  if (i - shift < (int)x.size() && i - shift >= 0) {
518  result[i] = x[i-shift];
519  }
520  else {
521  result[i] = sqrt(-1.0); // create a NaN
522  }
523  }
524 
525  Push(result);
526  }
527  }
528  }
529 
533  void Calculator::MinimumLine() {
534  QVector<double> result = Pop();
535 
536  double minVal = result[0];
537  for (int i = 0; i < result.size(); i++) {
538  if (!IsSpecial(result[i])) {
539  minVal = min(minVal, result[i]);
540  }
541  }
542 
543  result.clear();
544  result.push_back(minVal);
545  Push(result);
546  }
547 
548 
552  void Calculator::MaximumLine() {
553  QVector<double> result = Pop();
554 
555  double maxVal = result[0];
556  for (int i = 0; i < result.size(); i++) {
557  if (!IsSpecial(result[i])) {
558  maxVal = max(maxVal, result[i]);
559  }
560  }
561 
562  result.clear();
563  result.push_back(maxVal);
564  Push(result);
565  }
566 
567 
572  void Calculator::MinimumPixel() {
573  QVector<double> x = Pop();
574  QVector<double> y = Pop();
575  QVector<double> result;
576 
577  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
579  Push(result);
580  }
581 
582 
587  void Calculator::MaximumPixel() {
588  QVector<double> x = Pop();
589  QVector<double> y = Pop();
590  QVector<double> result;
591 
592  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
594  Push(result);
595  }
596 
597 
602  void Calculator::GreaterThan() {
603  QVector<double> y = Pop();
604  QVector<double> x = Pop();
605  QVector<double> result;
606 
607  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
609  Push(result);
610  }
611 
612 
617  void Calculator::LessThan() {
618  QVector<double> y = Pop();
619  QVector<double> x = Pop();
620  QVector<double> result;
621 
622  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
624  Push(result);
625  }
626 
627 
632  void Calculator::Equal() {
633  QVector<double> y = Pop();
634  QVector<double> x = Pop();
635  QVector<double> result;
636 
637  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
638  EqualOperator);
639  Push(result);
640  }
641 
642 
647  void Calculator::GreaterThanOrEqual() {
648  QVector<double> y = Pop();
649  QVector<double> x = Pop();
650  QVector<double> result;
651 
652  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
654  Push(result);
655  }
656 
657 
662  void Calculator::LessThanOrEqual() {
663  QVector<double> y = Pop();
664  QVector<double> x = Pop();
665  QVector<double> result;
666 
667  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
669  Push(result);
670  }
671 
672 
677  void Calculator::NotEqual() {
678  QVector<double> y = Pop();
679  QVector<double> x = Pop();
680  QVector<double> result;
681 
682  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
684  Push(result);
685  }
686 
687 
688  // Commented out because bitwise ops only work with integers instead of
689  // doubles
690 
694  void Calculator::And() {
695  QVector<double> y = Pop();
696  QVector<double> x = Pop();
697  QVector<double> result;
698 
699  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
701  Push(result);
702  }
703 
704 
708  void Calculator::Or() {
709  QVector<double> y = Pop();
710  QVector<double> x = Pop();
711  QVector<double> result;
712 
713  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
715  Push(result);
716  }
717 
718 
722  void Calculator::Sine() {
723  QVector<double> result = Pop();
724  PerformOperation(result, result.begin(), result.end(), sin);
725  Push(result);
726  }
727 
728 
732  void Calculator::Cosine() {
733  QVector<double> result = Pop();
734  PerformOperation(result, result.begin(), result.end(), cos);
735  Push(result);
736  }
737 
738 
742  void Calculator::Tangent() {
743  QVector<double> result = Pop();
744  PerformOperation(result, result.begin(), result.end(), tan);
745  Push(result);
746  }
747 
748 
752  void Calculator::Cosecant() {
753  QVector<double> result = Pop();
754  PerformOperation(result, result.begin(), result.end(), CosecantOperator);
755  Push(result);
756  }
757 
758 
762  void Calculator::Secant() {
763  QVector<double> result = Pop();
764  PerformOperation(result, result.begin(), result.end(), SecantOperator);
765  Push(result);
766  }
767 
768 
772  void Calculator::Cotangent() {
773  QVector<double> result = Pop();
774  PerformOperation(result, result.begin(), result.end(), CotangentOperator);
775  Push(result);
776  }
777 
778 
782  void Calculator::Arcsine() {
783  QVector<double> result = Pop();
784  PerformOperation(result, result.begin(), result.end(), asin);
785  Push(result);
786  }
787 
788 
792  void Calculator::Arccosine() {
793  QVector<double> result = Pop();
794  PerformOperation(result, result.begin(), result.end(), acos);
795  Push(result);
796  }
797 
798 
802  void Calculator::Arctangent() {
803  QVector<double> result = Pop();
804  PerformOperation(result, result.begin(), result.end(), atan);
805  Push(result);
806  }
807 
808 
812  void Calculator::ArcsineH() {
813  QVector<double> result = Pop();
814  PerformOperation(result, result.begin(), result.end(), asinh);
815  Push(result);
816  }
817 
818 
822  void Calculator::ArccosineH() {
823  QVector<double> result = Pop();
824  PerformOperation(result, result.begin(), result.end(), acosh);
825  Push(result);
826  }
827 
828 
832  void Calculator::ArctangentH() {
833  QVector<double> result = Pop();
834  PerformOperation(result, result.begin(), result.end(), atanh);
835  Push(result);
836  }
837 
838 
842  void Calculator::Arctangent2() {
843  QVector<double> y = Pop();
844  QVector<double> x = Pop();
845  QVector<double> result;
846 
847  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), atan2);
848  Push(result);
849  }
850 
851 
855  void Calculator::SineH() {
856  QVector<double> result = Pop();
857  PerformOperation(result, result.begin(), result.end(), sinh);
858  Push(result);
859  }
860 
861 
865  void Calculator::CosineH() {
866  QVector<double> result = Pop();
867  PerformOperation(result, result.begin(), result.end(), cosh);
868  Push(result);
869  }
870 
871 
875  void Calculator::TangentH() {
876  QVector<double> result = Pop();
877  PerformOperation(result, result.begin(), result.end(), tanh);
878  Push(result);
879  }
880 
881 
882  // Stack methods
883 
889  int Calculator::StackSize() {
890  return p_valStack->size();
891  }
892 
898  void Calculator::Push(QVector<double> &vect) {
899  p_valStack->push(vect);
900  }
901 
902 
908  void Calculator::Push(double scalar) {
909  QVector<double> s;
910  s.push_back(scalar);
911  Push(s);
912  }
913 
914 
920  void Calculator::Push(Buffer &buff) {
921  QVector<double> b(buff.size());
922 
923  for (int i = 0; i < buff.size(); i++) {
924  // Test for special pixels and map them to valid values
925  if (IsSpecial(buff[i])) {
926  if (Isis::IsNullPixel(buff[i])) {
927  //b[i] = NAN;
928  b[i] = sqrt(-1.0);
929  }
930  else if (Isis::IsHrsPixel(buff[i])) {
931  //b[i] = INFINITY;
932  b[i] = DBL_MAX * 2;
933  }
934  else if (Isis::IsHisPixel(buff[i])) {
935  //b[i] = INFINITY;
936  b[i] = DBL_MAX * 2;
937  }
938  else if (Isis::IsLrsPixel(buff[i])) {
939  //b[i] = -INFINITY;
940  b[i] = -DBL_MAX * 2;
941  }
942  else if (Isis::IsLisPixel(buff[i])) {
943  //b[i] = -INFINITY;
944  b[i] = -DBL_MAX * 2;
945  }
946  }
947  else
948  b[i] = buff[i];
949  }
950 
951  Push(b);
952  }
953 
954 
964  QVector<double> Calculator::Pop(bool keepSpecials) {
965  QVector<double> top;
966 
967  if (p_valStack->empty()) {
968  IString msg = "Math calculator stack is empty, cannot perform any "
969  "more operations.";
970  throw IException(IException::Unknown, msg, _FILEINFO_);
971  }
972 
973  top = p_valStack->top();
974 
975  if (keepSpecials) {
976  for (int i = 0; i < (int)top.size(); i++) {
977  if (std::isnan(top[i])) {
978  top[i] = Isis::Null;
979  }
980  // Test for +INFINITY
981  else if (top[i] > DBL_MAX) {
982  top[i] = Isis::Hrs;
983  }
984  // Test for -INFINITY)
985  else if (top[i] < -DBL_MAX) {
986  top[i] = Isis::Lrs;
987  }
988  else {
989  // Do nothing
990  }
991  }
992  }
993 
994  p_valStack->pop();
995 
996 
997  return top;
998  }
999 
1000 
1004  void Calculator::PrintTop() {
1005  if (p_valStack->empty()) return;
1006 
1007  QString temp;
1008  temp += "[ ";
1009  QVector<double> top = p_valStack->top();
1010  for (int i = 0; i < (int)top.size(); i++) {
1011  temp += QString::number(top[i]);
1012  temp += " ";
1013  }
1014  temp += "]";
1015  // On some operating systems, -nan was being outputted.
1016  // Because this method is only used as a cout in our tests, we do not
1017  // care about the difference between nan and -nan; they are the same in this case.
1018  temp.replace(QRegExp("-nan"), "nan");
1019  std::cout<<temp<<std::endl;
1020  }
1021 
1022 
1028  bool Calculator::Empty() {
1029  return p_valStack->empty();
1030  }
1031 
1032 
1036  void Calculator::Clear() {
1037  while (!p_valStack->empty()) {
1038  p_valStack->pop();
1039  }
1040  }
1041 
1042 
1052  void Calculator::PerformOperation(QVector<double> &results,
1053  QVector<double>::iterator arg1Start,
1054  QVector<double>::iterator arg1End,
1055  double operation(double)) {
1056  results.resize(arg1End - arg1Start);
1057 
1058  for (int pos = 0; pos < results.size(); pos++) {
1059  results[pos] = operation(*arg1Start);
1060 
1061  arg1Start++;
1062  }
1063  }
1064 
1065 
1081  void Calculator::PerformOperation(QVector<double> &results,
1082  QVector<double>::iterator arg1Start,
1083  QVector<double>::iterator arg1End,
1084  QVector<double>::iterator arg2Start,
1085  QVector<double>::iterator arg2End,
1086  double operation(double, double)) {
1087  if (arg1End - arg1Start != 1 && arg2End - arg2Start != 1 &&
1088  arg1End - arg1Start != arg2End - arg2Start) {
1089  IString msg = "The stack based calculator cannot operate on vectors "
1090  "of differing sizes.";
1091  throw IException(IException::Programmer, msg, _FILEINFO_);
1092  }
1093 
1094  int iSize = max(arg1End - arg1Start, arg2End - arg2Start);
1095  results.resize(iSize);
1096 
1097  for (int pos = 0; pos < results.size(); pos++) {
1098  results[pos] = operation(*arg1Start, *arg2Start);
1099 
1100  if (arg1Start + 1 != arg1End) arg1Start++;
1101  if (arg2Start + 1 != arg2End) arg2Start++;
1102  }
1103  }
1104 } // End of namespace Isis
double MinimumOperator(double a, double b)
Returns the min of a and b.
Definition: Calculator.cpp:311
Buffer for reading and writing cube data.
Definition: Buffer.h:69
double BitwiseAndOperator(double a, double b)
Returns the result of a bitwise AND accross a and b.
Definition: Calculator.cpp:258
bool IsLisPixel(const double d)
Returns if the input pixel is low instrument saturation.
Definition: SpecialPixel.h:310
double CosecantOperator(double a)
Returns the cosecant of the input a.
Definition: Calculator.cpp:210
double SecantOperator(double a)
Returns the secant of the input a.
Definition: Calculator.cpp:222
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
double LessThanOperator(double a, double b)
Returns 1.0 if a is less than b.
Definition: Calculator.cpp:146
bool IsLrsPixel(const double d)
Returns if the input pixel is low representation saturation.
Definition: SpecialPixel.h:322
double DivideOperator(double a, double b)
Returns the result of dividing a by b.
Definition: Calculator.cpp:94
Namespace for the standard library.
bool IsHisPixel(const double d)
Returns if the input pixel is high instrument saturation.
Definition: SpecialPixel.h:298
double CotangentOperator(double a)
Returns the cotangent of the input a.
Definition: Calculator.cpp:233
bool IsHrsPixel(const double d)
Returns if the input pixel is high representation saturation.
Definition: SpecialPixel.h:286
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:113
double BitwiseOrOperator(double a, double b)
Returns the result of a bitwise OR across a and b.
Definition: Calculator.cpp:271
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
double GreaterThanOrEqualOperator(double a, double b)
Returns 1.0 if a is greater than or equal to b.
Definition: Calculator.cpp:172
double ModulusOperator(double a, double b)
Returns the modulus of a by b.
Definition: Calculator.cpp:284
int Round(double a)
Returns the result of rounding the input a to the closest integer.
Definition: Calculator.cpp:245
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
double LessThanOrEqualOperator(double a, double b)
Returns 1.0 if a is less than or eqaul to b.
Definition: Calculator.cpp:185
double NegateOperator(double a)
Returns the nagative of the input parameter.
Definition: Calculator.cpp:68
double AddOperator(double a, double b)
Returns the result of additing a with b.
Definition: Calculator.cpp:107
double EqualOperator(double a, double b)
Returns 1.0 if a is equal ot b.
Definition: Calculator.cpp:159
double MultiplyOperator(double a, double b)
Returns the result of a multiplied by b.
Definition: Calculator.cpp:81
double MaximumOperator(double a, double b)
Returns the max of a and b.
Definition: Calculator.cpp:296
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool IsNullPixel(const double d)
Returns if the input pixel is null.
Definition: SpecialPixel.h:250
double NotEqualOperator(double a, double b)
Returns 1.0 is a is not equal to b.
Definition: Calculator.cpp:198
const double Lrs
Value for an Isis Low Representation Saturation pixel.
Definition: SpecialPixel.h:114
double SubtractOperator(double a, double b)
Returns the result of subtracting b from a.
Definition: Calculator.cpp:120
double GreaterThanOperator(double a, double b)
Returns 1.0 if a is greater than b.
Definition: Calculator.cpp:133
const double Hrs
Value for an Isis High Representation Saturation pixel.
Definition: SpecialPixel.h:132