USGS

Isis 3.0 Object Programmers' Reference

Home

Calculator.cpp

Go to the documentation of this file.
00001 
00023 #include <cmath>
00024 
00025 #include "ProcessByLine.h"
00026 #include "Calculator.h"
00027 #include "InfixToPostfix.h"
00028 #include "iException.h"
00029 #include "SpecialPixel.h"
00030 
00031 using namespace std;
00032 
00033 namespace Isis {
00049   double NegateOperator(double a) { return -1*a; }
00050 
00051 
00060   double MultiplyOperator(double a, double b) { return a*b; }
00061 
00062 
00071   double DivideOperator(double a, double b) { return a/b; }
00072 
00073 
00082   double AddOperator(double a, double b) { return a+b; }
00083 
00084 
00093   double SubtractOperator(double a, double b) { return a-b; }
00094 
00095 
00104   double GreaterThanOperator(double a, double b) { return a > b ? 1.0 : 0.0; }
00105 
00106 
00115   double LessThanOperator(double a, double b) { return a < b ? 1.0 : 0.0; }
00116 
00117 
00126   double EqualOperator(double a, double b) { return a == b ? 1.0 : 0.0; }
00127 
00128 
00137   double GreaterThanOrEqualOperator(double a, double b) { return a >= b ? 1.0 : 0.0; }
00138 
00139 
00148   double LessThanOrEqualOperator(double a, double b) { return a <= b ? 1.0 : 0.0; }
00149 
00150 
00159   double NotEqualOperator(double a, double b) { return a != b ? 1.0 : 0.0; }
00160 
00161 
00169   double CosecantOperator(double a) { return 1.0 / sin(a); }
00170 
00171 
00179   double SecantOperator(double a) { return 1.0 / cos(a); }
00180 
00188   double CotangentOperator(double a) { return 1.0 / tan(a); }
00189 
00190 
00198   int Round(double a) { return (a>0)? (int)(a+0.5) : (int)(a-0.5); }
00199 
00200 
00209   double BitwiseAndOperator(double a, double b) { return (double)(Round(a)&Round(b)); }
00210 
00211 
00220   double BitwiseOrOperator(double a, double b) { return (double)(Round(a)|Round(b)); }
00221 
00222 
00231   double ModulusOperator(double a, double b) { return (double)(Round(a)%Round(b)); }
00232 
00233 
00235   Calculator::Calculator() {}
00236 
00237 
00241   void Calculator::Negative() {
00242     std::vector<double> result = Pop();
00243     PerformOperation(result, result.begin(), result.end(), NegateOperator);
00244     Push(result);
00245   }
00246 
00247 
00251   void Calculator::Multiply() {
00252     std::vector<double> y = Pop();
00253     std::vector<double> x = Pop();
00254     std::vector<double> result;
00255 
00256     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), MultiplyOperator);
00257     Push(result); 
00258   }
00259 
00260 
00264   void Calculator::Add() { 
00265     std::vector<double> y = Pop(); 
00266     std::vector<double> x = Pop();
00267     std::vector<double> result;
00268     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), AddOperator);
00269     Push(result);
00270   }
00271 
00272 
00276   void Calculator::Subtract() { 
00277     std::vector<double> y = Pop();
00278     std::vector<double> x = Pop();
00279     std::vector<double> result;
00280     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), SubtractOperator);
00281     Push(result);
00282   }
00283 
00284 
00288   void Calculator::Divide() { 
00289     std::vector<double> y = Pop();
00290     std::vector<double> x = Pop();
00291     std::vector<double> result;
00292 
00293     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), DivideOperator);
00294     Push(result);
00295   }
00296 
00300   void Calculator::Modulus() { 
00301     std::vector<double> y = Pop();
00302     std::vector<double> x = Pop();
00303     std::vector<double> result;
00304 
00305     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), ModulusOperator);
00306     Push(result);
00307   }
00308 
00309 
00316   void Calculator::Exponent() {
00317     std::vector<double> exponent = Pop();
00318     std::vector<double> x = Pop();
00319     std::vector<double> result;
00320 
00321     PerformOperation(result, x.begin(), x.end(), exponent.begin(), exponent.end(), pow);
00322     Push(result);
00323   }
00324 
00325 
00331   void Calculator::SquareRoot() {
00332     std::vector<double> result = Pop();
00333     PerformOperation(result, result.begin(), result.end(), sqrt);
00334     Push(result);
00335   }
00336 
00337 
00341   void Calculator::AbsoluteValue() {
00342     std::vector<double> result = Pop();
00343     PerformOperation(result, result.begin(), result.end(), fabs);
00344     Push(result);
00345   }
00346 
00347 
00353   void Calculator::Log() {
00354      std::vector<double> result = Pop();
00355     PerformOperation(result, result.begin(), result.end(), log);
00356     Push(result);
00357   }
00358 
00359 
00363   void Calculator::Log10() {
00364     std::vector<double> result = Pop();
00365     PerformOperation(result, result.begin(), result.end(), log10);
00366     Push(result);
00367   }
00368 
00369 
00375   void Calculator::LeftShift() {
00376     std::vector<double> y = Pop();
00377     if(y.size() != 1) {
00378       std::string msg = "Must use scalars for shifting.";
00379       throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00380     }
00381     else { 
00382       std::vector<double> x = Pop();
00383   
00384       if((int)y[0] > (int)x.size()) { 
00385         std::string msg = "Shift value must be <= to number of samples.";
00386         throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00387       }
00388       else {
00389         std::vector<double> result;
00390         int shift = (int)y[0];
00391         result.resize(x.size());
00392 
00393         for(unsigned int i = 0; i < result.size(); i++) {
00394           if(i+shift < x.size() && i+shift >= 0)
00395             result[i] = x[i+shift];
00396           else
00397             result[i] = sqrt(-1.0); // create a NaN
00398         }
00399 
00400         Push(result);
00401       }
00402     }
00403   }
00404 
00405 
00411   void Calculator::RightShift() {
00412     std::vector<double> y = Pop();
00413     if(y.size() != 1) {
00414       std::string msg = "Must use scalars for shifting.";
00415       throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00416     }
00417     else { 
00418       std::vector<double> x = Pop();
00419   
00420       if((int)y[0] > (int)x.size()) { 
00421         std::string msg = "Shift value must be <= to number of samples.";
00422         throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00423       }
00424       else {
00425         std::vector<double> result;
00426         int shift = (int)y[0];
00427         result.resize(x.size());
00428 
00429         for(int i = 0; i < (int)result.size(); i++) {
00430           if(i-shift < (int)x.size() && i-shift >= 0) {
00431             result[i] = x[i-shift];
00432           }
00433           else {
00434             result[i] = sqrt(-1.0); // create a NaN
00435           }
00436         }
00437 
00438         Push(result);
00439       }
00440     }
00441   }
00442 
00443 
00447   void Calculator::Minimum() {
00448     std::vector<double> result = Pop();
00449 
00450     int size = result.size();
00451     double minVal = result[0];
00452     for(unsigned int i = 0; i < result.size(); i++) minVal = min(minVal, result[i]);
00453 
00454     result.clear();
00455     result.resize(size, minVal);
00456     Push(result);
00457   }
00458 
00459 
00463   void Calculator::Maximum() {
00464     std::vector<double> result = Pop();
00465 
00466     int size = result.size();
00467     double maxVal = result[0];
00468     for(unsigned int i = 0; i < result.size(); i++) maxVal = max(maxVal, result[i]);
00469 
00470     result.clear();
00471     result.resize(size, maxVal);
00472     Push(result);
00473   }
00474 
00475 
00480   void Calculator::GreaterThan() {
00481     std::vector<double> y = Pop();
00482     std::vector<double> x = Pop();
00483     std::vector<double> result;
00484 
00485     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), GreaterThanOperator);
00486     Push(result);
00487   }
00488 
00489 
00494   void Calculator::LessThan() {
00495     std::vector<double> y = Pop();
00496     std::vector<double> x = Pop();
00497     std::vector<double> result;
00498 
00499     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), LessThanOperator);
00500     Push(result);
00501   }
00502 
00503 
00508   void Calculator::Equal() {
00509     std::vector<double> y = Pop();
00510     std::vector<double> x = Pop();
00511     std::vector<double> result;
00512 
00513     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), EqualOperator);
00514     Push(result);
00515   }
00516 
00517 
00522   void Calculator::GreaterThanOrEqual() {
00523     std::vector<double> y = Pop();
00524     std::vector<double> x = Pop();
00525     std::vector<double> result;
00526 
00527     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), GreaterThanOrEqualOperator);
00528     Push(result);
00529   }
00530 
00531 
00536   void Calculator::LessThanOrEqual() {
00537     std::vector<double> y = Pop();
00538     std::vector<double> x = Pop();
00539     std::vector<double> result;
00540 
00541     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), LessThanOrEqualOperator);
00542     Push(result);
00543   }
00544 
00545 
00550   void Calculator::NotEqual() {
00551     std::vector<double> y = Pop();
00552     std::vector<double> x = Pop();
00553     std::vector<double> result;
00554 
00555     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), NotEqualOperator);
00556     Push(result);
00557   }
00558 
00559 
00560   // Commented out because bitwise ops only work with integers instead of doubles
00561 
00565   void Calculator::And() {
00566     std::vector<double> y = Pop();
00567     std::vector<double> x = Pop();
00568     std::vector<double> result;
00569 
00570     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), BitwiseAndOperator);
00571     Push(result);
00572   }
00573 
00574 
00578   void Calculator::Or() {
00579     std::vector<double> y = Pop();
00580     std::vector<double> x = Pop();
00581     std::vector<double> result;
00582 
00583     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), BitwiseOrOperator);
00584     Push(result);
00585   }
00586 
00587 
00591   void Calculator::Sine() { 
00592     std::vector<double> result = Pop();
00593     PerformOperation(result, result.begin(), result.end(), sin);
00594     Push(result);
00595   }
00596 
00597 
00601   void Calculator::Cosine() { 
00602     std::vector<double> result = Pop();
00603     PerformOperation(result, result.begin(), result.end(), cos);
00604     Push(result);
00605   }
00606 
00607 
00611   void Calculator::Tangent() { 
00612     std::vector<double> result = Pop();
00613     PerformOperation(result, result.begin(), result.end(), tan);
00614     Push(result);
00615   }
00616 
00617 
00621   void Calculator::Cosecant() { 
00622     std::vector<double> result = Pop();
00623     PerformOperation(result, result.begin(), result.end(), CosecantOperator);
00624     Push(result);
00625   }
00626 
00627 
00631   void Calculator::Secant() { 
00632     std::vector<double> result = Pop();
00633     PerformOperation(result, result.begin(), result.end(), SecantOperator);
00634     Push(result);
00635   }
00636 
00637 
00641   void Calculator::Cotangent() { 
00642     std::vector<double> result = Pop();
00643     PerformOperation(result, result.begin(), result.end(), CotangentOperator);
00644     Push(result);
00645   }
00646 
00647 
00651   void Calculator::Arcsine() { 
00652     std::vector<double> result = Pop();
00653     PerformOperation(result, result.begin(), result.end(), asin);
00654     Push(result);
00655   }
00656 
00657 
00661   void Calculator::Arccosine() { 
00662     std::vector<double> result = Pop();
00663     PerformOperation(result, result.begin(), result.end(), acos);
00664     Push(result);
00665   }
00666 
00667 
00671   void Calculator::Arctangent() { 
00672     std::vector<double> result = Pop();
00673     PerformOperation(result, result.begin(), result.end(), atan);
00674     Push(result);
00675   }
00676 
00677 
00681   void Calculator::ArcsineH() {
00682     std::vector<double> result = Pop();
00683     PerformOperation(result, result.begin(), result.end(), asinh);
00684     Push(result);
00685   }
00686 
00687 
00691   void Calculator::ArccosineH() {
00692     std::vector<double> result = Pop();
00693     PerformOperation(result, result.begin(), result.end(), acosh);
00694     Push(result);
00695   }
00696 
00697 
00701   void Calculator::ArctangentH() {
00702     std::vector<double> result = Pop();
00703     PerformOperation(result, result.begin(), result.end(), atanh);
00704     Push(result);
00705   }
00706 
00707 
00711   void Calculator::Arctangent2() {
00712     std::vector<double> y = Pop();
00713     std::vector<double> x = Pop();
00714     std::vector<double> result;
00715 
00716     PerformOperation(result, x.begin(), x.end(), y.begin(), y.end(), atan2);
00717     p_valStack.push(result);
00718   }
00719 
00720 
00724   void Calculator::SineH() { 
00725     std::vector<double> result = Pop();
00726     PerformOperation(result, result.begin(), result.end(), sinh);
00727     Push(result);
00728   }
00729 
00730 
00734   void Calculator::CosineH() { 
00735     std::vector<double> result = Pop();
00736     PerformOperation(result, result.begin(), result.end(), cosh);
00737     Push(result);
00738   }
00739 
00740 
00744   void Calculator::TangentH() { 
00745     std::vector<double> result = Pop();
00746     PerformOperation(result, result.begin(), result.end(), tanh);
00747     Push(result);
00748   }
00749 
00750 
00751   // Stack methods
00752 
00758   void Calculator::Push(std::vector<double> &vect) {
00759     p_valStack.push(vect);
00760   }
00761 
00762 
00768   void Calculator::Push(double scalar) {
00769     std::vector<double> s;
00770     s.push_back(scalar);
00771     Push(s);
00772   }
00773 
00774 
00780   void Calculator::Push(Buffer &buff) {
00781     std::vector<double> b(buff.size());
00782   
00783     for(int i = 0; i < buff.size(); i++) {
00784       // Test for special pixels and map them to valid values
00785       if(IsSpecial(buff[i])) { 
00786         if(Isis::IsNullPixel(buff[i])) {
00787           //b[i] = NAN;
00788           b[i] = sqrt(-1.0);
00789         }
00790         else if(Isis::IsHrsPixel(buff[i])) {
00791           //b[i] = INFINITY;
00792           b[i] = DBL_MAX * 2;
00793         }
00794         else if(Isis::IsHisPixel(buff[i])) {
00795           //b[i] = INFINITY;
00796           b[i] = DBL_MAX * 2;
00797         }
00798         else if(Isis::IsLrsPixel(buff[i])) {
00799           //b[i] = -INFINITY;
00800           b[i] = -DBL_MAX * 2;
00801         }
00802         else if(Isis::IsLisPixel(buff[i])) {
00803           //b[i] = -INFINITY;
00804           b[i] = -DBL_MAX * 2;
00805         }
00806       }
00807       else    
00808         b[i] = buff[i];
00809     } 
00810     p_valStack.push(b);
00811   }
00812 
00813 
00823   std::vector<double> Calculator::Pop(bool keepSpecials) {
00824     std::vector<double> top;
00825 
00826     if(p_valStack.empty()) {
00827       std::string msg = "Stack is empty, cannot perform any more operations.";
00828       throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00829     }
00830 
00831     top = p_valStack.top();
00832 
00833     if(keepSpecials) {
00834       for(int i = 0; i < (int)top.size(); i++) {
00835         if(isnan(top[i])) {
00836           top[i] = Isis::Null;
00837         }
00838         // Test for +INFINITY
00839         else if(top[i] > DBL_MAX) {
00840           top[i] = Isis::Hrs;
00841         }
00842         // Test for -INFINITY)
00843         else if(top[i] < -DBL_MAX) {
00844           top[i] = Isis::Lrs;
00845         }
00846         else { 
00847           // Do nothing 
00848         }
00849       }
00850     }
00851     
00852     p_valStack.pop();
00853 
00854 
00855     return top;
00856   }
00857 
00858 
00862   void Calculator::PrintTop() {
00863     if(p_valStack.empty()) return;
00864     
00865     std::cout << "[ ";
00866     std::vector<double> top = p_valStack.top();
00867     for(int i = 0; i < (int)top.size(); i++) {
00868       std::cout << top[i] << " ";
00869     }
00870     std::cout << "]" << std::endl;
00871   }
00872 
00873 
00879   bool Calculator::Empty() {
00880     return p_valStack.empty();
00881   }
00882 
00883 
00887   void Calculator::Clear() {
00888     while(!p_valStack.empty()) {
00889       p_valStack.pop();
00890     }
00891   }
00892 
00893 
00903   void Calculator::PerformOperation(std::vector<double> &results,
00904                                     std::vector<double>::iterator arg1Start, 
00905                                     std::vector<double>::iterator arg1End,
00906                                     double operation(double))
00907   {
00908     results.resize(arg1End-arg1Start);
00909 
00910     for(unsigned int pos = 0; pos < results.size(); pos++) {
00911       results[pos] = operation(*arg1Start);
00912       arg1Start++;
00913     }
00914   }
00915 
00916 
00932   void Calculator::PerformOperation(std::vector<double> &results,
00933                                     std::vector<double>::iterator arg1Start, 
00934                                     std::vector<double>::iterator arg1End,
00935                                     std::vector<double>::iterator arg2Start,
00936                                     std::vector<double>::iterator arg2End,
00937                                     double operation(double, double)) {
00938     if(arg1End-arg1Start != 1 && arg2End-arg2Start != 1 && 
00939        arg1End-arg1Start != arg2End-arg2Start) {
00940       std::string msg = "Cannot operate on vectors of differing sizes.";
00941       throw Isis::iException::Message(Isis::iException::Math, msg, _FILEINFO_);
00942     }
00943 
00944     int iSize = max(arg1End-arg1Start, arg2End-arg2Start);
00945     results.resize(iSize);
00946 
00947     for(unsigned int pos = 0; pos < results.size(); pos++) {
00948       results[pos] = operation(*arg1Start, *arg2Start);
00949 
00950       if(arg1Start+1 != arg1End) arg1Start++;
00951       if(arg2Start+1 != arg2End) arg2Start++;
00952     }
00953   }
00954 } // End of namespace Isis