USGS

Isis 3.0 Object Programmers' Reference

Home

Calculator.cpp
Go to the documentation of this file.
1 
23 #include <cmath>
24 
25 #include <QStack>
26 #include <QVector>
27 
28 #include "Calculator.h"
29 #include "InfixToPostfix.h"
30 #include "IException.h"
31 #include "SpecialPixel.h"
32 
33 using namespace std;
34 
35 namespace Isis {
51  double NegateOperator(double a) {
52  return -1 * a;
53  }
54 
55 
64  double MultiplyOperator(double a, double b) {
65  return a * b;
66  }
67 
68 
77  double DivideOperator(double a, double b) {
78  return a / b;
79  }
80 
81 
90  double AddOperator(double a, double b) {
91  return a + b;
92  }
93 
94 
103  double SubtractOperator(double a, double b) {
104  return a - b;
105  }
106 
107 
116  double GreaterThanOperator(double a, double b) {
117  return a > b ? 1.0 : 0.0;
118  }
119 
120 
129  double LessThanOperator(double a, double b) {
130  return a < b ? 1.0 : 0.0;
131  }
132 
133 
142  double EqualOperator(double a, double b) {
143  return a == b ? 1.0 : 0.0;
144  }
145 
146 
155  double GreaterThanOrEqualOperator(double a, double b) {
156  return a >= b ? 1.0 : 0.0;
157  }
158 
159 
168  double LessThanOrEqualOperator(double a, double b) {
169  return a <= b ? 1.0 : 0.0;
170  }
171 
172 
181  double NotEqualOperator(double a, double b) {
182  return a != b ? 1.0 : 0.0;
183  }
184 
185 
193  double CosecantOperator(double a) {
194  return 1.0 / sin(a);
195  }
196 
197 
205  double SecantOperator(double a) {
206  return 1.0 / cos(a);
207  }
208 
216  double CotangentOperator(double a) {
217  return 1.0 / tan(a);
218  }
219 
220 
228  int Round(double a) {
229  return (a > 0) ? (int)(a + 0.5) : (int)(a - 0.5);
230  }
231 
232 
241  double BitwiseAndOperator(double a, double b) {
242  return (double)(Round(a)&Round(b));
243  }
244 
245 
254  double BitwiseOrOperator(double a, double b) {
255  return (double)(Round(a) | Round(b));
256  }
257 
258 
267  double ModulusOperator(double a, double b) {
268  return (double)(Round(a) % Round(b));
269  }
270 
279  double MaximumOperator(double a, double b) {
280 
281  if (isnan(a)) return (a);
282  if (isnan(b)) return (b);
283  return (a > b) ? a : b;
284  }
285 
294  double MinimumOperator(double a, double b) {
295  if (isnan(a)) return (a);
296  if (isnan(b)) return (b);
297  return (a < b) ? a : b;
298  }
299 
300 
302  Calculator::Calculator() {
303  p_valStack = NULL;
304 
305  p_valStack = new QStack< QVector<double> >();
306  }
307 
309  Calculator::~Calculator() {
310  if(p_valStack) {
311  delete p_valStack;
312  p_valStack = NULL;
313  }
314  }
315 
316 
320  void Calculator::Negative() {
321  QVector<double> result = Pop();
322  PerformOperation(result, result.begin(), result.end(), NegateOperator);
323  Push(result);
324  }
325 
326 
330  void Calculator::Multiply() {
331  QVector<double> y = Pop();
332  QVector<double> x = Pop();
333  QVector<double> result;
334 
335  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), MultiplyOperator);
336  Push(result);
337  }
338 
339 
343  void Calculator::Add() {
344  QVector<double> y = Pop();
345  QVector<double> x = Pop();
346  QVector<double> result;
347  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), AddOperator);
348  Push(result);
349  }
350 
351 
355  void Calculator::Subtract() {
356  QVector<double> y = Pop();
357  QVector<double> x = Pop();
358  QVector<double> result;
359  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), SubtractOperator);
360  Push(result);
361  }
362 
363 
367  void Calculator::Divide() {
368  QVector<double> y = Pop();
369  QVector<double> x = Pop();
370  QVector<double> result;
371 
372  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), DivideOperator);
373  Push(result);
374  }
375 
379  void Calculator::Modulus() {
380  QVector<double> y = Pop();
381  QVector<double> x = Pop();
382  QVector<double> result;
383 
384  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), ModulusOperator);
385  Push(result);
386  }
387 
388 
395  void Calculator::Exponent() {
396  QVector<double> exponent = Pop();
397  QVector<double> x = Pop();
398  QVector<double> result;
399 
400  PerformOperation(result, x.begin(), x.end(), exponent.begin(), exponent.end(), pow);
401  Push(result);
402  }
403 
404 
410  void Calculator::SquareRoot() {
411  QVector<double> result = Pop();
412  PerformOperation(result, result.begin(), result.end(), sqrt);
413  Push(result);
414  }
415 
416 
420  void Calculator::AbsoluteValue() {
421  QVector<double> result = Pop();
422  PerformOperation(result, result.begin(), result.end(), fabs);
423  Push(result);
424  }
425 
426 
432  void Calculator::Log() {
433  QVector<double> result = Pop();
434  PerformOperation(result, result.begin(), result.end(), log);
435  Push(result);
436  }
437 
438 
442  void Calculator::Log10() {
443  QVector<double> result = Pop();
444  PerformOperation(result, result.begin(), result.end(), log10);
445  Push(result);
446  }
447 
448 
454  void Calculator::LeftShift() {
455  QVector<double> y = Pop();
456  if(y.size() != 1) {
457  IString msg = "When trying to do a left shift calculation, a non-scalar "
458  "shift value was encountered. Shifting requires scalars.";
459  throw IException(IException::Unknown, msg, _FILEINFO_);
460  }
461  else {
462  QVector<double> x = Pop();
463 
464  if((int)y[0] > (int)x.size()) {
465  IString msg = "When trying to do a left shift calculation, a shift "
466  "value greater than the data size was encountered. "
467  "Shifting by this value would erase all of the data.";
468  throw IException(IException::Unknown, msg, _FILEINFO_);
469  }
470  else {
471  QVector<double> result;
472  int shift = (int)y[0];
473  result.resize(x.size());
474 
475  for(int i = 0; i < result.size(); i++) {
476  if(i + shift < x.size() && i + shift >= 0)
477  result[i] = x[i+shift];
478  else
479  result[i] = sqrt(-1.0); // create a NaN
480  }
481 
482  Push(result);
483  }
484  }
485  }
486 
487 
493  void Calculator::RightShift() {
494  QVector<double> y = Pop();
495  if(y.size() != 1) {
496  IString msg = "When trying to do a right shift calculation, a non-scalar "
497  "shift value was encountered. Shifting requires scalars.";
498  throw IException(IException::Unknown, msg, _FILEINFO_);
499  }
500  else {
501  QVector<double> x = Pop();
502 
503  if((int)y[0] > (int)x.size()) {
504  IString msg = "When trying to do a right shift calculation, a shift "
505  "value greater than the data size was encountered. "
506  "Shifting by this value would erase all of the data.";
507  throw IException(IException::Unknown, msg, _FILEINFO_);
508  }
509  else {
510  QVector<double> result;
511  int shift = (int)y[0];
512  result.resize(x.size());
513 
514  for(int i = 0; i < (int)result.size(); i++) {
515  if(i - shift < (int)x.size() && i - shift >= 0) {
516  result[i] = x[i-shift];
517  }
518  else {
519  result[i] = sqrt(-1.0); // create a NaN
520  }
521  }
522 
523  Push(result);
524  }
525  }
526  }
527 
531  void Calculator::MinimumLine() {
532  QVector<double> result = Pop();
533 
534  double minVal = result[0];
535  for(int i = 0; i < result.size(); i++) {
536  if(!IsSpecial(result[i])) {
537  minVal = min(minVal, result[i]);
538  }
539  }
540 
541  result.clear();
542  result.push_back(minVal);
543  Push(result);
544  }
545 
546 
550  void Calculator::MaximumLine() {
551  QVector<double> result = Pop();
552 
553  double maxVal = result[0];
554  for(int i = 0; i < result.size(); i++) {
555  if(!IsSpecial(result[i])) {
556  maxVal = max(maxVal, result[i]);
557  }
558  }
559 
560  result.clear();
561  result.push_back(maxVal);
562  Push(result);
563  }
564 
565 
570  void Calculator::MinimumPixel() {
571  QVector<double> x = Pop();
572  QVector<double> y = Pop();
573  QVector<double> result;
574 
575  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
577  Push(result);
578  }
579 
580 
585  void Calculator::MaximumPixel() {
586  QVector<double> x = Pop();
587  QVector<double> y = Pop();
588  QVector<double> result;
589 
590  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
592  Push(result);
593  }
594 
595 
600  void Calculator::GreaterThan() {
601  QVector<double> y = Pop();
602  QVector<double> x = Pop();
603  QVector<double> result;
604 
605  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
607  Push(result);
608  }
609 
610 
615  void Calculator::LessThan() {
616  QVector<double> y = Pop();
617  QVector<double> x = Pop();
618  QVector<double> result;
619 
620  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
622  Push(result);
623  }
624 
625 
630  void Calculator::Equal() {
631  QVector<double> y = Pop();
632  QVector<double> x = Pop();
633  QVector<double> result;
634 
635  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
636  EqualOperator);
637  Push(result);
638  }
639 
640 
645  void Calculator::GreaterThanOrEqual() {
646  QVector<double> y = Pop();
647  QVector<double> x = Pop();
648  QVector<double> result;
649 
650  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
652  Push(result);
653  }
654 
655 
660  void Calculator::LessThanOrEqual() {
661  QVector<double> y = Pop();
662  QVector<double> x = Pop();
663  QVector<double> result;
664 
665  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
667  Push(result);
668  }
669 
670 
675  void Calculator::NotEqual() {
676  QVector<double> y = Pop();
677  QVector<double> x = Pop();
678  QVector<double> result;
679 
680  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
682  Push(result);
683  }
684 
685 
686  // Commented out because bitwise ops only work with integers instead of
687  // doubles
688 
692  void Calculator::And() {
693  QVector<double> y = Pop();
694  QVector<double> x = Pop();
695  QVector<double> result;
696 
697  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
699  Push(result);
700  }
701 
702 
706  void Calculator::Or() {
707  QVector<double> y = Pop();
708  QVector<double> x = Pop();
709  QVector<double> result;
710 
711  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(),
713  Push(result);
714  }
715 
716 
720  void Calculator::Sine() {
721  QVector<double> result = Pop();
722  PerformOperation(result, result.begin(), result.end(), sin);
723  Push(result);
724  }
725 
726 
730  void Calculator::Cosine() {
731  QVector<double> result = Pop();
732  PerformOperation(result, result.begin(), result.end(), cos);
733  Push(result);
734  }
735 
736 
740  void Calculator::Tangent() {
741  QVector<double> result = Pop();
742  PerformOperation(result, result.begin(), result.end(), tan);
743  Push(result);
744  }
745 
746 
750  void Calculator::Cosecant() {
751  QVector<double> result = Pop();
752  PerformOperation(result, result.begin(), result.end(), CosecantOperator);
753  Push(result);
754  }
755 
756 
760  void Calculator::Secant() {
761  QVector<double> result = Pop();
762  PerformOperation(result, result.begin(), result.end(), SecantOperator);
763  Push(result);
764  }
765 
766 
770  void Calculator::Cotangent() {
771  QVector<double> result = Pop();
772  PerformOperation(result, result.begin(), result.end(), CotangentOperator);
773  Push(result);
774  }
775 
776 
780  void Calculator::Arcsine() {
781  QVector<double> result = Pop();
782  PerformOperation(result, result.begin(), result.end(), asin);
783  Push(result);
784  }
785 
786 
790  void Calculator::Arccosine() {
791  QVector<double> result = Pop();
792  PerformOperation(result, result.begin(), result.end(), acos);
793  Push(result);
794  }
795 
796 
800  void Calculator::Arctangent() {
801  QVector<double> result = Pop();
802  PerformOperation(result, result.begin(), result.end(), atan);
803  Push(result);
804  }
805 
806 
810  void Calculator::ArcsineH() {
811  QVector<double> result = Pop();
812  PerformOperation(result, result.begin(), result.end(), asinh);
813  Push(result);
814  }
815 
816 
820  void Calculator::ArccosineH() {
821  QVector<double> result = Pop();
822  PerformOperation(result, result.begin(), result.end(), acosh);
823  Push(result);
824  }
825 
826 
830  void Calculator::ArctangentH() {
831  QVector<double> result = Pop();
832  PerformOperation(result, result.begin(), result.end(), atanh);
833  Push(result);
834  }
835 
836 
840  void Calculator::Arctangent2() {
841  QVector<double> y = Pop();
842  QVector<double> x = Pop();
843  QVector<double> result;
844 
845  PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), atan2);
846  Push(result);
847  }
848 
849 
853  void Calculator::SineH() {
854  QVector<double> result = Pop();
855  PerformOperation(result, result.begin(), result.end(), sinh);
856  Push(result);
857  }
858 
859 
863  void Calculator::CosineH() {
864  QVector<double> result = Pop();
865  PerformOperation(result, result.begin(), result.end(), cosh);
866  Push(result);
867  }
868 
869 
873  void Calculator::TangentH() {
874  QVector<double> result = Pop();
875  PerformOperation(result, result.begin(), result.end(), tanh);
876  Push(result);
877  }
878 
879 
880  // Stack methods
881 
883  int Calculator::StackSize() {
884  return p_valStack->size();
885  }
886 
892  void Calculator::Push(QVector<double> &vect) {
893  p_valStack->push(vect);
894  }
895 
896 
902  void Calculator::Push(double scalar) {
903  QVector<double> s;
904  s.push_back(scalar);
905  Push(s);
906  }
907 
908 
914  void Calculator::Push(Buffer &buff) {
915  QVector<double> b(buff.size());
916 
917  for(int i = 0; i < buff.size(); i++) {
918  // Test for special pixels and map them to valid values
919  if(IsSpecial(buff[i])) {
920  if(Isis::IsNullPixel(buff[i])) {
921  //b[i] = NAN;
922  b[i] = sqrt(-1.0);
923  }
924  else if(Isis::IsHrsPixel(buff[i])) {
925  //b[i] = INFINITY;
926  b[i] = DBL_MAX * 2;
927  }
928  else if(Isis::IsHisPixel(buff[i])) {
929  //b[i] = INFINITY;
930  b[i] = DBL_MAX * 2;
931  }
932  else if(Isis::IsLrsPixel(buff[i])) {
933  //b[i] = -INFINITY;
934  b[i] = -DBL_MAX * 2;
935  }
936  else if(Isis::IsLisPixel(buff[i])) {
937  //b[i] = -INFINITY;
938  b[i] = -DBL_MAX * 2;
939  }
940  }
941  else
942  b[i] = buff[i];
943  }
944 
945  Push(b);
946  }
947 
948 
958  QVector<double> Calculator::Pop(bool keepSpecials) {
959  QVector<double> top;
960 
961  if(p_valStack->empty()) {
962  IString msg = "Math calculator stack is empty, cannot perform any "
963  "more operations.";
964  throw IException(IException::Unknown, msg, _FILEINFO_);
965  }
966 
967  top = p_valStack->top();
968 
969  if(keepSpecials) {
970  for(int i = 0; i < (int)top.size(); i++) {
971  if(isnan(top[i])) {
972  top[i] = Isis::Null;
973  }
974  // Test for +INFINITY
975  else if(top[i] > DBL_MAX) {
976  top[i] = Isis::Hrs;
977  }
978  // Test for -INFINITY)
979  else if(top[i] < -DBL_MAX) {
980  top[i] = Isis::Lrs;
981  }
982  else {
983  // Do nothing
984  }
985  }
986  }
987 
988  p_valStack->pop();
989 
990 
991  return top;
992  }
993 
994 
998  void Calculator::PrintTop() {
999  if(p_valStack->empty()) return;
1000 
1001  std::cout << "[ ";
1002  QVector<double> top = p_valStack->top();
1003  for(int i = 0; i < (int)top.size(); i++) {
1004  std::cout << top[i] << " ";
1005  }
1006  std::cout << "]" << std::endl;
1007  }
1008 
1009 
1015  bool Calculator::Empty() {
1016  return p_valStack->empty();
1017  }
1018 
1019 
1023  void Calculator::Clear() {
1024  while(!p_valStack->empty()) {
1025  p_valStack->pop();
1026  }
1027  }
1028 
1029 
1039  void Calculator::PerformOperation(QVector<double> &results,
1040  QVector<double>::iterator arg1Start,
1041  QVector<double>::iterator arg1End,
1042  double operation(double)) {
1043  results.resize(arg1End - arg1Start);
1044 
1045  for(int pos = 0; pos < results.size(); pos++) {
1046  results[pos] = operation(*arg1Start);
1047 
1048  arg1Start++;
1049  }
1050  }
1051 
1052 
1068  void Calculator::PerformOperation(QVector<double> &results,
1069  QVector<double>::iterator arg1Start,
1070  QVector<double>::iterator arg1End,
1071  QVector<double>::iterator arg2Start,
1072  QVector<double>::iterator arg2End,
1073  double operation(double, double)) {
1074  if(arg1End - arg1Start != 1 && arg2End - arg2Start != 1 &&
1075  arg1End - arg1Start != arg2End - arg2Start) {
1076  IString msg = "The stack based calculator cannot operate on vectors "
1077  "of differing sizes.";
1078  throw IException(IException::Programmer, msg, _FILEINFO_);
1079  }
1080 
1081  int iSize = max(arg1End - arg1Start, arg2End - arg2Start);
1082  results.resize(iSize);
1083 
1084  for(int pos = 0; pos < results.size(); pos++) {
1085  results[pos] = operation(*arg1Start, *arg2Start);
1086 
1087  if(arg1Start + 1 != arg1End) arg1Start++;
1088  if(arg2Start + 1 != arg2End) arg2Start++;
1089  }
1090  }
1091 } // End of namespace Isis