Expression.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: Expression.cpp 2944 2011-10-27 08:04:41Z yanweignss $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 
00032 #include <sstream>
00033 #include <map>
00034 #include <list>
00035 #include <vector>
00036 #include <string>
00037 #include <ctype.h>
00038 #include <math.h>
00039 
00040 #include "icd_200_constants.hpp"
00041 #include "StringUtils.hpp"
00042 #include "Expression.hpp"
00043 
00044 namespace gpstk 
00045 {
00046    
00047    double Expression::BinOpNode::getValue() 
00048       throw (ExpressionException) 
00049    {
00050 
00051       // To get the value, compute the value of the left and
00052       // right operands, and combine them with the operator.
00053       double leftVal = left->getValue();
00054       double rightVal = right->getValue();
00055 
00056       if (op=="+") return leftVal + rightVal;
00057       if (op=="-") return leftVal - rightVal;
00058       if (op=="*") return leftVal * rightVal;
00059       if (op=="/") return leftVal / rightVal;
00060 
00061       // else THROW exception
00062       GPSTK_THROW(ExpressionException());
00063 
00064    }
00065 
00066    double Expression::FuncOpNode::getValue()
00067       throw (ExpressionException) 
00068    {
00069       // To get the value, compute the value of the right first
00070       double rightVal = right->getValue();
00071 
00072       if (op=="cos") return ::cos(rightVal);
00073       if (op=="sin") return ::sin(rightVal);
00074       if (op=="tan") return ::tan(rightVal);
00075       if (op=="acos") return ::acos(rightVal);
00076       if (op=="asin") return ::asin(rightVal);
00077       if (op=="atan") return ::atan(rightVal);
00078       if (op=="exp") return ::exp(rightVal);
00079       if (op=="abs") return ::fabs(rightVal);
00080       if (op=="sqrt") return ::sqrt(rightVal);
00081       if (op=="log") return ::log(rightVal);
00082       if (op=="log10") return ::log10(rightVal);
00083 
00084       // else THROW exception
00085       GPSTK_THROW(ExpressionException());
00086    }
00087 
00088    std::ostream& Expression::FuncOpNode::print(std::ostream& ostr) {
00089       ostr << op;
00090       right->print(ostr);
00091 
00092       return ostr;
00093    }
00094 
00095    std::ostream& Expression::BinOpNode::print(std::ostream& ostr) {
00096       ostr << "(";
00097       left->print(ostr);
00098       ostr << op;
00099       right->print(ostr);
00100       ostr << ")";
00101 
00102       return ostr;
00103    }
00104 
00105    void Expression::VarNode::setValue(double newValue)         
00106    {
00107       value=newValue;
00108       hasValue=true;
00109    };
00110          
00111    double Expression::VarNode::getValue(void) 
00112       throw (ExpressionException)
00113    {
00114       if (!hasValue) 
00115       { 
00116          ExpressionException ee("Variable " + name + " undefined."); 
00117          GPSTK_THROW(ee);
00118       }
00119       
00120       return value;
00121    }
00122    
00123    Expression::Token::Token(std::string iValue, int iPriority, 
00124                             bool isOp=false)
00125          :
00126          value(iValue), priority(iPriority), used(false), resolved(false),
00127          expNode(0), isOperator(isOp)
00128    {
00129    }
00130 
00131    void Expression::Token::print(std::ostream& ostr)
00132    {
00133       ostr <<" Value '" << value;
00134       ostr << "', operation priority " << priority << ", ";
00135     
00136       if (isOperator) ostr << "operator";
00137       else ostr << "not operator";
00138 
00139       ostr << ", ";
00140       
00141       if (used) ostr << "used,";
00142       else ostr << "not used,";
00143 
00144       if (resolved) ostr << "resolved";
00145       else ostr << "not resolved ";
00146 
00147       return;
00148    }
00149 
00150    bool Expression::operatorsDefined = false;
00151    std::map<std::string,int> Expression::operatorMap;
00152    std::map<std::string,std::string> Expression::argumentPatternMap;
00153    
00154    Expression::Expression(const std::string& istr)
00155          : root(0)
00156    {
00157       defineOperators();
00158       setExpression(istr);
00159    }
00160    
00161    void Expression::setExpression(const std::string& istr)
00162    {
00163       dumpLists();
00164       tokenize(istr);
00165       buildExpressionTree();
00166    }
00167 
00168    Expression::Expression(void)
00169          : root(0)
00170    {
00171       defineOperators();
00172       setExpression("0");
00173    }
00174 
00175    Expression::Expression(const Expression& rhs)
00176    {
00177       defineOperators();
00178       std::ostringstream ostr;
00179       rhs.print(ostr);
00180       setExpression(ostr.str());
00181    }
00182 
00183    Expression& Expression::operator=(const Expression& rhs)
00184    {
00185       std::ostringstream ostr;
00186       rhs.print(ostr);
00187       setExpression(ostr.str());
00188       return (*this);      
00189    }
00190    
00191    void Expression::dumpLists(void)
00192    {   
00193       // first release the points tracked by this Expression
00194       std::list<ExpNode *>::iterator i= eList.begin(), itemp;
00195       while (i!= eList.end())
00196       {
00197          itemp=i;
00198          itemp++;
00199          delete(*i);
00200          i=itemp;
00201       }
00202       std::list<ExpNode *> emptyENodeList;
00203       eList = emptyENodeList;
00204       std::list<Token> emptyTokenList;
00205       tList = emptyTokenList;
00206       root =0;
00207    }
00208       
00209 
00210    void Expression::defineOperators(void)
00211    {
00212       if (!operatorsDefined)
00213       {
00214          operatorMap["+"]=1; 
00215          operatorMap["-"]=1;
00216          operatorMap["*"]=2;
00217          operatorMap["/"]=2;
00218          operatorMap["^"]=3;
00219          operatorMap["cos"]=4;
00220          operatorMap["sin"]=4;
00221          operatorMap["tan"]=4;
00222          operatorMap["acos"]=4;
00223          operatorMap["asin"]=4;
00224          operatorMap["atan"]=4;
00225          operatorMap["exp"]=4;
00226          operatorMap["abs"]=4;
00227          operatorMap["sqrt"]=4;
00228          operatorMap["log"]=4;
00229          operatorMap["log10"]=4;
00230 
00231          argumentPatternMap["+"]="RL";
00232          argumentPatternMap["-"]="RL";
00233          argumentPatternMap["*"]="RL";
00234          argumentPatternMap["/"]="RL";
00235          argumentPatternMap["^"]="RL";
00236          argumentPatternMap["cos"]="R";
00237          argumentPatternMap["sin"]="R";
00238          argumentPatternMap["tan"]="R";
00239          argumentPatternMap["acos"]="R";
00240          argumentPatternMap["asin"]="R";
00241          argumentPatternMap["atan"]="R";
00242          argumentPatternMap["exp"]="R";
00243          argumentPatternMap["abs"]="R";
00244          argumentPatternMap["sqrt"]="R";
00245          argumentPatternMap["log"]="R";
00246          argumentPatternMap["log10"]="R";
00247 
00248          operatorsDefined = true;
00249       }
00250    }
00251    
00252    Expression::~Expression(void)
00253    {
00254       std::list<ExpNode *>::iterator i;      
00255       for (i=eList.begin(); i!=eList.end(); i++)
00256          delete (*i);
00257    }
00258    
00259    void Expression::tokenize(const std::string& istr)
00260    {
00261       using namespace std;
00262 
00263       // Remove spaces and parenthesis from the input string
00264       // Must store informatin from parenthesis in another list
00265       stringstream ss(istr);
00266       string str;
00267       char tempc;
00268       vector<int> baseOrder;
00269       int currentOrder = 0;
00270       
00271       while (ss >> skipws >> tempc)
00272       {
00273          bool strip=false;
00274          
00275          if (tempc == '(')
00276          {
00277             currentOrder+=10;
00278             strip=true;
00279          }
00280          
00281          if (tempc == ')')
00282          {
00283             currentOrder-=10;
00284             strip=true;
00285          }        
00286          
00287          if (!strip)
00288          { 
00289             baseOrder.push_back(currentOrder);
00290             str.append(&tempc,1);
00291          }
00292       }
00293       
00294       map<string, int>::iterator it;
00295       list<int> breaks;
00296       breaks.push_back(0);
00297       
00298       // Break the expression into candidates for tokens. First known 
00299       // operators and functions
00300       // are found and marked with as a "break" in the the string.        
00301       // Note the location and compute the order of operation of each.
00302       // key is location in string. value is ord. of op.
00303       map<int,int> breakPriority;
00304 
00305       // Note when the breaks are due to an operator or to an operand.
00306       // Each break can become a token but not all othem do. 
00307       // Key is location in the string, value is boolean, true for operators and functions.
00308       map<int, bool> breakType;
00309 
00310       for (it=operatorMap.begin(); it!=operatorMap.end(); it++)
00311       {
00312          int position = 0;
00313          while ((position=str.find(it->first,position+1))!=string::npos)
00314          {
00315             // Account for scientific notation
00316             bool sciNotation=false;
00317             if ((it->first=="+") || (it->first=="-")) 
00318             {
00319                sciNotation =
00320                   ( ( (str.substr(position-1,1)=="E") || 
00321                       (str.substr(position-1,1)=="e")    )         &&
00322                     (isdigit(str.substr(position-2,1).c_str()[0])) &&
00323                     (isdigit(str.substr(position+1,1).c_str()[0]))      );
00324             }
00325             
00326             if (!sciNotation)
00327             {
00328                breaks.push_back(position);
00329                breakPriority[position] = it->second + baseOrder[position];
00330                breakType[position] = true;
00331 
00332                int operandPos = position+(it->first.size());
00333                breaks.push_back(operandPos);
00334                breakPriority[operandPos] = baseOrder[operandPos];
00335                breakType[operandPos] = false;
00336             }
00337          }
00338          
00339       }
00340       breaks.push_back(str.size());
00341 
00342       // Sort the breaks into a list
00343       // Please note that sorting a linked list is expensive compared to
00344       // sorting a vector or map, as the search cost is high (lists are not sorted).
00345       // This should be revisited IF large expressions are handled by the GPSTk.
00346       breaks.sort();
00347 
00348       list<string> tokens;
00349       list<int>::iterator ls = breaks.begin(), rs = ls; // used to identify token string
00350 
00351       for (rs++ ;rs!=breaks.end(); rs++, ls++)
00352       {
00353          if (*rs!=*ls) // If not two operators in a row
00354          {
00355             string thisToken = str.substr(*ls,(*rs)-(*ls));
00356             int thisOop = breakPriority[*ls];
00357             bool isOp = breakType[*ls];
00358 
00359                // Create the token
00360             Token tok(thisToken,thisOop, isOp);
00361 
00362             if ( tok.getOperator() ) 
00363                tok.setArgumentPattern( argumentPatternMap[thisToken] );
00364             
00365             // Create an expression node, save it, and link it to the token
00366             ExpNode *expNode;
00367             
00368 
00369             if (!isOp) 
00370             {
00371                char testChar = thisToken.c_str()[0];
00372                if (isalpha(testChar))
00373                   expNode = new VarNode(thisToken);
00374                else
00375                   expNode = new ConstNode(StringUtils::asDouble(thisToken));
00376                eList.push_back(expNode);
00377                tok.setNode(expNode);
00378                tok.setResolved(true);
00379             }     
00380 
00381             // Now that the token has the best possible state, save it
00382             tList.push_back(tok);
00383          }
00384       }      
00385    } // end tokenize function
00386 
00387 
00388    int Expression::countResolvedTokens(void)
00389    {
00390       using namespace std;
00391       
00392       list<Token>::iterator itt;
00393    
00394       // How many have already been processed? Are we done yet?
00395       int totalResolved=0;
00396       for (itt = tList.begin(); itt!=tList.end(); itt++)
00397       {
00398          if (itt->getResolved()) totalResolved++;
00399       }
00400       return totalResolved;
00401    }
00402    
00403    
00404    void Expression::buildExpressionTree(void)
00405    {
00406       using namespace std;
00407        
00408       list<Token>::iterator itt, targetToken;
00409 
00410       if ((tList.size()==1)&&(tList.begin()->getResolved()))
00411       {
00412          root = tList.begin()->getNode();
00413          return;
00414       }
00415       
00416       int totalResolved = countResolvedTokens();
00417 
00418       while (totalResolved<tList.size())
00419       {
00420          
00421          // 
00422          // Step through tokens to find the value for the highest priority
00423          // that doesn not yet have an expression node ExpNode assigned to it.
00424          // A subtle but important sideeffect of this traversal is taht
00425          // operators with the same priority get evaluated from right to
00426          // left.
00427          itt=tList.begin();
00428          int highestP = -1;
00429 
00430          for (itt = tList.begin(); itt !=tList.end(); itt++)
00431          {
00432             if ( itt->getOperator() && !itt->getResolved() )
00433             {
00434                if (itt->getPriority()>highestP) 
00435                {
00436                   targetToken = itt;
00437                   highestP=itt->getPriority();
00438                }
00439             }
00440          }
00441 
00442          if ( targetToken->getOperator() )
00443          {
00444             // Find the arg(s) for this operator.
00445             list<Token>::iterator leftArg=targetToken, rightArg=leftArg;
00446 
00447             stringstream argstr(targetToken->getArgumentPattern());
00448             char thisArg;
00449             bool searching;
00450             
00451             while (argstr >> thisArg)
00452             {
00453                switch (thisArg) {
00454                   case 'R': 
00455                      searching = true;
00456 
00457                      while (searching)
00458                      {
00459                         if (rightArg==tList.end())// TODO throw exception
00460                            cout << "Mistake, no right arg for " << targetToken->getValue() << endl;
00461                         else
00462                         rightArg++;
00463 
00464                         searching = (rightArg->getUsed());
00465                      }
00466                      
00467                      break;
00468 
00469                   case 'L':
00470                
00471                         // Resolve left arg
00472                      searching=true;
00473 
00474                      while (searching)
00475                      {
00476                         if (leftArg == tList.begin()) // TODO throw
00477                            cout << "Mistake - no right argument for operator?!" << endl;
00478                         else
00479                            leftArg--;
00480 
00481                         searching = (leftArg->getUsed());
00482                      }
00483                      
00484                      break;
00485                } // end of argumentPattern cases
00486             } // done processing argument list
00487             
00488             
00489            if (targetToken->getArgumentPattern()=="RL")
00490            {
00491               ExpNode *opNode = 
00492               new BinOpNode(targetToken->getValue(),leftArg->getNode(), rightArg->getNode());
00493               targetToken->setNode(opNode);
00494               eList.push_back(opNode);
00495 
00496               targetToken->setResolved(true);
00497               root = targetToken->getNode();
00498 
00499               leftArg->setUsed();
00500               rightArg->setUsed();
00501            }
00502 
00503            if (targetToken->getArgumentPattern()=="R")
00504            {
00505               ExpNode *opNode = 
00506               new FuncOpNode(targetToken->getValue(),rightArg->getNode());
00507               targetToken->setNode(opNode);
00508 
00509               eList.push_back(opNode);
00510 
00511               targetToken->setResolved(true);
00512               root = targetToken->getNode();
00513 
00514               rightArg->setUsed();
00515            }
00516             
00517          } // If this is an operator
00518 
00519          // Are we done yet?
00520          totalResolved = countResolvedTokens();
00521       }      
00522       
00523    } // end buildExpressionTree
00524    
00525 
00526    bool Expression::set(const std::string name, double value)
00527    {
00528       using namespace std;
00529       
00530       bool gotSet;
00531 
00532       std::list<ExpNode *>::iterator i;
00533       int t;
00534       
00535       for (t=0, i=eList.begin(); i!=eList.end(); t++, i++)
00536       {
00537          VarNode *vnode = dynamic_cast<VarNode *> (*i);
00538          if (vnode!=0) 
00539          {
00540             if (StringUtils::upperCase(vnode->name) == 
00541                 StringUtils::upperCase(name))
00542             {
00543                vnode->setValue(value);
00544                gotSet = true;
00545             }
00546          }
00547       }
00548 
00549       return gotSet;
00550    }
00551 
00552 
00553    bool Expression::canEvaluate(void)
00554    {
00555       using namespace std;
00556       
00557       bool areSet=true;
00558 
00559       std::list<ExpNode *>::iterator i;
00560       int t;
00561       
00562       for (t=0, i=eList.begin(); i!=eList.end(); t++, i++)
00563       {
00564          VarNode *vnode = dynamic_cast<VarNode *> (*i);
00565          if (vnode!=0) 
00566          {
00567             areSet &= vnode->hasValue;
00568          }
00569       }
00570 
00571       return areSet;
00572    }
00573     
00574    bool Expression::setGPSConstants(void)
00575    {
00576       bool gotSet = false;
00577       
00578       gotSet |= set("gamma",(L1_FREQ / L2_FREQ)*(L1_FREQ / L2_FREQ));
00579       gotSet |= set("pi",PI);
00580       gotSet |= set("c",C_GPS_M);
00581       gotSet |= set("c_gps_m",C_GPS_M);
00582       gotSet |= set("l0",OSC_FREQ);
00583       gotSet |= set("f1",L1_MULT);
00584       gotSet |= set("f2",L2_MULT);
00585       gotSet |= set("l1",L1_FREQ);
00586       gotSet |= set("l2",L2_FREQ);
00587       gotSet |= set("wl1",C_GPS_M/L1_FREQ);
00588       gotSet |= set("wl2",C_GPS_M/L2_FREQ);
00589       return gotSet;
00590    }
00591    
00592    bool Expression::setRinexObs(const RinexObsData::RinexObsTypeMap& rotm)
00593    {
00594       bool gotSet = false;
00595       
00596       RinexObsData::RinexObsTypeMap::const_iterator i;
00597       for (i=rotm.begin(); i!=rotm.end(); i++)
00598          gotSet |= set(i->first.type, i->second.data);
00599 
00600       return gotSet;
00601    }
00602 
00603    // We use the rinex 3 type identifiers for this since the rinex 2 will leave
00604    // things ambigous. This is in contrast to the setRinexObs() method which
00605    // uses the rinex 2 type identifiers.
00606    bool Expression::setSvObsEpoch(const SvObsEpoch& soe)
00607    {
00608       bool gotSet = false;
00609       for (SvObsEpoch::const_iterator i=soe.begin(); i != soe.end(); i++)
00610       {
00611 
00612          // Note that there are some combinations of the following that are not
00613          // 'valid'. Well, they aren't defined in the RINEX 3 spec
00614          // Also, this needs to be moved to another file once we have
00615          // rinex 3 support in the src directory.
00616          std::string type, band, attribute;
00617          bool ignore=false;
00618          switch (i->first.type)
00619          {
00620             case ObsID::otRange:    type = "C"; break;
00621             case ObsID::otPhase:    type = "L"; break;
00622             case ObsID::otDoppler:  type = "D"; break;
00623             case ObsID::otSNR:      type = "S"; break;
00624             case ObsID::otSSI:      ignore = true; break;
00625             case ObsID::otLLI:      ignore = true; break;
00626             case ObsID::otTrackLen: ignore = true; break;
00627          }
00628 
00629          switch (i->first.band)
00630          {
00631             case ObsID::cbL1:   band = "1"; break;
00632             case ObsID::cbL2:   band = "2"; break;
00633             case ObsID::cbL5:   band = "5"; break;
00634             case ObsID::cbE6:   band = "6"; break;
00635             case ObsID::cbE5b:  band = "7"; break;
00636             case ObsID::cbE5ab: band = "8"; break;
00637          }
00638 
00639          switch (i->first.code)
00640          {
00641             case ObsID::tcCA:   attribute = "C"; break;
00642             case ObsID::tcP:    attribute = "P"; break;
00643             case ObsID::tcY:    attribute = "Y"; break;
00644             case ObsID::tcW:    attribute = "W"; break;
00645             case ObsID::tcN:    attribute = "N"; break;
00646             case ObsID::tcM:    attribute = "M"; break;
00647             case ObsID::tcC2M:  attribute = "S"; break;
00648             case ObsID::tcC2L:  attribute = "L"; break;
00649             case ObsID::tcC2LM: attribute = "X"; break;
00650             case ObsID::tcI5:   attribute = "I"; break;
00651             case ObsID::tcQ5:   attribute = "Q"; break;
00652             case ObsID::tcIQ5:  attribute = "X"; break;
00653             case ObsID::tcA:    attribute = "A"; break;
00654             case ObsID::tcB:    attribute = "B"; break;
00655             case ObsID::tcC:    attribute = "C"; break;
00656             case ObsID::tcBC:   attribute = "X"; break;
00657             case ObsID::tcABC:  attribute = "Z"; break;
00658          }
00659          if (ignore)
00660             continue;
00661 
00662          std::string id = type + band + attribute;
00663 
00664          if (id.length() != 3)
00665                std::cout << "Unimplimented ObsID:" << i->first << std::endl;
00666 
00667          gotSet |= set(id, i->second);
00668       }
00669       return gotSet;
00670    }
00671       
00672 } // end namespace gpstk

Generated on Wed Feb 8 03:30:59 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1