SNAP Library , Developer Reference  2013-01-07 14:03:36
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 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