// -*- mode:C++ ; compile-command: "g++-3.4 -I.. -g -c gauss.cc -Wall" -*- #include "giacPCH.h" /* * Copyright (C) 2001,14 R. De Graeve, 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 "gauss.h" #include "vecteur.h" #include "derive.h" #include "subst.h" #include "usual.h" #include "sym2poly.h" #include "solve.h" #include "ti89.h" #include "plot.h" #include "misc.h" #include "ifactor.h" #include "prog.h" #include "giacintl.h" #ifndef NO_NAMESPACE_GIAC namespace giac { #endif // ndef NO_NAMESPACE_GIAC vecteur quad(int &b,const gen & q, const vecteur & x,GIAC_CONTEXT){ //x=vecteur des variables, q=la fonction a tester,n=la dimension de x //b=2 si q est quadratique,=0,1 ou 3 si il y des termes d'ordre 0,1 ou 3 //renvoie (la jacobienne de q)/2 gen qs; gen dq; gen dqs; gen qdd; int n=int(x.size()); vecteur A; //creation d'une matrice carree A d'ordre n for (int i=0;isize()); if (s!=2) return gendimerr(contextptr); if (args._VECTptr->back().type==_VECT) return qxa(args._VECTptr->front(),*args._VECTptr->back()._VECTptr,contextptr); return symb_q2a(args); } static const char _q2a_s []="q2a"; static define_unary_function_eval (__q2a,&_q2a,_q2a_s); define_unary_function_ptr5( at_q2a ,alias_at_q2a,&__q2a,0,true); vecteur gauss(const gen & q, const vecteur & x, vecteur & D, vecteur & U, vecteur & P,GIAC_CONTEXT){ int n=int(x.size()); int b; gen u1; gen u2; gen q1; gen l1; gen l2; vecteur R(1); vecteur A; vecteur I; vecteur L; for (int i=0;i2 et on retourne q A=quad(b,q,x,contextptr); if (b!=2){ R[0]=q; vecteur vide; D=vide; U=vide; return(R); } //la forme q est quadratique de matrice A if (q==0) { //R[0]=q; vecteur vide(n); D=vide; U=vide; P=I; return(vide); } if (n==1){ gen q0=_factor(q,contextptr); R[0]=q0; vecteur un(1); un[0]=A[0][0]; D=un; U=x; P=I; return(R); } int r; r=n; for (int i=n-1 ;i>=0;i--){ if (A[i][i]!=0) { r=i; } } if (r!=n) { //il y a des termes carres u1=recursive_normal(rdiv(derive(q,x[r],contextptr),plus_two,contextptr),contextptr); q1=recursive_normal(q-rdiv(u1*u1,A[r][r],contextptr),contextptr); vecteur y; //y contient les variables qui restent (on enleve x[r]) for (int j=0;j=0;i--){ for (int j=i+1;j>=1;j--){ if (A[i][j]!=0) { r1=i; r2=j; } } } l1=rdiv(derive(q,x[r1],contextptr),2,contextptr); l2=rdiv(derive(q,x[r2],contextptr),2,contextptr); u1=recursive_normal(l1+l2,contextptr); u2=recursive_normal(l1-l2,contextptr); q1=recursive_normal(q-rdiv(plus_two*l1*l2,A[r1][r2],contextptr),contextptr); vecteur y; for (int j=0;jsize()); if (s!=2) return gendimerr(contextptr); if (args._VECTptr->back().type==_VECT) return _plus(gauss(args._VECTptr->front(),*(args._VECTptr->back()._VECTptr),contextptr),contextptr); return symb_gauss(args); } static const char _gauss_s []="gauss"; static define_unary_function_eval (__gauss,&_gauss,_gauss_s); define_unary_function_ptr5( at_gauss ,alias_at_gauss,&__gauss,0,true); gen axq(const vecteur &A,const vecteur & x,GIAC_CONTEXT){ //transforme une matrice carree (symetrique) en la forme quadratique q //(les variables sont dans x) int d; //d nbre de variables d=int(x.size()); int da; //il faut verifier que A est carree //A n'est pas forcement symetrique da=int(A.size()); if (!(is_squarematrix(A)) || (da!=d) ){ return gensizeerr(gettext("Invalid dimension")); } vecteur XL(1); XL=makevecteur(x); COUT<size()); if (s!=2) return gendimerr(contextptr); if ((args._VECTptr->front().type==_VECT) && (args._VECTptr->back().type==_VECT)) return axq(*args._VECTptr->front()._VECTptr,*args._VECTptr->back()._VECTptr,contextptr); return symb_a2q(args); } static const char _a2q_s []="a2q"; static define_unary_function_eval (__a2q,&_a2q,_a2q_s); define_unary_function_ptr5( at_a2q ,alias_at_a2q,&__a2q,0,true); vecteur qxac(const gen &q,const vecteur & x,GIAC_CONTEXT){ //transforme une forme quadratique en une matrice symetrique A //(les variables sont dans x) int d; //d nbre de variables d=int(x.size()); // int da; //il faut verifier que q est quadratique vecteur A; int b; A=quad(b,q,x,contextptr); if (b==2) { return(A); } else { return vecteur(1,gensizeerr(gettext("q is not quadratic"))); } } // rational parametrization of a conic, given cartesian equation and point over gen conique_ratparam(const gen & eq,const gen & M,GIAC_CONTEXT){ if (is_undef(M)) return undef; gen Mx,My,x(x__IDNT_e),y(y__IDNT_e),t(t__IDNT_e); ck_parameter_x(contextptr); ck_parameter_y(contextptr); ck_parameter_t(contextptr); reim(M,Mx,My,contextptr); gen eqM=_quo(makesequence(subst(eq,makevecteur(x,y),makevecteur(Mx+x,My+t*x),false,contextptr),x),contextptr); vecteur res=solve(eqM,x,0,contextptr); // x in terms of t if (res.size()!=1) return undef; return M+res[0]*(1+cst_i*t); } bool conique_reduite(const gen & equation_conique,const gen & pointsurconique,const vecteur & nom_des_variables,gen & x0, gen & y0, vecteur & V0, vecteur &V1, gen & propre,gen & equation_reduite, vecteur & param_curves,gen & ratparam,bool numeric,GIAC_CONTEXT){ ratparam=conique_ratparam(equation_conique,pointsurconique,contextptr); gen q(remove_equal(equation_conique)); vecteur x(nom_des_variables); if (x.size()!=2) return false; // setsizeerr(contextptr); identificateur iT(" T"); x.push_back(iT); //n est le nombre de variables en geo. projective int n=3; //nom des nouvelles variables vecteur A; gen qp; qp=q; for (int i=0;i X=-coeffy2/coeffx*Y^2 // X+i*Y=-coeffy2/coeffx*Y^2+i*Y gen coeff=-coeffy2/coeffx; #ifdef GIAC_HAS_STO_38 gen t(vx_var); #else gen t(t__IDNT_e); #endif ck_parameter_t(contextptr); gen Z=coeff*t*t+cst_i*t; Z=z0+zV0*Z; if (is_undef(ratparam)) ratparam=Z; param_curves.push_back(makevecteur(Z,t,-4,4,0.1,q,ratparam)); } } else { // a*c-b*b!=0 => on a une conique a centre ou 2 dr concourantes // ellipse/hyperbole if (b==0){ vp0=a; vp1=c; V0[0]=1; V0[1]=0; V1[0]=0; V1[1]=1; } else { //si b!=0 gen delta; delta=(a-c)*(a-c)+4*b*b; delta=normalize_sqrt(sqrt(delta,contextptr),contextptr); vp0=ratnormal((a+c+delta)/2,contextptr); vp1=ratnormal((a+c-delta)/2,contextptr); gen normv1(normalize_sqrt(sqrt(b*b+(vp0-a)*(vp0-a),contextptr),contextptr)); V0[0]=normal(b/normv1,contextptr); V0[1]=normal((vp0-a)/normv1,contextptr); V1[0]=-V0[1]; V1[1]=V0[0]; } //coord du centre x0=(-d*c+b*e)/(a*c-b*b); y0=(-a*e+d*b)/(a*c-b*b); gen z0=x0+cst_i*y0; gen zV0=V0[0]+cst_i*V0[1]; gen coeffcst=normal(d*x0+e*y0+f,contextptr); equation_reduite=vp0*pow(x[0],2)+vp1*pow(x[1],2)+ coeffcst; // parametric equations gen svp0(exact(sign(vp0,contextptr),contextptr)), svp1(exact(sign(vp1,contextptr),contextptr)), scoeffcst(exact(sign(coeffcst,contextptr),contextptr)); if (svp0.type==_INT_ && svp1.type==_INT_ && scoeffcst.type==_INT_){ #ifdef GIAC_HAS_STO_38 gen t(vx_var); #else gen t(t__IDNT_e); #endif ck_parameter_t(contextptr); int sprodvp = svp0.val * svp1.val; int sprodcoeff = svp0.val*scoeffcst.val; if (sprodvp>0){ // ellipse if (is_zero(coeffcst)){ #ifndef GIAC_HAS_STO_38 *logptr(contextptr) << gettext("Ellipsis reduced to (") << x0 << "," << y0 << ")" << endl; #endif param_curves.push_back(z0); return true; } if (sprodcoeff>0){ #ifndef GIAC_HAS_STO_38 *logptr(contextptr) << gettext("Empty ellipsis") << endl; #endif return true; } #ifndef GIAC_HAS_STO_38 *logptr(contextptr) << gettext("Ellipsis of center (") << x0 << "," << y0 << ")" << endl; #endif vp0=normalize_sqrt(sqrt(-coeffcst/vp0,contextptr),contextptr); vp1=normalize_sqrt(sqrt(-coeffcst/vp1,contextptr),contextptr); // (x[0]/vp0)^2 + (x[1]/vp1)^2 = 1 // => x[0]+i*x[1]=vp0*cos(t)+i*vp1*sin(t) // => x+i*y = x0+i*y0 + V0*(x[0]+i*y[0]) gen tmp; if (numeric){ if (!is_undef(ratparam)) tmp=subst(evalf(ratparam,1,contextptr),t,symbolic(at_tan,t/2),false,contextptr); else { tmp=evalf(vp0,1,contextptr)*symb_cos(t)+cst_i*evalf(vp1,1,contextptr)*symb_sin(t); tmp=evalf(z0,1,contextptr)+evalf(zV0,1,contextptr)*tmp; } } else { tmp=vp0*symb_cos(t)+cst_i*vp1*symb_sin(t); tmp=z0+zV0*tmp; } if (is_undef(ratparam)) ratparam=z0+zV0*(vp0*(1-pow(t,2))+cst_i*vp1*plus_two*t)/(1+pow(t,2)); bool rad = angle_radian(contextptr), deg = angle_degree(contextptr); param_curves.push_back(makevecteur(tmp,t,0, rad?cst_two_pi:(deg ? 360 : 400), rad?cst_two_pi/60:(deg?6:rdiv(20,3)),q,ratparam)); //grad } else { if (is_zero(coeffcst)){ // 2 secant lines at (x0,y0) #ifndef GIAC_HAS_STO_38 *logptr(contextptr) << gettext("2 secant lines at (") << x0 << "," << y0 << ")" << endl; #endif // vp0*X^2+vp1*Y^2=0 => Y=+/-sqrt(-vp0/vp1)*X gen directeur=normalize_sqrt(sqrt(-vp0/vp1,contextptr),contextptr); if (is_undef(ratparam)) ratparam=makevecteur(z0+zV0*(1+cst_i*directeur)*t,z0+zV0*(1-cst_i*directeur)*t); param_curves.push_back(gen(makevecteur(z0,z0+zV0*(1+cst_i*directeur)),_LINE__VECT)); param_curves.push_back(gen(makevecteur(z0,z0+zV0*(1-cst_i*directeur)),_LINE__VECT)); return true; } // hyperbole #ifndef GIAC_HAS_STO_38 *logptr(contextptr) << gettext("Hyperbola of center (") << x0 << "," << y0 << ")" << endl; #endif if (sprodcoeff<0) vp0=-vp0; else vp1=-vp1; vp0=normalize_sqrt(sqrt(coeffcst/vp0,contextptr),contextptr); vp1=normalize_sqrt(sqrt(coeffcst/vp1,contextptr),contextptr); gen tmp; if (numeric){ if (!is_undef(ratparam)) tmp=subst(evalf(ratparam,1,contextptr),t,symbolic(at_tan,t/2),false,contextptr); else { tmp=evalf(vp0,1,contextptr)*symbolic(sprodcoeff<0?at_cosh:at_sinh,t)+cst_i*evalf(vp1,1,contextptr)*symbolic(sprodcoeff<0?at_sinh:at_cosh,t); tmp=evalf(z0,1,contextptr)+evalf(zV0,1,contextptr)*tmp; } } else { tmp=vp0*symbolic(sprodcoeff<0?at_cosh:at_sinh,t)+cst_i*vp1*symbolic(sprodcoeff<0?at_sinh:at_cosh,t); tmp=z0+zV0*tmp; } bool noratparam=is_undef(ratparam); if (noratparam){ ratparam=vp0*gen((sprodcoeff<0)?(t+plus_one/t)/2:(t-plus_one/t)/2)+cst_i*vp1*((sprodcoeff<0)?(t-plus_one/t)/2:(t+plus_one/t)/2); ratparam=z0+zV0*ratparam; } param_curves.push_back(makevecteur(tmp,t,-3.14,3.14,0.0314,q,ratparam)); if (noratparam){ if (numeric){ tmp=(sprodcoeff<0?-1:1)*evalf(vp0,1,contextptr)*symbolic(sprodcoeff<0?at_cosh:at_sinh,t)+(sprodcoeff<0?1:-1)*cst_i*evalf(vp1,1,contextptr)*symbolic(sprodcoeff<0?at_sinh:at_cosh,t); tmp=evalf(z0,1,contextptr)+evalf(zV0,1,contextptr)*tmp; } else { tmp=(sprodcoeff<0?-1:1)*vp0*symbolic(sprodcoeff<0?at_cosh:at_sinh,t)+(sprodcoeff<0?1:-1)*cst_i*vp1*symbolic(sprodcoeff<0?at_sinh:at_cosh,t); tmp=z0+zV0*tmp; } param_curves.push_back(makevecteur(tmp,t,-3,3,0.1,q,ratparam)); } } } } return true; } #ifdef RTOS_THREADX bool quadrique_reduite(const gen & q,const gen & M,const vecteur & vxyz,gen & x,gen & y,gen & z,vecteur & u,vecteur & v,vecteur & w,vecteur & propre,gen & equation_reduite,vecteur & param_surface,vecteur & centre,bool numeric,GIAC_CONTEXT){ return false; } #else bool quadrique_reduite(const gen & q,const gen & M,const vecteur & vxyz,gen & x,gen & y,gen & z,vecteur & u,vecteur & v,vecteur & w,vecteur & propre,gen & equation_reduite,vecteur & param_surface,vecteur & centre,bool numeric,GIAC_CONTEXT){ if (vxyz.size()!=3) return false; // setdimerr(contextptr); x=vxyz[0]; y=vxyz[1]; z=vxyz[2]; identificateur idt("t"); gen t(idt),upar("u",contextptr),vpar("v",contextptr); ck_parameter_u(contextptr); ck_parameter_v(contextptr); gen Q=normal(t*t*(subst(q,vxyz,makevecteur(x/t,y/t,z/t),false,contextptr)),contextptr); // homogeneize matrice A=qxa(Q,makevecteur(x,y,z,t),contextptr); if (is_undef(A)) return false; if (numeric) A=*evalf_double(A,1,contextptr)._VECTptr; // unsigned r=_rank(A).val; matrice B=matrice_extract(A,0,0,3,3); if (is_undef(B)) return false; matrice C=makevecteur(A[0][3],A[1][3],A[2][3]); matrice P; egv(B,P,propre,contextptr,false,false,false); gen s1=propre[0],s2=propre[1],s3=propre[2]; if (is_zero(s1)) s1=0; if (is_zero(s2)) s2=0; if (is_zero(s3)) s3=0; P=mtran(P); P[0]=normal(_normalize(P[0],contextptr),contextptr); P[1]=normal(_normalize(P[1],contextptr),contextptr); P[2]=normal(_normalize(P[2],contextptr),contextptr); u=*P[0]._VECTptr; v=*P[1]._VECTptr; w=*P[2]._VECTptr; if ( s1==0 && s2!=0 ){ vecteur b(u); u=v; v=w; w=b; gen a(s1); s1=s2; s2=s3; s3=a; } if ( s2==0 && s3!=0 ){ vecteur b=w; w=v; v=u; u=b; gen a=s3; s3=s2; s2=s1; s1=a; } gen s1g=evalf_double(sign(s1,contextptr),1,contextptr); gen s2g=evalf_double(sign(s2,contextptr),1,contextptr); gen s3g=evalf_double(sign(s3,contextptr),1,contextptr); if (s1g.type!=_DOUBLE_ || s2g.type!=_DOUBLE_ || s3g.type!=_DOUBLE_){ *logptr(contextptr) << (gettext("Can't check sign ")+s1g.print(contextptr)+gettext(" or ")+s2g.print(contextptr)+gettext(" or ")+s3g.print(contextptr)) << endl; return false; } int s1s=int(s1g._DOUBLE_val), s2s=int(s2g._DOUBLE_val), s3s=int(s3g._DOUBLE_val); if (s3!=0){ // hence s1!=0 && s2!=0 if (s1s*s2s<0){ if (s1s*s3s>0){ // exchange s2 and s3 swap(v,w); swap(s2,s3); swap(s2s,s3s); } else { // s1s and s2s not same sign, s1s and s3s not same sign // therefore s2s and s3s have the same sign vecteur b(u); u=v; v=w; w=b; gen a(s1); s1=s2; s2=s3; s3=a; int as(s1s); s1s=s2s; s2s=s3s; s3s=as; } } // now s1 and s2 have the same sign } P=mtran(makevecteur(u,v,w)); vecteur CP=multvecteurmat(C,P); /* gen CPxyz=dotvecteur(CP,vxyz); gen c=normal(derive(CPxyz,vxyz),contextptr); if (c.type!=_VECT || c._VECTptr->size()!=3) return false; */ gen c=normal(CP,contextptr),d; gen c1(c._VECTptr->front()),c2((*c._VECTptr)[1]),c3(c._VECTptr->back()); gen ustep=_USTEP; ustep.subtype=_INT_PLOT; gen vstep=_VSTEP; vstep.subtype=_INT_PLOT; if (!is_zero(s1)){ if (!is_zero(s2)){ if (!is_zero(s3)){ gen tmp=normal(-c1/s1*u-c2/s2*v-c3/s3*w,contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=3) return false; centre=*tmp._VECTptr; d=normal(subst(q,vxyz,centre,false,contextptr),contextptr); equation_reduite=s1*pow(x,2)+s2*pow(y,2)+s3*pow(z,2)+d; gen dg=evalf_double(sign(d,contextptr),1,contextptr); if (dg.type!=_DOUBLE_) return false; // cksignerr(d); int ds=int(dg._DOUBLE_val); if (ds==0){ // if s3s*s1s>0 solution=1 point, else cone if (s3s*s1s>0) param_surface.push_back(centre); else { // s1*x^2+s2*y^2=-s3*z^2 -> x^2/a^2+y^2/b^2=z^2 gen a(sqrt(-s3/s1,contextptr)),b(sqrt(-s3/s2,contextptr)); gen eq=makevecteur(a*upar*symb_cos(vpar),b*upar*symb_sin(vpar),upar); *logptr(contextptr) << gettext("Cone of center ") << centre << endl; eq=centre+multmatvecteur(P,*eq._VECTptr); gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-5,5))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); ustep=symb_equal(ustep,1./2); vstep=symb_equal(vstep,cst_two_pi/20); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); } } // end if ds==0 else { if (s1s*s3s>0){ if (s1s*ds>0) *logptr(contextptr) << gettext("Empty ellipsoid") << endl; else { gen a=sqrt(-d/s1,contextptr),b=sqrt(-d/s2,contextptr),c=sqrt(-d/s3,contextptr); // x^2/a^2+y^2/b^2+z^2/c^2=1 gen eq=makevecteur(a*symb_sin(upar)*symb_cos(vpar),b*symb_sin(upar)*symb_sin(vpar),c*symb_cos(upar)); *logptr(contextptr) << gettext("Ellipsoid of center ") << centre << endl; eq=centre+multmatvecteur(P,*eq._VECTptr); gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(0,cst_pi))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); ustep=symb_equal(ustep,cst_pi/20); vstep=symb_equal(vstep,cst_two_pi/20); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); } } // end s1 and s3 of same sign else { // s1 and s2 have same sign, opposite to s3 if (s1s*ds>0){ gen a=sqrt(d/s1,contextptr),b=sqrt(d/s2,contextptr),c=sqrt(-d/s3,contextptr); // x^2/a^2+y^2/b^2+1=z^2/c^2, hyperboloide, 2 nappes gen eq=makevecteur(a*symb_sinh(upar)*symb_cos(vpar),b*symb_sinh(upar)*symb_sin(vpar),c*symb_cosh(upar)); eq=centre+multmatvecteur(P,*eq._VECTptr); *logptr(contextptr) << gettext("2-fold hyperboloid of center ") << centre << endl; gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(0,3))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); ustep=symb_equal(ustep,3./20); vstep=symb_equal(vstep,cst_two_pi/20); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); eq=makevecteur(a*symb_sinh(upar)*symb_cos(vpar),b*symb_sinh(upar)*symb_sin(vpar),-c*symb_cosh(upar)); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); } else { // s1, s2 opposite sign to s3,d gen a=sqrt(-d/s1,contextptr),b=sqrt(-d/s2,contextptr),c=sqrt(d/s3,contextptr); // x^2/a^2+y^2/b^2=z^2/c^2+1, hyperboloide, 2 nappes gen eq=makevecteur(a*symb_cosh(upar)*symb_cos(vpar),b*symb_cosh(upar)*symb_sin(vpar),c*symb_sinh(upar)); *logptr(contextptr) << gettext("2-fold hyperboloid of center ") << centre << endl; eq=centre+multmatvecteur(P,*eq._VECTptr); gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-3,3))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); ustep=symb_equal(ustep,3./20); vstep=symb_equal(vstep,cst_two_pi/20); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); } } } return true; } // end if (s3!=0) // s3==0, s1!=0, s2!=0 if (is_zero(c3)){ gen tmp=normal(multmatvecteur(P,makevecteur(-c1/s1,-c2/s2,0)),contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=3) return false; centre=*tmp._VECTptr; gen d(normal(subst(q,vxyz,centre,false,contextptr),contextptr)); gen dg=evalf_double(sign(d,contextptr),1,contextptr); if (dg.type!=_DOUBLE_) return false; // cksignerr(d); int ds=int(dg._DOUBLE_val); equation_reduite=s1*pow(x,2)+s2*pow(y,2)+d; if (s1s*s2s>0){ *logptr(contextptr) << gettext("Elliptic cylinder around ") << centre << endl; if (is_zero(d)) // line (cylinder of radius 0) param_surface.push_back(makevecteur(centre,centre+w)); else { // elliptic cylinder (maybe empty) if (s1s*ds<0){ // s1*x^2+s2*y^2=-d gen a(sqrt(-d/s1,contextptr)),b(sqrt(-d/s2,contextptr)); gen eq=makevecteur(a*symb_cos(vpar),b*symb_sin(vpar),upar); eq=centre+multmatvecteur(P,*eq._VECTptr); gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-5,5))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); ustep=symb_equal(ustep,1./2); vstep=symb_equal(vstep,cst_two_pi/20); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); } } return true; } // end s1 and s2 of same sign else { // s1 and s2 have opposite signs, s1*x^2+s2*y^2+d=0 if (is_zero(d)){ // 2 plans *logptr(contextptr) << gettext("2 plans intersecting at ") << centre << endl; gen n=u+sqrt(-s2/s1,contextptr)*v; param_surface.push_back(symbolic(at_hyperplan,gen(makevecteur(n,centre),_SEQ__VECT))); n=u-sqrt(-s2/s1,contextptr)*v; param_surface.push_back(symbolic(at_hyperplan,gen(makevecteur(n,centre),_SEQ__VECT))); return true; } else { // hyperbolic cylinder *logptr(contextptr) << gettext("Hyperbolic cylinder around ") << centre << endl; gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-5,5))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(-3,3))); ustep=symb_equal(ustep,1./2); vstep=symb_equal(vstep,0.3); if (s1s*ds<0){ // x^2/(-d/s1) - y^2/(d/s2)=1 gen a(sqrt(-d/s1,contextptr)),b(sqrt(d/s2,contextptr)); gen eq=makevecteur(a*symb_cosh(vpar),b*symb_sinh(vpar),upar); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); eq=makevecteur(-a*symb_cosh(vpar),b*symb_sinh(vpar),upar); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); return true; } else { // x^2/(d/s1) - y^2/(-d/s2)=-1 gen a(sqrt(d/s1,contextptr)),b(sqrt(-d/s2,contextptr)); gen eq=makevecteur(a*symb_sinh(vpar),b*symb_cosh(vpar),upar); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); eq=makevecteur(a*symb_sinh(vpar),-b*symb_cosh(vpar),upar); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); return true; } } } } // end c3==0 else { // s3==0, s1!=0, s2!=0, c3!=0 gen tmp=normal(-c1/s1*u-c2/s2*v,contextptr); if (tmp.type!=_VECT) return false; gen dred=subst(q,vxyz,*tmp._VECTptr,false,contextptr); tmp=normal(tmp-dred/(2*c3)*w,contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=3) return false; centre=*tmp._VECTptr; equation_reduite=s1*pow(x,2)+s2*pow(y,2)+2*c3*z; // parametrization of s1*x^2+s2*y^2+2*c3*z=0 if (s1s*s2s>0){ *logptr(contextptr) << gettext("Elliptic paraboloid of center ") << centre << endl; // if (s1s*s2s>0) x^2+y^2/(s1/s2)=-2*c3*z/s1 // x=u*cos(t), y=u*sqrt(s1/s2)*sin(t), z=-u^2*s1/2/c3 gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(0,5))); ustep=symb_equal(ustep,1./2); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(0,cst_two_pi))); vstep=symb_equal(vstep,cst_two_pi/20); gen a(sqrt(s1/s2,contextptr)),b(-s1/2/c3); gen eq=makevecteur(upar*symb_cos(vpar),a*upar*symb_sin(vpar),b*pow(upar,2)); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); return true; } else { // if (s1s*s2s<0) x^2-y^2/(-s1/s2)=-2*c3*z/s1 *logptr(contextptr) << gettext("Hyperbolic paraboloid of center ") << centre << endl; gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-3,3))); ustep=symb_equal(ustep,0.3); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(-3,3))); vstep=symb_equal(vstep,0.3); gen a(-s1/s2),b(s1/2/c3); gen eq=makevecteur(upar,sqrt(a,contextptr)*vpar,b*(pow(vpar,2)-pow(upar,2))); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); return true; } } } // end if (!is_zero(s2)) // here s3==0, s2==0, s1!=0 gen tmp=normal(-c1/s1*u,contextptr); // gen tmp=normal(multmatvecteur(P,makevecteur(-c1/s1,0,0)),contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=3) return false; // gen tmp=normal(multmatvecteur(P,makevecteur(-c1/s1,0,0)),contextptr); if (!is_zero(c2) || !is_zero(c3)){ gen c4=normalize_sqrt(sqrt(c2*c2+c3*c3,contextptr),contextptr); gen v1=normal(multmatvecteur(P,makevecteur(0,c3/c4,-c2/c4)),contextptr); gen w1=normal(multmatvecteur(P,makevecteur(0,c2/c4,c3/c4)),contextptr); gen dred=subst(q,vxyz,*tmp._VECTptr,false,contextptr); P=mtran(makevecteur(u,v1,w1)); v=*v1._VECTptr; w=*w1._VECTptr; tmp=tmp+normal(-dred/(2*c4)*w1,contextptr); // tmp=tmp+normal(multmatvecteur(P,makevecteur(0,0,-d/(2*c4))),contextptr); if (tmp.type!=_VECT || tmp._VECTptr->size()!=3) return false; centre=*tmp._VECTptr; // ??? dred=normal(subst(q,vxyz,centre),contextptr); equation_reduite=s1*pow(x,2)+2*c4*z; // ???+dred; gen ueq=symbolic(at_equal,makesequence(upar,symb_interval(-5,5))); gen veq=symbolic(at_equal,makesequence(vpar,symb_interval(-5,5))); ustep=symb_equal(ustep,1./2); vstep=symb_equal(vstep,1./2); *logptr(contextptr) << gettext("Paraboloid cylinder") << endl; gen eq=makevecteur(upar,vpar,-s1*pow(upar,2)/2/c4); eq=centre+multmatvecteur(P,*eq._VECTptr); param_surface.push_back(makevecteur(eq,ueq,veq,ustep,vstep)); return true; } else { // c2==0 and c3==0 *logptr(contextptr) << gettext("2 parallel plans") << endl; centre=*tmp._VECTptr; gen dred=normal(subst(q,vxyz,centre,false,contextptr),contextptr); equation_reduite=s1*pow(x,2)+dred; if (is_zero(dred)){ // a single plan multiplicity 2 param_surface.push_back(symbolic(at_hyperplan,gen(makevecteur(u,centre),_SEQ__VECT))); } gen dg=evalf_double(sign(dred,contextptr),1,contextptr); if (dg.type!=_DOUBLE_) return false; // cksignerr(d); int ds=int(dg._DOUBLE_val); if (s1s*ds<0){ // 2 plans x = +/- sqrt(-dred/s1) gen a(sqrt(-dred/s1,contextptr)); param_surface.push_back(symbolic(at_hyperplan,gen(makevecteur(u,centre+a*u),_SEQ__VECT))); param_surface.push_back(symbolic(at_hyperplan,gen(makevecteur(u,centre-a*u),_SEQ__VECT))); } return true; } } // end if !is_zero(s1) return false; } #endif // RTOS_THREADX gen conique_quadrique_reduite(const gen & args,GIAC_CONTEXT,bool conique){ vecteur v(gen2vecteur(args)); int s=int(v.size()); if (!s || s>4) return gendimerr(contextptr); if (s==4) v=makevecteur(v[0],makevecteur(v[1],v[2],v[3])); if (s==3) v=makevecteur(v[0],makevecteur(v[1],v[2])); if (s==1){ v.push_back(conique?makevecteur(x__IDNT_e,y__IDNT_e):makevecteur(x__IDNT_e,y__IDNT_e,z__IDNT_e)); } if (v[0].type==_SYMB && v[1].type==_VECT){ gen x0,y0,z0,eq_reduite,propre,ratparam; vecteur V0,V1,V2,param_curves,centre,proprev; if (v[1]._VECTptr->size()==3){ quadrique_reduite(v[0],undef,*v[1]._VECTptr,x0,y0,z0,V0,V1,V2,proprev,eq_reduite,param_curves,centre,false,contextptr); return makevecteur(centre,mtran(makevecteur(V0,V1,V2)),proprev,eq_reduite,param_curves); } else { if (!conique_reduite(v[0],undef,*v[1]._VECTptr,x0,y0,V0,V1,propre,eq_reduite,param_curves,ratparam,false,contextptr)) return gensizeerr(contextptr); return makevecteur(makevecteur(x0,y0),mtran(makevecteur(V0,V1)),propre,eq_reduite,param_curves); } } return gentypeerr(contextptr); } gen _conique_reduite(const gen & args,GIAC_CONTEXT){ if ( args.type==_STRNG && args.subtype==-1) return args; return conique_quadrique_reduite(args,contextptr,true); } static const char _conique_reduite_s []="reduced_conic"; static define_unary_function_eval (__conique_reduite,&_conique_reduite,_conique_reduite_s); define_unary_function_ptr5( at_conique_reduite ,alias_at_conique_reduite,&__conique_reduite,0,true); gen _quadrique_reduite(const gen & args,GIAC_CONTEXT){ if ( args.type==_STRNG && args.subtype==-1) return args; return conique_quadrique_reduite(args,contextptr,false); } static const char _quadrique_reduite_s []="reduced_quadric"; static define_unary_function_eval (__quadrique_reduite,&_quadrique_reduite,_quadrique_reduite_s); define_unary_function_ptr5( at_quadrique_reduite ,alias_at_quadrique_reduite,&__quadrique_reduite,0,true); #ifndef NO_NAMESPACE_GIAC } // namespace giac #endif // ndef NO_NAMESPACE_GIAC