SNAP Library, Developer Reference  2012-10-02 12:56:23
SNAP, a general purpose network analysis and graph mining library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
exp.cpp
Go to the documentation of this file.
00001 
00002 // Expression-Value
00003 PExpVal TExpVal::UndefExpVal=NULL;
00004 PExpVal TExpVal::ZeroExpVal=NULL;
00005 
00006 bool TExpVal::operator==(const TExpVal& ExpVal) const {
00007   if (ValType!=ExpVal.ValType){return false;}
00008   switch (ValType){
00009     case evtUndef: return true;
00010     case evtFlt: return Flt==ExpVal.Flt;
00011     case evtStr: return Str==ExpVal.Str;
00012     case evtVec:{
00013       if (ValV.Len()!=ExpVal.ValV.Len()){return false;}
00014       for (int VecValN=0; VecValN<ExpVal.ValV.Len(); VecValN++){
00015         if (*ValV[VecValN]!=*ExpVal.ValV[VecValN]){return false;}}
00016       return true;}
00017     case evtLst:{
00018       if (ValL.Len()!=ExpVal.ValL.Len()){return false;}
00019       TExpValLN ValLN=ValL.First();
00020       TExpValLN ExpValLN=ExpVal.ValL.First();
00021       while (ValLN!=NULL){
00022         if (*ValLN->GetVal()!=*ExpValLN->GetVal()){return false;}
00023         ValLN=ValLN->Next();
00024         ExpValLN=ExpValLN->Next();
00025       }
00026       return true;}
00027     default: Fail; return false;
00028   }
00029 }
00030 
00031 bool TExpVal::operator<(const TExpVal& ExpVal) const {
00032   if (ValType!=ExpVal.ValType){
00033     return ValType<ExpVal.ValType;}
00034   switch (ValType){
00035     case evtUndef: return false;
00036     case evtFlt: return Flt<ExpVal.Flt;
00037     case evtStr: return Str<ExpVal.Str;
00038     case evtVec:{
00039       int VecValN=0;
00040       while ((VecValN<ValV.Len())&&(VecValN<ExpVal.ValV.Len())){
00041         if (*ValV[VecValN]<*ExpVal.ValV[VecValN]){return true;}
00042         else if (*ValV[VecValN]==*ExpVal.ValV[VecValN]){VecValN++;}
00043         else {return false;}
00044       }
00045       return ValV.Len()<ExpVal.ValV.Len();}
00046     case evtLst:{
00047       if (ValL.Len()!=ExpVal.ValL.Len()){return false;}
00048       TExpValLN ValLN=ValL.First();
00049       TExpValLN ExpValLN=ExpVal.ValL.First();
00050       while ((ValLN!=NULL)&&(ExpValLN!=NULL)){
00051         if (*ValLN->GetVal()<*ExpValLN->GetVal()){
00052           return true;}
00053         else if (*ValLN->GetVal()==*ExpValLN->GetVal()){
00054           ValLN=ValLN->Next(); ExpValLN=ExpValLN->Next();}
00055         else {return false;}
00056       }
00057       return ValLN==NULL;}
00058     default: Fail; return false;
00059   }
00060 }
00061 
00062 int TExpVal::GetFltValAsInt(const bool& ThrowExceptP) const {
00063   double Flt=GetFltVal();
00064   if ((Flt<double(TInt::Mn))&&(double(TInt::Mx)<Flt)){
00065     if (ThrowExceptP){TExcept::Throw("Float too big for integer.");}
00066     else {Flt=0;}
00067   }
00068   return int(Flt);
00069 }
00070 
00071 void TExpVal::SaveTxt(TOLx& Lx) const {
00072   TExpValType _ValType=TExpValType(int(ValType));
00073   switch (_ValType){
00074     case evtUndef: Lx.PutIdStr("Undef"); break;
00075     case evtFlt: Lx.PutFlt(Flt); break;
00076     case evtStr: Lx.PutQStr(Str); break;
00077     case evtVec:{
00078       Lx.PutSym(syLBrace);
00079       for (int ValN=0; ValN<ValV.Len(); ValN++){
00080         ValV[ValN]->SaveTxt(Lx);}
00081       Lx.PutSym(syRBrace);
00082       break;}
00083     case evtLst:{
00084       Lx.PutSym(syLBracket);
00085       TExpValLN ValLN=ValL.First();
00086       for (int ValN=0; ValN<ValL.Len(); ValN++){
00087         ValLN->GetVal()->SaveTxt(Lx); ValLN=ValLN->Next();}
00088       Lx.PutSym(syRBracket);
00089       break;}
00090     default: Fail;
00091   }
00092 }
00093 
00094 void TExpVal::SaveTxt(const PSOut& SOut) const {
00095   TOLx Lx(SOut, TFSet()|oloCmtAlw|oloSigNum|oloCsSens);
00096   SaveTxt(Lx);
00097 }
00098 
00099 TStr TExpVal::GetStr() const {
00100   PSOut SOut=TMOut::New(); TMOut& MOut=*(TMOut*)SOut();
00101   SaveTxt(SOut);
00102   TStr ExpValStr=TStr::LoadTxt(MOut.GetSIn());
00103   return ExpValStr;
00104 }
00105 
00106 PExpVal TExpVal::MkClone(const PExpVal& ExpVal){
00107   PExpVal CloneExpVal=TExpVal::New();
00108   CloneExpVal->ValType=ExpVal->ValType;
00109   CloneExpVal->Flt=ExpVal->Flt;
00110   CloneExpVal->Str=ExpVal->Str;
00111   CloneExpVal->ValV.Gen(ExpVal->ValV.Len(), 0);
00112   for (int VecValN=0; VecValN<ExpVal->ValV.Len(); VecValN++){
00113     CloneExpVal->ValV.Add(MkClone(ExpVal->ValV[VecValN]));
00114   }
00115   TExpValLN ExpValLN=ExpVal->ValL.First();
00116   while (ExpValLN!=NULL){
00117     CloneExpVal->ValL.AddBack(MkClone(ExpValLN->GetVal()));
00118     ExpValLN=ExpValLN->Next();
00119   }
00120   return CloneExpVal;
00121 }
00122 
00123 PExpVal TExpVal::GetUndefExpVal(){
00124   if (UndefExpVal.Empty()){
00125     UndefExpVal=TExpVal::New();}
00126   return UndefExpVal;
00127 }
00128 
00129 PExpVal TExpVal::GetZeroExpVal(){
00130   if (ZeroExpVal.Empty()){
00131     ZeroExpVal=TExpVal::New(double(0));}
00132   return ZeroExpVal;
00133 }
00134 
00136 // Expression-Environment
00137 bool TExpEnv::IsFuncOk(
00138  const TStr& RqFuncNm, const TExpFuncArgType& RqFuncArgType,
00139  const TStr& FuncNm, const TExpValV& ArgValV){
00140   if (RqFuncNm.GetUc()!=FuncNm.GetUc()){return false;}
00141   switch (RqFuncArgType){
00142     case efatVoid: return ArgValV.Len()==0;
00143     case efatFlt:
00144       if (ArgValV.Len()!=1){return false;}
00145       if (ArgValV[0]->GetValType()!=evtFlt){return false;}
00146       return true;
00147     case efatStr:
00148       if (ArgValV.Len()!=1){return false;}
00149       if (ArgValV[0]->GetValType()!=evtStr){return false;}
00150       return true;
00151     case efatFltFlt:
00152       if (ArgValV.Len()!=2){return false;}
00153       if (ArgValV[0]->GetValType()!=evtFlt){return false;}
00154       if (ArgValV[1]->GetValType()!=evtFlt){return false;}
00155       return true;
00156     case efatFltStr:
00157       if (ArgValV.Len()!=2){return false;}
00158       if (ArgValV[0]->GetValType()!=evtFlt){return false;}
00159       if (ArgValV[1]->GetValType()!=evtStr){return false;}
00160       return true;
00161     case efatStrFlt:
00162       if (ArgValV.Len()!=2){return false;}
00163       if (ArgValV[0]->GetValType()!=evtStr){return false;}
00164       if (ArgValV[1]->GetValType()!=evtFlt){return false;}
00165       return true;
00166     case efatStrStr:
00167       if (ArgValV.Len()!=2){return false;}
00168       if (ArgValV[0]->GetValType()!=evtStr){return false;}
00169       if (ArgValV[1]->GetValType()!=evtStr){return false;}
00170       return true;
00171     case efatStrAny:
00172       if (ArgValV.Len()!=2){return false;}
00173       if (ArgValV[0]->GetValType()!=evtStr){return false;}
00174       return true;
00175     default: Fail; return false;
00176   }
00177 }
00178 
00179 PExpEnv TExpEnv::DfExpEnv=PExpEnv(new TExpEnv());
00180 
00182 // Expression-Built-Ins
00183 TExpBi::TExpBi():
00184   ExpBiNmToIdH(100), ExpBiIdToArgTypeH(100){
00185   // constants
00186   AddBi("Undef", ebi_Undef);
00187   AddBi("True", ebi_True);
00188   AddBi("False", ebi_False);
00189   AddBi("E", ebi_E);
00190   AddBi("Pi", ebi_Pi);
00191 
00192   // trigonometric funcions
00193   AddBi("Sin", ebi_Sin, ebatFlt);
00194   AddBi("Cos", ebi_Cos, ebatFlt);
00195   AddBi("Tan", ebi_Tan, ebatFlt);
00196   AddBi("ASin", ebi_ASin, ebatFlt);
00197   AddBi("ACos", ebi_ACos, ebatFlt);
00198   AddBi("ATan", ebi_ATan, ebatFlt);
00199   AddBi("SinH", ebi_SinH, ebatFlt);
00200   AddBi("CosH", ebi_CosH, ebatFlt);
00201   AddBi("TanH", ebi_TanH, ebatFlt);
00202 
00203   // exponential functions
00204   AddBi("Pow", ebi_Pow, ebatFltFlt);
00205   AddBi("Exp", ebi_Exp, ebatFlt);
00206   AddBi("Sqr", ebi_Sqr, ebatFlt);
00207   AddBi("Sqrt", ebi_Sqrt, ebatFlt);
00208   AddBi("Log", ebi_Log, ebatFlt);
00209   AddBi("Log10", ebi_Log10, ebatFlt);
00210 
00211   // number manipulation functions
00212   AddBi("Ceil", ebi_Ceil, ebatFlt);
00213   AddBi("Floor", ebi_Floor, ebatFlt);
00214   AddBi("Int", ebi_Int, ebatFlt);
00215   AddBi("Frac", ebi_Frac, ebatFlt);
00216   AddBi("Abs", ebi_Abs, ebatFlt);
00217 
00218   // random deviates
00219   AddBi("UniDev", ebi_UniDev, ebatVoid);
00220   AddBi("NrmDev", ebi_NrmDev, ebatVoid);
00221   AddBi("ExpDev", ebi_ExpDev, ebatVoid);
00222   AddBi("GamDev", ebi_GamDev, ebatFlt);
00223   AddBi("PoiDev", ebi_PoiDev, ebatFlt);
00224   AddBi("BinDev", ebi_BinDev, ebatFltFlt);
00225   AddBi("UniDevStep", ebi_UniDevStep, ebatFltFlt);
00226 
00227   // assign values to constants
00228   Val_Undef=TExpVal::GetUndefExpVal();
00229   Val_True=TExpVal::New(double(1));
00230   Val_False=TExpVal::New(double(0));
00231   Val_E=TExpVal::New(TMath::E);
00232   Val_Pi=TExpVal::New(TMath::Pi);
00233 }
00234 
00235 void TExpBi::AddBi(const TStr& ExpBiNm, const TExpBiId& ExpBiId,
00236  const TExpBiArgType& ExpBiArgType){
00237   ExpBiNmToIdH.AddDat(ExpBiNm.GetUc(), TInt(int(ExpBiId)));
00238   ExpBiIdToArgTypeH.AddDat(TInt(int(ExpBiId)), TInt(int(ExpBiArgType)));
00239 }
00240 
00241 bool TExpBi::IsExpBiId(const TStr& ExpBiNm, TExpBiId& ExpBiId){
00242   int ExpBiIdP;
00243   if (ExpBiNmToIdH.IsKey(ExpBiNm.GetUc(), ExpBiIdP)){
00244     ExpBiId=TExpBiId(int(ExpBiNmToIdH[ExpBiIdP])); return true;
00245   } else {
00246     ExpBiId=ebi_Undef; return false;
00247   }
00248 }
00249 
00250 TExpBiArgType TExpBi::GetExpBiArgType(const TExpBiId& ExpBiId){
00251   TInt ExpBiArgType=ExpBiIdToArgTypeH.GetDat(TInt(int(ExpBiId)));
00252   return TExpBiArgType(int(ExpBiArgType));
00253 }
00254 
00255 void TExpBi::AssertArgs(const int& RqArgs, const int& ActArgs){
00256   if (RqArgs!=ActArgs){
00257     TExcept::Throw("Invalid number of arguments.");
00258   }
00259 }
00260 
00261 void TExpBi::AssertArgValType(
00262  const TExpValType& ExpValType, const PExpVal& ExpVal){
00263   if (ExpValType!=ExpVal->GetValType()){
00264     TExcept::Throw("Invalid type of argument.");
00265   }
00266 }
00267 
00268 PExpVal TExpBi::GetBiConstVal(const TExpBiId& ExpBiId){
00269   switch (ExpBiId){
00270     case ebi_Undef: return Val_Undef;
00271     case ebi_True: return Val_True;
00272     case ebi_False: return Val_False;
00273     case ebi_E: return Val_E;
00274     case ebi_Pi: return Val_Pi;
00275     default: TExcept::Throw("Invalid constant."); return Val_Undef;
00276   }
00277 }
00278 
00279 PExpVal TExpBi::GetBiFuncVal(
00280  const TExpBiId& ExpBiId, const TExpValV& ArgValV, const PExpEnv& ExpEnv){
00281   TExpBiArgType ExpBiArgType=TExpBi::GetExpBiArgType(ExpBiId);
00282   int Args=ArgValV.Len();
00283   double ArgFlt1=0; double ArgFlt2=0;
00284   switch (ExpBiArgType){
00285     case ebatUndef: Fail; break;
00286     case ebatVoid:
00287       AssertArgs(0, Args); break;
00288     case ebatFlt:
00289       AssertArgs(1, Args);
00290       AssertArgValType(evtFlt, ArgValV[0]);
00291       ArgFlt1=ArgValV[0]->GetFltVal(); break;
00292     case ebatFltFlt:
00293       AssertArgs(2, Args);
00294       AssertArgValType(evtFlt, ArgValV[0]);
00295       AssertArgValType(evtFlt, ArgValV[1]);
00296       ArgFlt1=ArgValV[0]->GetFltVal();
00297       ArgFlt2=ArgValV[1]->GetFltVal(); break;
00298     default: Fail;
00299   }
00300   PExpVal ExpVal;
00301   switch (ExpBiId){
00302     // trigonometric funcions
00303     case ebi_Sin: ExpVal=TExpVal::New(sin(ArgFlt1)); break;
00304     case ebi_Cos: ExpVal=TExpVal::New(cos(ArgFlt1)); break;
00305     case ebi_Tan: ExpVal=TExpVal::New(tan(ArgFlt1)); break;
00306     case ebi_ASin: ExpVal=TExpVal::New(asin(ArgFlt1)); break;
00307     case ebi_ACos: ExpVal=TExpVal::New(acos(ArgFlt1)); break;
00308     case ebi_ATan: ExpVal=TExpVal::New(atan(ArgFlt1)); break;
00309     case ebi_SinH: ExpVal=TExpVal::New(sinh(ArgFlt1)); break;
00310     case ebi_CosH: ExpVal=TExpVal::New(cosh(ArgFlt1)); break;
00311     case ebi_TanH: ExpVal=TExpVal::New(tanh(ArgFlt1)); break;
00312 
00313     // exponential functions
00314     case ebi_Pow: ExpVal=TExpVal::New(pow(ArgFlt1, ArgFlt2)); break;
00315     case ebi_Exp: ExpVal=TExpVal::New(exp(ArgFlt1)); break;
00316     case ebi_Sqr: ExpVal=TExpVal::New(TMath::Sqr(ArgFlt1)); break;
00317     case ebi_Sqrt: ExpVal=TExpVal::New(sqrt(ArgFlt1)); break;
00318     case ebi_Log: ExpVal=TExpVal::New(log(ArgFlt1)); break;
00319     case ebi_Log10: ExpVal=TExpVal::New(log10(ArgFlt1)); break;
00320 
00321     // number manipulation functions
00322     case ebi_Ceil: ExpVal=TExpVal::New(ceil(ArgFlt1)); break;
00323     case ebi_Floor: ExpVal=TExpVal::New(floor(ArgFlt1)); break;
00324     case ebi_Int:{
00325       double Int; modf(ArgFlt1, &Int);
00326       ExpVal=TExpVal::New(Int); break;}
00327     case ebi_Frac:{
00328       double Frac, Int; Frac=modf(ArgFlt1, &Int);
00329       ExpVal=TExpVal::New(Frac); break;}
00330     case ebi_Abs: ExpVal=TExpVal::New(fabs(ArgFlt1)); break;
00331 
00332     // random deviates
00333     case ebi_UniDev: ExpVal=TExpVal::New(ExpEnv->GetRnd().GetUniDev()); break;
00334     case ebi_NrmDev: ExpVal=TExpVal::New(ExpEnv->GetRnd().GetNrmDev()); break;
00335     case ebi_ExpDev: ExpVal=TExpVal::New(ExpEnv->GetRnd().GetExpDev()); break;
00336     case ebi_GamDev:{
00337       int ArgInt1=int(ArgFlt1);
00338       ExpVal=TExpVal::New(ExpEnv->GetRnd().GetGammaDev(ArgInt1)); break;}
00339     case ebi_PoiDev:{
00340       ExpVal=TExpVal::New(ExpEnv->GetRnd().GetPoissonDev(ArgFlt1)); break;}
00341     case ebi_BinDev:{
00342       int ArgInt2=int(ArgFlt2);
00343       ExpVal=TExpVal::New(ExpEnv->GetRnd().GetBinomialDev(ArgFlt1, ArgInt2)); break;}
00344     case ebi_UniDevStep:{
00345       int ArgInt1=int(ArgFlt1); if (ArgInt1<0){ArgInt1=0;}
00346       int ArgInt2=int(ArgFlt2);
00347       ExpVal=TExpVal::New(TRnd::GetUniDevStep(ArgInt1, ArgInt2)); break;}
00348     case ebi_NrmDevStep:{
00349       int ArgInt1=int(ArgFlt1); if (ArgInt1<0){ArgInt1=0;}
00350       int ArgInt2=int(ArgFlt2);
00351       ExpVal=TExpVal::New(TRnd::GetNrmDevStep(ArgInt1, ArgInt2)); break;}
00352     case ebi_ExpDevStep:{
00353       int ArgInt1=int(ArgFlt1); if (ArgInt1<0){ArgInt1=0;}
00354       int ArgInt2=int(ArgFlt2);
00355       ExpVal=TExpVal::New(TRnd::GetExpDevStep(ArgInt1, ArgInt2)); break;}
00356 
00357     default: TExcept::Throw("Invalid function.");
00358   }
00359   return ExpVal;
00360 }
00361 
00363 // Expression
00364 TExpBi TExp::ExpBi;
00365 
00366 const TFSet TExp::MulOpSymSet(syAsterisk, sySlash, syPercent, syHash, syAmpersand);
00367 const TFSet TExp::UAddOpSymSet(syPlus, syMinus);
00368 const TFSet TExp::AddOpSymSet(syPlus, syMinus, syVBar);
00369 const TFSet TExp::RelOpSymSet(syEq, syNEq, syLss, syGtr, syLEq, syGEq);
00370 
00371 const TFSet TExp::FactExpExpect(syFlt, syIdStr, syQStr, syLParen);
00372 const TFSet TExp::MulExpExpect(FactExpExpect);
00373 const TFSet TExp::AddExpExpect(MulExpExpect, UAddOpSymSet);
00374 const TFSet TExp::RelExpExpect(AddExpExpect);
00375 const TFSet TExp::ExpExpect(RelExpExpect);
00376 
00377 PExpVal TExp::EvalExpOp(
00378  const PExpEnv& ExpEnv, const bool& DbgP, TChA& DbgChA){
00379   PExpVal OutExpVal;
00380   TExpOp _ExpOp=TExpOp(int(ExpOp));
00381   switch (_ExpOp){
00382     case eoUPlus:
00383     case eoUMinus:
00384     case eoNot:{
00385       PExpVal ExpVal=ArgExpV[0]->EvalExp(ExpEnv, DbgP, DbgChA);
00386       TExpValType ExpValType=ExpVal->GetValType();
00387       if (ExpValType==evtFlt){
00388         TFlt Flt;
00389         switch (_ExpOp){
00390           case eoUPlus: Flt=ExpVal->GetFltVal(); break;
00391           case eoUMinus: Flt=-ExpVal->GetFltVal(); break;
00392           case eoNot: Flt=double(ExpVal->GetFltValAsInt()==0);
00393           default: Fail; Flt=0;
00394         }
00395         OutExpVal=TExpVal::New(Flt);
00396       } else {
00397         TExcept::Throw("Bad argument types.");
00398       }
00399       break;}
00400     case eoPlus:
00401     case eoMinus:
00402     case eoMul:
00403     case eoDiv:
00404     case eoIDiv:
00405     case eoMod:
00406     case eoAnd:
00407     case eoOr:{
00408       PExpVal LExpVal=ArgExpV[0]->EvalExp(ExpEnv, DbgP, DbgChA);
00409       PExpVal RExpVal=ArgExpV[1]->EvalExp(ExpEnv, DbgP, DbgChA);
00410       TExpValType LExpValType=LExpVal->GetValType();
00411       TExpValType RExpValType=RExpVal->GetValType();
00412       if ((LExpValType==evtFlt)&&(RExpValType==evtFlt)){
00413         // check left expression
00414         double LVal=LExpVal->GetFltVal();
00415         int LValExpon; frexp(LVal, &LValExpon);
00416         if (LValExpon>150){LExpVal=TExpVal::GetZeroExpVal();}
00417         // check right expression
00418         double RVal=LExpVal->GetFltVal();
00419         int RValExpon; frexp(RVal, &RValExpon);
00420         if (RValExpon>150){RExpVal=TExpVal::GetZeroExpVal();}
00421         // calculate
00422         TFlt Flt;
00423         switch (_ExpOp){
00424           case eoPlus: Flt=LExpVal->GetFltVal()+RExpVal->GetFltVal(); break;
00425           case eoMinus: Flt=LExpVal->GetFltVal()-RExpVal->GetFltVal(); break;
00426           case eoMul: Flt=LExpVal->GetFltVal()*RExpVal->GetFltVal(); break;
00427           case eoDiv:
00428             if (RExpVal->GetFltVal()==0){TExcept::Throw("Division by zero.");}
00429             else {Flt=LExpVal->GetFltVal()/RExpVal->GetFltVal();}
00430             break;
00431           case eoIDiv:
00432             if (RExpVal->GetFltValAsInt()==0){TExcept::Throw("Division by zero.");}
00433             else {Flt=LExpVal->GetFltValAsInt()/RExpVal->GetFltValAsInt();}
00434             break;
00435           case eoMod:
00436             if (RExpVal->GetFltValAsInt()==0){TExcept::Throw("Division by zero.");}
00437             else {Flt=LExpVal->GetFltValAsInt()%RExpVal->GetFltValAsInt();}
00438             break;
00439           case eoAnd:
00440             Flt=(LExpVal->GetFltValAsInt()!=0)&&(RExpVal->GetFltValAsInt()!=0); break;
00441           case eoOr:
00442             Flt=(LExpVal->GetFltValAsInt()!=0)||(RExpVal->GetFltValAsInt()!=0); break;
00443           default: Fail; Flt=0;
00444         }
00445         OutExpVal=TExpVal::New(Flt);
00446       } else
00447       if ((_ExpOp==eoPlus)&&(LExpValType==evtStr)&&(RExpValType==evtStr)){
00448         TStr Str=LExpVal->GetStrVal()+RExpVal->GetStrVal();
00449         OutExpVal=TExpVal::New(Str);
00450       } else {
00451         TExcept::Throw("Bad argument types.");
00452       }
00453       break;}
00454     case eoEq:
00455     case eoNEq:
00456     case eoLss:
00457     case eoGtr:
00458     case eoLEq:
00459     case eoGEq:{
00460       PExpVal LExpVal=ArgExpV[0]->EvalExp(ExpEnv, DbgP, DbgChA);
00461       PExpVal RExpVal=ArgExpV[1]->EvalExp(ExpEnv, DbgP, DbgChA);
00462       TExpValType LExpValType=LExpVal->GetValType();
00463       TExpValType RExpValType=RExpVal->GetValType();
00464       if ((LExpValType==evtFlt)&&(RExpValType==evtFlt)){
00465         TFlt Flt;
00466         switch (_ExpOp){
00467           case eoEq: Flt=double(LExpVal->GetFltVal()==RExpVal->GetFltVal()); break;
00468           case eoNEq: Flt=double(LExpVal->GetFltVal()!=RExpVal->GetFltVal()); break;
00469           case eoLss: Flt=double(LExpVal->GetFltVal()<RExpVal->GetFltVal()); break;
00470           case eoGtr: Flt=double(LExpVal->GetFltVal()>RExpVal->GetFltVal()); break;
00471           case eoLEq: Flt=double(LExpVal->GetFltVal()<=RExpVal->GetFltVal()); break;
00472           case eoGEq: Flt=double(LExpVal->GetFltVal()>=RExpVal->GetFltVal()); break;
00473           default: Fail; Flt=0;
00474         }
00475         OutExpVal=TExpVal::New(Flt);
00476       } else
00477       if ((LExpValType==evtStr)&&(RExpValType==evtStr)){
00478         TFlt Flt;
00479         switch (_ExpOp){
00480           case eoEq: Flt=double(LExpVal->GetStrVal()==RExpVal->GetStrVal()); break;
00481           case eoNEq: Flt=double(LExpVal->GetStrVal()!=RExpVal->GetStrVal()); break;
00482           case eoLss: Flt=double(LExpVal->GetStrVal()<RExpVal->GetStrVal()); break;
00483           case eoGtr: Flt=double(LExpVal->GetStrVal()>RExpVal->GetStrVal()); break;
00484           case eoLEq: Flt=double(LExpVal->GetStrVal()<=RExpVal->GetStrVal()); break;
00485           case eoGEq: Flt=double(LExpVal->GetStrVal()>=RExpVal->GetStrVal()); break;
00486           default: Fail; Flt=0;
00487         }
00488         OutExpVal=TExpVal::New(Flt);
00489       } else {
00490         TExcept::Throw("Bad argument types.");
00491       }
00492       break;}
00493     case eoIf:{
00494       PExpVal CondExpVal=ArgExpV[0]->EvalExp(ExpEnv, DbgP, DbgChA);
00495       TExpValType CondExpValType=CondExpVal->GetValType();
00496       if (CondExpValType==evtFlt){
00497         PExpVal ExpVal;
00498         if (CondExpVal->GetFltVal()!=0){
00499           ExpVal=ArgExpV[1]->EvalExp(ExpEnv, DbgP, DbgChA);
00500         } else {
00501           ExpVal=ArgExpV[2]->EvalExp(ExpEnv, DbgP, DbgChA);
00502         }
00503         OutExpVal=ExpVal;
00504       } else {
00505         TExcept::Throw("Bad argument types.");
00506       }
00507       break;}
00508     default: Fail; OutExpVal=NULL;
00509   }
00510   if (DbgP){
00511     DbgChA+="['"; DbgChA+=TExp::GetExpOpStr(_ExpOp);
00512     DbgChA+="'='"; DbgChA+=OutExpVal->GetStr(); DbgChA+="'] ";
00513   }
00514   return OutExpVal;
00515 }
00516 
00517 PExpVal TExp::EvalExp(
00518  const PExpEnv& ExpEnv, const bool& DbgP, TChA& DbgChA){
00519   PExpVal OutExpVal;
00520   TExpType _ExpType=TExpType(int(ExpType));
00521   switch (_ExpType){
00522     case etUndef:
00523       OutExpVal=TExpVal::GetUndefExpVal();
00524       break;
00525     case etVal:
00526       OutExpVal=ExpVal;
00527       break;
00528     case etVec:{
00529       PExpVal ExpVal=TExpVal::New(evtVec);
00530       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00531         PExpVal ArgExpVal=
00532          PExpVal(ArgExpV[ArgExpN]->EvalExp(ExpEnv, DbgP, DbgChA));
00533         ExpVal->AddToVec(ArgExpVal);
00534       }
00535       OutExpVal=ExpVal;
00536       break;}
00537     case etLst:{
00538       PExpVal ExpVal=TExpVal::New(evtLst);
00539       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00540         PExpVal ArgExpVal=
00541          PExpVal(ArgExpV[ArgExpN]->EvalExp(ExpEnv, DbgP, DbgChA));
00542         ExpVal->AddToLst(ArgExpVal);
00543       }
00544       OutExpVal=ExpVal;
00545       break;}
00546     case etOp:
00547       OutExpVal=EvalExpOp(ExpEnv, DbgP, DbgChA); break;
00548     case etVar:{
00549       bool IsVar=false;
00550       PExpVal ExpVal=ExpEnv->GetVarVal(ExpNm.GetUc(), IsVar);
00551       if (!IsVar){TExcept::Throw(TStr("Variable not defined (")+ExpNm+").");}
00552       OutExpVal=ExpVal;
00553       break;}
00554     case etBiConst:
00555       OutExpVal=ExpBi.GetBiConstVal(TExpBiId(int(ExpBiId)));
00556       break;
00557     case etFunc:
00558     case etBiFunc:{
00559       TExpValV ArgExpValV(ArgExpV.Len(), 0);
00560       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00561         PExpVal ArgExpVal=
00562          PExpVal(ArgExpV[ArgExpN]->EvalExp(ExpEnv, DbgP, DbgChA));
00563         ArgExpValV.Add(ArgExpVal);
00564       }
00565       switch (_ExpType){
00566         case etFunc:{
00567           bool IsFunc=false;
00568           PExpVal ExpVal=ExpEnv->GetFuncVal(ExpNm.GetUc(), ArgExpValV, IsFunc);
00569           if (!IsFunc){
00570             TExcept::Throw(TStr("Function not defined (")+ExpNm+").");}
00571           OutExpVal=ExpVal;
00572           break;}
00573         case etBiFunc:
00574           OutExpVal=ExpBi.GetBiFuncVal(TExpBiId(int(ExpBiId)), ArgExpValV, ExpEnv);
00575           break;
00576         default: Fail; OutExpVal=NULL;
00577       }
00578       break;}
00579     default: Fail; OutExpVal=NULL;
00580   }
00581   if (DbgP){
00582     switch (_ExpType){
00583       case etVal:
00584       case etOp:
00585         break;
00586       case etUndef:
00587       case etVec:
00588       case etLst:{
00589         TStr ExpTypeStr=TExp::GetExpTypeStr(_ExpType);
00590         DbgChA+='['; DbgChA+=ExpTypeStr; DbgChA+='=';
00591         DbgChA+=OutExpVal->GetStr(); DbgChA+="] ";
00592         break;}
00593       case etVar:
00594       case etBiConst:
00595       case etFunc:
00596       case etBiFunc:
00597         DbgChA+='['; DbgChA+=ExpNm; DbgChA+='=';
00598         DbgChA+=OutExpVal->GetStr(); DbgChA+="] ";
00599         break;
00600       default: Fail;
00601     }
00602   }
00603   return OutExpVal;
00604 }
00605 
00606 TExpOp TExp::GetExpOpFromLxSym(const TLxSym& LxSym){
00607   switch (LxSym){
00608     case syPlus: return eoPlus;
00609     case syMinus: return eoMinus;
00610     case syAsterisk: return eoMul;
00611     case sySlash: return eoDiv;
00612     case syPercent: return eoMod;
00613     case syExclamation: return eoNot;
00614     case syVBar: return eoOr;
00615     case syAmpersand: return eoAnd;
00616     case syQuestion: return eoIf;
00617     case syHash: return eoIDiv;
00618     case syEq: return eoEq;
00619     case syNEq: return eoNEq;
00620     case syLss: return eoLss;
00621     case syGtr: return eoGtr;
00622     case syLEq: return eoLEq;
00623     case syGEq: return eoGEq;
00624     default: Fail; return eoUndef;
00625   }
00626 }
00627 
00628 TLxSym TExp::GetLxSymFromExpOp(const TExpOp& ExpOp){
00629   switch (ExpOp){
00630     case eoUPlus: return syPlus;
00631     case eoUMinus: return syMinus;
00632     case eoNot: return syExclamation;
00633     case eoPlus: return syPlus;
00634     case eoMinus: return syMinus;
00635     case eoMul: return syAsterisk;
00636     case eoDiv: return sySlash;
00637     case eoIDiv: return syHash;
00638     case eoMod: return syPercent;
00639     case eoAnd: return syAmpersand;
00640     case eoOr: return syVBar;
00641     case eoEq: return syEq;
00642     case eoNEq: return syNEq;
00643     case eoLss: return syLss;
00644     case eoGtr: return syGtr;
00645     case eoLEq: return syLEq;
00646     case eoGEq: return syGEq;
00647     case eoIf: return syQuestion;
00648     default: Fail; return syUndef;
00649   }
00650 }
00651 
00652 PExp TExp::LoadTxtFact(TILx& Lx, const TFSet& Expect){
00653   PExp Exp;
00654   switch (Lx.Sym){
00655     case syFlt:{
00656       PExpVal ExpVal=TExpVal::New(Lx.Flt);
00657       Exp=PExp(new TExp(ExpVal));
00658       Lx.GetSym(Expect);
00659       break;}
00660     case syIdStr:{
00661       TStr ExpNm=Lx.Str;
00662       Lx.GetSym(TFSet(Expect)|syLParen);
00663       if (Lx.Sym==syLParen){
00664         TExpV ArgExpV;
00665         Lx.GetSym(TFSet(ExpExpect)|syRParen);
00666         while (Lx.Sym!=syRParen){
00667           if (Lx.Sym==syComma){Lx.GetSym(ExpExpect);}
00668           PExp ArgExp=LoadTxtExp(Lx, TFSet()|syComma|syRParen);
00669           ArgExpV.Add(ArgExp);
00670         }
00671         Lx.GetSym(Expect);
00672         Exp=PExp(new TExp(ExpNm, ArgExpV));
00673       } else {
00674         Exp=PExp(new TExp(ExpNm));
00675       }
00676       break;}
00677     case syQStr:{
00678       PExpVal ExpVal=TExpVal::New(Lx.Str);
00679       Exp=PExp(new TExp(ExpVal));
00680       Lx.GetSym(Expect);
00681       break;}
00682     case syLParen:{
00683       Lx.GetSym(ExpExpect);
00684       Exp=LoadTxtExp(Lx, TFSet()|syRParen);
00685       Exp->IsParen=true;
00686       Lx.GetSym(Expect);
00687       break;}
00688     default: Fail;
00689   }
00690   return Exp;
00691 }
00692 
00693 PExp TExp::LoadTxtMulExp(TILx& Lx, const TFSet& Expect){
00694   PExp Exp=LoadTxtFact(Lx, TFSet(Expect)|MulOpSymSet);
00695   while (MulOpSymSet.In(Lx.Sym)){
00696     TExpOp ExpOp=GetExpOpFromLxSym(Lx.Sym);
00697     Lx.GetSym(FactExpExpect);
00698     PExp RExp=LoadTxtFact(Lx, TFSet(Expect)|MulOpSymSet);
00699     Exp=PExp(new TExp(ExpOp, Exp, RExp));
00700   }
00701   return Exp;
00702 }
00703 
00704 PExp TExp::LoadTxtAddExp(TILx& Lx, const TFSet& Expect){
00705   TExpOp PrefExpOp=eoUndef;
00706   if (Lx.Sym==syPlus){PrefExpOp=eoUPlus; Lx.GetSym(MulExpExpect);}
00707   else if (Lx.Sym==syMinus){PrefExpOp=eoUMinus; Lx.GetSym(MulExpExpect);}
00708   PExp Exp=LoadTxtMulExp(Lx, TFSet(Expect)|AddOpSymSet);
00709   if (PrefExpOp!=eoUndef){
00710     Exp=PExp(new TExp(PrefExpOp, Exp));}
00711   while (AddOpSymSet.In(Lx.Sym)){
00712     TExpOp ExpOp=GetExpOpFromLxSym(Lx.Sym);
00713     Lx.GetSym(MulExpExpect);
00714     PExp RExp=LoadTxtMulExp(Lx, TFSet(Expect)|AddOpSymSet);
00715     Exp=PExp(new TExp(ExpOp, Exp, RExp));
00716   }
00717   return Exp;
00718 }
00719 
00720 PExp TExp::LoadTxtRelExp(TILx& Lx, const TFSet& Expect){
00721   PExp Exp=LoadTxtAddExp(Lx, TFSet(Expect)|RelOpSymSet);
00722   if (RelOpSymSet.In(Lx.Sym)){
00723     TExpOp ExpOp=GetExpOpFromLxSym(Lx.Sym);
00724     Lx.GetSym(AddExpExpect);
00725     PExp RExp=LoadTxtAddExp(Lx, Expect);
00726     Exp=PExp(new TExp(ExpOp, Exp, RExp));
00727   }
00728   return Exp;
00729 }
00730 
00731 PExp TExp::LoadTxtExp(TILx& Lx, const TFSet& Expect){
00732   PExp Exp=LoadTxtRelExp(Lx, TFSet(Expect)|syQuestion);
00733   if (Lx.Sym==syQuestion){
00734     TExpOp ExpOp=GetExpOpFromLxSym(Lx.Sym);
00735     Lx.GetSym(ExpExpect);
00736     PExp ThenExp=LoadTxtExp(Lx, TFSet()|syColon);
00737     Lx.GetSym(ExpExpect);
00738     PExp ElseExp=LoadTxtExp(Lx, Expect);
00739     Exp=PExp(new TExp(ExpOp, Exp, ThenExp, ElseExp));
00740   }
00741   return Exp;
00742 }
00743 
00744 void TExp::SaveTxtOp(TOLx& Lx) const {
00745   IAssert(TExpType(static_cast<int>(ExpType))==etOp);
00746   TExpOp _ExpOp=TExpOp(int(ExpOp));
00747   TLxSym OpSym=GetLxSymFromExpOp(_ExpOp);
00748   switch (_ExpOp){
00749     case eoUPlus:
00750     case eoUMinus:
00751     case eoNot:
00752       Lx.PutSym(OpSym); ArgExpV[0]->SaveTxt(Lx);
00753       break;
00754     case eoPlus: case eoMinus:
00755     case eoMul: case eoDiv:
00756     case eoIDiv: case eoMod:
00757     case eoAnd: case eoOr:
00758     case eoEq: case eoNEq:
00759     case eoLss: case eoGtr:
00760     case eoLEq: case eoGEq:
00761       ArgExpV[0]->SaveTxt(Lx); Lx.PutSym(OpSym); ArgExpV[1]->SaveTxt(Lx);
00762       break;
00763     case eoIf:
00764       ArgExpV[0]->SaveTxt(Lx); Lx.PutSym(OpSym);
00765       ArgExpV[1]->SaveTxt(Lx); Lx.PutSym(syColon); ArgExpV[2]->SaveTxt(Lx);
00766       break;
00767     default: Fail;
00768   }
00769 }
00770 
00771 TExp::TExp(const TExpOp& _ExpOp,
00772  const PExp& Exp1, const PExp& Exp2, const PExp& Exp3):
00773   ExpType(etOp), IsParen(false),
00774   ExpVal(), ExpNm(), ExpOp(_ExpOp), ExpBiId(), ArgExpV(){
00775   ArgExpV.Add(Exp1);
00776   if (!Exp2.Empty()){ArgExpV.Add(Exp2);}
00777   if (!Exp3.Empty()){ArgExpV.Add(Exp3);}
00778 }
00779 
00780 TExp::TExp(const PExpVal& _ExpVal):
00781   ExpType(etVal), IsParen(false),
00782   ExpVal(_ExpVal), ExpNm(), ExpOp(), ExpBiId(), ArgExpV(){}
00783 
00784 TExp::TExp(const TStr& _VarNm):
00785   ExpType(), IsParen(false),
00786   ExpVal(), ExpNm(_VarNm), ExpOp(), ExpBiId(), ArgExpV(){
00787   TExpBiId _ExpBiId;
00788   if (ExpBi.IsExpBiId(ExpNm, _ExpBiId)){
00789     ExpType=etBiConst;
00790     ExpBiId=TInt(int(_ExpBiId));
00791   } else {
00792     ExpType=etVar;
00793   }
00794 }
00795 
00796 TExp::TExp(const TStr& _FuncNm, const TExpV& _ArgExpV):
00797   ExpType(), IsParen(false),
00798   ExpVal(), ExpNm(_FuncNm), ExpOp(), ExpBiId(), ArgExpV(_ArgExpV){
00799   TExpBiId _ExpBiId;
00800   if (ExpBi.IsExpBiId(ExpNm, _ExpBiId)){
00801     ExpType=etBiFunc;
00802     ExpBiId=TInt(int(_ExpBiId));
00803   } else {
00804     ExpType=etFunc;
00805   }
00806 }
00807 
00808 PExp TExp::LoadTxt(
00809  const PSIn& SIn, bool& Ok, TStr& MsgStr, const TFSet& Expect){
00810   TILx Lx(SIn, TFSet()|iloCmtAlw|iloCsSens|iloExcept);
00811   PExp Exp; Ok=true; MsgStr="Ok";
00812   try {
00813     Lx.GetSym(ExpExpect);
00814     Exp=LoadTxtExp(Lx, Expect);
00815   }
00816   catch (PExcept Except){
00817     Ok=false; MsgStr=Except->GetMsgStr();
00818     Exp=PExp(new TExp(etUndef));
00819   }
00820   return Exp;
00821 }
00822 
00823 void TExp::SaveTxt(TOLx& Lx) const {
00824   if (IsParen){Lx.PutSym(syLParen);}
00825   TExpType _ExpType=TExpType(int(ExpType));
00826   switch (_ExpType){
00827     case etVal:
00828       ExpVal->SaveTxt(Lx); break;
00829     case etVec:{
00830       Lx.PutSym(syLBrace);
00831       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00832         if (ArgExpN>0){Lx.PutSym(syComma);}
00833         ArgExpV[ArgExpN]->SaveTxt(Lx);
00834       }
00835       Lx.PutSym(syRBrace);
00836       break;}
00837     case etLst:{
00838       Lx.PutSym(syLBracket);
00839       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00840         if (ArgExpN>0){Lx.PutSym(syComma);}
00841         ArgExpV[ArgExpN]->SaveTxt(Lx);
00842       }
00843       Lx.PutSym(syRBracket);
00844       break;}
00845     case etOp:
00846       SaveTxtOp(Lx); break;
00847     case etVar:
00848     case etBiConst:
00849       Lx.PutIdStr(ExpNm); break;
00850     case etFunc:
00851     case etBiFunc:{
00852       Lx.PutIdStr(ExpNm);
00853       Lx.PutSym(syLParen);
00854       for (int ArgExpN=0; ArgExpN<ArgExpV.Len(); ArgExpN++){
00855         if (ArgExpN>0){Lx.PutSym(syComma);}
00856         ArgExpV[ArgExpN]->SaveTxt(Lx);
00857       }
00858       Lx.PutSym(syRParen);
00859       break;}
00860     default: Fail;
00861   }
00862   if (IsParen){Lx.PutSym(syRParen);}
00863 }
00864 
00865 TStr TExp::GetStr() const {
00866   PSOut SOut=TMOut::New(); TMOut& MOut=*(TMOut*)SOut();
00867   SaveTxt(SOut);
00868   TStr ExpStr=TStr::LoadTxt(MOut.GetSIn());
00869   return ExpStr;
00870 }
00871 
00872 TStr TExp::GetTopObjNm() const {
00873   TStr TopObjNm;
00874   TExpType _ExpType=TExpType(int(ExpType));
00875   switch (_ExpType){
00876     case etOp:{
00877       TExpOp _ExpOp=TExpOp(int(ExpOp));
00878       TopObjNm=GetExpOpStr(_ExpOp);
00879       break;}
00880     case etVar:
00881     case etBiConst:
00882     case etFunc:
00883     case etBiFunc:{
00884       TopObjNm=ExpNm; break;}
00885     default: break;
00886   }
00887   return TopObjNm;
00888 }
00889 
00890 int TExp::GetArgExps() const {
00891   return ArgExpV.Len();
00892 }
00893 
00894 TStr TExp::GetArgExpStr(const int& ArgExpN) const {
00895   return ArgExpV[ArgExpN]->GetStr();
00896 }
00897 
00898 PExpVal TExp::Eval(
00899  bool& Ok, TStr& MsgStr, const bool& DbgP, TStr& DbgStr, const PExpEnv& ExpEnv){
00900   Ok=true; MsgStr="Ok";
00901   PExpVal ExpVal; TChA DbgChA;
00902   if (DbgP){DbgChA+="Debug Expression: ";}
00903   try {
00904     ExpVal=EvalExp(ExpEnv, DbgP, DbgChA);
00905   }
00906   catch (PExcept E){
00907     Ok=false; MsgStr=E->GetMsgStr();
00908   }
00909   if (!Ok){return TExpVal::GetUndefExpVal();}
00910   if (DbgP){
00911     DbgChA+='['; DbgChA+=GetStr(); DbgChA+=" -> ";
00912     DbgChA+=ExpVal->GetStr(); DbgChA+="] "; DbgChA+=MsgStr;
00913     DbgStr=DbgChA;
00914   }
00915   return ExpVal;
00916 }
00917 
00918 PExpVal TExp::LoadAndEvalExpL(
00919  const TStr& ExpLStr, bool& Ok, TStr& MsgStr, const PExpEnv& ExpEnv){
00920   // create final expression value
00921   PExpVal ExpVal;
00922   // transform exp. str. to input stream
00923   PSIn SIn=TStrIn::New(ExpLStr);
00924   // create lexical
00925   TILx Lx(SIn, TFSet()|iloCmtAlw|iloCsSens|iloExcept);
00926   TFSet Expect=TFSet()|sySemicolon|syEof;
00927   // load & evaluate expression separated by semicolon
00928   while (Lx.Sym!=syEof){
00929     // create expression
00930     PExp Exp; Ok=true; MsgStr="Ok";
00931     try {
00932       Lx.GetSym(ExpExpect);
00933       Exp=LoadTxtExp(Lx, Expect);
00934     }
00935     catch (PExcept Except){
00936       Ok=false; MsgStr=Except->GetMsgStr();
00937       Exp=PExp(new TExp(etUndef));
00938     }
00939     // evaluate expression
00940     if (Ok){
00941       ExpVal=Exp->Eval(Ok, MsgStr, ExpEnv);
00942       //printf("%s\n", ExpVal->GetStr().CStr());
00943       if (!Ok){
00944         return NULL;}
00945     } else {
00946       return NULL;
00947     }
00948   }
00949   return ExpVal;
00950 }
00951 
00952 TStr TExp::GetExpTypeStr(const TExpType& ExpType){
00953   switch (ExpType){
00954     case etUndef: return "Undef";
00955     case etVal: return "Val";
00956     case etVec: return "Vec";
00957     case etLst: return "Lst";
00958     case etOp: return "Op";
00959     case etVar: return "Var";
00960     case etBiConst: return "BiConst";
00961     case etFunc: return "Func";
00962     case etBiFunc: return "BiFunc";
00963     default: Fail; return "";
00964   }
00965 }
00966 
00967 void TExp::GetBiDescV(TStrPrV& BiDescV){
00968   BiDescV.Clr();
00969   // constants
00970   BiDescV.Add(TStrPr("True", "Logical 'True' == 1."));
00971   BiDescV.Add(TStrPr("False", "Logical 'False' == 0."));
00972   BiDescV.Add(TStrPr("E", "Nat. logarithm basis (2.7182...)."));
00973   BiDescV.Add(TStrPr("Pi", "Constant pi (3.1415...)."));
00974 
00975   // trigonometric funcions
00976   BiDescV.Add(TStrPr("Sin(X)", "Sine of angle in radians."));
00977   BiDescV.Add(TStrPr("Cos(X)", "Cosine of angle in radians."));
00978   BiDescV.Add(TStrPr("Tan(X)", "Tangent of angle in radians."));
00979   BiDescV.Add(TStrPr("ASin(X)", "Arc sine of (-1..+1)."));
00980   BiDescV.Add(TStrPr("ACos(X)", "Arc cosine of (-1..+1)."));
00981   BiDescV.Add(TStrPr("ATan(X)", "Arc tangent of (-inf..+inf)."));
00982   BiDescV.Add(TStrPr("SinH(X)", "Hyperbolic sine."));
00983   BiDescV.Add(TStrPr("CosH(X)", "Hyperbolic cosine."));
00984   BiDescV.Add(TStrPr("TanH(X)", "Hyperbolic tangent."));
00985 
00986   // exponential functions
00987   BiDescV.Add(TStrPr("Pow(X, Y)", "X to the power of Y."));
00988   BiDescV.Add(TStrPr("Exp(X)", "Exponential E to the power of X."));
00989   BiDescV.Add(TStrPr("Sqr(X)", "X squared."));
00990   BiDescV.Add(TStrPr("Sqrt(X)", "Positive square root."));
00991   BiDescV.Add(TStrPr("Log(X)", "Natural logarithm."));
00992   BiDescV.Add(TStrPr("Log10(X)", "Base 10 logarithm."));
00993 
00994   // number manipulation functions
00995   BiDescV.Add(TStrPr("Ceil(X)", "The smallest integer not less than X."));
00996   BiDescV.Add(TStrPr("Floor(X)", "The largest integer not greater than X."));
00997   BiDescV.Add(TStrPr("Int(X)", "Integer part of X."));
00998   BiDescV.Add(TStrPr("Frac(X)", "Fractional part of X."));
00999   BiDescV.Add(TStrPr("Abs(X)", "Absolute value of X."));
01000 
01001   // random deviates
01002   BiDescV.Add(TStrPr("UniDev()", "Uniform deviate (0..1)."));
01003   BiDescV.Add(TStrPr("NrmDev()", "Normal deviate (0, 1)."));
01004   BiDescV.Add(TStrPr("ExpDev()", "Exponential deviate."));
01005   BiDescV.Add(TStrPr("GamDev(Order)", "Gamma deviate of Order."));
01006   BiDescV.Add(TStrPr("PoiDev(Mean)", "Poisson deviate."));
01007   BiDescV.Add(TStrPr("BinDev(Prb, Trials)", "Binomial deviate."));
01008 
01009   // operators
01010   BiDescV.Add(TStrPr("+N", "Unary plus."));
01011   BiDescV.Add(TStrPr("-N", "Unary minus."));
01012   BiDescV.Add(TStrPr("!L", "Not."));
01013   BiDescV.Add(TStrPr("N1+N2", "Plus."));
01014   BiDescV.Add(TStrPr("N1-N2", "Minus."));
01015   BiDescV.Add(TStrPr("N1*N2", "Multiply."));
01016   BiDescV.Add(TStrPr("N1/N2", "Division."));
01017   BiDescV.Add(TStrPr("N1#N2", "Integer division."));
01018   BiDescV.Add(TStrPr("N1%N2", "Modulo."));
01019   BiDescV.Add(TStrPr("L1&L2", "And."));
01020   BiDescV.Add(TStrPr("L1|L2", "Or."));
01021   BiDescV.Add(TStrPr("E1=E2", "Equal."));
01022   BiDescV.Add(TStrPr("E1<>E2", "Not equal."));
01023   BiDescV.Add(TStrPr("E1<E2", "Less."));
01024   BiDescV.Add(TStrPr("E1>E2", "Greater."));
01025   BiDescV.Add(TStrPr("E1<=E2", "Less or equal."));
01026   BiDescV.Add(TStrPr("E1>=E2", "Greater or equal."));
01027   BiDescV.Add(TStrPr("L?E1:E2", "If L then return E1 else return E2."));
01028 }
01029 
01031 // Expression-Help-Object
01032 TStr TExpHelpObj::GetHdArgNmStr() const {
01033   TChA ChA;
01034   switch (Type){
01035     case ehotOp: {// operator
01036       TStr OpStr=HdItem->GetNm();
01037       if (ArgItemV.Len()==1){
01038         ChA+=OpStr; ChA+=" "; ChA+=ArgItemV[0]->GetNm();
01039       } else
01040       if (ArgItemV.Len()==2){
01041         ChA+=ArgItemV[0]->GetNm();
01042         ChA+=" "; ChA+=OpStr; ChA+=" ";
01043         ChA+=ArgItemV[1]->GetNm();
01044       } else
01045       if (ArgItemV.Len()==3){
01046         ChA+=ArgItemV[0]->GetNm();
01047         ChA+=" "; ChA+=OpStr; ChA+=" ";
01048         ChA+=ArgItemV[1]->GetNm();
01049         ChA+=" "; ChA+=":"; ChA+=" ";
01050         ChA+=ArgItemV[2]->GetNm();
01051       } else {
01052         Fail;
01053       }
01054       break;}
01055     case ehotVar: // variable
01056       ChA+=HdItem->GetNm(); break;
01057     case ehotFunc: // function
01058       ChA+=HdItem->GetTypeStr(); ChA+=" <- ";
01059       ChA+=HdItem->GetNm();
01060       ChA+="(";
01061       {for (int ArgN=0; ArgN<ArgItemV.Len(); ArgN++){
01062         if (ArgN>0){ChA+=", ";}
01063         ChA+=ArgItemV[ArgN]->GetNm();
01064       }}
01065       ChA+=")";
01066       break;
01067     case ehotTempl: // template
01068       ChA+=HdItem->GetTypeStr(); break;
01069     default: Fail;
01070   }
01071   return ChA;
01072 }
01073 
01074 TExpHelpObjType TExpHelpObj::GetObjTypeFromStr(const TStr& TypeStr){
01075   if (TypeStr=="Op"){return ehotOp;}
01076   else if (TypeStr=="Var"){return ehotVar;}
01077   else if (TypeStr=="Func"){return ehotFunc;}
01078   else if (TypeStr=="Templ"){return ehotTempl;}
01079   else {TExcept::Throw("Invalid object type.", TypeStr); return ehotUndef;}
01080 }
01081 
01083 // Expression-Help
01084 PExpHelp TExpHelp::LoadXml(const PSIn& SIn){
01085   // create expression help
01086   PExpHelp ExpHelp=TExpHelp::New();
01087   // load xml with expression help
01088   PXmlDoc Doc=TXmlDoc::LoadTxt(SIn);
01089   // retrieve objects
01090   TXmlTokV ObjTokV; Doc->GetTagTokV("ExpHelp|Obj", ObjTokV);
01091   for (int ObjTokN=0; ObjTokN<ObjTokV.Len(); ObjTokN++){
01092     PXmlTok ObjTok=ObjTokV[ObjTokN];
01093     // type
01094     TStr TypeStr=ObjTok->GetTagTok("Type")->GetTokStr(false);
01095     // category
01096     TStr CatNm=ObjTok->GetTagTok("Cat")->GetTokStr(false);
01097     // header
01098     TStr HdNm=ObjTok->GetTagTok("Head|Name")->GetTokStr(false);
01099     TStr HdTypeStr=ObjTok->GetTagTok("Head|Type")->GetTokStr(false);
01100     TStr HdDescStr=ObjTok->GetTagTok("Head|Desc")->GetTokStr(false);
01101     PExpHelpItem HdItem=
01102      TExpHelpItem::New(HdNm, HdTypeStr, HdDescStr, "");
01103     // arguments
01104     TXmlTokV ArgTokV; ObjTok->GetTagTokV("Args|Arg", ArgTokV);
01105     TExpHelpItemV ArgItemV;
01106     for (int ArgTokN=0; ArgTokN<ArgTokV.Len(); ArgTokN++){
01107       PXmlTok ArgTok=ArgTokV[ArgTokN];
01108       // argument
01109       TStr ArgNm=ArgTok->GetTagTok("Name")->GetTokStr(false);
01110       TStr ArgTypeStr=ArgTok->GetTagTok("Type")->GetTokStr(false);
01111       TStr ArgDescStr=ArgTok->GetTagTok("Desc")->GetTokStr(false);
01112       TStr ArgDfValStr=ArgTok->GetTagTok("Default")->GetTokStr(false);
01113       PExpHelpItem ArgItem=
01114        TExpHelpItem::New(ArgNm, ArgTypeStr, ArgDescStr, ArgDfValStr);
01115       ArgItemV.Add(ArgItem);
01116     }
01117     // create & add object
01118     TExpHelpObjType Type=TExpHelpObj::GetObjTypeFromStr(TypeStr);
01119     PExpHelpObj Obj=TExpHelpObj::New(Type, CatNm, HdItem, ArgItemV);
01120     ExpHelp->AddObj(Obj);
01121   }
01122   // return result
01123   return ExpHelp;
01124 }
01125 
01126 void TExpHelp::GetCatNmV(TStrV& CatNmV) const {
01127   CatNmV.Clr();
01128   for (int ObjN=0; ObjN<ObjV.Len(); ObjN++){
01129     TStr CatNm=ObjV[ObjN]->GetCatNm();
01130     CatNmV.AddUnique(CatNm);
01131   }
01132   CatNmV.Ins(0, "All");
01133 }
01134 
01135 void TExpHelp::GetObjHdNmV(const TStr& CatNm, TStrV& ObjHdNmV) const {
01136   ObjHdNmV.Clr();
01137   for (int ObjN=0; ObjN<ObjV.Len(); ObjN++){
01138     TStr ObjCatNm=ObjV[ObjN]->GetCatNm();
01139     TStr ObjHdNm=ObjV[ObjN]->GetHdItem()->GetNm();
01140     if ((CatNm.Empty())||(CatNm=="All")||(CatNm==ObjCatNm)){
01141       ObjHdNmV.AddUnique(ObjHdNm);}
01142   }
01143   ObjHdNmV.Sort();
01144 }
01145 
01146 PExpHelpObj TExpHelp::GetObj(const TStr& ObjNm) const {
01147   PExpHelpObj Obj;
01148   for (int ObjN=0; ObjN<ObjV.Len(); ObjN++){
01149     if (ObjV[ObjN]->GetHdItem()->GetNm().GetUc()==ObjNm.GetUc()){
01150       return ObjV[ObjN];}
01151   }
01152   return NULL;
01153 }
01154