#include #include #include "expclass.h" static bool Factorial( Exp *E,int node, bool pre, int arg,Exp::NodeType t, bool eval) { if(!eval) return false; // use at Evaluation stage if(t!=Exp::Number) return false; // can only do numbers if(pre) return false; // ! is postfix double x=1,n=E->GetValue(arg),i; // get n if(n>100 || E->GetSign(arg)<0) return false; // size limit for(i=2; i<=n; i++) x*=i; // calculation E->ToNumber(node,x); // replace n! with result return true; } static bool ShiftL( Exp *E, int node, bool eval) {// shift left, also right with -ve shift if(!eval) return false; // do in eval mode only int left=E->GetLink(node,0); int lt=E->GetType(left); if(lt!=Exp::Number && lt!=Exp::Frac) return false; // number on left? int right=E->GetLink(node,1); int rt=E->GetType(right); if(rt!=Exp::Number && rt!=Exp::Frac) return false; // and on right double vleft=E->ValueOf(left); // works for Fracs too double vright=E->ValueOf(right); E->ToNumber(node,vleft*std::pow(2,vright)); // cheating return true; // because we changed something } static bool Power( Exp *E,int node, bool eval) { if(eval) return false; else { // try replacing cos()^2 with 1-sin()^2 int n=E->GetLink(node,0); // cos(x)? if(E->GetText(n)=="cos()") // check its cos()^2 if(E->GetType(node,1)==Exp::Number && E->GetValue(node,1)==2.0) { int Root=E->GetRoot(node); // full expression int old_size=E->GetSize(Root); // its size, in nodes, to compare later QString old_ex=E->ExpText(node); // in case it needs to go back n=E->GetLink(n,0); // x is only child of cos() QString x=E->ExpText(n); // "x" // (1-sin( x )^2) QString ex="(1-sin("+x+")^2)"; E->ReplaceExp(node,ex); // test if its shorter if(old_size<=E->GetSize(Root)) // if not { E->ReplaceExp(node,old_ex); // put old back return false; // no change } else return true; // changed } } return false; // no change } static bool Var( Exp *E,int node, int key, bool eval) { // replace e and pi with constants if(!eval) return false; switch(key) { case 1: // pi E->ToNumber(node,2*std::asin(1)); break; case 2: // e E->ToNumber(node,std::exp(1)); break; default: return false; // no change } return true; // changed } // example trig calculations static bool SinFun( Exp *E,int node, int arg,Exp::NodeType t, bool eval) { if(!eval) return false; if(t!=Exp::Number && t!=Exp::Frac) return false; E->ToNumber(node,std::sin(E->ValueOf(arg))); return true; } static bool CosFun( Exp *E,int node, int arg,Exp::NodeType t, bool eval) { if(!eval) return false; if(t!=Exp::Number && t!=Exp::Frac) return false; E->ToNumber(node,std::cos(E->ValueOf(arg))); return true; } static bool TanFun( Exp *E,int node, int arg,Exp::NodeType t, bool eval) { if(!eval) return false; if(t!=Exp::Number && t!=Exp::Frac) return false; E->ToNumber(node,std::tan(E->ValueOf(arg))); return true; } // recognize and solve Quadratic static bool SolveFun( Exp *E,int n, int arg1,Exp::NodeType t1, int arg2,Exp::NodeType t2, bool eval) { Q_UNUSED(arg1) if(eval) return false; // do some checks so we don't waste time if(t1!=Exp::Plus) return false; // root is + if(t2!=Exp::Variable) return false; // we need indi var if(E->FreeOf(arg1,Exp::Power,2)) return false; // must have ^ QString x=E->GetText(arg2); // "x" indi var string if(E->FreeOf(arg1,x,2)) return false; // must be a fun of x // check Signature // get sig by testing standard formula // short form is OK, only one indi var QString sig="solve(){}(+(*$#)(*(^$#)#)#)$"; // tell Consts() and Signature() indi variable x // and used to collect parts, i.e. a,b,c QList parts={x}; // if a or b missing set them to 1 E->Consts(n,parts); // Get and compare signature E->Signature(n,parts); int np=parts.count(); if(np!=7) return false; // check it was not x^2 or something if(parts[5]!=sig) return false; // short form is next to last // get index in parts from test results above // solve(a*x^2+b*x+c){x} // 3 0 2 1 0 4 if(parts[2]!="2") return false; // not quadratic if not 2 QString a=parts[3]; QString b=parts[1]; QString c=parts[4]; // (- b +(( b ^2-4* a * c )^0.5))/(2* a ) QString s1="(-"+b+"+(("+b+"^2-4*"+a+"*"+c+")^0.5))/(2*"+a+")"; // (- b -(( b ^2-4* a * c )^0.5))/(2* a ) QString s2="(-"+b+"-(("+b+"^2-4*"+a+"*"+c+")^0.5))/(2*"+a+")"; // two results returned in a , list E->ReplaceExp(n,"("+s1+","+s2+")"); return true; } // utility function to find Signature and parts of Expression // this is useful when writing functions like solve above static bool Parts( Exp *E,int n, int arg1,Exp::NodeType t1, int arg2,Exp::NodeType t2, bool eval) { Q_UNUSED(n) Q_UNUSED(t1) if(eval) return false; QList parts; // for indi var, and captured parts int nv=E->LinksCount(arg2); if(nv==0 || t2!=Exp::Comma) parts.append(E->ExpText(arg2)); else for(int i=0; iGetLink(arg2,i); parts.append(E->ExpText(l)); } QList parts2=parts; std::cout<<"\nSignature();\n"; E->Signature(arg1,parts); for(int i=0; iSimplify(arg1); E->Consts(arg1,parts2); std::cout<<"-> "<ExpText(arg1).toStdString()<<"\n"; std::cout<<"\nSignature();\n"; E->Signature(arg1,parts2); for(int i=0; i parts; // for indi var, and captured parts while(s[0]!='q' || strlen(s)>1) { std::cin.getline(s,1024); exp=s; // Enter and Simplify expression int e1=E.NewExp(exp); // check for errors if(E.GetType(e1)==Exp::Error) { exp=E.GetText(e1); std::cout<<"-> "< "<