// -*- mode:C++ ; compile-command: "g++-3.4 -I.. -DHAVE_CONFIG_H -DIN_GIAC -g -c subst.cc" -*-
#include "giacPCH.h"
/*
* Copyright (C) 2000,14 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
#include "subst.h"
#include "symbolic.h"
#include "sym2poly.h"
#include "unary.h"
#include "usual.h"
#include "derive.h"
#include "intg.h"
#include "prog.h"
#include "lin.h"
#include "solve.h"
#include "plot.h"
#include "modpoly.h"
#include "maple.h"
#include "ti89.h"
#include "alg_ext.h"
#include "giacintl.h"
#ifndef NO_NAMESPACE_GIAC
namespace giac {
#endif // ndef NO_NAMESPACE_GIAC
gen checkanglemode(GIAC_CONTEXT){
if (!angle_radian(contextptr))
//grad
return gensizeerr(gettext("This function works only in radian mode"));
return 0;
}
// bool quote_subst=false;
/*
static vector merge(const vector & v,const vector & w){
vector res(v);
vector ::const_iterator it=w.begin(),itend=w.end();
for (;it!=itend;++it){
res.push_back(*it);
}
return res;
}
static vector merge(const vector & v,const vector & w){
vector res(v);
vector ::const_iterator it=w.begin(),itend=w.end();
for (;it!=itend;++it){
res.push_back(*it);
}
return res;
}
*/
// sin, cos, tan in terms of tan(x/2)
gen sin2tan2(const gen & e,GIAC_CONTEXT){
gen a=symb_tan(rdiv(e,plus_two,contextptr));
return rdiv(plus_two*a,pow(a,2)+1,contextptr);
}
gen cos2tan2(const gen & e,GIAC_CONTEXT){
gen a=symb_tan(rdiv(e,plus_two,contextptr));
return rdiv(1-pow(a,2),pow(a,2)+1,contextptr);
}
gen tan2tan2(const gen & e,GIAC_CONTEXT){
gen a=symb_tan(rdiv(e,plus_two,contextptr));
return rdiv(plus_two*a,1-pow(a,2),contextptr);
}
// hyperbolic trig to exp
gen sinh2exp(const gen & e,GIAC_CONTEXT){
gen a=exp(e,contextptr);
return rdiv(a-inv(a,contextptr),plus_two,contextptr);
}
gen cosh2exp(const gen & e,GIAC_CONTEXT){
gen a=exp(e,contextptr);
return rdiv(a+inv(a,contextptr),plus_two,contextptr);
}
gen tanh2exp(const gen & e,GIAC_CONTEXT){
gen a=pow(exp(e,contextptr),2);
return rdiv(a-plus_one,a+plus_one,contextptr);
}
// trig to exp
gen degtorad(const gen & g,GIAC_CONTEXT){
if (angle_radian(contextptr))
return g;
return g*deg2rad_e;
}
gen radtodeg(const gen & g,GIAC_CONTEXT){
if (angle_radian(contextptr))
return g;
return g*gen(180)/cst_pi;
}
//grad (next few commands
gen angletorad(const gen & g,GIAC_CONTEXT){
if (angle_radian(contextptr))
return g;
else if(angle_degree(contextptr))
return g*deg2rad_e;
else
return g*grad2rad_e;
}
gen radtoangle(const gen & g,GIAC_CONTEXT){
if(angle_radian(contextptr))
return g;
else if(angle_degree(contextptr))
return g*gen(180)/cst_pi;
else
return g*gen(200)/cst_pi;
}
gen sin2exp(const gen & e,GIAC_CONTEXT){
gen a=exp(cst_i*angletorad(e,contextptr),contextptr);
return rdiv(a-inv(a,contextptr),plus_two*cst_i,contextptr);
}
gen cos2exp(const gen & e,GIAC_CONTEXT){
gen a=exp(cst_i*angletorad(e,contextptr),contextptr);
return rdiv(a+inv(a,contextptr),plus_two,contextptr);
}
gen tan2exp(const gen & e,GIAC_CONTEXT){
gen a=pow(exp(cst_i*angletorad(e,contextptr),contextptr),2);
return rdiv(a-plus_one,cst_i*(a+plus_one),contextptr);
}
gen exp2sincos(const gen & e,GIAC_CONTEXT){
gen a=re(e,contextptr),b=im(e,contextptr);
return exp(a,contextptr)*(cos(radtoangle(b,contextptr),contextptr)+cst_i*sin(radtoangle(b,contextptr),contextptr));
}
gen tantosincos(const gen & e,GIAC_CONTEXT){
return rdiv(symb_sin(e),symb_cos(e),contextptr);
}
gen tantosincos2(const gen & e,GIAC_CONTEXT){
gen e2=ratnormal(2*e,contextptr);
return rdiv(symb_sin(e2),(1+symb_cos(e2)),contextptr);
}
gen tantocossin2(const gen & e,GIAC_CONTEXT){
gen e2=ratnormal(2*e,contextptr);
return rdiv((1-symb_cos(e2)),symb_sin(e2),contextptr);
}
gen asintoacos(const gen & e,GIAC_CONTEXT){
if (angle_radian(contextptr))
return cst_pi_over_2-acos(e,contextptr);
else if(angle_degree(contextptr))
return 90-acos(e,contextptr);
//grad
else
return 100 - acos(e, contextptr);
}
gen acostoasin(const gen & e,GIAC_CONTEXT){
if (angle_radian(contextptr))
return cst_pi_over_2-asin(e,contextptr);
else if(angle_degree(contextptr))
return 90-asin(e,0);
//grad
else
return 90-asin(e,0);
}
gen asintoatan(const gen & e,GIAC_CONTEXT){
return symb_atan(rdiv(e,sqrt(1-pow(e,plus_two,contextptr),contextptr),contextptr));
}
gen atantoasin(const gen & e,GIAC_CONTEXT){
return symb_asin(rdiv(e,sqrt(1+pow(e,plus_two,contextptr),contextptr),contextptr));
}
gen acostoatan(const gen & e,GIAC_CONTEXT){
return cst_pi_over_2-asintoatan(e,contextptr);
}
gen atantoacos(const gen & e,GIAC_CONTEXT){
return _asin2acos(atantoasin(e,contextptr),contextptr);
}
gen asin2ln(const gen & g_orig,GIAC_CONTEXT){
//grad
gen g=angletorad(g_orig,contextptr);
return cst_i*ln(g+sqrt(pow(g,2)-1,contextptr),contextptr)+cst_pi_over_2;
}
gen acos2ln(const gen & g_orig,GIAC_CONTEXT){
//grad
gen g=angletorad(g_orig,contextptr);
return -cst_i*ln(g+sqrt(pow(g,2)-1,contextptr),contextptr);
}
gen atan2ln(const gen & g_orig,GIAC_CONTEXT){
//grad
gen g=angletorad(g_orig,contextptr);
return rdiv(cst_i*ln(rdiv(cst_i+g,cst_i-g),contextptr),plus_two,contextptr);
}
// g=[base, exponant]
gen trigcospow(const gen & g0,GIAC_CONTEXT){
gen g(g0);
if (g.type!=_VECT)
return gensizeerr(contextptr);
g.subtype=_SEQ__VECT;
vecteur & v=*g._VECTptr;
gen & base=v.front();
gen & expo=v.back();
if ( (base.type!=_SYMB) || (expo.type!=_INT_) )
return symbolic(at_pow,g);
gen tmpcos=symb_cos(base._SYMBptr->feuille);
int ediv=expo.val/2,emod=expo.val%2;
if (base._SYMBptr->sommet==at_sin)
return pow(1-pow(tmpcos,2),ediv)*pow(base,emod);
if (base._SYMBptr->sommet==at_tan){
gen tmp=pow(tmpcos,2);
tmp=rdiv(plus_one,tmp,contextptr)-plus_one; // 1/ cos^2 -1
return pow(tmp,ediv)*pow(rdiv(symb_sin(base._SYMBptr->feuille),tmpcos,contextptr),emod);
}
return symbolic(at_pow,g);
}
gen trigsinpow(const gen & g0,GIAC_CONTEXT){
gen g(g0);
if (g.type!=_VECT)
return gensizeerr(contextptr);
g.subtype=_SEQ__VECT;
vecteur & v=*g._VECTptr;
gen & base=v.front();
gen & expo=v.back();
if ( (base.type!=_SYMB) || (expo.type!=_INT_) )
return symbolic(at_pow,g);
gen tmpsin=symb_sin(base._SYMBptr->feuille);
int ediv=expo.val/2,emod=expo.val%2;
if (base._SYMBptr->sommet==at_cos)
return pow(1-pow(tmpsin,2),ediv)*pow(base,emod);
if (base._SYMBptr->sommet==at_tan){
gen tmp=pow(tmpsin,2);
tmp=rdiv(tmp,plus_one-tmp,contextptr); // sin^2/ (1-sin^2)
return pow(tmp,ediv)*pow(rdiv(tmpsin,symb_cos(base._SYMBptr->feuille),contextptr),emod);
}
return symbolic(at_pow,g);
}
gen trigtanpow(const gen & g0,GIAC_CONTEXT){
gen g(g0);
if (g.type!=_VECT)
return gensizeerr(contextptr);
g.subtype=_SEQ__VECT;
vecteur & v=*g._VECTptr;
gen & base=v.front();
gen & expo=v.back();
if ( (base.type!=_SYMB) || (expo.type!=_INT_) )
return symbolic(at_pow,g);
gen tmptan=symb_tan(base._SYMBptr->feuille);
int ediv=expo.val/2,emod=expo.val%2;
if (base._SYMBptr->sommet==at_cos)
return pow(1+pow(tmptan,2),-ediv)*pow(base,emod);
if (base._SYMBptr->sommet==at_sin){
gen tmp=pow(tmptan,2);
tmp=rdiv(tmp,plus_one+tmp,contextptr); // tan^2/ (1+tan^2)
return pow(tmp,ediv)*pow(tmptan*symb_cos(base._SYMBptr->feuille),emod);
}
return symbolic(at_pow,g);
}
gen pownegtoinvpow(const gen & g0,GIAC_CONTEXT){
gen g(g0);
if (g.type!=_VECT)
return gensizeerr(contextptr);
g.subtype=_SEQ__VECT;
vecteur & v(*g._VECTptr);
if (v.size()!=2)
return gensizeerr(contextptr);
if (v[1].type!=_SYMB)
return symbolic(at_pow,g);
unary_function_ptr &u=v[1]._SYMBptr->sommet;
if (u==at_neg)
return inv(powtopowexpand(makevecteur(v[0],v[1]._SYMBptr->feuille),contextptr),contextptr);
return symbolic(at_pow,g);
}
gen powtopowexpand(const gen & g0,GIAC_CONTEXT){
gen g(g0);
if (g.type!=_VECT)
return gensizeerr(contextptr);
g.subtype=_SEQ__VECT;
vecteur & v(*g._VECTptr);
if (v.size()!=2)
return gensizeerr(contextptr);
if (v[1].type!=_SYMB)
return symbolic(at_pow,g);
unary_function_ptr &u=v[1]._SYMBptr->sommet;
if (u==at_neg)
return inv(powtopowexpand(makevecteur(v[0],v[1]._SYMBptr->feuille),contextptr),contextptr);
if ( (v[1]._SYMBptr->feuille.type!=_VECT) || ((u!=at_plus) && (u!=at_prod)) )
return symbolic(at_pow,g);
vecteur & w=*v[1]._SYMBptr->feuille._VECTptr;
const_iterateur it=w.begin(),itend=w.end();
if (u==at_plus){
gen res(plus_one);
for (;it!=itend;++it)
res=res*powtopowexpand(makevecteur(v[0],*it),contextptr);
return res;
}
if (u==at_prod){
if (w.size()!=2)
return symbolic(at_pow,g);
if (w[0].type==_INT_)
return pow(powtopowexpand(makevecteur(v[0],w[1]),contextptr),w[0],contextptr);
if (w[1].type==_INT_)
return pow(powtopowexpand(makevecteur(v[0],w[0]),contextptr),w[1],contextptr);
}
return symbolic(at_pow,g);
}
gen exptopower(const gen & g,GIAC_CONTEXT){
if (is_zero(g)) return 1;
gen a,ar,ai,b;
if (has_i(g) && !complex_mode(contextptr) && contains(g,cst_pi) && is_linear_wrt(g,cst_pi,a,b,contextptr) && !is_zero(a)){
// exp(pi*a+b)
reim(a,ar,ai,contextptr);
// checked added for ai otherwise expre:=2*pi*sin(a*pi)/(1-cos(2*a*pi));simplify(expre); is wrong
if (is_zero(ar) && is_assumed_integer(ai,contextptr))
return exptopower(b,contextptr)*pow(-1,ai,contextptr);
}
vecteur l(lop(g,at_ln));
if (l.size()!=1)
return symbolic(at_exp,g);
identificateur tmp(" x");
gen gg=subst(g,l,vecteur(1,tmp),false,contextptr);
if (!is_linear_wrt(gg,tmp,a,b,contextptr) || has_i(a))
return symbolic(at_exp,g);
return exp(b,contextptr)*pow(l[0]._SYMBptr->feuille,a,contextptr);
}
// One substitution of an identifier
static void subst_vecteur(const vecteur & v,const gen & i,const gen & newi,vecteur & w,bool quotesubst,GIAC_CONTEXT){
if (&v==&w){
vecteur::iterator it=w.begin(),itend=w.end();
for (;it!=itend;++it)
*it=subst(*it,i,newi,quotesubst,contextptr);
}
else {
w.reserve(v.size());
vecteur::const_iterator it=v.begin(),itend=v.end();
for (;it!=itend;++it)
w.push_back(subst(*it,i,newi,quotesubst,contextptr));
}
}
vecteur subst(const vecteur & v,const gen & i,const gen & newi,bool quotesubst,GIAC_CONTEXT){
vecteur w;
subst_vecteur(v,i,newi,w,quotesubst,contextptr);
return w;
}
static bool has_subst(const gen & e,const gen & i,const gen & newi,gen & newe,bool quotesubst,GIAC_CONTEXT);
static bool has_subst_vect(const gen & e,const gen & i,const gen & newi,gen & newe,bool quotesubst,GIAC_CONTEXT){
const vecteur & v =*e._VECTptr;
const_iterateur it=v.begin(),itend=v.end();
for (;it!=itend;++it){
if (has_subst(*it,i,newi,newe,quotesubst,contextptr))
break;
}
if (it==itend)
return false;
gen res(new_ref_vecteur(*e._VECTptr),e.subtype);
vecteur & w =*res._VECTptr;
iterateur jt=w.begin()+(it-v.begin());
*jt=newe;
newe=res;
for (++jt,++it;it!=itend;++it,++jt){
if (!has_subst(*it,i,newi,*jt,quotesubst,contextptr))
*jt=*it;
}
return true;
}
static gen subst_integrate(const gen & e,const gen & i,const gen & newi,bool quotesubst,int intg,GIAC_CONTEXT){
vecteur v=*e._SYMBptr->feuille._VECTptr;
int s=int(v.size());
if ( (s>1) && (v[1]==i) ){
vecteur l(*_lname(newi,contextptr)._VECTptr);
if (!l.empty() && l.front()==cst_pi)
l.erase(l.begin());
if (l.empty())
return gensizeerr(contextptr);
v[1]=l.front();
v=subst(v,i,newi,quotesubst,contextptr);
gen der=derive(newi,l.front(),contextptr);
if (intg==0 && der!=1)
return gensizeerr("Unable to handle sum change of variables");
else
v[0]=v[0]*der;
if (is_undef(v[0]))
return v[0];
if (s>2){
identificateur t(" tsubst");
vecteur w=solve(newi-t,*l.front()._IDNTptr,1,contextptr);
if (w.empty())
return gensizeerr(gettext("Unable to solve"));
if (s>3){
bool ordonne=is_greater(v[3],v[2],contextptr);
v[2]=limit(w.front(),t,v[2],ordonne?1:-1,contextptr);
v[3]=limit(w.front(),t,v[3],ordonne?-1:1,contextptr);
}
else
v[2]=limit(w.front(),t,v[2],0,contextptr);
}
return symbolic((intg==0?at_sum:at_integrate),gen(v,_SEQ__VECT));
}
return symbolic((intg==0?at_sum:at_integrate),gen(subst(v,i,newi,quotesubst,contextptr),_SEQ__VECT));
}
static gen subst_derive(const gen & e,const gen & i,const gen & newi,bool quotesubst,GIAC_CONTEXT){
if (series_flags(contextptr) & (1<<7))
return symbolic(at_of,makesequence(e,symb_equal(i,newi)));
vecteur v=*e._SYMBptr->feuille._VECTptr;
int s=int(v.size());
if ( (s==2) && (v[1]==i) ){
vecteur l(*_lname(newi,contextptr)._VECTptr);
if (l.empty())
return gensizeerr(contextptr);
v[1]=l.front();
v=subst(v,i,newi,quotesubst,contextptr);
return rdiv(symbolic(at_derive,gen(v,_SEQ__VECT)),derive(newi,l.front(),contextptr),contextptr);
}
// Warning: ? return e for desolve (is_linear_diffeq)
return symbolic(at_derive,subst(gen(v,_SEQ__VECT),i,newi,quotesubst,contextptr));
// return e;
}
static bool has_subst(const gen & e,const gen & i,const gen & newi,gen & newe,bool quotesubst,GIAC_CONTEXT){
switch (e.type){
case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _REAL: case _STRNG: case _MOD: case _SPOL1: case _USER:
return false;
case _IDNT: case _FUNC:
if (e==i){
newe=newi;
return true;
}
else
return false;
case _SYMB:
if (e==i){
newe=newi;
return true;
}
if (i.type==_FUNC && e._SYMBptr->sommet==i){
if (!has_subst(e._SYMBptr->feuille,i,newi,newe,quotesubst,contextptr))
newe=e._SYMBptr->feuille;
newe=newi(newe,contextptr);
return true;
}
if ( e._SYMBptr->sommet==at_pow && i.type==_SYMB && i._SYMBptr->sommet==at_exp && (*(e._SYMBptr->feuille._VECTptr))[1]*ln((*(e._SYMBptr->feuille._VECTptr))[0],contextptr) == i._SYMBptr->feuille ) {
CERR << e << "=" << i << endl;
newe=newi;
return true;
}
if ( (e._SYMBptr->sommet==at_integrate || !strcmp(e._SYMBptr->sommet.ptr()->s,"integration") || !strcmp(e._SYMBptr->sommet.ptr()->s,"int")) && (e._SYMBptr->feuille.type==_VECT) && (i.type==_IDNT) ){
newe=subst_integrate(e,i,newi,quotesubst,1,contextptr);
return true;
}
if ( e._SYMBptr->sommet==at_sum && e._SYMBptr->feuille.type==_VECT && (i.type==_IDNT) ){
newe=subst_integrate(e,i,newi,quotesubst,0,contextptr);
return true;
}
if ( (e._SYMBptr->sommet==at_derive) && (e._SYMBptr->feuille.type==_VECT) &&(i.type==_IDNT) ){
newe=subst_derive(e,i,newi,quotesubst,contextptr);
return true;
}
if (has_subst(e._SYMBptr->feuille,i,newi,newe,quotesubst,contextptr)){
if (quotesubst || e._SYMBptr->sommet.quoted())
newe=symbolic(e._SYMBptr->sommet,newe);
else
newe=e._SYMBptr->sommet(newe,contextptr);
return true;
}
else
return false;
case _VECT:
return has_subst_vect(e,i,newi,newe,quotesubst,contextptr);
case _FRAC:
if (e==i){
newe=newi;
return true;
}
newe=fraction(subst(e._FRACptr->num,i,newi,quotesubst,contextptr),subst(e._FRACptr->den,i,newi,quotesubst,contextptr));
return true;
default:
#ifndef NO_STDEXCEPT
settypeerr(contextptr);
#endif
return false;
}
}
gen subst(const gen & e,const gen & i,const gen & newi,bool quotesubst,GIAC_CONTEXT){
if (is_inequation(newi) || newi.is_symb_of_sommet(at_and) || newi.is_symb_of_sommet(at_ou))
return gensizeerr(contextptr);
if (i.type==_VECT){
if (newi.type!=_VECT || i._VECTptr->size()!=newi._VECTptr->size()){
#ifndef NO_STDEXCEPT
setdimerr(contextptr);
#endif
return e;
}
return subst(e,*i._VECTptr,*newi._VECTptr,quotesubst,contextptr);
}
if (i.type!=_IDNT && i.type!=_SYMB && i.type!=_FUNC)
*logptr(contextptr) << gettext("Warning, replacing ") << i << gettext(" by ") << newi << gettext(", a substitution variable should perhaps be purged.") << endl;
gen res;
if (has_subst(e,i,newi,res,quotesubst,contextptr))
return res;
else
return e;
}
gen quotesubst(const gen & e,const gen & i,const gen & newi,GIAC_CONTEXT){
return subst(e,i,newi,true,contextptr);
}
#ifdef GIAC_MULTISUBST
static int multisubst(const gen & e,vecteur & res,const gen & x,const vecteur & xval,GIAC_CONTEXT);
static int multisubst_frac(const gen & e,vecteur & res,const gen & x,const vecteur & xval,GIAC_CONTEXT){
vecteur resn,resd;
const gen & N=e._FRACptr->num;
const gen & D=e._FRACptr->den;
int mn=multisubst_frac(N,resn,x,xval,contextptr);
int md=multisubst_frac(D,resd,x,xval,contextptr);
if (!mn && !md)
return 0;
int n=xval.size();
res=xval;
if (mn){
if (md){
for (int i=0;i vi(s) ;
std::vector mi(s);
int m=0;
for (int i=0;itype=_VECT;
it->__VECTptr=new_ref_vecteur(s);
#endif
}
for (int i=0;ifeuille,res,x,xval,contextptr);
// FIXME integrate and derive
if (!m)
return 0;
iterateur it=res.begin(),itend=res.end();
for (;it!=itend;++it){
*it=e._SYMBptr->sommet.quoted()?symbolic(e._SYMBptr->sommet,*it):e._SYMBptr->sommet(*it,contextptr);
}
return 1;
}
// returns 1 if e evals to several values
// or 0 if they are all same = x
static int multisubst(const gen & e,vecteur & res,const gen & x,const vecteur & xval,GIAC_CONTEXT){
switch (e.type){
case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _REAL: case _STRNG: case _MOD: case _SPOL1: case _USER:
return 0;
case _IDNT: case _FUNC:
if (e==x){
res=xval;
return 1;
}
else
return 0;
case _SYMB:
if (e==x){
res=xval;
return 1;
}
return multisubst_symb(e,res,x,xval,contextptr);
case _VECT:
return multisubst_vect(e,res,x,xval,contextptr);
case _FRAC:
if (e==x){
res=xval;
return 1;
}
return multisubst_frac(e,res,x,xval,contextptr);
default:
return gentypeerr(contextptr);
}
return 0;
}
static vecteur multisubst(const gen & g,const gen & x,const vecteur & xval,GIAC_CONTEXT){
int s=xval.size();
vecteur res;
if (multisubst(g,res,x,xval,contextptr))
return res;
else
return vecteur(s,g);
}
static gen _multisubst(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (args.type!=_VECT || args._VECTptr->size()!=3)
return gendimerr(contextptr);
const vecteur & v=*args._VECTptr;
if (v[2].type!=_VECT)
return gensizeerr(contextptr);
if (v[2]._VECTptr->empty())
return v[2];
return multisubst(v[0],v[1],*v[2]._VECTptr,contextptr);
}
static const char _multisubst_s []="multisubst";
static define_unary_function_eval (__multisubst,&giac::_multisubst,_multisubst_s);
define_unary_function_ptr5( at_multisubst ,alias_at_multisubst,&__multisubst,0,true);
#endif // GIAC_MULTISUBST
sparse_poly1 subst(const sparse_poly1 & v,const gen & i,const gen & newi,bool quotesubst,GIAC_CONTEXT){
sparse_poly1 p;
sparse_poly1::const_iterator it=v.begin(),itend=v.end();
p.reserve(itend-it);
gen e;
for (;it!=itend;++it){
e=recursive_normal(subst(it->coeff,i,newi,quotesubst,contextptr),contextptr);
if (!is_zero(e))
p.push_back(monome(e,it->exponent));
}
return p;
}
vecteur sortsubst(const vecteur & v,const vecteur & i,const vecteur & newi,bool quotesubst,GIAC_CONTEXT){
if (i.empty())
return v;
if (v==i)
return newi;
vecteur w;
w.reserve(v.size());
vecteur::const_iterator it=v.begin(),itend=v.end();
for (;it!=itend;++it)
w.push_back(sortsubst(*it,i,newi,quotesubst,contextptr));
return w;
}
// used for sorting
static bool first_sort(const gen & a,const gen & b){
return islesscomplexthanf(a[0],b[0]); // FIXME GIAC_CONTEXT
}
// g known to be in interval
static int findpos(const_iterateur it,const_iterateur itend,const gen & g){
const gen & itg=*it;
if (g==itg)
return 1;
int n=int(itend-it);
if (n<2)
return 0;
n /= 2;
const_iterateur itmid=it+n;
const gen & itgmid = *itmid;
if (islesscomplexthanf(g,itgmid))
return findpos(it,itmid,g);
else {
int f=findpos(itmid,itend,g);
return f?n+f:0;
}
}
int findpos(const vecteur & v,const gen & g){
const_iterateur it=v.begin(),itend=v.end();
if (it==itend)
return 0;
if (g==*it)
return 1;
if (g==*(itend-1))
return int(itend-it);
if (itend-it<=2)
return 0;
if (islesscomplexthanf(g,*it) || islesscomplexthanf(*(itend-1),g))
return 0;
return findpos(it,itend,g);
}
// Multiple substitutions
static void sort2(vecteur & i,vecteur & newi,GIAC_CONTEXT){
for (unsigned k=0;ksommet==at_pow){
pos=findpos(i,exp((*(e._SYMBptr->feuille._VECTptr))[1]*ln((*(e._SYMBptr->feuille._VECTptr))[0],contextptr),contextptr) );
if (pos)
return newi[pos-1];
}
if (e._SYMBptr->feuille.type==_VECT){
gen ef(sortsubst(*e._SYMBptr->feuille._VECTptr,i,newi,quotesubst,contextptr));
ef.subtype=e._SYMBptr->feuille.subtype;
if (quotesubst || e._SYMBptr->sommet.quoted()
// || e._SYMBptr->sommet==at_pow
|| (e._SYMBptr->sommet==at_pow && ef.type==_VECT && ef._VECTptr->size()==2 && ef._VECTptr->front().type>_POLY && !is_zero(ef._VECTptr->front()))
)
return symbolic(e._SYMBptr->sommet,ef);
else
return e._SYMBptr->sommet(ef,contextptr);
}
else {
gen ef=sortsubst(e._SYMBptr->feuille,i,newi,quotesubst,contextptr);
if (quotesubst || e._SYMBptr->sommet.quoted())
return symbolic(e._SYMBptr->sommet,ef);
else
return e._SYMBptr->sommet(ef,contextptr);
}
case _VECT:
return gen(sortsubst(*e._VECTptr,i,newi,quotesubst,contextptr),e.subtype);
case _FRAC:
pos=findpos(i,e);
if (pos)
return newi[pos-1];
return fraction(sortsubst(e._FRACptr->num,i,newi,quotesubst,contextptr),sortsubst(e._FRACptr->den,i,newi,quotesubst,contextptr));
default:
pos=findpos(i,e);
if (pos)
return newi[pos-1];
return e;
}
}
gen subst(const gen & e,const vecteur & i,const vecteur & newi,bool quotesubst,GIAC_CONTEXT){
if (i.empty()) return e;
vecteur sorti(i),sortnewi(newi);
sort2(sorti,sortnewi,contextptr);
return sortsubst(e,sorti,sortnewi,quotesubst,contextptr);
}
gen subst(const gen & e,const vector & v,const vector< gen_op_context > & w,bool quotesubst,GIAC_CONTEXT){
if (v.empty())
return e;
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
vecteur res;
res.reserve(itend-it);
for (;it!=itend;++it)
res.push_back(subst(*it,v,w,quotesubst,contextptr));
return gen(res,e.subtype);
}
if (e.type!=_SYMB)
return e;
if (e._SYMBptr->sommet==at_entry || e._SYMBptr->sommet==at_ans)
return gensizeerr(contextptr);
gen arg=subst(e._SYMBptr->feuille,v,w,quotesubst,contextptr);
int n=equalposcomp(v,&e._SYMBptr->sommet);
if (!n){
if (quotesubst){
gen res=symbolic(e._SYMBptr->sommet,arg);
res.subtype=e.subtype;
return res;
}
return e._SYMBptr->sommet(arg,contextptr);
}
gen tmp=w[n-1](arg,contextptr);
return tmp;
}
// Quick check if e contains some ptr of v
bool has_op_list(const gen & e,const unary_function_ptr * v){
if (e.type==_SYMB){
if (equalposcomp(v,&e._SYMBptr->sommet))
return true;
return has_op_list(e._SYMBptr->feuille,v);
}
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
for (;it!=itend;++it){
if (has_op_list(*it,v))
return true;
}
}
return false;
}
// Quick check if e contains v
bool has_op(const gen & e,const unary_function_ptr & u){
if (e.type==_SYMB){
if (u==e._SYMBptr->sommet)
return true;
return has_op(e._SYMBptr->feuille,u);
}
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
for (;it!=itend;++it){
if (has_op(*it,u))
return true;
}
}
return false;
}
gen subst(const gen & e,const unary_function_ptr * v,const gen_op_context * w,bool quotesubst,GIAC_CONTEXT,bool recursive_nonrat){
if (*v==0 || !has_op_list(e,v))
return e;
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
vecteur res;
res.reserve(itend-it);
for (;it!=itend;++it)
res.push_back(subst(*it,v,w,quotesubst,contextptr,recursive_nonrat));
return gen(res,e.subtype);
}
if (e.type!=_SYMB)
return e;
// recursive call only for rational operators
gen arg=e._SYMBptr->feuille; int pos=-1;
if (recursive_nonrat || ((pos= equalposcomp(analytic_sommets,e._SYMBptr->sommet)) && (pos<=4 || (pos==5 && is_integer(e._SYMBptr->feuille[1])))))
arg=subst(arg,v,w,quotesubst,contextptr,recursive_nonrat);
int n=equalposcomp(v,e._SYMBptr->sommet);
if (!n){
if (quotesubst){
gen res=symbolic(e._SYMBptr->sommet,arg);
res.subtype=e.subtype;
return res;
}
return e._SYMBptr->sommet(arg,contextptr);
}
gen tmp=w[n-1](arg,contextptr);
return tmp;
}
gen subst(const gen & e,const vector & v,const vector< gen_op > & w,bool quotesubst,GIAC_CONTEXT){
if (v.empty())
return e;
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
vecteur res;
res.reserve(itend-it);
for (;it!=itend;++it)
res.push_back(subst(*it,v,w,quotesubst,contextptr));
return gen(res,e.subtype);
}
if (e.type!=_SYMB)
return e;
gen arg=subst(e._SYMBptr->feuille,v,w,quotesubst,contextptr);
int n=equalposcomp(v,&e._SYMBptr->sommet);
if (!n){
if (quotesubst){
gen res=symbolic(e._SYMBptr->sommet,arg);
res.subtype=e.subtype;
return res;
}
return e._SYMBptr->sommet(arg,contextptr);
}
gen tmp=w[n-1](arg);
return tmp;
}
gen halftan(const gen & e,GIAC_CONTEXT){
return subst(e,sincostan_tab,halftan_tab,false,contextptr);
}
gen _halftan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_halftan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_halftan,contextptr);
return halftan(args,contextptr);
}
static const char _halftan_s []="halftan";
static define_unary_function_eval (__halftan,&giac::_halftan,_halftan_s);
define_unary_function_ptr5( at_halftan ,alias_at_halftan,&__halftan,0,true);
// sin(x)=-cos(x+pi/2)
static gen shift_sin(const gen & x,GIAC_CONTEXT){
return -symb_cos(ratnormal(x+cst_pi_over_2,contextptr));
}
// cos(x)=sin(x+pi/2)
static gen shift_cos(const gen & x,GIAC_CONTEXT){
return symb_sin(ratnormal(x+cst_pi_over_2,contextptr));
}
// tan(x+pi/2)=-1/tan(x)
static gen shift_tan(const gen & x,GIAC_CONTEXT){
return minus_one/symb_tan(ratnormal(x+cst_pi_over_2,contextptr));
}
const gen_op_context shift_phase_v_tab[]={shift_sin,shift_cos,shift_tan};
gen shift_phase(const gen & e,GIAC_CONTEXT){
return subst(e,sincostan_tab,shift_phase_v_tab,false,contextptr);
}
gen _shift_phase(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (is_equal(args))
return apply_to_equal(args,_shift_phase,contextptr);
return shift_phase(args,contextptr);
}
static const char _shift_phase_s []="shift_phase";
static define_unary_function_eval (__shift_phase,&giac::_shift_phase,_shift_phase_s);
define_unary_function_ptr5( at_shift_phase ,alias_at_shift_phase,&__shift_phase,0,true);
gen inv_test_exp(const gen & e,GIAC_CONTEXT){
if ( (e.type==_SYMB) && (e._SYMBptr->sommet==at_exp))
return symbolic(at_exp,-e._SYMBptr->feuille);
return inv(e,contextptr);
}
gen rewrite_hyper(const gen & e,GIAC_CONTEXT){
/*
vector vu;
vu.push_back(at_sinh);
vu.push_back(at_cosh);
vu.push_back(at_tanh);
vu.push_back(at_inv);
vector vv(hyp2exp_tab,hyp2exp_tab+3);
vv.push_back(inv_test_exp);
return subst(e,vu,vv,false,contextptr);
*/
return subst(e,sinhcoshtanhinv_tab,hypinv2exp_tab,false,contextptr);
}
gen hyp2exp(const gen & e,GIAC_CONTEXT){
return subst(e,sinhcoshtanh_tab,hyp2exp_tab,false,contextptr);
}
gen _hyp2exp(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_hyp2exp(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_hyp2exp,contextptr);
return hyp2exp(args,contextptr);
}
static const char _hyp2exp_s []="hyp2exp";
static define_unary_function_eval (__hyp2exp,&giac::_hyp2exp,_hyp2exp_s);
define_unary_function_ptr5( at_hyp2exp ,alias_at_hyp2exp,&__hyp2exp,0,true);
gen sincos(const gen & e,GIAC_CONTEXT){
//grad
if (angle_radian(contextptr)){
gen tmp=subst(e,tan_tab,tan2sincos_tab,true,contextptr);
tmp=_pow2exp(tmp,contextptr);
tmp=subst(tmp,exp_tab,exp2sincos_tab,false,contextptr);
tmp=_exp2pow(tmp,contextptr);
return tmp;
}
else
return e;
}
gen _sincos(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_sincos(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_sincos,contextptr);
return sincos(args,contextptr);
}
static const char _sincos_s []="sincos";
static define_unary_function_eval (__sincos,&giac::_sincos,_sincos_s);
define_unary_function_ptr5( at_sincos ,alias_at_sincos,&__sincos,0,true);
gen trig2exp(const gen & e,GIAC_CONTEXT){
//grad
if (angle_radian(contextptr))
return subst(e,sincostan_tab,trig2exp_tab,false,contextptr);
else
return e;
}
gen _trig2exp(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_trig2exp(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_trig2exp,contextptr);
return trig2exp(args,contextptr);
}
static const char _trig2exp_s []="trig2exp";
static define_unary_function_eval (__trig2exp,&giac::_trig2exp,_trig2exp_s);
define_unary_function_ptr5( at_trig2exp ,alias_at_trig2exp,&__trig2exp,0,true);
gen halftan_hyp2exp(const gen & e,GIAC_CONTEXT){
return subst(e,sincostansinhcoshtanh_tab,halftan_hyp2exp_tab,false,contextptr);
}
gen _halftan_hyp2exp(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_halftan_hyp2exp(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_halftan_hyp2exp,contextptr);
return halftan_hyp2exp(args,contextptr);
}
static const char _halftan_hyp2exp_s []="halftan_hyp2exp";
static define_unary_function_eval (__halftan_hyp2exp,&giac::_halftan_hyp2exp,_halftan_hyp2exp_s);
define_unary_function_ptr5( at_halftan_hyp2exp ,alias_at_halftan_hyp2exp,&__halftan_hyp2exp,0,true);
gen asin2acos(const gen & e,GIAC_CONTEXT){
return subst(e,asin_tab,asin2acos_tab,false,contextptr);
}
gen _asin2acos(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_asin2acos(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_asin2acos,contextptr);
return asin2acos(args,contextptr);
}
static const char _asin2acos_s []="asin2acos";
static define_unary_function_eval (__asin2acos,&giac::_asin2acos,_asin2acos_s);
define_unary_function_ptr5( at_asin2acos ,alias_at_asin2acos,&__asin2acos,0,true);
gen asin2atan(const gen & e,GIAC_CONTEXT){
return subst(e,asin_tab,asin2atan_tab,false,contextptr);
}
gen _asin2atan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_asin2atan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_asin2atan,contextptr);
return asin2atan(args,contextptr);
}
static const char _asin2atan_s []="asin2atan";
static define_unary_function_eval (__asin2atan,&giac::_asin2atan,_asin2atan_s);
define_unary_function_ptr5( at_asin2atan ,alias_at_asin2atan,&__asin2atan,0,true);
gen acos2asin(const gen & e,GIAC_CONTEXT){
return subst(e,acos_tab,acos2asin_tab,false,contextptr);
}
gen _acos2asin(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_acos2asin(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,acos2asin,contextptr);
return acos2asin(args,contextptr);
}
static const char _acos2asin_s []="acos2asin";
static define_unary_function_eval (__acos2asin,&giac::_acos2asin,_acos2asin_s);
define_unary_function_ptr5( at_acos2asin ,alias_at_acos2asin,&__acos2asin,0,true);
gen acos2atan(const gen & e,GIAC_CONTEXT){
return subst(e,acos_tab,acos2atan_tab,false,contextptr);
}
gen _acos2atan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_acos2atan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_acos2atan,contextptr);
return acos2atan(args,contextptr);
}
static const char _acos2atan_s []="acos2atan";
static define_unary_function_eval (__acos2atan,&giac::_acos2atan,_acos2atan_s);
define_unary_function_ptr5( at_acos2atan ,alias_at_acos2atan,&__acos2atan,0,true);
gen atan2asin(const gen & e,GIAC_CONTEXT){
return subst(e,atan_tab,atan2asin_tab,false,contextptr);
}
gen _atan2asin(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_atan2asin(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_atan2asin,contextptr);
return atan2asin(args,contextptr);
}
static const char _atan2asin_s []="atan2asin";
static define_unary_function_eval (__atan2asin,&giac::_atan2asin,_atan2asin_s);
define_unary_function_ptr5( at_atan2asin ,alias_at_atan2asin,&__atan2asin,0,true);
gen atan2acos(const gen & e,GIAC_CONTEXT){
return subst(e,atan_tab,atan2acos_tab,false,contextptr);
}
gen _atan2acos(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_atan2acos(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_atan2acos,contextptr);
return atan2acos(args,contextptr);
}
static const char _atan2acos_s []="atan2acos";
static define_unary_function_eval (__atan2acos,&giac::_atan2acos,_atan2acos_s);
define_unary_function_ptr5( at_atan2acos ,alias_at_atan2acos,&__atan2acos,0,true);
gen atrig2ln(const gen & e,GIAC_CONTEXT){
if (angle_radian(contextptr))
return subst(e,asinacosatan_tab,atrig2ln_tab,false,contextptr);
else
return e;
}
gen _atrig2ln(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_atrig2ln(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_atrig2ln,contextptr);
return atrig2ln(args,contextptr);
}
static const char _atrig2ln_s []="atrig2ln";
static define_unary_function_eval (__atrig2ln,&giac::_atrig2ln,_atrig2ln_s);
define_unary_function_ptr5( at_atrig2ln ,alias_at_atrig2ln,&__atrig2ln,0,true);
bool is_rational(const gen & g){
if (is_integer(g))
return true;
if (g.type!=_FRAC)
return false;
return is_integer(g._FRACptr->num) && is_integer(g._FRACptr->den);
}
// if g is a symbolic depending linearly and rationnaly on a ln,
// factors out this term before taking the exp
static gen rewrite_strong_exp(const gen & g_orig,GIAC_CONTEXT){
if (g_orig.type!=_SYMB)
return exp(g_orig,contextptr);
gen g(g_orig),res(plus_one);
vecteur v(lop(lvar(g),at_ln));
v.insert(v.begin(),cst_pi);
int s=int(v.size());
identificateur t(" t");
for (int i=0;ifeuille,dg._SYMBptr->feuille,contextptr);
else
res=res*pow(v[i]._SYMBptr->feuille,dg,contextptr);
}
}
return res*exp(normal(g,contextptr),contextptr);
}
// After extracting the cst coeff of g
// if g is a linear combination of the components of wrt,
// this will return the coeffs of the linear comb
// otherwise it will add g at the end of wrt and return [0...0 1]
// It assumes that g and the coeff of wrt are multivariate rat. fractions
vecteur as_linear_combination(const gen & g,vecteur & wrt,GIAC_CONTEXT){
vecteur v(wrt);
v.push_back(g);
gen d;
lcmdeno_converted(v,d,contextptr);
gen cl=v.back();
int n=int(wrt.size());
vecteur res(n),mat;
polynome p;
if (cl.type<_POLY){
// code added 26 may 2015 for simplify(exp(1/2+t/2)-exp(t/2)*exp(1/2));
for (unsigned i=0;i(cl,v[i]._POLYptr->dim));
break;
}
}
}
if (p.coord.empty() && cl.type!=_POLY){ // search for a non poly in wrt
gen gg;
int i;
for (i=0;inum.type==_INT_) && (gg._FRACptr->den.type==_INT_) )
break;
}
}
if (i==n){
wrt.push_back(g);
res.push_back(plus_one);
}
else
res[i]=gg;
return res;
}
// we are now back to express cl as linear comb with integer coeff
// but here in multivariate polynomials
// we build now a linear system and solve it
if (p.coord.empty())
p=*cl._POLYptr;
vector< monomial >::const_iterator it=p.coord.begin(),itend=p.coord.end();
for (;it!=itend;++it){
const index_m & i=it->index;
vecteur tmp(n+1);
tmp.back()=it->value;
for (int j=0,k;jposition(i)) >=0 )
tmp[j]=gg._POLYptr->coord[k].value;
}
else {
if (i.is_zero())
tmp[j]=gg;
}
}
mat.push_back(tmp);
}
// add monomials that are not inside the last polynomial
polynome fait(p);
for (int j=0,k;j >::const_iterator it=pj.coord.begin(),itend=pj.coord.end();
for (;it!=itend;++it){
const index_m & i=it->index;
k=fait.position(i);
if (k>=0 ) // this monomial is already in the system
continue;
fait=fait+monomial(plus_one,i);
// make a new line in the system for this new monomial
vecteur tmp(n+1);
tmp.back()=zero;
for (int J=0,K;Jposition(i)) >=0 )
tmp[J]=GG._POLYptr->coord[K].value;
}
else {
if (i.is_zero())
tmp[J]=GG;
}
}
mat.push_back(tmp);
}
}
// take re and im since coeffs are reals
// FIXME: should have a better algo for rational coeffs
mat=mergevecteur(*re(mat,contextptr)._VECTptr,*im(mat,contextptr)._VECTptr);
// find solutions in kernel of mat
matrice noyau=mker(mat,contextptr);
// try each row of noyau that has a non-zero last coeff
// since the first row coeff is -1 all coeff must be rationals
int ns=int(noyau.size());
for (int i=0;itype!=_INT_)
break;
}
if (jt!=jtend)
continue;
// additional check: w.v=0
gen check=dotvecteur(w,v);
if (!is_zero(check))
continue;
gg=w.back();
w.pop_back();
res=divvecteur(w,-gg);
return res;
}
// no solution found
wrt.push_back(g);
res.push_back(plus_one);
return res;
}
bool is_unit(const gen & g){
if (g.type==_INT_)
return (g.val==1) || (g.val==-1);
if (g.type==_ZINT)
return (g==1) || (g==-1);
if (g.type==_CPLX)
return (g._CPLXptr->type==_INT_) && (g._CPLXptr->val==0) && ( (g._CPLXptr+1)->type==_INT_) && ( ( (g._CPLXptr+1)->val==1) || ( (g._CPLXptr+1)->val==-1) );
if (g.type==_POLY)
return (g._POLYptr->coord.size()==1) && (g._POLYptr->coord.front().index.is_zero()) && is_unit(g._POLYptr->coord.front().value);
return false;
}
bool is_algebraic_extension(const gen & g){
if (g.type==_EXT)
return true;
if (g.type==_POLY && g._POLYptr->dim==0 && !g._POLYptr->coord.empty())
return is_algebraic_extension(g._POLYptr->coord.front().value);
return false;
}
// a is an extension, search if can be expressed as a product of powers of ext
static bool ext_relation(const gen & a0,const vecteur & ext,const vecteur & vars,vecteur & coeffs,GIAC_CONTEXT){
if (ext.empty())
return false;
gen a=r2e(a0,vars,contextptr);
vecteur w=*r2e(ext,vars,contextptr)._VECTptr;
w.push_back(a);
vecteur l(lidnt(w));
if (!l.empty()){ // check for random values of the variables
vecteur lval=vranm(int(l.size()),0,0);
// should be improved to take care of assumptions and avoid bad eval points
w=subst(w,l,lval,false,contextptr);
}
int s=int(w.size());
matrice test(s);
gen precision=1<<30; // 2^30
for (int i=0;i go to the next element of primeargs
++i;
continue;
}
if (is_unit(primeargs[i])){
primeargs[i]=g;
continue;
}
decompose(g,primeargs,extargs,i,vars,contextptr);
}
if (!is_unit(a))
primeargs.push_back(a);
}
static gen branch_evalf(const gen & g,GIAC_CONTEXT){
if (is_undef(g))
return g;
vecteur v(*_lname(evalf(g,1,contextptr),contextptr)._VECTptr);
gen gg(g);
int s=int(v.size());
for (int i=0;iis_symb_of_sommet(at_exp))
continue;
index_t shift_index(s);
int nv=n.valuation(i);
shift_index[i]=-nv;
n=n.shift(shift_index);
int dv=d.valuation(i);
shift_index[i]=-dv;
d=d.shift(shift_index);
int v=nv-dv;
res=res+v*it->_SYMBptr->feuille;
}
res=res+ln(r2sym(n,l,contextptr)/r2sym(d,l,contextptr),contextptr);
return res;
}
static gen simplifylnexp(const gen & g,GIAC_CONTEXT){
vecteur l(lop(g,at_ln));
int s=int(l.size());
if (!s)
return g;
vecteur lsub;
for (int i=0;ifeuille,contextptr));
return quotesubst(g,l,lsub,contextptr);
}
static void rlvar(const gen &e,vecteur & res,bool alg){
vecteur v;
if (alg){
vecteur tmp=alg_lvar(e);
// make one list from the matrix
const_iterateur it=tmp.begin(),itend=tmp.end();
for (;it!=itend;++it){
if (it->type==_VECT){
const_iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end();
for (;jt!=jtend;++jt){
if (!equalposcomp(v,*jt))
v.push_back(*jt);
}
}
}
}
else
v=lvar(e);
vecteur::const_iterator it=v.begin(),itend=v.end();
for (;it!=itend;++it){
if (!equalposcomp(res,*it)){
// recursive call
res.push_back(*it);
if (it->type==_SYMB) {
rlvar(it->_SYMBptr->feuille,res,alg);
if (it->_SYMBptr->sommet==at_pow)
rlvar(symbolic(at_ln,(*(it->_SYMBptr->feuille._VECTptr))[0]),res,alg);
}
}
}
}
// recursive (alg) list of var
vecteur rlvar(const gen &e,bool alg){
vecteur res;
rlvar(e,res,alg);
gen_sort_f(res.begin(),res.end(),symb_size_less);
return res;
}
gen _pow2exp(const gen & e,GIAC_CONTEXT){
if ( e.type==_STRNG && e.subtype==-1) return e;
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
vecteur v;
v.reserve(itend-it);
for (;it!=itend;++it)
v.push_back(_pow2exp(*it,contextptr));
return gen(v,e.subtype);
}
if (e.type!=_SYMB)
return e;
gen var,res;
if (is_algebraic_program(e,var,res))
return symbolic(at_program,makesequence(var,0,_pow2exp(res,contextptr)));
if ( (e._SYMBptr->sommet==at_pow || e._SYMBptr->sommet==at_surd || e._SYMBptr->sommet==at_NTHROOT) && e._SYMBptr->feuille.type==_VECT && e._SYMBptr->feuille._VECTptr->size()==2){
vecteur v=*e._SYMBptr->feuille._VECTptr;
if (e._SYMBptr->sommet==at_NTHROOT)
swapgen(v[0],v[1]);
/*
if (v[0].type==_VECT)
return gensizeerr(gettext("Conversion of ^ of list/matrices to exp/ln not allowed. For symbolic power of square matrices, try matpow instead of ^"));
*/
if (v[1].type!=_INT_ && v[1].type!=_FRAC){
gen tmp=-v[0];
gen tmp1=(e._SYMBptr->sommet==at_surd || e._SYMBptr->sommet==at_NTHROOT)?inv(v[1],contextptr):v[1];
tmp1=_pow2exp(tmp1,contextptr);
if (is_strictly_positive(tmp,contextptr))
return exp(tmp1*_pow2exp(ln(tmp,contextptr),contextptr),contextptr)*symb_exp(v[1]*cst_i*cst_pi);
else
return exp(tmp1*_pow2exp(ln(v[0],contextptr),contextptr),contextptr);
}
}
return e._SYMBptr->sommet(_pow2exp(e._SYMBptr->feuille,contextptr),contextptr);
}
static const char _pow2exp_s []="pow2exp";
static define_unary_function_eval (__pow2exp,&_pow2exp,_pow2exp_s);
define_unary_function_ptr5( at_pow2exp ,alias_at_pow2exp,&__pow2exp,0,true);
gen pow2expln(const gen & e,const identificateur & x,GIAC_CONTEXT){
if (e.type==_VECT){
const_iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
vecteur v;
v.reserve(itend-it);
for (;it!=itend;++it)
v.push_back(pow2expln(*it,x,contextptr));
return v;
}
if (e.type!=_SYMB)
return e;
if (e._SYMBptr->feuille.type==_VECT){
vecteur & v=*e._SYMBptr->feuille._VECTptr;
if ((e._SYMBptr->sommet==at_pow) && ( contains(v[1],x) ||(v[1].type!=_INT_ && contains(v[0],x) ) ) )
return symb_exp(pow2expln(v[1],x,contextptr)*symb_ln(pow2expln(v[0],x,contextptr)));
}
return e._SYMBptr->sommet(pow2expln(e._SYMBptr->feuille,x,contextptr),contextptr);
}
gen pow2expln(const gen & e,GIAC_CONTEXT){
if (e.type==_VECT)
return apply(e,pow2expln,contextptr);
if (e.type!=_SYMB)
return e;
if (e._SYMBptr->feuille.type==_VECT){
vecteur & v=*e._SYMBptr->feuille._VECTptr;
if (e._SYMBptr->sommet==at_pow && v[1].type!=_INT_ && !(v[1].type==_FRAC && is_integer(v[0])))
return symb_exp(pow2expln(v[1],contextptr)*symb_ln(pow2expln(v[0],contextptr)));
}
return e._SYMBptr->sommet(pow2expln(e._SYMBptr->feuille,contextptr),contextptr);
}
gen simplifyfactorial(const gen & g,GIAC_CONTEXT){
vecteur l(lop(g,at_factorial));
int s=int(l.size());
if (s<2)
return g;
// look if difference of arguments in l are integers
vecteur newl(s);
// newl will contain couples of arg of factorials and integers shift
newl[0]=makevecteur(l[0]._SYMBptr->feuille,zero);
for (int i=1;ifeuille;
newl[i]=makevecteur(current,zero);
for (int j=0;j=0){
newl[i]=makevecteur(base,difference);
break;
}
// current is the new factorial basis, change base in newl
newl[i]=makevecteur(current,zero);
for (k=0;k0;--j){
product=product*(base+j);
}
newl[i]=product*symbolic(at_factorial,base);
}
return subst(g,l,newl,false,contextptr);
}
gen simplifypsi(const gen & g,GIAC_CONTEXT){
vecteur l(lop(g,at_Psi));
int s=int(l.size());
if (s<2)
return g;
// look if difference of arguments in l are integers
vecteur newl(s);
// newl will contain couples of arg of Psi and integers shift
newl[0]=makevecteur(l[0]._SYMBptr->feuille,zero);
for (int i=1;ifeuille;
newl[i]=makevecteur(current,zero);
for (int j=0;jsize()==2 && difference._VECTptr->back()==0)
difference=difference._VECTptr->front();
if (difference.type!=_INT_)
continue;
int k=difference.val;
if (k>=0){
newl[i]=makevecteur(base,difference);
break;
}
// current is the new Psi basis, change base in newl
newl[i]=makevecteur(current,zero);
for (k=0;ksize()==2){
expo=-1-base._VECTptr->back();
base0=base._VECTptr->front();
}
int shift=newl[i][1].val;
gen somme=0;
for (int j=shift-1;j>=0;--j){
somme += pow(base0+j,expo,contextptr);
}
newl[i]=somme+symbolic(at_Psi,base);
}
return subst(g,l,newl,false,contextptr);
}
gen gammatofactorial(const gen & x,GIAC_CONTEXT){
if (x.is_symb_of_sommet(at_plus) && x._SYMBptr->feuille.type==_VECT){
vecteur v = *x._SYMBptr->feuille._VECTptr;
if (v.size()==2 && v.back()==plus_one)
return symbolic(at_factorial,v.front());
if (v.size()>2 && v.back()==plus_one){
v.pop_back();
return symbolic(at_factorial,symbolic(at_plus,gen(v,_SEQ__VECT)));
}
}
if (x.type==_VECT)
return symbolic(at_Gamma,x);
return symbolic(at_factorial,x-1);
}
gen gamma2factorial(const gen & g,GIAC_CONTEXT){
return subst(g,gamma_tab,gamma2factorial_tab,false,contextptr);
}
gen factorialtogamma(const gen & g,GIAC_CONTEXT){
return symbolic(at_Gamma,g+1);
}
gen factorial2gamma(const gen & g,GIAC_CONTEXT){
return subst(g,factorial_tab,factorial2gamma_tab,false,contextptr);
}
gen tsimplify_common(const gen & e,GIAC_CONTEXT){
gen g=pow2expln(e,contextptr);
g=gamma2factorial(g,contextptr);
g=simplifyfactorial(g,contextptr);
g=simplifypsi(g,contextptr);
// analyse of args of ln
g=simplifylnexp(g,contextptr);
vecteur l(lop(g,at_ln));
int s=int(l.size());
if (s>1){
vecteur argln(s);
for (int i=0;ifeuille,contextptr); // was tsimplify, but replacing sin/cos in arg of ln is bad
// check for common factors between args
// now we make a vector of prime together values and rewrite
// each arg as a product of these values + a multiple of 2*pi*i
// arg <--> [ powers multiple_2*pi ]
// Initialization
vecteur vars(alg_lvar(argln));
// FIXME alg_lvar for alg ext but requires decompose to work!
for (int i=0;ifeuille,contextptr); // was tsimplify, but replacing sin/cos in terms of complex exp is bad
// check for linear relations with rational coefficients between args
// add i*pi and ln to the linear relations checking
// First convert everything to multivariate fractions
vecteur vars(1,cst_pi);
lvar(newl,vars);
vecteur ln_vars(lop(newl,at_ln));
vecteur independant(*e2r(ln_vars,vars,contextptr)._VECTptr);
int n_ln=int(independant.size());
independant.push_back(e2r(cst_i*cst_pi,vars,contextptr));
matrice m;
int st=step_infolevel(contextptr);
step_infolevel(0,contextptr);
for (int i=0;isize()),r=int(m.size());
for (int i=0;isize());
if (msfeuille,inv(lcmg,contextptr),contextptr);
else
independant[i]=rewrite_strong_exp(r2e(rdiv(independant[i],lcmg,contextptr),vars,contextptr),contextptr);
}
m=mtran(mt);
// compute exp[newl]
for (int i=0;i1 && angle_radian(contextptr))
g=subst(e,sincostan_tab,trig2exp_tab,false,contextptr,false); // g=trig2exp(e,contextptr);
if (s2>1 && angle_radian(contextptr))
g=subst(g,asinacosatan_tab,atrig2ln_tab,false,contextptr,false);//g=atrig2ln(g,contextptr);
bool b=complex_mode(contextptr);
complex_mode(true,contextptr);
g=tsimplify_common(g,contextptr);
complex_mode(b,contextptr);
int tg=taille(g,8*te); // since sin/cos are coded as exp(i*...)
if (tg>=8*te){
g=gamma2factorial(e,contextptr);
g=simplifyfactorial(g,contextptr);
return g;
}
return g;
}
gen _tsimplify(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tsimplify(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tsimplify,contextptr);
return tsimplify(args,contextptr);
}
static const char _tsimplify_s []="tsimplify";
static define_unary_function_eval (__tsimplify,&giac::_tsimplify,_tsimplify_s);
define_unary_function_ptr5( at_tsimplify ,alias_at_tsimplify,&__tsimplify,0,true);
// find symbolic vars in g that have u has sommet
vecteur lop(const gen & g,const unary_function_ptr & u){
if (!has_op(g,u))
return vecteur(0);
if (g.type==_SYMB) {
vecteur vrec=lop(g._SYMBptr->feuille,u);
if (g._SYMBptr->sommet==u)
vrec.push_back(g);
return vrec;
}
if (g.type!=_VECT)
return vecteur(0);
vecteur res;
const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
for (;it!=itend;++it)
res=mergeset(res,lop(*it,u));
return res;
}
// find symbolic vars in g that have u has sommet
vecteur lop(const gen & g,const unary_function_ptr * u){
if (!has_op(g,*u))
return vecteur(0);
if (g.type==_SYMB) {
vecteur vrec=lop(g._SYMBptr->feuille,u);
if (g._SYMBptr->sommet==u)
vrec.push_back(g);
return vrec;
}
if (g.type!=_VECT)
return vecteur(0);
vecteur res;
const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
for (;it!=itend;++it)
res=mergeset(res,lop(*it,u));
return res;
}
// find symbolic vars in g that have u has sommet
vecteur loptab(const gen & g,const unary_function_ptr * v){
if (g.type==_SYMB) {
if (equalposcomp(v,g._SYMBptr->sommet))
return vecteur(1,g);
else
return loptab(g._SYMBptr->feuille,v);
}
if (g.type!=_VECT)
return vecteur(0);
vecteur res;
const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
for (;it!=itend;++it)
res=mergeset(res,loptab(*it,v));
return res;
}
// find symbolic vars in g that have u has sommet
vecteur lop(const gen & g,const vector & v){
if (g.type==_SYMB) {
if (equalposcomp(v,&g._SYMBptr->sommet))
return vecteur(1,g);
else
return lop(g._SYMBptr->feuille,v);
}
if (g.type!=_VECT)
return vecteur(0);
vecteur res;
const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
for (;it!=itend;++it)
res=mergeset(res,lop(*it,v));
return res;
}
gen expln2trig(const gen & g,GIAC_CONTEXT){
if (g.type==_VECT)
return apply(g,contextptr,expln2trig);
if (g.type!=_SYMB)
return g;
if (g._SYMBptr->sommet==at_inv){
// inv[*]=*[inv]
// inv[exp]=exp[neg]
const gen & f=g._SYMBptr->feuille;
if (f.type==_SYMB){
const unary_function_ptr & s=f._SYMBptr->sommet;
const gen & ff=f._SYMBptr->feuille;
if (s==at_exp)
return expln2trig(symbolic(at_exp,-ff),contextptr);
if (s==at_prod)
return _prod(expln2trig(inv(ff,contextptr),contextptr),contextptr);
if (s==at_pow)
return pow(expln2trig(inv(ff._VECTptr->front(),contextptr),contextptr),ff._VECTptr->back(),contextptr);
}
// otherwise multiply by the conjugate
gen tmp=expln2trig(g._SYMBptr->feuille,contextptr);
gen retmp=re(tmp,contextptr);
gen imtmp=im(tmp,contextptr);
return (retmp-cst_i*imtmp)*inv(pow(retmp,2)+pow(imtmp,2),contextptr);
}
if (g._SYMBptr->sommet==at_exp)
return sincos(g,contextptr);
gen f=expln2trig(g._SYMBptr->feuille,contextptr);
if (g._SYMBptr->sommet!=at_plus && g._SYMBptr->sommet!=at_prod && g._SYMBptr->sommet!=at_inv && g._SYMBptr->sommet!=at_pow && g._SYMBptr->sommet!=at_neg)
f=normal(f,contextptr);
if (g._SYMBptr->sommet==at_ln){
gen gre=simplify(re(f,contextptr),contextptr);
gen gim=simplify(im(f,contextptr),contextptr);
if (is_zero(gre))
return ln(pow(gim,2),contextptr)/2+sign(gim,contextptr)*cst_i*cst_pi_over_2;
if (is_zero(gim)){
if (complex_mode(contextptr))
return rdiv(ln(pow(gre,2),contextptr),plus_two,contextptr)+cst_i*(plus_one-sign(gre,contextptr))*cst_pi_over_2;
else
return ln(gre,contextptr);
}
return rdiv(ln(pow(gre,2)+pow(gim,2),contextptr),plus_two,contextptr)+cst_i*(atan(gim/gre,contextptr)+sign(gim,contextptr)*(plus_one-sign(gre,contextptr))*cst_pi_over_2);
}
return symbolic(g._SYMBptr->sommet,f);
}
gen gen_feuille(const gen & g){
if (g.type==_SYMB)
return g._SYMBptr->feuille;
return g;
}
gen cossinexp2rootof(const gen & e,GIAC_CONTEXT){
gen f=trig2exp(e,contextptr);
vecteur l(lvar(f)),l1,l2;
int n,d,q,r;
for (unsigned i=0;ifeuille;
if (contains(li,cst_pi)){
li=ratnormal(li/cst_pi/cst_i,contextptr);
if (li.type==_FRAC && li._FRACptr->num.type==_INT_ && li._FRACptr->den.type==_INT_){
n=li._FRACptr->num.val;
d=li._FRACptr->den.val;
if (d<0){ n=-n; d=-d; }
q=n/d;
r=n%d;
if (q%2)
q=-1;
else
q=1;
if (r<0) r += 2*d;
// exp(r*i*pi/d) -> use rootof([1,..,0],cyclotomic(2*d))
vecteur vr(r+1);
vr[0]=1;
vecteur vc(cyclotomic(2*d));
vr = vr % vc;
if (!is_undef(vc)){
l1.push_back(l[i]);
l2.push_back(q*symb_rootof(vr,vc,contextptr));
}
}
}
}
}
if (l1.empty())
return e;
f=subst(f,l1,l2,false,contextptr);
return f;
}
gen powneg2invpow(const gen & e,GIAC_CONTEXT){
return subst(e,pow_tab,powneg2invpow_tab,false,contextptr);
}
bool in_cklin(const gen & tmp){
if (tmp.is_symb_of_sommet(at_neg))
return in_cklin(tmp._SYMBptr->feuille);
if (tmp.is_symb_of_sommet(at_exp) && has_i(tmp))
return true;
if (tmp.is_symb_of_sommet(at_pow))
return in_cklin(tmp._SYMBptr->feuille[0]);
if (tmp.is_symb_of_sommet(at_prod)){
gen t=tmp._SYMBptr->feuille;
if (t.type==_VECT){
const_iterateur it=t._VECTptr->begin(),itend=t._VECTptr->end();
for (;it!=itend;++it)
if (in_cklin(*it))
return true;
}
}
return false;
}
// ck if g has a denominator with exponentials, if so linearize
gen cklin(const gen & g,GIAC_CONTEXT){
vecteur gn,gd;
prod2frac(g,gn,gd);
if (gd.empty())
return g;
for (unsigned i=0;ifeuille;
}
for (int i=0;ifeuille;
if (equalposcomp(vabs,arg)){
vs1.push_back(symbolic(at_sign,arg));
vs2.push_back(symbolic(at_abs,arg)/arg);
}
}
if (!vs1.empty())
e=subst(e,vs1,vs2,false,contextptr);
// ratnormal added for E:=2*exp(t/25)/(19+exp(t/25)); F:=simplifier(int(E,t));
// M:=(1/50)*int(E,t,50,100); simplify(M)
vecteur lnv=lop(e,at_ln);
if (!lnv.empty()){
gen trye=lncollect(ratnormal(e_orig,contextptr),contextptr);
if (lop(trye,at_ln).size()feuille.type!=_VECT){
if (e._SYMBptr->sommet!=at_inv && e._SYMBptr->sommet!=at_neg)
return e._SYMBptr->sommet(simplify(e._SYMBptr->feuille,contextptr),contextptr);
}
vabs=lop(e,at_abs);
vecteur vabs2(vabs);
iterateur it=vabs2.begin(),itend=vabs2.end();
for (;it!=itend;++it){
*it=symbolic(at_abs,factor(it->_SYMBptr->feuille,false,contextptr));
}
e=quotesubst(e,vabs,vabs2,contextptr);
vabs=lop(lvar(e),at_pow);
vabs2=vabs;
it=vabs2.begin(); itend=vabs2.end();
for (;it!=itend;++it){
gen tmp=it->_SYMBptr->feuille;
if (tmp.type==_VECT && tmp._VECTptr->size()==2){
gen tmp1=simplify(tmp._VECTptr->front(),contextptr);
tmp1=pow(tmp1,tmp._VECTptr->back(),contextptr);
gen tmp2=normal(tmp1,contextptr);
*it=tmp2;
}
}
// try to rewrite powers with less indep. vars
vecteur bases,bases2;
if (vabs2.size()>1){
#ifdef NO_STDEXCEPT
vecteur vabs2tmp=*tsimplify_common(vabs2,contextptr)._VECTptr;
if (is_undef(vabs2tmp)){
*logptr(contextptr) << vabs2tmp << endl;
return e_orig;
}
// check for rootof?
vabs2=vabs2tmp;
#else
vabs2=*tsimplify_common(vabs2,contextptr)._VECTptr;
#endif
if (1){
int S=int(vabs2.size());
vector base(S),expo(S);
for (int i=0;inum!=1 || e._FRACptr->den.type!=_INT_){
bases.push_back(g);
base[i]=int(bases.size()-1);
expo[i]=1;
continue;
}
int p=equalposcomp(bases,b);
if (p==0){
bases.push_back(b);
base[i]=int(bases.size()-1);
expo[i]=e._FRACptr->den.val;
continue;
}
base[i]=p-1;
expo[i]=e._FRACptr->den.val;
}
// find lcm of exponent of indices i having the same base
vector lcms(bases.size(),1);
for (int i=0;ifeuille),contextptr),contextptr);
if (!lop(tmp,at_exp).empty())
vabs.push_back(vabs2[i]);
}
}
if (!vabs.empty() && debug_infolevel)
*logptr(contextptr) << gettext("simplify preserving ") << vabs << endl;
int s=int(vabs.size());
vabs2=vecteur(s);
for (int i=0;i1){
// retry with trigtan/trigcos/trigsin/halftan
e2=recursive_normal(_trigtan(e,contextptr),contextptr);
if (int(loptab(e2,sincostan_tab).size())1)
return quotesubst(e,vabs2,vabs,contextptr);
}
}
#endif
gen g=tsimplify_noexpln(e,s1,s2,contextptr);
gen glin=cklin(g,contextptr);
bool glinb=glin!=g;
g=glin;
g=_exp2pow(g,contextptr);
if (s1<=1 && s2<= 1){
g=quotesubst(g,vabs2,vabs,contextptr);
return ratnormal(g,contextptr);//glinb?g:ratnormal(g,contextptr);
}
int te=taille(e,RAND_MAX);
int tg=taille(g,10*te);
if (tg>=10*te)
return esave;
// convert back to trig and atrig functions
g=expln2trig(g,contextptr);
if (!complex_mode(contextptr) && !has_i(g)){
if (s1){
if (v1.front().is_symb_of_sommet(at_sin)){
g=trigsin(g,contextptr);
g=recursive_normal(g,contextptr);
return quotesubst(g,vabs2,vabs,contextptr);
}
}
return recursive_normal(trigcos(g,contextptr),contextptr);
}
gen reg,img;
reim(g,reg,img,contextptr);
reg=recursive_normal(re(g,contextptr),contextptr);
img=recursive_normal(im(g,contextptr),contextptr);
if (s1){
gen g1=normal(trigcos(reg,contextptr),contextptr)+cst_i*normal(trigcos(img,contextptr),contextptr);
gen g2=normal(trigsin(reg,contextptr),contextptr)+cst_i*normal(trigsin(img,contextptr),contextptr);
g1=quotesubst(g1,vabs2,vabs,contextptr);
g2=quotesubst(g2,vabs2,vabs,contextptr);
int g1s=int(lvar(g1).size()), g2s=int(lvar(g2).size());
if (g1s!=g2s)
return g1sback())){
// simplify with side relations
#ifdef NO_STDEXCEPT
return _greduce(args,contextptr);
#else
try {
return _greduce(args,contextptr);
}
catch(std::runtime_error & e){
*logptr(contextptr) << e.what() << endl;
}
#endif
}
return apply(args,_simplify,contextptr);
}
if (is_equal(args))
return apply_to_equal(args,_simplify,contextptr);
int st=step_infolevel(contextptr);
step_infolevel(0,contextptr);
int c=calc_mode(contextptr);
calc_mode(0,contextptr);
vecteur sub1,sub2;
surd2pow(args,sub1,sub2,contextptr);
if (!sub2.empty())
sub2=subst(sub2,at_abs,at_nop,false,contextptr);
res=args;
if (!sub1.empty())
res=subst(res,sub1,sub2,false,contextptr);
#ifdef NO_STDEXCEPT
res=simplify(res,contextptr);
#else
try {
res=simplify(res,contextptr);
} catch (...){
}
#endif
if (!sub1.empty())
res=subst(res,sub2,sub1,false,contextptr);
step_infolevel(st,contextptr);
calc_mode(c,contextptr);
if ( (c==1 || c==-38 || c==38) && !lop(res,at_rootof).empty())
res=ratnormal(args,contextptr);
return res;
}
static const char _simplify_s []="simplify";
static define_unary_function_eval (__simplify,&giac::_simplify,_simplify_s);
define_unary_function_ptr5( at_simplify ,alias_at_simplify,&__simplify,0,true);
gen trigcos(const gen & e,GIAC_CONTEXT){
return subst(simplifier(e,contextptr),pow_tab,trigcos_tab,false,contextptr);
}
gen _trigcos(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_trigcos(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_trigcos,contextptr);
gen g=ratnormal(_tan2sincos(args,contextptr),contextptr);
return normal(trigcos(g,contextptr),contextptr);
}
static const char _trigcos_s []="trigcos";
static define_unary_function_eval (__trigcos,&giac::_trigcos,_trigcos_s);
define_unary_function_ptr5( at_trigcos ,alias_at_trigcos,&__trigcos,0,true);
gen trigsin(const gen & e,GIAC_CONTEXT){
return subst(simplifier(e,contextptr),pow_tab,trigsin_tab,false,contextptr);
}
gen _trigsin(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_trigsin(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_trigsin,contextptr);
gen g=ratnormal(_tan2sincos(args,contextptr),contextptr);
return normal(trigsin(g,contextptr),contextptr);
}
static const char _trigsin_s []="trigsin";
static define_unary_function_eval (__trigsin,&giac::_trigsin,_trigsin_s);
define_unary_function_ptr5( at_trigsin ,alias_at_trigsin,&__trigsin,0,true);
gen trigtan(const gen & e,GIAC_CONTEXT){
return subst(simplifier(e,contextptr),pow_tab,trigtan_tab,false,contextptr);
}
gen _sin2costan(const gen & args,GIAC_CONTEXT);
gen _trigtan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_trigtan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_trigtan,contextptr);
gen g=ratnormal(_sin2costan(args,contextptr),contextptr);
return normal(trigtan(g,contextptr),contextptr);
}
static const char _trigtan_s []="trigtan";
static define_unary_function_eval (__trigtan,&giac::_trigtan,_trigtan_s);
define_unary_function_ptr5( at_trigtan ,alias_at_trigtan,&__trigtan,0,true);
gen tan2sincos(const gen & e,GIAC_CONTEXT){
return subst(e,tan_tab,tan2sincos_tab,false,contextptr);
}
gen _tan2sincos(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tan2sincos(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tan2sincos,contextptr);
return tan2sincos(args,contextptr);
}
static const char _tan2sincos_s []="tan2sincos";
static define_unary_function_eval (__tan2sincos,&giac::_tan2sincos,_tan2sincos_s);
define_unary_function_ptr5( at_tan2sincos ,alias_at_tan2sincos,&__tan2sincos,0,true);
static gen sintocostan(const gen & e,GIAC_CONTEXT){
return tan(e,contextptr)*cos(e,contextptr);
}
gen sin2_costan(const gen & e,GIAC_CONTEXT){
vector< gen_op_context > sin2costan_v(1,sintocostan);
vector sin_v(1,at_sin);
return subst(e,sin_v,sin2costan_v,false,contextptr);
}
gen _sin2costan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_sin2costan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_sin2costan,contextptr);
return sin2_costan(args,contextptr);
}
static const char _sin2costan_s []="sin2costan";
static define_unary_function_eval (__sin2costan,&giac::_sin2costan,_sin2costan_s);
define_unary_function_ptr5( at_sin2costan ,alias_at_sin2costan,&__sin2costan,0,true);
static gen costosintan(const gen & e,GIAC_CONTEXT){
return sin(e,contextptr)/tan(e,contextptr);
}
gen cos2sintan(const gen & e,GIAC_CONTEXT){
vector< gen_op_context > cos2sintan_v(1,costosintan);
vector cos_v(1,at_cos);
return subst(e,cos_v,cos2sintan_v,false,contextptr);
}
gen _cos2sintan(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_cos2sintan(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_cos2sintan,contextptr);
return cos2sintan(args,contextptr);
}
static const char _cos2sintan_s []="cos2sintan";
static define_unary_function_eval (__cos2sintan,&giac::_cos2sintan,_cos2sintan_s);
define_unary_function_ptr5( at_cos2sintan ,alias_at_cos2sintan,&__cos2sintan,0,true);
gen tan2sincos2(const gen & e,GIAC_CONTEXT){
return subst(e,tan_tab,tan2sincos2_tab,false,contextptr);
}
gen _tan2sincos2(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tan2sincos2(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tan2sincos2,contextptr);
return tan2sincos2(args,contextptr);
}
static const char _tan2sincos2_s []="tan2sincos2";
static define_unary_function_eval (__tan2sincos2,&giac::_tan2sincos2,_tan2sincos2_s);
define_unary_function_ptr5( at_tan2sincos2 ,alias_at_tan2sincos2,&__tan2sincos2,0,true);
gen tan2cossin2(const gen & e,GIAC_CONTEXT){
return subst(e,tan_tab,tan2cossin2_tab,false,contextptr);
}
gen _tan2cossin2(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tan2cossin2(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tan2cossin2,contextptr);
return tan2cossin2(args,contextptr);
}
static const char _tan2cossin2_s []="tan2cossin2";
static define_unary_function_eval (__tan2cossin2,&giac::_tan2cossin2,_tan2cossin2_s);
define_unary_function_ptr5( at_tan2cossin2 ,alias_at_tan2cossin2,&__tan2cossin2,0,true);
gen tcollect(const gen & args,bool output_cos,GIAC_CONTEXT){
gen errcode=checkanglemode(contextptr);
if (is_undef(errcode)) return errcode;
vecteur v;
tlin(args,v,contextptr);
// v= [coeff, sin/cos/1]
int s=int(v.size());
vector deja;
gen res,argu;
for (int i=1;ifeuille;
int j=i+2;
for (;jfeuille==argu) )
break;
}
if (j>=s)
res = res + v[i-1]*v[i];
else { // found 2 trig terms with the same arg, combine
deja.push_back(j);
gen coscoeff,sincoeff;
if (v[i]._SYMBptr->sommet==at_cos){
coscoeff=v[i-1];
sincoeff=v[j-1];
}
else {
coscoeff=v[j-1];
sincoeff=v[i-1];
}
gen newcoeff=normal(sqrt(pow(coscoeff,2)+pow(sincoeff,2),contextptr),contextptr);
if (output_cos){
gen angle=normal(arg(coscoeff+cst_i*sincoeff,contextptr),contextptr);
res=res+newcoeff*symbolic(at_cos,argu-angle);
}
else {
gen angle=normal(arg(sincoeff+cst_i*coscoeff,contextptr),contextptr);
res=res+newcoeff*symbolic(at_sin,argu+angle);
}
}
}
return res;
}
gen tcollect(const gen & args,GIAC_CONTEXT){
return tcollect(args,true,contextptr);
}
gen _tcollect(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tcollect(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tcollect,contextptr);
return apply(args,contextptr,tcollect);
}
static const char _tcollect_s []="tcollect";
static define_unary_function_eval (__tcollect,&giac::_tcollect,_tcollect_s);
define_unary_function_ptr5( at_tcollect ,alias_at_tcollect,&__tcollect,0,true);
gen tcollectsin(const gen & args,GIAC_CONTEXT){
return tcollect(args,false,contextptr);
}
gen _tcollectsin(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_tcollectsin(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_tcollectsin,contextptr);
return apply(args,contextptr,tcollectsin);
}
static const char _tcollectsin_s []="tcollectsin";
static define_unary_function_eval (__tcollectsin,&giac::_tcollectsin,_tcollectsin_s);
define_unary_function_ptr5( at_tcollectsin ,alias_at_tcollectsin,&__tcollectsin,0,true);
static const char _rassembler_trigo_s []="rassembler_trigo";
static define_unary_function_eval (__rassembler_trigo,&giac::_tcollect,_rassembler_trigo_s);
define_unary_function_ptr5( at_rassembler_trigo ,alias_at_rassembler_trigo,&__rassembler_trigo,0,true);
static void postlncollect(vecteur & rescoeff,vecteur & resargln,vecteur & res,GIAC_CONTEXT){
gen d;
lcmdeno(rescoeff,d,contextptr);
const_iterateur it=rescoeff.begin(),itend=rescoeff.end();
const_iterateur jt=resargln.begin();
gen lnint(plus_one);
res.reserve(2*(itend-it));
for (;it!=itend;++it,++jt){
if (is_zero(*it))
continue;
if (it->type==_INT_ && absint(it->val)val);
else {
res.push_back(*it/d);
res.push_back(*jt);
}
}
if (!is_one(lnint)){
res.push_back(inv(d,contextptr));
res.push_back(lnint);
}
}
// -> [ coeffln argln ...]
static vecteur inlncollect(const gen & args,GIAC_CONTEXT){
if (args.type!=_SYMB)
return makevecteur(args,symbolic(at_exp,1));
const unary_function_ptr & u=args._SYMBptr->sommet;
gen g=args._SYMBptr->feuille;
if (u==at_ln)
return makevecteur(1,g);
if (u==at_plus){
if (g.type!=_VECT)
return inlncollect(g,contextptr);
vecteur rescoeff,resargln;
const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(),jt,jtend;
for (;it!=itend;++it){
vecteur tmp(inlncollect(*it,contextptr));
jt=tmp.begin();
jtend=tmp.end();
for (;jt!=jtend;jt+=2){
int i;
if ( (i=equalposcomp(resargln,*(jt+1))) ){
rescoeff[i-1]=normal(rescoeff[i-1]+*jt,contextptr);
}
else {
rescoeff.push_back(*jt);
resargln.push_back(*(jt+1));
}
}
}
vecteur res;
postlncollect(rescoeff,resargln,res,contextptr);
return res;
}
if (u==at_neg){
vecteur tmp(inlncollect(g,contextptr));
iterateur it=tmp.begin(),itend=tmp.end();
for (;it!=itend;it+=2){
*it=-*it;
}
return tmp;
}
if (u==at_prod){
if (g.type!=_VECT)
return inlncollect(g,contextptr);
// is there a ln in g?
const_iterateur it=g._VECTptr->begin(),it0=g._VECTptr->begin(),itend=g._VECTptr->end();
for (;it!=itend;++it){
if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_ln) )
break;
}
if (it!=itend){
vecteur v(mergevecteur(vecteur(it0,it),vecteur(it+1,itend)));
gen tmp=_prod(v,contextptr);
vecteur vcoeff(1,tmp),varg(1,it->_SYMBptr->feuille),res;
postlncollect(vcoeff,varg,res,contextptr);
return res;
}
}
return makevecteur((u)(_lncollect(g,contextptr),contextptr),
symbolic(at_exp,1));
}
gen lncollect(const gen & args,GIAC_CONTEXT){
vecteur v(inlncollect(args,contextptr));
gen res;
const_iterateur it=v.begin(),itend=v.end();
for (;it!=itend;it+=2){
res = res + (*it) * ln (*(it+1),contextptr);
}
return res;
}
gen _lncollect(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_lncollect(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_lncollect,contextptr);
return apply(args,lncollect,contextptr);
}
static const char _lncollect_s []="lncollect";
static define_unary_function_eval (__lncollect,&giac::_lncollect,_lncollect_s);
define_unary_function_ptr5( at_lncollect ,alias_at_lncollect,&__lncollect,0,true);
gen powexpand(const gen & e,GIAC_CONTEXT){
return subst(e,pow_tab,powexpand_tab,false,contextptr);
}
gen _powexpand(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_powexpand(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_powexpand,contextptr);
return apply(args,powexpand,contextptr);
}
static const char _powexpand_s []="powexpand";
static define_unary_function_eval (__powexpand,&giac::_powexpand,_powexpand_s);
define_unary_function_ptr5( at_powexpand ,alias_at_powexpand,&__powexpand,0,true);
gen exp2pow(const gen & e,GIAC_CONTEXT){
return subst(e,exp_tab,exp2power_tab,false,contextptr);
}
gen _exp2pow(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_exp2pow(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_exp2pow,contextptr);
return apply(args,exp2pow,contextptr);
}
static const char _exp2pow_s []="exp2pow";
static define_unary_function_eval (__exp2pow,&giac::_exp2pow,_exp2pow_s);
define_unary_function_ptr5( at_exp2pow ,alias_at_exp2pow,&__exp2pow,0,true);
gen factor_xn(const gen & args,const gen & x,GIAC_CONTEXT){
vecteur l(1,x);
lvar(args,l);
gen temp=e2r(args,l,contextptr);
gen n,d;
fxnd(temp,n,d);
l.erase(l.begin());
vecteur nv(gen2vecteur(r2e(polynome2poly1(n,1),l,contextptr)));
vecteur dv(gen2vecteur(r2e(polynome2poly1(d,1),l,contextptr)));
int ns=int(nv.size()),ds=int(dv.size());
int n1=ns-ds;
return pow(x,n1)*symb_horner(nv,x,ns-1)/symb_horner(dv,x,ds-1);
}
gen factor_xn(const gen & args,GIAC_CONTEXT){
return factor_xn(args,vx_var,contextptr);
}
gen _factor_xn(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
gen var,res;
if (is_algebraic_program(args,var,res))
return symbolic(at_program,makesequence(var,0,_factor_xn(res,contextptr)));
if (is_equal(args))
return apply_to_equal(args,_factor_xn,contextptr);
return apply(args,factor_xn,contextptr);
}
static const char _factor_xn_s []="factor_xn";
static define_unary_function_eval (__factor_xn,&giac::_factor_xn,_factor_xn_s);
define_unary_function_ptr5( at_factor_xn ,alias_at_factor_xn,&__factor_xn,0,true);
static const char _developper_s []="developper";
static define_unary_function_eval (__developper,&giac::expand,_developper_s);
define_unary_function_ptr5( at_developper ,alias_at_developper,&__developper,0,true);
static const char _factoriser_s []="factoriser";
static define_unary_function_eval (__factoriser,&giac::_factor,_factoriser_s);
define_unary_function_ptr5( at_factoriser ,alias_at_factoriser,&__factoriser,0,true);
static const char _factoriser_xn_s []="factoriser_xn";
static define_unary_function_eval (__factoriser_xn,&giac::_factor_xn,_factoriser_xn_s);
define_unary_function_ptr5( at_factoriser_xn ,alias_at_factoriser_xn,&__factoriser_xn,0,true);
static const char _resoudre_s []="resoudre";
static define_unary_function_eval_quoted (__resoudre,&giac::_solve,_resoudre_s);
define_unary_function_ptr5( at_resoudre ,alias_at_resoudre,&__resoudre,_QUOTE_ARGUMENTS,true);
static const char _substituer_s []="substituer";
static define_unary_function_eval (__substituer,&giac::_subst,_substituer_s);
define_unary_function_ptr5( at_substituer ,alias_at_substituer,&__substituer,0,true);
static const char _deriver_s []="deriver";
static define_unary_function_eval (__deriver,&giac::_derive,_deriver_s);
define_unary_function_ptr5( at_deriver ,alias_at_deriver,&__deriver,0,true);
static const char _integrer_s []="integrer";
static define_unary_function_eval (__integrer,&giac::_integrate,_integrer_s);
define_unary_function_ptr5( at_integrer ,alias_at_integrer,&__integrer,0,true);
static const char _limite_s []="limite";
static define_unary_function_eval (__limite,&giac::_limit,_limite_s);
define_unary_function_ptr5( at_limite ,alias_at_limite,&__limite,0,true);
static void find_conjugates(const gen & g,vecteur & v_in,vecteur & v_out){
v_in.clear();
v_out.clear();
vecteur v1(lop(g,at_pow));
int n=int(v1.size());
for (int i=0;ifeuille;
if (tmp.type!=_VECT)
continue;
vecteur & v=*tmp._VECTptr;
if (v.size()==2 && v.back().type==_FRAC && v.back()._FRACptr->den==plus_two){
v_in.push_back(v1[i]);
v_out.push_back(-v1[i]);
break ; // change only 1 sqrt
}
}
}
gen _mult_conjugate(const gen & g0,GIAC_CONTEXT){
if ( g0.type==_STRNG && g0.subtype==-1) return g0;
gen g(g0);
bool deno=true;
if (g.type==_VECT && g._VECTptr->size()==2){
if (g._VECTptr->back()==at_numer)
deno=false;
g=g._VECTptr->front();
}
gen n,d;
vecteur v_in,v_out;
prod2frac(g,v_in,v_out);
n=_prod(v_in,contextptr);
d=_prod(v_out,contextptr);
find_conjugates(d,v_in,v_out);
// search sqrt in d
if (!deno || v_in.empty()){
find_conjugates(n,v_in,v_out);
gen mult=subst(n,v_in,v_out,false,contextptr);
n=n*mult; // n=simplify(n*mult);
d=d*mult;
}
else {
gen mult=subst(d,v_in,v_out,false,contextptr);
d=d*mult; // d=simplify(d*mult);
n=n*mult;
}
return n/d;
}
static const char _mult_conjugate_s []="mult_conjugate";
static define_unary_function_eval (__mult_conjugate,&_mult_conjugate,_mult_conjugate_s);
define_unary_function_ptr5( at_mult_conjugate ,alias_at_mult_conjugate,&__mult_conjugate,0,true);
gen _mult_c_conjugate(const gen & g0,GIAC_CONTEXT){
if ( g0.type==_STRNG && g0.subtype==-1) return g0;
gen g(g0);
bool deno=true;
if (g.type==_VECT && g._VECTptr->size()==2){
if (g._VECTptr->back()==at_numer)
deno=false;
g=g._VECTptr->front();
}
gen n,d;
vecteur v_in,v_out;
prod2frac(g,v_in,v_out);
n=_prod(v_in,contextptr);
d=_prod(v_out,contextptr);
if (deno && !is_zero(im(d,contextptr))){
gen mult=conj(d,contextptr);
if (n==1)
n=mult;
else
n=symbolic(at_prod,gen(makevecteur(n,mult),_SEQ__VECT));
if (d==1)
d=mult;
else
d=symbolic(at_prod,gen(makevecteur(d,mult),_SEQ__VECT));
}
else {
if (!is_zero(im(n,contextptr))){
gen mult=conj(n,contextptr);
if (n==1)
n=mult;
else
n=symbolic(at_prod,gen(makevecteur(n,mult),_SEQ__VECT));
if (d==1)
d=mult;
else
d=symbolic(at_prod,gen(makevecteur(d,mult),_SEQ__VECT));
}
}
return n/d;
}
static const char _mult_c_conjugate_s []="mult_c_conjugate";
static define_unary_function_eval_quoted (__mult_c_conjugate,&_mult_c_conjugate,_mult_c_conjugate_s);
define_unary_function_ptr5( at_mult_c_conjugate ,alias_at_mult_c_conjugate,&__mult_c_conjugate,_QUOTE_ARGUMENTS,true);
static const char _multiplier_conjugue_s []="multiplier_conjugue";
static define_unary_function_eval (__multiplier_conjugue,&giac::_mult_conjugate,_multiplier_conjugue_s);
define_unary_function_ptr5( at_multiplier_conjugue ,alias_at_multiplier_conjugue,&__multiplier_conjugue,0,true);
static const char _multiplier_conjugue_complexe_s []="multiplier_conjugue_complexe";
static define_unary_function_eval (__multiplier_conjugue_complexe,&giac::_mult_c_conjugate,_multiplier_conjugue_complexe_s);
define_unary_function_ptr5( at_multiplier_conjugue_complexe ,alias_at_multiplier_conjugue_complexe,&__multiplier_conjugue_complexe,0,true);
gen _combine(const gen & args,const context * contextptr){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (args.type!=_VECT)
return gensizeerr(contextptr);
vecteur & v=*args._VECTptr;
int s=int(v.size());
if (s<2)
return gensizeerr(contextptr);
gen & f=v[s-1];
gen g=v.front();
if (f.type==_FUNC){
if (f==at_sincos || f==at_sin || f==at_cos)
return tcollect(g,contextptr);
if (f==at_exp)
return _lin(g,contextptr);
if (f==at_ln)
return lncollect(g,contextptr);
return gensizeerr(contextptr);
}
if (f.type==_INT_ && f.val>=0) {
int i=f.val;
if (f.subtype==_INT_MAPLECONVERSION){
switch (i){
case _TRIG:
return tcollect(g,contextptr);
case _EXPLN:
return _lin(lncollect(g,contextptr),contextptr);
default:
return gensizeerr(contextptr);
}
}
}
return gensizeerr(contextptr);
}
static const char _combine_s []="combine";
static define_unary_function_eval (__combine,&_combine,_combine_s);
define_unary_function_ptr5( at_combine ,alias_at_combine,&__combine,0,true);
static gen rectangular2polar(const gen & g,const context * contextptr){
gen args=remove_at_pnt(g);
gen module=abs(args,contextptr),argument=arg(args,contextptr);
module=normal(module,contextptr);
if (is_zero(argument))
return module;
gen res=module*symbolic(at_exp,cst_i*argument);
if (calc_mode(contextptr)==1)
return symb_quote(res);
return res;
}
gen _rectangular2polar(const gen & args,const context * contextptr){
if ( args.type==_STRNG && args.subtype==-1) return args;
return apply(args,rectangular2polar,contextptr);
}
static const char _rectangular2polar_s []="rectangular2polar";
static define_unary_function_eval (__rectangular2polar,&_rectangular2polar,_rectangular2polar_s);
define_unary_function_ptr5( at_rectangular2polar ,alias_at_rectangular2polar,&__rectangular2polar,0,true);
static gen polar2rectangular(const gen & g,const context * contextptr){
gen args=remove_at_pnt(g);
gen reel=re(args,contextptr), imag=im(args,contextptr);
return reel+cst_i*imag;
}
gen _polar2rectangular(const gen & args,const context * contextptr){
if ( args.type==_STRNG && args.subtype==-1) return args;
return apply(args,polar2rectangular,contextptr);
}
static const char _polar2rectangular_s []="polar2rectangular";
static define_unary_function_eval (__polar2rectangular,&_polar2rectangular,_polar2rectangular_s);
define_unary_function_ptr5( at_polar2rectangular ,alias_at_polar2rectangular,&__polar2rectangular,0,true);
// x,y,z->rho,theta in [-pi/2..pi/2],psi
// x=rho*cos(theta)*cos(phi), y=rho*cos(theta)*sin(phi), z=rho*sin(theta)
// rho=sqrt(x^2+y^2+z^2)
static gen rectangular2spherical(const gen & g,const context * contextptr){
if (g.type!=_VECT || g._VECTptr->size()!=3)
return gensizeerr(contextptr);
vecteur & v =*g._VECTptr;
gen x =v[0],y=v[1],z=v[2];
gen rho2=x*x+y*y+z*z;
gen rho=sqrt(rho2,contextptr);
gen theta=asin(z/rho,contextptr);
gen phi=arg(x+cst_i*y,contextptr);
return makevecteur(rho,theta,phi);
}
gen _rectangular2spherical(const gen & args,const context * contextptr){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (args.type==_VECT && args._VECTptr->size()==3 && args._VECTptr->front().type!=_VECT)
return rectangular2spherical(args,contextptr);
return apply(args,rectangular2spherical,contextptr);
}
static const char _rectangular2spherical_s []="rectangular2spherical";
static define_unary_function_eval (__rectangular2spherical,&_rectangular2spherical,_rectangular2spherical_s);
define_unary_function_ptr5( at_rectangular2spherical ,alias_at_rectangular2spherical,&__rectangular2spherical,0,true);
static gen spherical2rectangular(const gen & g,const context * contextptr){
if (g.type!=_VECT || g._VECTptr->size()!=3)
return gensizeerr(contextptr);
vecteur & v =*g._VECTptr;
gen rho=v[0],theta=v[1],phi=v[2];
gen rhocos=rho*cos(theta,contextptr);
return makevecteur(rhocos*cos(phi,contextptr),rhocos*sin(phi,contextptr),rho*sin(theta,contextptr));
}
gen _spherical2rectangular(const gen & args,const context * contextptr){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (args.type==_VECT && args._VECTptr->size()==3 && args._VECTptr->front().type!=_VECT)
return spherical2rectangular(args,contextptr);
return apply(args,spherical2rectangular,contextptr);
}
static const char _spherical2rectangular_s []="spherical2rectangular";
static define_unary_function_eval (__spherical2rectangular,&_spherical2rectangular,_spherical2rectangular_s);
define_unary_function_ptr5( at_spherical2rectangular ,alias_at_spherical2rectangular,&__spherical2rectangular,0,true);
static gen heavisidetosign(const gen & args,GIAC_CONTEXT){
return (1+sign(args,contextptr))/2;
}
const gen_op_context heaviside2sign_tab[]={heavisidetosign,0};
gen Heavisidetosign(const gen & args,GIAC_CONTEXT){
return subst(args,Heaviside_tab,heaviside2sign_tab,false,contextptr);
// return subst(args,vector(1,at_Heaviside), vector< gen_op_context >(1,heavisidetosign),false,contextptr);
}
gen _Heavisidetosign(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (is_equal(args))
return apply_to_equal(args,Heavisidetosign,contextptr);
return apply(args,Heavisidetosign,contextptr);
}
static gen heavisidetopiecewise(const gen & args,GIAC_CONTEXT){
return symbolic(at_piecewise,makesequence(symb_superieur_strict(args,0),1,0));
}
const gen_op_context heaviside2piecewise_tab[]={heavisidetopiecewise,0};
gen Heavisidetopiecewise(const gen & args,GIAC_CONTEXT){
return subst(args,Heaviside_tab,heaviside2piecewise_tab,false,contextptr);
// return subst(args,vector(1,at_Heaviside), vector< gen_op_context >(1,heavisidetopiecewise),false,contextptr);
}
gen _Heavisidetopiecewise(const gen & args,GIAC_CONTEXT){
if ( args.type==_STRNG && args.subtype==-1) return args;
if (is_equal(args))
return apply_to_equal(args,Heavisidetopiecewise,contextptr);
return apply(args,Heavisidetopiecewise,contextptr);
}
#ifndef USE_GMP_REPLACEMENTS
// find simplest between some trig simplifications, by Luka Marohnić
gen _trigsimplify(const gen & g,GIAC_CONTEXT) {
if (g.type==_STRNG && g.subtype==-1) return g;
vecteur can(1,_simplify(g,contextptr));
can.push_back(_texpand(can.back(),contextptr));
can.push_back(_tcollect(can.back(),contextptr));
for (int i=1;i<3;++i) {
can.push_back(_trigtan(can[i],contextptr));
can.push_back(_trigsin(can[i],contextptr));
can.push_back(_trigcos(can[i],contextptr));
can.push_back(_tlin(can[i],contextptr));
}
int n=can.size();
for (int i=0;i