// -*- mode:C++ ; compile-command: "g++-3.4 -I.. -g -c intgab.cc -DHAVE_CONFIG_H -DIN_GIAC" -*- #include "giacPCH.h" /* * Copyright (C) 2000,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ using namespace std; #include #include "vector.h" #include #include #include "sym2poly.h" #include "usual.h" #include "intgab.h" #include "subst.h" #include "derive.h" #include "lin.h" #include "vecteur.h" #include "gausspol.h" #include "plot.h" #include "prog.h" #include "modpoly.h" #include "series.h" #include "tex.h" #include "ifactor.h" #include "risch.h" #include "solve.h" #include "intg.h" #include "desolve.h" #include "alg_ext.h" #include "misc.h" #include "maple.h" #include "rpn.h" #include "giacintl.h" #ifdef HAVE_LIBGSL #include #include #include #include #include #include #endif #ifndef NO_NAMESPACE_GIAC namespace giac { #endif // ndef NO_NAMESPACE_GIAC // check whether an expression is meromorphic // returns -1 if x is not an IDNT // return 2 if rational // return 3 if rational fraction of x, sin(a*x+b), cos(a*x+b) // return 4 if rational fraction of x, exp(a*x+b) where re(a)!=0 // return 5 if ln(P)*A==rational fraction + B==rational fraction // TODO: 6 if exp(a[0]*x^2+a[1]*x+a[2])*b+P, P,b =rational, a[0]<0 int is_meromorphic(const gen & g,const gen & x,gen & a,gen & b,gen & P,GIAC_CONTEXT){ if (x.type!=_IDNT) return -1; if (g.type<=_IDNT) return 2; if (g.type==_VECT){ const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); for (;it!=itend;++it){ if (!is_meromorphic(*it,x,a,b,P,contextptr)) return 0; } return 1; } if (g.type==_SYMB){ vecteur v; rlvarx(g,x,v); islesscomplexthanf_sort(v.begin(),v.end()); if (v==vecteur(1,x)) return 2; if (v.size()<2 || v[1].type!=_SYMB) return 0; P=v[1]._SYMBptr->feuille; if (v.size()==2) { if (v[1].is_symb_of_sommet(at_exp)){ if (is_linear_wrt(P,x,a,b,contextptr)){ if (is_zero(re(a,contextptr))){ a=a/cst_i; b=b/cst_i; return 3; } return 4; } identificateur t(" t"); gen tt(t); gen g2=subst(g,v[1],tt,false,contextptr),bcst; if (is_linear_wrt(g2,t,b,bcst,contextptr)){ gen A,B,C; if (is_quadratic_wrt(P,x,A,B,C,contextptr) && is_strictly_positive(-A,contextptr)){ a=makevecteur(A,B,C); P=bcst; return 6; } } } if ( (v[1].is_symb_of_sommet(at_cos) || v[1].is_symb_of_sommet(at_sin)) && is_linear_wrt(P,x,a,b,contextptr) && is_zero(im(a,contextptr)) ) return 3; if (v[1].is_symb_of_sommet(at_ln)){ identificateur t(" t"); gen tt(t); gen g2=subst(g,v[1],tt,false,contextptr); if (is_linear_wrt(g2,t,a,b,contextptr)) return 5; } } if (v.size()==3){ if (v[1].is_symb_of_sommet(at_cos) && v[2].is_symb_of_sommet(at_sin)){ gen v2f=v[2]._SYMBptr->feuille; if (P==v2f && is_linear_wrt(P,x,a,b,contextptr) && is_zero(im(a,contextptr))) return 3; } } const_iterateur it=v.begin(),itend=v.end(); for (;it!=itend;++it){ if (it->type==_IDNT) continue; if (it->type!=_SYMB) return 0; unary_function_ptr * u=&it->_SYMBptr->sommet; if (u==at_sin || u==at_cos || u==at_tan || u==at_exp || u==at_sinh || u==at_cosh || u==at_tanh){ // the argument must not have singularities if (find_singularities(it->_SYMBptr->feuille,*x._IDNTptr,1,contextptr).empty()) continue; } return 0; } return 1; } return 0; } int fast_is_even_odd(const gen & f,const gen & x,GIAC_CONTEXT){ if (f==x) // x is odd return 2; if (f.type==_VECT){ vecteur & v =*f._VECTptr; const_iterateur it=v.begin(),itend=v.end(); int res=0,current; for (;it!=itend;++it){ if (! (current=fast_is_even_odd(*it,x,contextptr)) ) return 0; if (!res) res=current; if (res!=current) return 0; } return res; } if (f.type!=_SYMB) // constant is even return 1; gen & ff=f._SYMBptr->feuille; int res; const unary_function_ptr & u = f._SYMBptr->sommet; if (u==at_pow && ff.type==_VECT && ff._VECTptr->size()==2){ gen ff2=ff._VECTptr->back(); if (ff2.type==_INT_){ gen ff1=ff._VECTptr->front(); res=fast_is_even_odd(ff1,x,contextptr); if (res<2) return res; return (ff2.val%2)?2:1; } return 0; } res=fast_is_even_odd(ff,x,contextptr); if (res<2) return res; // ff is odd if (u==at_plus || u==at_neg || u==at_inv || u==at_sin || u==at_tan || u==at_sinh || u==at_tanh || u==at_atan || u==at_atanh) return res; if (u==at_prod){ if (ff.type!=_VECT || (ff._VECTptr->size()%2)) return res; return 1; } if (u==at_cos || u==at_cosh || u==at_abs) return 1; return 0; } // 0 none, 1 even, 2 odd int is_even_odd(const gen & f,const gen & x,GIAC_CONTEXT){ int res=fast_is_even_odd(f,x,contextptr); if (res) return res; gen f1=f,f2=subst(f,x,-x,false,contextptr); if (lvar(f)==vecteur(1,x)){ // rational case if (is_zero(normal(f1-f2,contextptr))) return 1; if (is_zero(normal(f1+f2,contextptr))) return 2; return 0; } f1=normal(_texpand(f1,contextptr),contextptr); f2=normal(_texpand(f2,contextptr),contextptr); if (f1==f2) return 1; if (is_zero(ratnormal(f1+f2,contextptr))) return 2; return 0; } bool has_sparse_poly1(const gen & g){ if (g.type==_SPOL1) return true; if (g.type==_VECT){ vecteur & v=*g._VECTptr; for (size_t i=0;ifeuille); return false; } // residue of g at x=a gen residue(const gen & g_,const gen & x,const gen & a,GIAC_CONTEXT){ if (x.type!=_IDNT) return gensizeerr(contextptr); gen xval=x._IDNTptr->eval(1,x,contextptr); if (xval!=x){ _purge(x,contextptr); xval=x._IDNTptr->eval(1,x,contextptr); if (xval!=x){ string s="Unable to purge "+x.print(contextptr)+ ", choose another free variable name"; *logptr(contextptr) << s << endl; return gensizeerr(s); } gen res=residue(g_,x,a,contextptr); sto(xval,x,contextptr); return res; } gen g1=fxnd(g_); if (g1.type==_VECT && g1._VECTptr->size()==2){ gen n=g1._VECTptr->front(),d=derive(g1._VECTptr->back(),x,contextptr); gen da=subst(d,*x._IDNTptr,a,false,contextptr); if (!is_zero(da)){ gen na=subst(n,*x._IDNTptr,a,false,contextptr); n=recursive_normal(na/da,contextptr); if (!is_zero(n) && !is_undef(n) && !is_inf(n)) return n; } } gen g=_pow2exp(tan2sincos(g_,contextptr),contextptr); for (int ordre=2;ordre2 && v[1].type==_IDNT){ vecteur res=find_singularities(v[0],*v[1]._IDNTptr,(is_zero(v[2])?1:9),contextptr); comprim(res); return res; } return singular(v[0],v[1],contextptr); } static const char _singular_s []="singular"; static define_unary_function_eval (__singular,&_singular,_singular_s); define_unary_function_ptr5( at_singular ,alias_at_singular,&__singular,0,true); bool assume_t_in_ab(const gen & t,const gen & a,const gen & b,bool exclude_a,bool exclude_b,GIAC_CONTEXT){ vecteur v_interval(1,gen(makevecteur(a,b),_LINE__VECT)); vecteur v_excluded; if (exclude_a) v_excluded.push_back(a); if (exclude_b) v_excluded.push_back(b); return !is_undef(sto(gen(makevecteur(gen(_DOUBLE_).change_subtype(1),v_interval,v_excluded),_ASSUME__VECT),t,contextptr)); } // reduce g, a rational fraction wrt to x, to a sqff lnpart // and adds the non sqff integrated part to ratpart static bool intreduce(const gen & e,const gen & x,gen & lnpart,gen & ratpart,GIAC_CONTEXT){ vecteur l; l.push_back(x); // insure x is the main var l=vecteur(1,l); alg_lvar(e,l); int s=int(l.front()._VECTptr->size()); if (!s){ l.erase(l.begin()); s=int(l.front()._VECTptr->size()); } if (!s) return false; gen r=e2r(e,l,contextptr); gen r_num,r_den; fxnd(r,r_num,r_den); if (r_num.type==_EXT){ return false; } if (r_den.type!=_POLY){ l.front()._VECTptr->front()=x; lnpart=0; if (r_num.type==_POLY) ratpart=rdiv(r2e(r_num._POLYptr->integrate(),l,contextptr),r2sym(r_den,l,contextptr),contextptr); else ratpart=e*x; return true; } polynome den(*r_den._POLYptr),num(s); if (r_num.type==_POLY) num=*r_num._POLYptr; else num=polynome(r_num,s); l.front()._VECTptr->front()=x; polynome p_content(lgcd(den)); factorization vden(sqff(den/p_content)); // first square-free factorization vector< pf > pfde_VECT; polynome ipnum(s),ipden(s),temp(s),tmp(s); partfrac(num,den,vden,pfde_VECT,ipnum,ipden); vector< pf >::iterator it=pfde_VECT.begin(); vector< pf >::const_iterator itend=pfde_VECT.end(); vector< pf > ratpartv; for (;it!=itend;++it){ pf single(intreduce_pf(*it,ratpartv)); lnpart += r2e(single.num,l,contextptr)/r2e(single.den,l,contextptr); // FIXME: add ratpartv to ratpart } return true; } static bool intgab_sincos(const gen & g,const gen & x,const gen & a,const gen & b,gen & A, gen & B,gen & res,GIAC_CONTEXT){ gen g1=trig2exp(g,contextptr); // write it as a rational fraction of x,X=exp(i*(A*x+b)) identificateur Xid(" X"); gen X(Xid),expx(exp(cst_i*(A*x+B),contextptr)); g1=subst(g1,expx,X,false,contextptr); if (is_positive(-A,contextptr)) g1=subst(g1,X,inv(X,contextptr),false,contextptr); // Separable variables? vecteur f=factors(g1,x,contextptr); // Factor then split factors gen xfact(plus_one),Xfact(plus_one); if (separate_variables(f,Xid,x,Xfact,xfact,contextptr)){ // xfact must be a proper fraction if (!is_zero(limit(xfact,*x._IDNTptr,plus_inf,1,contextptr))){ res=undef; return true; } // Xfact must be rewritten as a generalized polynomial part // + a rational part N/D, the roots of D are in pairs r, 1/conj(r) // if there are roots with norm = 1, D vanishes inf. times on R // hence the integral is undef // we select all roots with norm > 1 and take the corresp. part of // the partial fraction expansion, we have // N/D=2*re(true_poly_part)+2*re(n/d)-re(n(0)/d(0)) // where d has no poles in C^+ and X tends to 0 at inf in C^+ vecteur vX(1,X); lvar(Xfact,vX); gen ND=sym2r(Xfact,vX,contextptr); gen N,D; fxnd(ND,N,D); polynome Np,Dp,Q,R; if (D.type!=_POLY) return false; Dp=*D._POLYptr; if (N.type==_POLY) Np=*N._POLYptr; else Np=polynome(N,1); Np.TDivRem(Dp,Q,R); int Qd=Q.degree(0); // Q is the true poly part if (Qd){ // Dp must be divisible by Qd int Dval=Dp.valuation(0); if (Dval!=Qd) return false; // setsizeerr(); index_t decal(vX.size()); decal[0]=-Dval; Dp=Dp.shift(decal); polynome XQd(gen(1),int(vX.size())),U(int(vX.size())),V(int(vX.size())),C(int(vX.size())); decal[0]=Dval; XQd=XQd.shift(decal); Tabcuv(Dp,XQd,R,U,V,C); // C*Np=Dp*U+X^Dval*V // Np/(Dp*X^Dval)=V/Dp/C+... R=V; Dp=Dp*C; } if (!Q.coord.empty() && Q.coord.back().index.is_zero()) Q.coord.back().value=Q.coord.back().value/2; // R/Dp is the true fractional part, Q is the true poly. part // now check roots of norm=1 gen dp=r2sym(Dp,vX,contextptr); identificateur XXi(" x"),XYi(" y"); gen XX(XXi),XY(XYi); dp=subst(dp,X,XX+cst_i*XY,false,contextptr); dp=_resultant(gen(makevecteur(dp,XX*XX+XY*XY-1,XY),_SEQ__VECT),contextptr); if (is_undef(dp)) return false; dp=gcd(re(dp,contextptr),im(dp,contextptr),contextptr); vecteur vdp=factors(dp,XX,contextptr); int vdps=int(vdp.size()); for (int i=0;i0){ res=undef; return true; } } // ok, now find roots of norm>1 factorization fd; polynome Dp_content; gen extra_div=1; if (!factor(Dp,Dp_content,fd,false,true,true,1,extra_div) || extra_div!=1){ *logptr(contextptr) << gettext("Unable to factor ") << r2sym(Dp,vX,contextptr) << endl; res=undef; return true; } // check that each factor has degree 1 polynome D1(gen(1),int(vX.size())); factorization::const_iterator f_it=fd.begin(),f_itend=fd.end(); for (;f_it!=f_itend;++f_it){ if (f_it->fact.degree(0)>1){ *logptr(contextptr) << gettext("Unable to factor ") << r2sym(f_it->fact,vX,contextptr) << endl; res=undef; return true; } if (f_it->fact.coord.size()==2){ gen f1=f_it->fact.coord.front().value; gen f2=f_it->fact.coord.back().value; gen f21=r2sym(-f2/f1,vecteur(0),contextptr); if (is_positive(abs(f21,contextptr)-1,contextptr)) D1=D1*pow(f_it->fact,f_it->mult); } } // end f_it // keep only those roots polynome D2,tmp,U,V,C; Dp.TDivRem(D1,D2,tmp); Tabcuv(D1,D2,R,U,V,C); // R/D=(D1*U+D2*V)/(C*D1*D2) -> V/(C*D1) Dp=C*D1; R=V; // back to integrating 2*Re(R/Dp) // find R/Dp at 0, real part should be substracted vecteur Rv(polynome2poly1(R,1)),Dv(polynome2poly1(Dp,1)),Qv(polynome2poly1(Q,1)); vecteur vX1(vX.begin()+1,vX.end()); Rv=*r2sym(Rv,vX1,contextptr)._VECTptr; Dv=*r2sym(Dv,vX1,contextptr)._VECTptr; Qv=*r2sym(Qv,vX1,contextptr)._VECTptr; gen correc=re(Rv.back()/Dv.back(),contextptr); xfact=xfact*(2*(horner(Rv,expx)/horner(Dv,expx)+horner(Qv,expx))-correc); res=0; vecteur v=singular(xfact,x,contextptr); if (!v.empty() && is_undef(v.front())) return false; int s=int(v.size()); for (int i=0;ilexsorted_degree(); int dendeg=0; if (Aden.type==_POLY) dendeg=Aden._POLYptr->lexsorted_degree(); if (numdeg>=dendeg-1) return false; // A must have non real roots vecteur rA=singular(A,x,contextptr); if (!rA.empty() && is_undef(rA)) return false; vecteur Pv=factors(P,x,contextptr); int Pvs=int(Pv.size()/2); for (int Pi=0;Pi0, contour is C- // for im<=0, contour is C+, // for roots of P take +residue(ln(x-r)*A) // for poles of P take -residue(ln(x-r)*A) int rAs=int(rA.size()),rPs=int(rP.size()); for (int i=0;i x+2*i*pi/A // if the rat frac of x and rat frac of exp are separate // the problem is to find a function such that // f(.+2*i*pi/A)-f(.)=ratfrac(x) identificateur Xid(" X"); gen X(Xid),expx(symb_exp(A*x+B)); gen g1=subst(g,expx,X,false,contextptr); // Separable variables? vecteur f=factors(g1,x,contextptr); // Factor then split factors gen xfact(plus_one),Xfact(plus_one),T(2*cst_i*cst_pi/A); gen imT(im(T,contextptr)); if (separate_variables(f,x,Xid,xfact,Xfact,contextptr)){ // rescale xfact, in order to find a discrete antiderivative gen xfactscaled=subst(xfact,x,x*T,false,contextptr),remains_to_sum,xfactint; if (!rational_sum(xfactscaled,x,xfactint,remains_to_sum, /* psi allowed */ true,contextptr)) return false; // psi function has poles at 0,-1,-2,... // all have Laurent series -1/(x-pole) xfactint=ratnormal(subst(xfactint,x,x/T,false,contextptr),contextptr); // now int()==contour_integral of xfactint*Xfact over rectangle // -inf .. + inf -> inf+T ..-inf+T -> // just compute all residues at poles where im is in [0,im(T)] // for xfactint, poles are the same as the poles of xfact translated // for Xfact, find pole in X then take A*x+B=ln(pole in X) vecteur rA=singular(xfact,x,contextptr); vecteur rP=singular(Xfact,X,contextptr); if (is_undef(rA) || is_undef(rP)) return false; gen tmp=xfactint*subst(Xfact,X,expx,false,contextptr); gen somme_residus; int rAs=int(rA.size()),rPs=int(rP.size()); for (int i=0;i0) but should handle transc. func. // correctly... #ifndef NO_STDEXCEPT try { #endif gen gl,glim; identificateur t(" t"),r(" r"); gen gt(t),gr(r),geff(g); if (typeint==2){ // replace g by the log part of g if (intgab_ratfrac(g,x,res,contextptr)){ return true; } gen ratpart,lnpart; if (!intreduce(g,x,lnpart,ratpart,contextptr)) return false; gl=limit(g,*x._IDNTptr,plus_inf,1,contextptr); geff=lnpart; } else { // has limit 0 at infinity in the upper or lower half plane // replace x by r*exp(i.t), assume(t in ]0,pi[ or ]-pi,0[) // and look for limit(r*g) glim=gr*subst(g,x,gr*symbolic(at_exp,cst_i*t),false,contextptr); if (!assume_t_in_ab(gt,0,cst_pi,true,true,contextptr)) return false; gl=limit(glim,r,plus_inf,1,contextptr); } if (is_zero(gl)){ // use upper half plan res=0; vecteur v=singular(geff,x,contextptr); if (is_undef(v)) return false; int s=int(v.size()),nresidue=0; for (int i=0;isommet==at_pow && g._SYMBptr->feuille.type==_VECT && g._SYMBptr->feuille._VECTptr->size()==2) return symb_pow(g._SYMBptr->feuille._VECTptr->front(),-g._SYMBptr->feuille._VECTptr->back()); if (g._SYMBptr->sommet==at_prod && g._SYMBptr->feuille.type==_VECT){ vecteur v=*g._SYMBptr->feuille._VECTptr; for (unsigned i=0;i inv_v(1,at_inv); vector< gen_op_context > applyinv_v(1,doapplyinv); return subst(g,inv_v,applyinv_v,false,contextptr); } static bool intgab(const gen & g0,const gen & x,const gen & a,const gen & b,gen & res,bool nonrecursive,GIAC_CONTEXT){ if (x.type!=_IDNT) return false; if (is_zero(g0)){ res=zero; return true; } if (a==unsigned_inf || b==unsigned_inf){ *logptr(contextptr) << gettext("Please use +infinity or -infinity since infinity is unsigned") << endl; return false; } if (is_strictly_greater(a,b,contextptr)){ bool bo=intgab(g0,x,b,a,res,contextptr); res=-res; return bo; } if (!is_strictly_greater(b,a,contextptr)) return false; if (equalposcomp(lidnt(a),x) || equalposcomp(lidnt(b),x)) return false; vecteur subst1,subst2; surd2pow(g0,subst1,subst2,contextptr); gen g0_(subst(g0,subst1,subst2,false,contextptr)),g0mult(1); // apply inv to pow and * g0_=applyinv(g0_,contextptr); if (is_undef(g0_)) return false; if (x.type==_IDNT && g0_.is_symb_of_sommet(at_prod) && g0_._SYMBptr->feuille.type==_VECT){ // extract csts vecteur v=*g0_._SYMBptr->feuille._VECTptr,v1,v2; for (unsigned i=0;ifeuille; if (g0_.type==_VECT && g0_._VECTptr->size()==2){ gen expo=g0_._VECTptr->back(); gen base=g0_._VECTptr->front(); vecteur lv=lvarxwithinv(base,x,contextptr);//rlvarx(base,x); if (lv.size()==1 && lv.front()==x){ int na=0,nb=0; for (;;){ gen tmp=_quorem(makesequence(base,x-a,x),contextptr); if (tmp.type==_VECT && tmp._VECTptr->size()==2 && tmp._VECTptr->back()==0){ ++na; base=tmp._VECTptr->front(); continue; } tmp=_quorem(makesequence(base,b-x,x),contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=2 || tmp._VECTptr->back()!=0) break; ++nb; base=tmp._VECTptr->front(); } if (derive(base,x,contextptr)==0){ g0mult=pow(base,expo,contextptr); g0_=symbolic(at_pow,makesequence(x-a,na*expo))*symbolic(at_pow,makesequence(b-x,nb*expo)); nb=0; // insure next test is not true } if (nb==1 && !na){ base=g0_._VECTptr->front(); gen tmp=_horner(makesequence(base,a,x),contextptr); base=base-tmp; for (;;){ gen tmp=_quorem(makesequence(base,x-a,x),contextptr); if (tmp.type==_VECT && tmp._VECTptr->size()==2 && tmp._VECTptr->back()==0){ ++na; base=tmp._VECTptr->front(); continue; } break; } if (derive(base,x,contextptr)==0){ // pow(-base,expo)*int(((b-a)^na-(x-a)^na)^expo,x,a,b) // let x=a+(b-a)*t^(1/na) // -> pow(-base,expo)*(b-a)^(1+na*expo)/na*int((1-t)^expo*t^(1/na-1),t,0,1) res= pow(-base,expo,contextptr)*pow(b-a,1+na*expo,contextptr)*Gamma(inv(na,contextptr),contextptr)*Gamma(expo+1,contextptr)/Gamma(expo+1+inv(na,contextptr),contextptr)/na; return true; } } // nb==1 && !na } } } if (!is_inf(a) && !is_inf(b) && g0_.is_symb_of_sommet(at_prod) && g0_._SYMBptr->feuille.type==_VECT && g0_._SYMBptr->feuille._VECTptr->size()==2){ // Beta? // rewrite ^ of powers vecteur v=*g0_._SYMBptr->feuille._VECTptr,v1; for (unsigned i=0;ifeuille,vb=v1.back()._SYMBptr->feuille; if (va.type==_VECT && va._VECTptr->size()==2 && vb.type==_VECT && vb._VECTptr->size()==2){ gen va1=va._VECTptr->front(),va1x,va1c,va2=va._VECTptr->back(),vb1=vb._VECTptr->front(),vb2=vb._VECTptr->back(),vb1x,vb1c; if (va1.is_symb_of_sommet(at_pow) && va1._SYMBptr->feuille.type==_VECT && va1._SYMBptr->feuille._VECTptr->size()==2){ va2=va1._SYMBptr->feuille._VECTptr->back()*va2; va1=va1._SYMBptr->feuille._VECTptr->front(); } if (vb1.is_symb_of_sommet(at_pow) && vb1._SYMBptr->feuille.type==_VECT && vb1._SYMBptr->feuille._VECTptr->size()==2){ vb2=vb1._SYMBptr->feuille._VECTptr->back()*vb2; vb1=vb1._SYMBptr->feuille._VECTptr->front(); } if (is_linear_wrt(va1,x,va1x,va1c,contextptr) && is_linear_wrt(vb1,x,vb1x,vb1c,contextptr)){ if (is_zero(recursive_normal(va1c/va1x+a,contextptr),contextptr) && is_zero(recursive_normal(vb1c/vb1x+b,contextptr),contextptr)){ // int( (va1x*(x-a))^va2*(vb1x*(x-b))^vb2,a,b) res=g0mult*pow(va1x,va2,contextptr)*pow(-vb1x,vb2,contextptr)*pow(b-a,va2+vb2+1,contextptr)*Beta(va2+1,vb2+1,contextptr); return true; } if (is_zero(recursive_normal(va1c/va1x+b,contextptr),contextptr) && is_zero(recursive_normal(vb1c/vb1x+a,contextptr),contextptr)){ // int( (va1x*(x-b))^va2*(vb1x*(x-a))^vb2,a,b) res=g0mult*pow(-va1x,va2,contextptr)*pow(vb1x,vb2,contextptr)*pow(b-a,va2+vb2+1,contextptr)*Beta(va2+1,vb2+1,contextptr); return true; } } } } } // detect Dirac vecteur v=lop(g0,at_Dirac); if (!v.empty()){ gen A,B,a0,b0; #ifdef GIAC_HAS_STO_38 identificateur t("tsumab_"); #else identificateur t(" tsumab"); #endif gen h=quotesubst(g0,v.front(),t,contextptr); if (!is_linear_wrt(h,t,A,B,contextptr)) return false; gen heav=v.front()._SYMBptr->feuille; if (heav.type==_VECT && heav._VECTptr->size()==2 && heav._VECTptr->back().type==_INT_ ){ int diracorder=heav._VECTptr->back().val; if (diracorder<0){ *logptr(contextptr) << gettext("Negative second Dirac argument") << endl; return false; } A=derive(A,x,diracorder,contextptr); if (is_undef(A)) return false; if (diracorder%2) A=-A; heav=heav._VECTptr->front(); } if (!is_linear_wrt(heav,x,a0,b0,contextptr) || is_zero(a0)) return false; if (!intgab(B,x,a,b,res,contextptr)) return false; gen c=-b0/a0; if (ck_is_greater(c,a,contextptr) && ck_is_greater(b,c,contextptr)) res += quotesubst(A,x,c,contextptr); else *logptr(contextptr) << gettext("Warning, Dirac function outside summation interval") << endl; return true; } if (a==b){ res=0; return true; } gen g=hyp2exp(g0,contextptr); vecteur lvarg = lvar(g); bool rational = lvarg==vecteur(1,x); if (!rational){ int s1=nvars_depend_x(loptab(g,sincostan_tab),x); // rewrite cos/sin/tan if more than 1 available, // do not rewrite atan/asin/acos if (s1) // check added otherwise int(1/(x-a)^999,x,a-1,a+1) takes forever g=tsimplify_noexpln(g,s1,0,contextptr); } // FIXME should check integrability at -/+inf if (a==minus_inf){ gen A=limit(g,*x._IDNTptr,a,1,contextptr); if (!is_zero(A) && b!=plus_inf){ res=-a*A; return !is_undef(res); // true; } if (b==plus_inf){ vecteur singu=find_singularities(g,*x._IDNTptr,0 /* real singularities*/,contextptr); if (!singu.empty()){ *logptr(contextptr) << "Warning, singularities at " << singu << endl; if (calc_mode(contextptr)==1 || abs_calc_mode(contextptr)==38){ res=undef; return true; } } gen B=limit(g,*x._IDNTptr,b,-1,contextptr); if (!is_zero(B)){ if (is_zero(A)) res=b*B; else res=b*B-a*A; return !is_undef(res); // true; } int ieo=is_even_odd(g,x,contextptr); if (ieo==2){ res=0; return true; } if (is_zero(A) && intgab_r(g,x,a,b,rational,res,contextptr)) return true; if (ieo==1){ // simplify g on 0..inf assumesymbolic(symb_superieur_egal(x,0),0,contextptr); gen g1=eval(g,1,contextptr); purgenoassume(x,contextptr); if (g1!=eval(g,1,contextptr)){ res=2*_integrate(makesequence(g1,x,0,plus_inf),contextptr); return true; } } return false; } // end b==plus_inf (a is still minus_inf) // subst x by x+b, check parity: even -> 1/2 int(-inf,+inf) gen gb=subst(g,x,x+b,false,contextptr); int eo=is_even_odd(gb,x,contextptr); if (eo==1){ if ( (rational && intgab_ratfrac(gb,x,res,contextptr)) || intgab(gb,x,a,plus_inf,res,contextptr) ){ if (!is_inf(res)) res=ratnormal(res/2,contextptr); return true; } } vecteur v; rlvarx(gb,x,v); int vs=int(v.size()); for (int i=0;ifeuille,a,b; // if f is a*x make the change of var x=-exp(t) if (is_linear_wrt(f,x,a,b,contextptr) && is_zero(b)){ vecteur vin=makevecteur(v[i],x); vecteur vout=makevecteur(ln(-a,contextptr)+x,-exp(x,contextptr)); gb=quotesubst(gb,vin,vout,contextptr)*exp(x,contextptr); return intgab(gb,x,minus_inf,plus_inf,res,contextptr); } } } return false; } // end a==minus_inf if (b==plus_inf){ gen ga=subst(g,x,x+a,false,contextptr); // additional check for int(t^n/(exp(alpha*t)-1),t,0,inf)=n!/alpha^(n+1)*Zeta(n+1) vecteur vax=rlvarx(ga,x); if (vax.size()==2 && vax.front()==x && vax.back().is_symb_of_sommet(at_exp)){ gen expo=vax.back(),expo_a,expo_b; if (is_linear_wrt(expo._SYMBptr->feuille,x,expo_a,expo_b,contextptr) && is_strictly_positive(expo_a,contextptr)){ gen gand=_fxnd(ga,contextptr); if (gand.type==_VECT && gand._VECTptr->size()==2){ gen gan=gand._VECTptr->front(),gad=gand._VECTptr->back(),gad_a,gad_b; // gad must be a power of expo-exp(expo_b), starting with linear if (rlvarx(gan,x).size()==1 && is_linear_wrt(gad,expo,gad_a,gad_b,contextptr)){ // gad=gad_a*(expo+gad_b/gad_a) gen test=ratnormal(gad_a*exp(expo_b,contextptr)+gad_b,contextptr); if (is_zero(test)){ // -1/gad_b*int(gan/(exp(expo_a*t)-1),t,0,inf) gen ganv=_coeff(makesequence(gan,x),contextptr); if (ganv.type==_VECT && !ganv._VECTptr->empty() && is_zero(ganv._VECTptr->back())){ res=0; vecteur v=*ganv._VECTptr; gen facti=pow(expo_a,-2,contextptr); for (int i=1;isize()==2){ gen exponum=expofact._VECTptr->front(),expoden=expofact._VECTptr->back(); int n=_degree(makesequence(expoden,y),contextptr).val; gen coeffden=ratnormal(expoden/pow(y-y0,n,contextptr),contextptr); if (n>1 && is_zero(derive(coeffden,y,contextptr))){ // 1/expoden*xfact*exponum(y)/(y-1)^n, y'=expo_a*y gen additional=_quorem(makesequence(exponum,pow(y-1,n-1),y),contextptr); exponum=additional[1]; gen xfactc=_coeff(makesequence(xfact,x),contextptr); if (xfactc.type==_VECT && !xfactc._VECTptr->empty()){ vecteur & xfactv=*xfactc._VECTptr; // check cancellation of xfact at 0 at least order n bool check=true; for (int i=1;i<=n;++i){ if (xfactv[xfactv.size()-i]!=0){ check=false; break; } } if (check){ // reduce degree by integration by part // int(P(t)*Q(e^at)/(e^at-1)^n= // int( (1/(n-1)*P'/a-P)*Q(e^at)+1/(n-1)P*Q'(e^at))/(e^at-1)^(n-1) gen int1=(derive(xfact,x,contextptr)/((n-1)*expo_a)-xfact)*subst(exponum/pow(y-1,n-1,contextptr),y,exp(expo_a*x,contextptr),false,contextptr); int1=_integrate(makesequence(int1,x,0,plus_inf),contextptr); gen int2=xfact/gen(n-1)*subst(derive(exponum,y,contextptr)/pow(y-1,n-1,contextptr),y,exp(expo_a*x,contextptr),false,contextptr); int2=_integrate(makesequence(int2,x,0,plus_inf),contextptr); gen int3=xfact*subst(additional[0]/(y-1),y,exp(expo_a*x,contextptr),false,contextptr); int3=_integrate(makesequence(int3,x,0,plus_inf),contextptr); res=(int1+int2+int3)/coeffden; return true; } } } } } } // end if (is_linear_wrt(expo...)) } // end varx.size()==2 int eo=is_even_odd(ga,x,contextptr); if (eo==1){ vecteur singu=find_singularities(g,*x._IDNTptr,0 /* real singularities*/,contextptr); if (singu.empty()){ if ( (rational && intgab_ratfrac(ga,x,res,contextptr)) || intgab(ga,x,minus_inf,plus_inf,res,contextptr) ){ if (!is_inf(res)) res=ratnormal(res/2,contextptr); return !is_undef(res); } } } vecteur v; rlvarx(ga,x,v); int vs=int(v.size()); for (int i=0;ifeuille,a,b; // if f is a*x make the change of var x=exp(t) if (is_linear_wrt(f,x,a,b,contextptr) && is_zero(b)){ vecteur vin=makevecteur(v[i],x); vecteur vout=makevecteur(ln(a,contextptr)+x,exp(x,contextptr)); ga=quotesubst(ga,vin,vout,contextptr)*exp(x,contextptr); return intgab(ga,x,minus_inf,plus_inf,res,contextptr); } } } return false; } gen gab=subst(g0,x,b,false,contextptr)-subst(g0,x,a,false,contextptr); gen gabd; if (!has_evalf(gab,gabd,1,contextptr) || is_zero(gabd)) gab=simplify(gab,contextptr); gen gm=subst(g0,x,b,false,contextptr)+subst(g0,x,a,false,contextptr); if (!has_evalf(gm,gabd,1,contextptr) || is_zero(gabd)) gm=simplify(gm,contextptr); if (is_constant_wrt(g,x,contextptr)){ res=g*(b-a); return true; } int eo=0; if (is_zero(gab) || is_zero(gm) ){ identificateur t("tintgab_"); gen tt(t); gm=subst(g0,x,tt+(a+b)/2,false,contextptr); eo=is_even_odd(gm,tt,contextptr); } if (!nonrecursive && eo==1){ if (!intgab(g0,x,a,(a+b)/2,res,true,contextptr)) return false; res=2*res; return true; } if (eo==2){ #if 0 // set to 1 if you want to check for singularities before returning 0 vecteur sp=find_singularities(g,*x._IDNTptr,false,contextptr); for (int i=0;isommet!=at_exp && vx[i]._SYMBptr->sommet!=at_sin && vx[i]._SYMBptr->sommet!=at_cos && vx[i]._SYMBptr->sommet!=at_tan)) gm=1; } if (is_zero(gm)){ gm=subst(g0,x,x+(b-a),false,contextptr); gm=simplify(gm-g0,contextptr); } } #ifndef NO_STDEXCEPT try { #endif if (is_zero(gm)){ // try to rewrite g as a function of exp(2*i*pi*x/(b-a)) g=_lin(trig2exp(g0,contextptr),contextptr); vecteur v; rlvarx(g,x,v); islesscomplexthanf_sort(v.begin(),v.end()); int i,s=int(v.size()); if (s>=2){ gen v0,alpha,beta,alphacur,betacur,gof,periode,periodecur; for (i=0;ifeuille; if (is_linear_wrt(v0arg,x,alphacur,betacur,contextptr) && is_integer( (periodecur=normal(alphacur*(b-a)/cst_two_pi/cst_i,contextptr)) )){ periode=gcd(periode,periodecur,contextptr); } } } if (!is_zero(periode)){ alpha=normal(periode*cst_two_pi/(b-a)*cst_i,contextptr); if (is_zero(re(alpha,contextptr))){ beta=normal(betacur*alpha/alphacur,contextptr); gen radius=exp(re(beta,contextptr),contextptr); // vO=exp(alpha*x+beta) -> x=(ln(v0)-beta)/alpha vecteur vin=makevecteur(x); vecteur vout=makevecteur((ln(x,contextptr)-beta)/alpha); // check for essential singularities vecteur v2=lop(recursive_normal(rlvarx(subst(v,vin,vout,false,contextptr),x),contextptr),at_exp); vecteur w2=singular(v2,x,contextptr); unsigned w2i=0; for (;w2i-alpha alpha=-alpha; beta=normal(betacur*alpha/alphacur,contextptr); radius=exp(re(beta,contextptr),contextptr); // vO=exp(alpha*x+beta) -> x=(ln(v0)-beta)/alpha vin=makevecteur(x); vout=makevecteur((ln(x,contextptr)-beta)/alpha); // check for essential singularities v2=lop(recursive_normal(rlvarx(subst(v,vin,vout,false,contextptr),x),contextptr),at_exp); w2=singular(v2,x,contextptr); w2i=0; for (;w2i0) return false; roots.clear(); if (deg<1) return true; roots=crationalroot(PP,false); roots=*_sort(roots,contextptr)._VECTptr; if (int(roots.size())!=deg) return false; return true; } // tmp1=sum_k a_k x^k, find sum_k a_k/s_k x^k // where s_x=product(k-decals[i],i) and decals[i] is rationnal // if decals[i] is an integer, multiply by x^(-1-decals[i]), int // and mult by x^decals[i] static bool in_sumab_int(gen & tmp1,const gen & gx,const vecteur & decals,const gen & lcoeff,GIAC_CONTEXT){ int nstep=int(decals.size()); gen coeff=lcoeff; gen remains; for (int i=0;inum; gen d=decals[i]._FRACptr->den; // coeff*(k-n/d)=coeff/d*(d*k-n) coeff = coeff/d; // sum a_k/(d*k-n)*gx^k // set gx=X^d : sum_ a_k/(d*k-n)*X^(d*k) tmp1=subst(tmp1,gx,pow(gx,d,contextptr),false,contextptr); tmp1=tmp1*pow(gx,-1-n,contextptr); tmp1=integrate_id_rem(tmp1,gx,remains,contextptr,0); if (is_undef(tmp1)) return false; tmp1=tmp1-limit(tmp1,*gx._IDNTptr,0,1,contextptr); if (is_inf(tmp1)) return false; // for sum(1/((n+1)*(2*n-1)),n,0,inf); tmp1=ratnormal(tmp1*pow(gx,n,contextptr),contextptr); tmp1=ratnormal(subst(tmp1,gx,pow(gx,inv(d,contextptr),contextptr),false,contextptr),contextptr); } else { tmp1=tmp1*pow(gx,-1-decals[i],contextptr); tmp1=integrate_id_rem(tmp1,gx,remains,contextptr,0); if (is_undef(tmp1)) return false; tmp1=tmp1-limit(tmp1,*gx._IDNTptr,0,1,contextptr); tmp1=tmp1*pow(gx,decals[i],contextptr); } if (!is_zero(remains)) return false; } tmp1=tmp1/coeff; return true; // do_lnabs(b,contextptr); } static bool sumab_int(gen & tmp1,const gen & gx,const vecteur & decals,const gen & lcoeff,GIAC_CONTEXT){ bool b=do_lnabs(contextptr); do_lnabs(false,contextptr); // bool c=complex_mode(contextptr); // complex_mode(true,contextptr); bool bres=in_sumab_int(tmp1,gx,decals,lcoeff,contextptr); do_lnabs(b,contextptr); // complex_mode(c,contextptr); return bres; } static bool sumab_ps(const polynome & Q,const polynome & R,const vecteur & v,const gen & a,const gen & x,const gen & g,bool est_reel,const polynome & p,const polynome & s,gen & res,GIAC_CONTEXT){ // p corresponds to derivation, s to integration // cerr << "p=" << p << " s=" << s << " Q=" << Q << " R=" << R << endl; // Q must be independant of x // If R is independant of x we use the geometric series // If R=x-integer the exponential (must change bounds by integer) // If R=2x(2x+1) sinh/cosh etc. if (Q.degree(0)==0){ // count "integrations" step in s int intstep; vecteur decals; polynome lcoeffs; if (is_admissible_poly(s,intstep,lcoeffs,decals,contextptr)){ gen lcoeff=r2e(lcoeffs,v,contextptr); #ifdef GIAC_HAS_STO_38 identificateur idx("sumw_"); // identificateur idx(" x"); // #else identificateur idx(" sumw"); // identificateur idx(" x"); // #endif gen gx(idx); // ("` sumw`",contextptr); // parser instead of temporary otherwise bug with a:=1; ZT(f,z):=sum(f(n)/z^n,n,0,inf); ZT(k->c^k,z); ZT; // otherwise while purge(gx) happens, the string `sumw` is destroyed // and the global map is not sorted correctly anymore if (!assume_t_in_ab(gx,0,1,true,true,contextptr)) return false; // R must be the product of degree(R) consecutive terms int r=R.degree(0); if (r==1){ vecteur Rv=iroots(R); if (Rv.size()!=1){ purgenoassume(gx,contextptr); return false; } gen R0=Rv[0]; if (is_strictly_greater(R0,a,contextptr)){ res=undef; purgenoassume(gx,contextptr); return true; } // Q=Q/R.coord.front().value; index_t ind=R.coord.front().index.iref(); ind[0]=0; gen Qg=r2e(Q,v,contextptr)/r2e(polynome(monomial(R.coord.front().value,ind)),v,contextptr); // (g|x=a)*s(a)/p(a)/Q^(a-R0)/(a-R0)!*sum(p(n)/s(n)*Q^(n-R0)/(n-R0)!,n=a..inf); // first compute sum(p(n)*Q^(n-R0)/(n-R0)!,n=R0..inf) // = sum(p(n+R0)*Q^(n)/n!,n=0..inf) int d=p.degree(0); gen Pg=r2e(p,v,contextptr); vecteur vx(d+1),vy(d+1); for (int i=0;i<=d;++i){ vx[i]=i; vy[i]=ratnormal(subst(Pg,x,R0+i,false,contextptr),contextptr); } vecteur w=divided_differences(vx,vy); // p(n+R0)=w[0]+w[1]*n+w[2]*n*(n-1)+... // hence the sum is exp(Q)*(w[0]+w[1]*Q+...) reverse(w.begin(),w.end()); gen tmp1=symb_horner(w,gx)*exp(gx,contextptr),remains; // substract sum(p(n)*Q^(n-R0)/(n-R0)!,n=R0..a-1) for (int n=R0.val;n=2){ polynome Rc=lgcd(R); vecteur Rv=polynome2poly1(R/Rc,1); // Rv should be a multiple of (r*x-R0)*(r*x-(R0+1))*... // -Rv[1]/Rv[0]= sum of roots = r*R0 + sum(j,j=0..r-1) // R0 = -Rv[1]/Rv[0] - (r-1)/2 gen R0=-Rv[1]/Rv[0]-gen(r-1)/gen(2); if (R0.type!=_INT_){ purgenoassume(gx,contextptr); return false; } // check that Rv = cst*product(r*x-(R0+j),j=0..r-1) vecteur test(1,1); for (int j=0;jr*a.val){ res=undef; purgenoassume(gx,contextptr); return true; } Rc=Rv[0]/pow(gen(r),r)*Rc; gen Qg=r2e(Q,v,contextptr)/r2e(Rc,v,contextptr); if (r==2) Qg=sqrt(Qg,contextptr); else Qg=pow(Qg,inv(gen(r),contextptr),contextptr); // (g|x=a)*s(a)/p(a)/Qg^(r*a-R0)*(r*a-R0)!*sum(p(n)/s(n)*Qg^(r*n-R0)/(r*n-R0)!,n=a..inf); gen coeffa=g*r2e(s,v,contextptr)/r2e(p,v,contextptr)/pow(Qg,r*a-R0,contextptr)*factorial(r*a.val-r0); coeffa=limit(coeffa,*x._IDNTptr,a,1,contextptr); // Set k=r*n-R0 and compute sum((p/s)((k+R0)/r)*X^k/k!,k=r*a-R0..inf) int d=p.degree(0); gen Pg=r2e(p,v,contextptr); vecteur vx(d+1),vy(d+1); for (int i=0;i<=d;++i){ vx[i]=i; vy[i]=ratnormal(subst(Pg,x,(i+R0)/r,false,contextptr),contextptr); } vecteur w=divided_differences(vx,vy); reverse(w.begin(),w.end()); gen tmp=symb_horner(w,gx)*exp(gx,contextptr),remains; // substract sum(...,k=0..r*a-R0-1) for (int k=0;k0);somme(x^(4n+1)/(4n+1)!,n,1,inf); tmp -= subst(Pg,x,(k+R0)/r,false,contextptr)*pow(gx,k)/factorial(k); } // keep terms which are = -R0 mod r = N // for example if r=2 and R0 even, keep even terms // that is (f(X)+f(-X))/2 // more generally take // 1/r*sum(f(X*exp(2i pi*k/r))*exp(-2i pi*k*N/r),k=0..r-1) int N= -r0 % r; gen tmp1=0,tmpadd; for (int k=0;kfeuille.type==_VECT){ vecteur vp=*gp._SYMBptr->feuille._VECTptr; res=0; int i=0; for (;ifeuille,x,a,b,contextptr) && in_sumab(B,x,a_orig,b_orig,res,testi,false,contextptr)){ // sum(A*Kronecker(a*x+b),x,a_orig,b_orig)+res gen xval=-b/a; if (is_integer(xval) && is_greater(xval,a_orig,contextptr) && is_greater(b_orig,xval,contextptr)) res += subst(A,x,xval,false,contextptr); return true; } } vD=lop(v,at_Heaviside); if (!vD.empty()){ gen vD0=vD.front(),A,B,a,b; if (is_linear_wrt(g,vD0,A,B,contextptr) && is_linear_wrt(vD0._SYMBptr->feuille,x,a,b,contextptr) && in_sumab(B,x,a_orig,b_orig,res,testi,false,contextptr)){ // sum(A*Heaviside(a*x+b),x,a_orig,b_orig)+res gen xval=-b/a,resadd; if (is_integer(xval) && is_strictly_positive(a,contextptr) && in_sumab(A,x,max(a_orig,xval,contextptr),b_orig,resadd,testi,false,contextptr)){ res += resadd; return true; } } } v=loptab(v,sincostan_tab); bool est_reel=testi?!has_i(g):true; if (!v.empty()){ gen w=trig2exp(v,contextptr); vecteur vexp; lin(subst(g,v,*w._VECTptr,true,contextptr),vexp,contextptr); const_iterateur it=vexp.begin(),itend=vexp.end(); for (;it!=itend;){ gen coeff=*it,tmp; ++it; // it -> on the arg of the exp that must be linear gen axb=coeff*symbolic(at_exp,*it); ++it; if (!sumab(axb,*x._IDNTptr,a_orig,b_orig,tmp,!est_reel,contextptr)){ return false; } res += tmp; } return true; } v.clear(); polynome p,q,r; gen a(a_orig),b(b_orig); if (!est_reel || complex_mode(contextptr)){ bool b=complex_mode(contextptr); complex_mode(contextptr)=false; gen reg(g),img(0),reres,imres; if (!est_reel){ reg=re(g,contextptr),img=im(g,contextptr); } if (!in_sumab(reg,x,a_orig,b_orig,reres,false,false,contextptr) || !in_sumab(img,x,a_orig,b_orig,imres,false,false,contextptr)){ complex_mode(contextptr)=b; return false; } complex_mode(contextptr)=b; res=reres+cst_i*imres; return true; } bool Hyper=is_hypergeometric(g,*x._IDNTptr,v,p,q,r,contextptr); // g(x+1)/g(x) as p(x+1)/p(x)*q(x)/r(x+1) if (Hyper){ // Newton binomial: sum_{x=a}^{b} comb(b-a,x-a)*p^x = (p+1)^(b-a)*p^a // n=b-a // comb(n,x+1-a)*p^(x+1)/comb(n,x-a)/p^x // = p*(x-a)!*(n-x+a)!/(x+1-a)!/(n-x-1+a)!=p*(n-x+a)/(x+1-a) // q=(-qa)*(n-x+a)=(-qa)*(b-x), r=ra*(x-a) -> -q/qa+r/ra=n // can be generallized with j-unitroots to // sum_{x=a}^{b} comb(b-a,j*x-j*a)*p^x // gen Q=r2sym(q,v,contextptr),R=r2sym(r,v,contextptr),Qa,Qb,Ra,Rb; if (a.type==_INT_ && b==plus_inf && p.lexsorted_degree()==0 && r.coord.size()==1 && q+r==0 ){ // gen coeff=inv(r.coord.front().value,contextptr); int pui=r.lexsorted_degree(); // coeff*sum((-1)^k/k^pui,k,a,inf) // if a is even set res=0, if a is odd set res=-1/a^pui and a++ res=0; R=inv(R,contextptr); if (pui==1){ if (a.val<=0){ res=R*plus_inf; return true; } res=symbolic(at_ln,2); if (a.val>1) res = res-_sum(makesequence(R,x,1,a.val-1),contextptr); res=res*subst(g/R,x,1,false,contextptr); return true; } // add sum(1/k^pui,k,a,inf) // -> 2*sum(1/(2*k)^pui,k,a/2,inf)=2^(1-pui)*sum(1/k^pui,k,a/2,inf) res = - _sum(makesequence(R,x,a,plus_inf),contextptr) + pow(2,1-pui,contextptr)*_sum(makesequence(R,x,(a.val+1)/2,plus_inf),contextptr); res = -res*subst(g/R,x,a,false,contextptr); return true; } gen n=b-a; if (is_linear_wrt(Q,x,Qa,Qb,contextptr) && is_linear_wrt(R,x,Ra,Rb,contextptr)){ // Q/R=(Qa*x+Qb)/(Ra*x+Rb)=(-Qa/Ra)*(-x-Qb/Qa)/(x+Rb/Ra) gen trueb=normal(-Qb/Qa,contextptr); gen truea=normal(-Rb/Ra,contextptr); gen truen=normal(trueb-truea,contextptr); gen diffa=normal(a-truea,contextptr); gen diffb=normal(b-trueb,contextptr); if (diffa.type==_INT_ && diffb.type==_INT_){ gen P=r2sym(p,v,contextptr); if (p.lexsorted_degree()==0){ res = P*(-Qa/Ra)+1; if (!is_zero(res)) res=simplify(pow(res,truen,contextptr)*limit(g,*x._IDNTptr,truea,0,contextptr),contextptr); if (absint(diffb.val)>100 || absint(diffa.val)>100) return false; if (diffb.val>0){ // b>trueb: add sum(g,x,trueb+1,b-1) for (int i=0;i0){ // a>truea : substract sum(g,x,truea,a-1) for (int i=0;isize()!=2) return false; // setsizeerr(); if (!in_sumab(gsurP*prod,x,a_orig,b_orig,tmpres,false,false,contextptr)) return false; res += tmp._VECTptr->back()*tmpres; prod = prod*R; R=subst(R,x,x-1,false,contextptr); // R=R-1; P=tmp._VECTptr->front(); } return true; } } } if (!is_inf(a) && !is_inf(b)) return false; if (b==plus_inf && a.type==_INT_ && Hyper){ polynome s,Q,R; // limit of q/r at infinity must be 0 gen test=r2e(q,v,contextptr)/r2e(r,v,contextptr); test=ratnormal(test*test-1,contextptr); if (is_zero(test)){ res=_limit(gen(makevecteur(g,x,plus_inf),_SEQ__VECT),contextptr); if (!is_zero(res)){ return is_inf(res); } } if (is_strictly_positive(test,contextptr)){ res=_limit(gen(makevecteur(g,x,plus_inf),_SEQ__VECT),contextptr); return true; } r=taylor(r,1); // r(x)/q(x)=s(x+1)/s(x)*R(x)/Q(x+1) AB2PQR(r,q,s,R,Q); R=taylor(R,-1); simplify(p,s); // IMPROVE: make a partial fraction decomposition of p(n)/s(n) // [could also make ln return ln(1-x) instead of ln(x-1)] if (sumab_ps(Q,R,v,a,x,g,est_reel,p,s,res,contextptr)) return true; } gen A,B,P; int type=is_meromorphic(g,x,A,B,P,contextptr); int even=is_even_odd(g,x,contextptr); bool complete=(a==minus_inf && b==plus_inf); if (type==2){ if (!is_zero(limit(g,*x._IDNTptr,plus_inf,0,contextptr))){ res=undef; return true; } if ( complete || even==1){ if (!complete){ if (a==minus_inf){ a=-b; b=plus_inf; } if (a.type!=_INT_) return false; } int ai=a.val; // find the value of int(cos(pi*x)/sin(pi*x)*g,circle(0,R)) vecteur v=singular(g,x,contextptr); if (is_undef(v)) return false; gen g2=g*cst_pi*symb_cos(cst_pi*x)/symb_sin(cst_pi*x); // if root is integer it must not be inside a..b // the sum of residues of v + sum(g,n=-inf..inf, n not in v) will be 0 gen somme_residus; int vs=int(v.size()); gen correc=0; for (int i=0;i0){ for (int i=1;i=ai;--i) correc += quotesubstcheck(g,x,i,v,contextptr); } res=(-quotesubstcheck(g,x,0,v,contextptr)-somme_residus)/2; } res=correc+res; res=recursive_normal(trig2exp(res,contextptr),contextptr); return true; } } return false; } // if true put int(g,x=a..b) into res // a or b must be +/-infinity and afeuille); int args=int(argv.size()),i; res=0; gen tmp; for (i=0;ifeuille; if (heav.type==_VECT && heav._VECTptr->size()==3){ B=B+A*heav._VECTptr->back(); A=A*((*heav._VECTptr)[1]-heav._VECTptr->back()); heav=heav._VECTptr->front(); } else return false; // setsizeerr(); if (!is_linear_wrt(heav,x,a,b,contextptr) || is_zero(a)) return false; if (!sumab(B,x,a_orig,b_orig,res,testi,contextptr)) return false; gen c=-b/a; if (ck_is_greater(c,a_orig,contextptr) && ck_is_greater(b_orig,c,contextptr)) res += quotesubst(A,x,c,contextptr); else *logptr(contextptr) << gettext("Warning, Dirac function outside summation interval") << endl; return true; } // detect Heaviside v=lop(g,at_Heaviside); if (v.empty()) return in_sumab(g,x,a_orig,b_orig,res,testi,true /* do partfrac */,contextptr); gen A,B,a,b; identificateur t(" tsumab"); gen h=quotesubst(g,v.front(),t,contextptr); if (!is_linear_wrt(h,t,A,B,contextptr)) return false; // A*Heaviside()+B gen heav=v.front()._SYMBptr->feuille; if (!is_linear_wrt(heav,x,a,b,contextptr) || is_zero(a)) return false; if (!sumab(B,x,a_orig,b_orig,res,testi,contextptr)) return false; // for A additional condition a*x+b>=0 : if a>0 x>=-b/a else x<=-b/a gen c=-b/a; gen newa,newb; if (ck_is_positive(a,contextptr)){ if (ck_is_greater(a_orig,c,contextptr)){ newa=a_orig; newb=b_orig; } else { if (ck_is_greater(b_orig,c,contextptr)){ newa=_ceil(c,contextptr); newb=b_orig; } else return true; } } else { if (ck_is_greater(a_orig,c,contextptr)) return true; if (ck_is_greater(b_orig,c,contextptr)){ newa=a_orig; newb=_floor(c,contextptr); } else { newa=a_orig; newb=b_orig; } } gen sumA; if (!sumab(A,x,newa,newb,sumA,testi,contextptr)) return false; res += sumA; return true; } #ifndef NO_NAMESPACE_GIAC } // namespace giac #endif // ndef NO_NAMESPACE_GIAC