#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) { // int powers of _i int n1=E->GetLink(node,1); if(E->GetType(n1)==Exp::Number) { double v=E->GetValue(n1); // if was -ve it will have been reciprocated int V=((int)(v+0.5)); QString s=E->ExpText(node); if(s.contains("_i") && v==V) {// maybe one V=V%4; if(E->GetSign(node,0)==1 && s.left(3)=="_i^") // +_i^ { if(V==0) {E->ToNumber(node,1); return true;} if(V==1) return false; if(V==2) {E->ToNumber(node,-1); return true;} if(V==3) {E->ReplaceExp(node,"-_i"); return true;} } else if(s.left(6)=="(-_i)^") { // -_i^ if(V==0) {E->ReplaceExp(node,"1"); return true;} if(V==1) return false; if(V==2) {E->ToNumber(node,-1); return true;} if(V==3) {E->ReplaceExp(node,"_i"); return true;} } } } 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 Devide( Exp *E,int node, bool eval) { if(eval) { // possible x/_i... int n1=E->GetLink(node,1); if(!E->FreeOf(n1,"_i",2)) { if(E->GetType(n1)==Exp::RBracket) // look inside brackets in a/(b*c) n1=E->GetLink(n1,0); int t=E->GetType(n1); if(t==Exp::Symbol || t==Exp::Times) {// only alter x/_i or x/(a*_i*...) QList parts; int n=E->PartsText(n1,parts),i; // factors of * parts.append(E->GetText(n1)); n++; // include possible lone _i for(i=0; iToNumber(E->GetLink(n1,i),1); // change to 1 else // its a lonesome _i E->ToNumber(n1,1); // ditto E->InsertTimes(node,-1); // move to top of fraction E->AdoptSym(node,"_i",1); // put _i back return true; } } } } } return false; } static bool Sym( 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; } bool Query(Exp *E,int node,bool pre,int arg,Exp::NodeType t,bool eval) {// conditional operator ?(test){true,false} test==0 for false if(!pre) return false; if(t!=Exp::RCBracket) return false; int condition=E->GetLink(arg,0); if(E->GetType(condition)!=Exp::Number) return false; int actions=E->GetLink(arg,1); if(E->LinksCount(actions)!=2) return false; int tru=E->GetLink(actions,0); int fal=E->GetLink(actions,1); if(E->GetValue(condition)==0) E->Over(node,fal); else E->Over(node,tru); 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::Symbol) 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<<"-> "< "< "<