1 // -*- mode:C++ ; compile-command: "g++ -I.. -I../include -DHAVE_CONFIG_H -DIN_GIAC -DGIAC_GENERIC_CONSTANTS -fno-strict-aliasing -g -c gen.cc -Wall" -*-
2 #include "giacPCH.h"
3 #ifdef KHICAS
4 #include "kdisplay.h"
5 #if defined DEVICE && !defined NSPIRE_NEWLIB
6 size_t stackptr=0x20036000;
7 #else
8 size_t stackptr=0xffffffffffffffff;
9 #endif
10 #endif
11 
12 /*
13  *  Copyright (C) 2001,14 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
14  *
15  *  This program is free software; you can redistribute it and/or modify
16  *  it under the terms of the GNU General Public License as published by
17  *  the Free Software Foundation; either version 3 of the License, or
18  *  (at your option) any later version.
19  *
20  *  This program is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *  GNU General Public License for more details.
24  *
25  *  You should have received a copy of the GNU General Public License
26  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
27  */
28 using namespace std;
29 #if !defined NSPIRE && !defined FXCG && !defined KHICAS
30 #include <cstdlib>
31 #include <iomanip>
32 #endif
33 #define __USE_ISOC9X 1
34 #include <stdexcept>
35 #include <ctype.h>
36 #include <math.h>
37 #include <list>
38 #include <errno.h>
39 #include <string.h>
40 // #include <wstring.h>
41 #include "gen.h"
42 #include "gausspol.h"
43 #include "identificateur.h"
44 #include "poly.h"
45 #include "usual.h"
46 #include "input_lexer.h"
47 #include "sym2poly.h"
48 #include "vecteur.h"
49 #include "modpoly.h"
50 #include "alg_ext.h"
51 #include "prog.h"
52 #include "rpn.h"
53 #include "plot.h"
54 #include "intg.h"
55 #include "subst.h"
56 #include "derive.h"
57 #include "threaded.h"
58 #include "maple.h"
59 #include "solve.h"
60 #include "csturm.h"
61 #include "sparse.h"
62 #if defined GIAC_HAS_STO_38 || defined NSPIRE || defined NSPIRE_NEWLIB || defined FXCG || defined GIAC_GGB || defined USE_GMP_REPLACEMENTS || defined KHICAS
is_graphe(const giac::gen & g,std::string & disp_out,const giac::context *)63 inline bool is_graphe(const giac::gen &g,std::string &disp_out,const giac::context *){ return false; }
64 #else
65 #include "graphtheory.h"
66 #endif
67 #include "giacintl.h"
68 #ifdef RTOS_THREADX
69 extern "C" uint32_t mainThreadStack[];
70 #endif
71 #ifdef HAVE_PTHREAD_H
72 #include <pthread.h>
73 #endif
74 
75 #ifdef EMCC_BIND
76 #include <emscripten/bind.h>
77 #endif
78 
79 #if defined EMCC && !defined GIAC_GGB
80 
81 #if 0 // def EMCC_GLUT
82 #include <GL/glut.h>
83 #else
84 #include "SDL/SDL.h"
85 #include <SDL/SDL_ttf.h>
86 #include <emscripten.h>
87 //#include "SDL/SDL_image.h"
88 #include "SDL/SDL_opengl.h"
89 #endif
90 
91 #include "opengl.h"
92 #endif
93 
94 #ifdef USE_GMP_REPLACEMENTS
95 #undef HAVE_GMPXX_H
96 #undef HAVE_LIBMPFR
97 #endif
98 
99 #ifndef NO_NAMESPACE_GIAC
100 namespace giac {
101 #endif // ndef NO_NAMESPACE_GIAC
102 
103 #if 0 // def ASPEN_GEOMETRY
104 #define ALLOCSMALL
105 #endif
106 
107 #ifdef ALLOCSMALL
108 
109   // 32 bytes structure: 4096/32=128 slots of memory
110   struct eight_int {
111     int i1,i2,i3,i4,i5,i6,i7,i8;
112   };
113 
114   struct six_int {
115     int i1,i2,i3,i4,i5,i6;
116   };
117 
118   struct four_int {
119     int i1,i2,i3,i4;
120   };
121 
122 #ifdef RTOS_THREADX
123   const int ALLOC24=5*32;
124   const int ALLOC32=2*32;
125   const int ALLOC16=4*32;
126   static unsigned int freeslot24[ALLOC24/32]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,0xffffffff};
127   static unsigned int freeslot16[ALLOC16/32]={0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
128   static unsigned int freeslot32[ALLOC32/32]={0xffffffff, 0xffffffff};
129 #else
130   const int ALLOC24=16*32;
131   const int ALLOC32=16*32;
132   const int ALLOC16=16*32;
133   static unsigned int freeslot24[ALLOC24/32]={
134     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
135     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
136     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
137     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
138   };
139   static unsigned int freeslot16[ALLOC16/32]={
140     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
141     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
142     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
143     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
144   };
145   static unsigned int freeslot32[ALLOC32/32]={
146     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
147     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
148     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
149     0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
150   };
151 #endif
152   static six_int tab24[ALLOC24];
153   static four_int tab16[ALLOC16];
154   static eight_int tab32[ALLOC32];
155 
freeslotpos(unsigned n)156   unsigned freeslotpos(unsigned n){
157     unsigned r=1;
158     if (n<<16==0) r+= 16, n>>=16;
159     if (n<<24==0) r+= 8, n>>=8;
160     if (n<<28==0) r+= 4, n>>=4;
161     if (n<<30==0) r+= 2, n>>=2;
162     r -= n&1;
163     return r;
164   }
165 
allocfast(std::size_t size)166   static void* allocfast(std::size_t size){
167     int i,pos;
168     if (size==24){
169       for (i=0;i<ALLOC24/32;++i){
170 	if (freeslot24[i]){
171 	  pos=freeslotpos(freeslot24[i]);
172 	  freeslot24[i] &= ~(1<<pos);
173 	  return (void *) (tab24+i*32+pos);
174 	}
175       }
176     }
177     if (size==16){
178       for (i=0;i<ALLOC16/32;++i){
179 	if (freeslot16[i]){
180 	  pos=freeslotpos(freeslot16[i]);
181 	  freeslot16[i] &= ~(1<<pos);
182 	  return (void *) (tab16+i*32+pos);
183 	}
184       }
185     }
186     if (size==32){
187       for (i=0;i<ALLOC32/32;++i){
188 	if (freeslot32[i]){
189 	  pos=freeslotpos(freeslot32[i]);
190 	  freeslot32[i] &= ~(1<<pos);
191 	  return (void *) (tab32+i*32+pos);
192 	}
193       }
194     }
195     void * p =  std::malloc(size);
196 #ifndef NO_STDEXCEPT
197     if(!p) {
198       std::bad_alloc ba;
199       throw ba;
200     }
201 #endif
202     return p;
203   }
204 
deletefast(void * obj)205   static void deletefast(void* obj){
206     if ( ((size_t)obj >= (size_t) &tab24[0]) &&
207 	 ((size_t)obj < (size_t) &tab24[ALLOC24]) ){
208       int pos= ((size_t)obj -((size_t) &tab24[0]))/sizeof(six_int);
209       freeslot24[pos/32] |= 1 << (pos%32);
210       return;
211     }
212     if ( ((size_t)obj>=(size_t) &tab16[0] ) &&
213 	 ((size_t)obj<(size_t) &tab16[ALLOC16] ) ){
214       * (unsigned *) obj= 0;
215       int pos= ((size_t)obj -((size_t) &tab16[0]))/sizeof(four_int);
216       freeslot16[pos/32] |= 1 << (pos%32);
217       return;
218     }
219     if ( ((size_t)obj>=(size_t) &tab32[0]) &&
220 	 ((size_t)obj<(size_t) &tab32[ALLOC32]) ){
221       int pos= ((size_t)obj -((size_t) &tab32[0]))/sizeof(eight_int);
222       freeslot32[pos/32] |= 1 << (pos%32);
223     }
224     else
225       free(obj);
226   }
227 #endif // ALLOCSMALL
228 
229 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
deletecomplex(ref_complex * ptr)230   inline void deletecomplex(ref_complex * ptr){
231     delete ptr ;
232   }
233 #else
deletecomplex(ref_complex * ptr)234   static void deletecomplex(ref_complex * ptr){
235     ptr->re=0;
236     ptr->im=0;
237     deletefast(ptr);
238   }
239 #endif
240 
241 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
deletesymbolic(ref_symbolic * ptr)242   inline void deletesymbolic(ref_symbolic * ptr){
243     delete ptr ;
244   }
245 #else
deletesymbolic(ref_symbolic * ptr)246   static void deletesymbolic(ref_symbolic * ptr){
247     ptr->s.feuille=0;
248     deletefast(ptr);
249   }
250 #endif
251 
252 #if defined(SMARTPTR64) || !defined(IMMEDIATE_VECTOR) || !defined(ALLOCSMALL)
delete_ref_vecteur(ref_vecteur * ptr)253   void delete_ref_vecteur(ref_vecteur * ptr){
254     delete ptr ;
255   }
256 #else
delete_ref_vecteur(ref_vecteur * ptr)257   void delete_ref_vecteur(ref_vecteur * ptr){
258     ptr->v.clear();
259     deletefast(ptr);
260   }
261 #endif
262 
263   /*
264   unsigned control_c_counter=0;
265   unsigned control_c_counter_mask=0xff;
266   */
267 
268 #ifdef HAVE_LIBPTHREAD
269   pthread_mutex_t mpfr_mutex = PTHREAD_MUTEX_INITIALIZER;
270   pthread_mutex_t locale_mutex = PTHREAD_MUTEX_INITIALIZER;
271 #endif
272 
sprintfdouble(char * ch,const char * format,double d)273   void sprintfdouble(char * ch,const char * format,double d){
274 #ifdef FXCG
275     sprint_double(ch,d); // no format
276 #else
277 #ifdef NSPIRE
278     dtostr(d,8,ch); // FIXME!
279 #else
280 #ifdef EMCC
281     sprintf(ch,format,d);
282 #else
283     my_sprintf(ch,format,d);
284 #endif
285 #endif
286 #endif
287   }
288 
289   // bool is_inevalf=false;
290 
last_evaled_function(GIAC_CONTEXT)291   static string last_evaled_function(GIAC_CONTEXT){
292     const char * last =last_evaled_function_name(contextptr);
293     if (!last)
294       return "";
295     string res;
296     bool paren=true;
297     if (abs_calc_mode(contextptr)==38 && !strcmp(last,"sqrt"))
298       res="√";
299     else {
300       string tmp=unlocalize(autosimplify(contextptr));
301       if (tmp!=last)
302 	res=last;
303       else
304 	paren=false;
305     }
306     if (paren) res +="(";
307     const gen * lastarg= last_evaled_argptr(contextptr);
308     if (lastarg){
309       if (strcmp(last,"try_catch")==0 && lastarg->type==_VECT && !lastarg->_VECTptr->empty()){ // workaround for optimizations on some operations like *
310 	res = lastarg->_VECTptr->front().print(contextptr);
311 	paren = false;
312       }
313       else
314 	res += lastarg->print(contextptr);
315     }
316     if (paren) res += ")";
317     debug_struct * dbg = debug_ptr(contextptr);
318     if (!dbg->sst_at_stack.empty()){
319       res += gettext(" in ");
320       gen pos=dbg->args_stack.back();
321       string tmp;
322       if (pos.type==_VECT && pos._VECTptr->size()>=2){
323 	vecteur v(pos._VECTptr->begin()+1,pos._VECTptr->end());
324 	if (v.size()==1){
325 	  if (v.front().type==_VECT && v.front()._VECTptr->empty())
326 	    tmp=pos._VECTptr->front().print(contextptr)+"()";
327 	  else
328 	    tmp=pos._VECTptr->front().print(contextptr)+"("+v.front().print(contextptr)+")";
329 	}
330 	else
331 	  tmp = pos._VECTptr->front().print(contextptr)+"("+gen(v,_SEQ__VECT).print(contextptr)+")";
332       }
333       else
334 	tmp = pos.print(contextptr);
335       res += tmp;
336       res += gettext(" instruction #");
337       res += print_INT_(dbg->current_instruction);
338       res += gettext(" error, try debug(")+tmp+")";
339     }
340     else
341       res += ' ';
342     return res+"\n ";
343   }
344 
345 #ifdef NO_STDEXCEPT // FIXME
settypeerr(GIAC_CONTEXT)346   void settypeerr(GIAC_CONTEXT){
347     gentypeerr(contextptr);
348   }
349 
setsizeerr(GIAC_CONTEXT)350   void setsizeerr(GIAC_CONTEXT){
351     gensizeerr(contextptr);
352   }
353 
setdimerr(GIAC_CONTEXT)354   void setdimerr(GIAC_CONTEXT){
355     gendimerr(contextptr);
356   }
357 
settypeerr(const string & s)358   void settypeerr(const string & s){
359     gentypeerr(s);
360   }
361 
setsizeerr(const string & s)362   void setsizeerr(const string & s){
363     gensizeerr(s);
364   }
365 
setdimerr(const string & s)366   void setdimerr(const string & s){
367     gendimerr(s);
368   }
369 
divisionby0err(const gen & e,GIAC_CONTEXT)370   void divisionby0err(const gen & e,GIAC_CONTEXT){
371     gendivisionby0err(e,contextptr);
372   }
373 
cksignerr(const gen & e,GIAC_CONTEXT)374   void cksignerr(const gen & e,GIAC_CONTEXT){
375     gencksignerr(e,contextptr);
376   }
377 
invalidserieserr(const string & s,GIAC_CONTEXT)378   void invalidserieserr(const string & s,GIAC_CONTEXT){
379     geninvalidserieserr(s,contextptr);
380   }
381 
toofewargs(const string & s,GIAC_CONTEXT)382   void toofewargs(const string & s,GIAC_CONTEXT){
383     gentoofewargs(s,contextptr);
384   }
385 
toomanyargs(const string & s,GIAC_CONTEXT)386   void toomanyargs(const string & s,GIAC_CONTEXT){
387     gentoomanyargs(s,contextptr);
388   }
389 
maxordererr(GIAC_CONTEXT)390   void maxordererr(GIAC_CONTEXT){
391     genmaxordererr(contextptr);
392   }
393 
setstabilityerr(GIAC_CONTEXT)394   void setstabilityerr(GIAC_CONTEXT){
395     genstabilityerr(contextptr);
396   }
397 #else
settypeerr(GIAC_CONTEXT)398   void settypeerr(GIAC_CONTEXT){
399     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Bad Argument Type")));
400   }
401 
setsizeerr(GIAC_CONTEXT)402   void setsizeerr(GIAC_CONTEXT){
403     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Bad Argument Value")));
404   }
405 
setdimerr(GIAC_CONTEXT)406   void setdimerr(GIAC_CONTEXT){
407     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Invalid dimension")));
408   }
409 
settypeerr(const string & s)410   void settypeerr(const string & s){
411     throw(std::runtime_error(s+gettext(" Error: Bad Argument Type")));
412   }
413 
setsizeerr(const string & s)414   void setsizeerr(const string & s){
415     throw(std::runtime_error(s+gettext(" Error: Bad Argument Value")));
416   }
417 
setdimerr(const string & s)418   void setdimerr(const string & s){
419     throw(std::runtime_error(s+gettext(" Error: Invalid dimension")));
420   }
421 
divisionby0err(const gen & e,GIAC_CONTEXT)422   void divisionby0err(const gen & e,GIAC_CONTEXT){
423     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Division of ") + e.print(contextptr)+ gettext(" by 0")));
424   }
425 
cksignerr(const gen & e,GIAC_CONTEXT)426   void cksignerr(const gen & e,GIAC_CONTEXT){
427     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Unable to check sign: ")+e.print(contextptr)));
428   }
429 
invalidserieserr(const string & s,GIAC_CONTEXT)430   void invalidserieserr(const string & s,GIAC_CONTEXT){
431     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Invalid series expansion: ")+s));
432   }
433 
toofewargs(const string & s,GIAC_CONTEXT)434   void toofewargs(const string & s,GIAC_CONTEXT){
435     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Too few arguments: ")+s));
436   }
437 
toomanyargs(const string & s,GIAC_CONTEXT)438   void toomanyargs(const string & s,GIAC_CONTEXT){
439     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Too many arguments: ")+s));
440   }
441 
maxordererr(GIAC_CONTEXT)442   void maxordererr(GIAC_CONTEXT){
443     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("Max order (")+gen(max_series_expansion_order).print(contextptr)+gettext(") exceeded or non unidirectional series")));
444   }
445 
setstabilityerr(GIAC_CONTEXT)446   void setstabilityerr(GIAC_CONTEXT){
447     throw(std::runtime_error(last_evaled_function(contextptr)+gettext("calculation size limit exceeded")));
448   }
449 #endif // NO_STDEXCEPT
450 
undeferr(const string & s)451   gen undeferr(const string & s){
452 #ifdef EMCC
453     CERR << s << '\n';
454 #endif
455 #if defined NSPIRE || defined FXCG
456     wait_1ms(1);
457 #else
458 #ifdef GIAC_HAS_STO_38
459     usleep(10);
460 #else
461     usleep(1000);
462 #endif
463 #endif
464 #if !defined NO_STDEXCEPT && !defined EMCC
465     if (debug_infolevel!=-5)
466       throw(std::runtime_error(s));
467 #endif
468     gen res(string2gen(s,false));
469     res.subtype=-1;
470     return res;
471   }
472 
gentypeerr(GIAC_CONTEXT)473   gen gentypeerr(GIAC_CONTEXT){
474     return undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Type"));
475   }
476 
gentypeerr(gen & g,GIAC_CONTEXT)477   void gentypeerr(gen & g,GIAC_CONTEXT){
478     g=undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Type"));
479   }
480 
gensizeerr(GIAC_CONTEXT)481   gen gensizeerr(GIAC_CONTEXT){
482     return undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Value"));
483   }
484 
gensizeerr(gen & g,GIAC_CONTEXT)485   void gensizeerr(gen & g,GIAC_CONTEXT){
486     g=undeferr(last_evaled_function(contextptr)+gettext("Error: Bad Argument Value"));
487   }
488 
gendimerr(GIAC_CONTEXT)489   gen gendimerr(GIAC_CONTEXT){
490     return undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid dimension"));
491   }
492 
gendimerr(gen & g,GIAC_CONTEXT)493   void gendimerr(gen & g,GIAC_CONTEXT){
494     g=undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid dimension"));
495   }
496 
gentypeerr(const string & s)497   gen gentypeerr(const string & s){
498     return undeferr(s+gettext(" Error: Bad Argument Type"));
499   }
500 
gentypeerr(const char * ch,gen & g)501   void gentypeerr(const char * ch,gen & g){
502     g=undeferr(string(gettext(ch))+gettext(" Error: Bad Argument Type"));
503   }
504 
gensizeerr(const string & s)505   gen gensizeerr(const string & s){
506     return undeferr(s+gettext(" Error: Bad Argument Value"));
507   }
508 
gensizeerr(const char * ch,gen & g)509   void gensizeerr(const char * ch,gen & g){
510     g=undeferr(string(gettext(ch))+gettext(" Error: Bad Argument Value"));
511   }
512 
gendimerr(const string & s)513   gen gendimerr(const string & s){
514     return undeferr(s+gettext(" Error: Invalid dimension"));
515   }
516 
gendimerr(const char * ch,gen & g)517   void gendimerr(const char * ch,gen & g){
518     g=undeferr(string(gettext(ch))+gettext(" Error: Invalid dimension"));
519   }
520 
gendivisionby0err(const gen & e,GIAC_CONTEXT)521   gen gendivisionby0err(const gen & e,GIAC_CONTEXT){
522     return undeferr(last_evaled_function(contextptr)+gettext("Error: Division of ") + e.print(contextptr)+ gettext(" by 0"));
523   }
524 
gencksignerr(const gen & e,GIAC_CONTEXT)525   gen gencksignerr(const gen & e,GIAC_CONTEXT){
526     return undeferr(last_evaled_function(contextptr)+gettext("Error: Unable to check sign: ")+e.print(contextptr));
527   }
528 
geninvalidserieserr(const string & s,GIAC_CONTEXT)529   gen geninvalidserieserr(const string & s,GIAC_CONTEXT){
530     *logptr(contextptr) << undeferr(last_evaled_function(contextptr)+gettext("Error: Invalid series expansion: ")+s) << '\n';
531     return undef;
532   }
533 
gentoofewargs(const string & s,GIAC_CONTEXT)534   gen gentoofewargs(const string & s,GIAC_CONTEXT){
535     return undeferr(last_evaled_function(contextptr)+gettext("Error: Too few arguments: ")+s);
536   }
537 
gentoomanyargs(const string & s,GIAC_CONTEXT)538   gen gentoomanyargs(const string & s,GIAC_CONTEXT){
539     return undeferr(last_evaled_function(contextptr)+gettext("Error: Too many arguments: ")+s);
540   }
541 
genmaxordererr(GIAC_CONTEXT)542   gen genmaxordererr(GIAC_CONTEXT){
543     return undeferr(last_evaled_function(contextptr)+gettext("Error: Max order (")+gen(max_series_expansion_order).print(contextptr)+gettext(") exceeded or non unidirectional series"));
544   }
545 
genstabilityerr(GIAC_CONTEXT)546   gen genstabilityerr(GIAC_CONTEXT){
547     return undeferr(last_evaled_function(contextptr)+gettext("Error: calculation size limit exceeded"));
548   }
549 
550   // void parseerror(){
551   //  throw(std::runtime_error("Parse error"));
552   // }
553 
554   enum { debugtype=_CPLX };
555 #define debugtypeptr _CPLXptr
556 
557   /* Constructors, destructors, copy */
vector2vecteur(const vecteur & v)558   gen vector2vecteur(const vecteur & v){
559     gen g=v.back()-v.front();
560     if (g.type!=_VECT)
561       return makenewvecteur(re(g,context0),im(g,context0));
562     return g;
563   }
564 
change_subtype(int newsubtype)565   gen gen::change_subtype(int newsubtype){
566     subtype=newsubtype;
567     return *this;
568   }
569 
change_subtype(const gen & g,int newsubtype)570   gen change_subtype(const gen & g,int newsubtype){
571     gen g_(g);
572     g_.subtype=newsubtype;
573     return g_;
574   }
575 
complex_display_ptr(const gen & g)576   int * complex_display_ptr(const gen & g) {
577     if (g.type!=_CPLX)
578       return 0;
579     return (int *)(g._CPLXptr)-1;
580   }
581 
gen(long i)582   gen::gen(long i) {
583 #ifdef COMPILE_FOR_STABILITY
584     control_c();
585 #endif
586 #ifdef SMARTPTR64
587     * ((ulonglong * ) this)=0;
588 #endif
589     val=(int)i;
590     //    longlong temp=val;
591     if (val==i && val!=1<<31){
592 #ifndef SMARTPTR64
593       type=_INT_;
594       subtype=0;
595 #endif
596     }
597     else {
598 #ifdef SMARTPTR64
599       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(64)) << 16;
600 #else
601       __ZINTptr = new ref_mpz_t(64);
602 #endif
603       type =_ZINT;
604       subtype=0;
605       // convert longlong to mpz_t
606       bool signe=(i<0);
607       if (signe)
608 	i=-i;
609       unsigned int i1=sizeof(long)==4?0:i>>32;
610       unsigned int i2=(unsigned int)i;
611       mpz_set_ui(*_ZINTptr,i1);
612       mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
613       mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
614       if (signe)
615 	mpz_neg(*_ZINTptr,*_ZINTptr);
616     }
617   }
618 
gen(longlong i)619   gen::gen(longlong i) {
620 #ifdef COMPILE_FOR_STABILITY
621     control_c();
622 #endif
623 #ifdef SMARTPTR64
624     * ((ulonglong * ) this)=0;
625 #endif
626     val=(int)i;
627     //    longlong temp=val;
628     if (val==i && val!=1<<31){
629 #ifndef SMARTPTR64
630       type=_INT_;
631       subtype=0;
632 #endif
633     }
634     else {
635 #ifdef SMARTPTR64
636       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(64)) << 16;
637 #else
638       __ZINTptr = new ref_mpz_t(64);
639 #endif
640       type =_ZINT;
641       subtype=0;
642       // convert longlong to mpz_t
643       bool signe=(i<0);
644       if (signe)
645 	i=-i;
646       unsigned int i1=i>>32;
647       unsigned int i2=(unsigned int)i;
648       mpz_set_ui(*_ZINTptr,i1);
649       mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
650       mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
651       if (signe)
652 	mpz_neg(*_ZINTptr,*_ZINTptr);
653       /*
654       longlong lbase=65536;
655       long base=65536;
656       longlong i1=i/lbase;
657       long i2=i1/lbase; // i2=i/2^32
658       //COUT << "Initialization of " << _ZINTptr << '\n' ;
659       mpz_init_set_si(*_ZINTptr,i2);
660       mpz_mul_ui(*_ZINTptr,*_ZINTptr,base); // i/2^32 * 2^16
661       long i2mod=i1 % lbase;
662       if (i2mod>0)
663 	mpz_add_ui(*_ZINTptr,*_ZINTptr,i2mod);
664       else
665 	mpz_sub_ui(*_ZINTptr,*_ZINTptr,-i2mod); // i/2^16
666       mpz_mul_ui(*_ZINTptr,*_ZINTptr,base); // i/2^16 * 2^16
667       long i1mod = i % lbase;
668       if (i1mod>0)
669 	mpz_add_ui(*_ZINTptr,*_ZINTptr,i1mod);
670       else
671 	mpz_sub_ui(*_ZINTptr,*_ZINTptr,-i1mod); // i
672       */
673     }
674   }
675 
gen(longlong i,int nbits)676   gen::gen(longlong i,int nbits) {
677 #ifdef COMPILE_FOR_STABILITY
678     control_c();
679 #endif
680 #ifdef SMARTPTR64
681     * ((ulonglong * ) this)=0;
682 #endif
683     val=(int)i;
684     //    longlong temp=val;
685     if (val==i && val!=1<<31){
686 #ifndef SMARTPTR64
687       type=_INT_;
688       subtype=0;
689 #endif
690     }
691     else {
692 #ifdef SMARTPTR64
693       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(nbits)) << 16;
694 #else
695       __ZINTptr = new ref_mpz_t(nbits);
696 #endif
697       type =_ZINT;
698       subtype=0;
699       // convert longlong to mpz_t
700       bool signe=(i<0);
701       if (signe)
702 	i=-i;
703       unsigned int i1=i>>32;
704       unsigned int i2=(unsigned int)i;
705       mpz_set_ui(*_ZINTptr,i1);
706       mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
707       mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
708       if (signe)
709 	mpz_neg(*_ZINTptr,*_ZINTptr);
710     }
711   }
712 
713 #ifdef INT128
gen(int128_t i)714   gen::gen(int128_t i) {
715 #ifdef COMPILE_FOR_STABILITY
716     control_c();
717 #endif
718 #ifdef SMARTPTR64
719     * ((ulonglong * ) this)=0;
720 #endif
721     val=i;
722     //    longlong temp=val;
723     if (val==i && val!=1<<31){
724 #ifndef SMARTPTR64
725       type=_INT_;
726       subtype=0;
727 #endif
728     }
729     else {
730 #ifdef SMARTPTR64
731       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(128)) << 16;
732 #else
733       __ZINTptr = new ref_mpz_t(128);
734 #endif
735       type =_ZINT;
736       subtype=0;
737       bool signe=(i<0);
738       if (signe)
739 	i=-i;
740 #if !defined(USE_GMP_REPLACEMENTS)
741       mpz_import(*_ZINTptr,4/* count*/,-1/*1 for least significant first*/,4/* sizeof unsigned*/,0,0,&i);
742       // CERR << gen(*_ZINTptr) ;
743 #else
744       unsigned int i3= i;
745       i = i>>32;
746       unsigned int i2= i;
747       i = i>>32;
748       unsigned int i1= i;
749       i = i>>32;
750       // convert to mpz_t
751       if (i1 || i){
752 	mpz_set_ui(*_ZINTptr,(unsigned int) i);
753 	mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
754 	mpz_add_ui(*_ZINTptr,*_ZINTptr,i1);
755 	mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
756 	mpz_add_ui(*_ZINTptr,*_ZINTptr,i2);
757       }
758       else
759 	mpz_set_ui(*_ZINTptr,i2);
760       mpz_mul_2exp(*_ZINTptr,*_ZINTptr,32);
761       mpz_add_ui(*_ZINTptr,*_ZINTptr,i3);
762 #endif
763       if (signe)
764 	mpz_neg(*_ZINTptr,*_ZINTptr);
765       // CERR << " " << gen(*_ZINTptr) << '\n' ;
766     }
767   }
768 #endif
769 
gen(const mpz_t & m)770   gen::gen(const mpz_t & m) {
771     if (int(mpz_sizeinbase(m,2))>MPZ_MAXLOG2){
772       type=0;
773 #if 1
774       *this=undef;
775 #else
776       *this=mpz_sgn(m)==-1?minus_inf:plus_inf;
777 #endif
778       return;
779     }
780 #ifdef COMPILE_FOR_STABILITY
781     control_c();
782 #endif
783 #ifdef SMARTPTR64
784       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(m)) << 16;
785 #else
786     __ZINTptr= new ref_mpz_t(m);
787 #endif
788 #ifdef KHICAS
789       if ((size_t) _ZINTptr > stackptr)
790 	ctrl_c=interrupted=true;
791 #endif
792     type =_ZINT;
793     subtype=0;
794   }
795 
796 #if defined HAVE_GMPXX_H && !defined USE_GMP_REPLACEMENTS
gen(const mpz_class & m)797   gen::gen(const mpz_class & m){
798     int l=mpz_sizeinbase(m.get_mpz_t(),2);
799     if (l<32){
800       type = _INT_;
801       val = mpz_get_si(m.get_mpz_t());
802     }
803     else {
804 #ifdef SMARTPTR64
805       ref_mpz_t * ptr=new ref_mpz_t;
806       mpz_set(ptr->z,m.get_mpz_t());
807       * ((ulonglong * ) this) = ulonglong(ptr) << 16;
808 #else
809       __ZINTptr= new ref_mpz_t();
810 #ifdef KHICAS
811       if ((size_t) _ZINTptr > stackptr)
812 	ctrl_c=interrupted=true;
813 #endif
814       mpz_set(__ZINTptr->z,m.get_mpz_t());
815 #endif
816       type =_ZINT;
817     }
818     subtype=0;
819   }
820 #endif
821 
gen(const identificateur & s)822   gen::gen(const identificateur & s){
823 #ifdef COMPILE_FOR_STABILITY
824     control_c();
825 #endif
826 #ifdef SMARTPTR64
827     * ((ulonglong * ) this) = ulonglong(new ref_identificateur(s)) << 16;
828 #else
829     __IDNTptr= new ref_identificateur(s);
830 #endif
831     type=_IDNT;
832     subtype=0;
833   }
834 
835 #if defined(SMARTPTR64) || !defined(IMMEDIATE_VECTOR) || !defined(ALLOCSMALL)
new_ref_vecteur(const vecteur & v)836   ref_vecteur * new_ref_vecteur(const vecteur & v){
837     return new ref_vecteur(v);
838   }
839 #else
new_ref_vecteur(const vecteur & v)840   ref_vecteur * new_ref_vecteur(const vecteur & v){
841     ref_vecteur * ptr=(ref_vecteur *) allocfast(sizeof(ref_vecteur));
842     ptr->ref_count=1;
843     *(unsigned *)&ptr->v=0;
844     *((unsigned *)&ptr->v+1)=0;
845     *((unsigned *)&ptr->v+2)=0;
846     *((unsigned *)&ptr->v+3)=0;
847     *((unsigned *)&ptr->v+4)=0;
848     *((unsigned *)&ptr->v+5)=0;
849     *((unsigned *)&ptr->v+6)=0;
850     ptr->v=v;
851     return ptr;
852   }
853 #endif
854 
gen(const vecteur & v,short int s)855   gen::gen(const vecteur & v,short int s)
856   {
857 #ifdef SMARTPTR64
858     * ((ulonglong * ) this) = ulonglong(new ref_vecteur(v)) << 16;
859 #else
860     __VECTptr= new_ref_vecteur(v);
861 #endif
862 #ifdef KHICAS
863     if (v.size()>1 &&
864 	( (size_t) _VECTptr > stackptr ||
865 	  (size_t) _VECTptr->begin() > stackptr)
866 	)
867       ctrl_c=interrupted=true;
868 #endif
869     type=_VECT;
870     subtype=(signed char)s;
871   }
872 
gen(ref_vecteur * vptr,short int s)873   gen::gen(ref_vecteur * vptr,short int s){
874 #ifdef SMARTPTR64
875     * ((ulonglong * ) this) = ulonglong(vptr) << 16;
876 #else
877     __VECTptr= vptr;
878 #endif
879     type=_VECT;
880     subtype=(signed char)s;
881 #ifdef KHICAS
882     if (_VECTptr->size()>1 &&
883 	( (size_t) _VECTptr > stackptr ||
884 	  (size_t) _VECTptr->begin() > stackptr)
885 	)
886       ctrl_c=interrupted=true;
887 #endif
888   }
889 
890 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
new_ref_symbolic(const symbolic & s)891   ref_symbolic * new_ref_symbolic(const symbolic & s){
892     return new ref_symbolic(s);
893   }
894 #else
new_ref_symbolic(const symbolic & s)895   ref_symbolic * new_ref_symbolic(const symbolic & s){
896     ref_symbolic * ptr=(ref_symbolic *) allocfast(sizeof(ref_symbolic));
897     ptr->ref_count=1;
898     * (unsigned *) &ptr->s.sommet = 0;
899     ptr->s.feuille.type=0;
900     ptr->s=s;
901     return ptr;
902   }
903 #endif
904 
gen(const symbolic & s)905   gen::gen(const symbolic & s){
906 #ifdef COMPILE_FOR_STABILITY
907     control_c();
908 #endif
909 #ifdef SMARTPTR64
910     * ((ulonglong * ) this) = ulonglong(new_ref_symbolic(s)) << 16;
911 #else
912     __SYMBptr = new_ref_symbolic(s) ;
913 #endif
914     type = _SYMB;
915     subtype = 0;
916 #ifdef KHICAS
917     if (_SYMBptr->sommet!=at_restart && _SYMBptr->sommet!=at_purge && (size_t) _SYMBptr > stackptr)
918       ctrl_c=interrupted=true;
919 #endif
920   }
921 
gen(ref_symbolic * sptr)922   gen::gen(ref_symbolic * sptr){
923 #ifdef SMARTPTR64
924     * ((ulonglong * ) this) = ulonglong(sptr) << 16;
925 #else
926     __SYMBptr = sptr;
927 #endif
928     type = _SYMB;
929     subtype = 0;
930 #ifdef KHICAS
931     if (_SYMBptr->sommet!=at_restart && _SYMBptr->sommet!=at_purge && (size_t) _SYMBptr > stackptr)
932       ctrl_c=interrupted=true;
933 #endif
934   }
935 
gen(ref_identificateur * sptr)936   gen::gen(ref_identificateur * sptr){
937 #ifdef SMARTPTR64
938     * ((ulonglong * ) this) = ulonglong(sptr) << 16;
939 #else
940     __IDNTptr = sptr;
941 #endif
942     type = _IDNT;
943     subtype = 0;
944   }
945 
gen(const gen_user & g)946   gen::gen(const gen_user & g){
947 #ifdef SMARTPTR64
948     * ((ulonglong * ) this) = ulonglong(new ref_gen_user(g)) << 16;
949 #else
950     __USERptr = new ref_gen_user(g) ;
951 #endif
952     type = _USER;
953     subtype=0;
954   }
955 
gen(ref_gen_user * sptr)956   gen::gen(ref_gen_user * sptr){
957 #ifdef SMARTPTR64
958     * ((ulonglong * ) this) = ulonglong(sptr) << 16;
959 #else
960     __USERptr = sptr;
961 #endif
962     type = _USER;
963     subtype = 0;
964   }
965 
gen(const eqwdata & g)966   gen::gen(const eqwdata & g){
967 #ifdef SMARTPTR64
968       * ((ulonglong * ) this) = ulonglong(new ref_eqwdata(g)) << 16;
969 #else
970     __EQWptr = new ref_eqwdata(g);
971 #endif
972     type = _EQW;
973     subtype=0;
974   }
975 
gen(const grob & g)976   gen::gen(const grob & g){
977 #ifdef SMARTPTR64
978       * ((ulonglong * ) this) = ulonglong(new ref_grob(g)) << 16;
979 #else
980     __GROBptr = new ref_grob(g);
981 #endif
982     type = _GROB;
983     subtype=0;
984   }
985 
makemap()986   gen makemap(){
987     gen g;
988 #ifdef SMARTPTR64
989       * ((ulonglong * ) &g) = ulonglong(new ref_gen_map) << 16;
990 #else
991 #if 1 // def NSPIRE
992       g.__MAPptr = new ref_gen_map;
993 #else
994     g.__MAPptr = new ref_gen_map(ptr_fun(islesscomplexthanf));
995 #endif
996 #endif
997     g.type=_MAP;
998     g.subtype=0;
999     return g;
1000   }
1001 
gen(const gen_map & s)1002   gen::gen(const gen_map & s){
1003 #ifdef SMARTPTR64
1004       * ((ulonglong * ) this) = ulonglong(new ref_gen_map(s)) << 16;
1005 #else
1006     __MAPptr = new ref_gen_map(s) ;
1007 #endif
1008     type = _MAP;
1009     subtype = 0;
1010   }
1011 
gen(const polynome & p)1012   gen::gen(const polynome & p){
1013     subtype=0;
1014     if (p.coord.empty()){
1015       type = _INT_;
1016       val = 0;
1017     }
1018     else {
1019       if (Tis_constant<gen>(p) && is_atomic(p.coord.front().value) ){
1020 	type = _INT_;
1021 	* this = p.coord.front().value;
1022       }
1023       else {
1024 #ifdef SMARTPTR64
1025       * ((ulonglong * ) this) = ulonglong(new Tref_tensor<gen>(p)) << 16;
1026 #else
1027 	__POLYptr = new Tref_tensor<gen>(p) ;
1028 #endif
1029 #ifdef KHICAS
1030 	if ((size_t) _POLYptr > stackptr)
1031 	  ctrl_c=interrupted=true;
1032 #endif
1033 	type = _POLY;
1034       }
1035     }
1036   }
1037 
gen(const fraction & p)1038   gen::gen(const fraction & p){
1039     subtype=0;
1040     if (is_undef(p.num) || is_undef(p.den)){
1041       type=_INT_;
1042       *this=undef;
1043       return;
1044     }
1045     if (is_inf(p.den)){
1046       type=_INT_;
1047       val=0;
1048       if (is_inf(p.num))
1049 	*this=undef;
1050       return;
1051     }
1052     if (is_exactly_zero(p.num)){
1053       type=_INT_;
1054       val=0;
1055       return;
1056     }
1057     if (is_one(p.den)){
1058       type=_INT_;
1059       *this = p.num;
1060       return;
1061     }
1062     if (is_minus_one(p.den)){
1063       type=_INT_;
1064       *this = -p.num;
1065     }
1066     else {
1067 #ifdef SMARTPTR64
1068       * ((ulonglong * ) this) = ulonglong(new Tref_fraction<gen>(p)) << 16;
1069 #else
1070       __FRACptr = new Tref_fraction<gen>(p) ;
1071 #endif
1072       type = _FRAC;
1073     }
1074   }
1075 
gen(Tref_tensor<gen> * pptr)1076   gen::gen(Tref_tensor<gen> * pptr){
1077 #ifdef SMARTPTR64
1078     * ((ulonglong * ) this) = ulonglong(pptr) << 16;
1079 #else
1080     __POLYptr = pptr ;
1081 #endif
1082 #ifdef KHICAS
1083     if ((size_t) _POLYptr > stackptr)
1084       ctrl_c=interrupted=true;
1085 #endif
1086     subtype=0;
1087     type = _POLY;
1088   }
1089 
1090   // WARNING coerce *mptr to an int if possible, in this case delete mptr
1091   // Pls do not use this constructor unless you know exactly what you do!!
gen(ref_mpz_t * mptr)1092   gen::gen(ref_mpz_t * mptr){
1093     int l=mpz_sizeinbase(mptr->z,2);
1094     // if (l<17){
1095     if (l<32){
1096       type = _INT_;
1097       val = mpz_get_si(mptr->z);
1098       // COUT << "Destruction by mpz_t * " << *mptr << '\n';
1099       delete mptr;
1100     }
1101     else {
1102       if (l>MPZ_MAXLOG2){
1103 	type=0;
1104 #if 1
1105 	*this=undef;
1106 #else
1107 	*this=(mpz_sgn(mptr->z)==-1)?minus_inf:plus_inf;
1108 #endif
1109 	delete mptr;
1110 	return;
1111       }
1112 #ifdef SMARTPTR64
1113       * ((ulonglong * ) this) = ulonglong(mptr) << 16;
1114 #else
1115       __ZINTptr = mptr;
1116 #endif
1117 #ifdef KHICAS
1118       if ((size_t) _ZINTptr > stackptr)
1119 	ctrl_c=interrupted=true;
1120 #endif
1121       type =_ZINT;
1122     }
1123     subtype=0;
1124     // COUT << *this << '\n';
1125   }
1126 
1127   // WARNING coerce *mptr to an int if possible, in this case delete mptr
1128   // Pls do not use this constructor unless you know exactly what you do!!
ref_mpz_t2gen(ref_mpz_t * mptr,gen & g)1129   bool ref_mpz_t2gen(ref_mpz_t * mptr,gen & g){
1130     if (g.type>_DOUBLE_){
1131       g=mptr;
1132       return true;
1133     }
1134     int l=mpz_sizeinbase(mptr->z,2);
1135     // if (l<17){
1136     if (l<32){
1137       g.type=_INT_;
1138       g.subtype=0;
1139       g.val = mpz_get_si(mptr->z);
1140       // COUT << "Destruction by mpz_t * " << *mptr << '\n';
1141       return false;
1142     }
1143     else {
1144       if (l>MPZ_MAXLOG2){
1145 	g.type=0;
1146 #if 1
1147 	g=undef;
1148 #else
1149 	g=(mpz_sgn(mptr->z)==-1)?minus_inf:plus_inf;
1150 #endif
1151 	return false;
1152       }
1153 #ifdef SMARTPTR64
1154       * ((ulonglong * ) &g) = ulonglong(mptr) << 16;
1155 #else
1156       g.__ZINTptr = mptr;
1157 #endif
1158       g.type =_ZINT;
1159       g.subtype=0;
1160       return true;
1161     }
1162   }
1163 
gen(const my_mpz & z)1164   gen::gen(const my_mpz& z){
1165     int l=mpz_sizeinbase(z.ptr,2);
1166     if (l<32){
1167       type = _INT_;
1168       val = mpz_get_si(z.ptr);
1169     }
1170     else {
1171       if (l>MPZ_MAXLOG2){
1172 	type=0;
1173 #if 1
1174 	*this=undef;
1175 #else
1176 	*this=(mpz_sgn(z.ptr)==-1)?minus_inf:plus_inf;
1177 #endif
1178 	return;
1179       }
1180 #ifdef SMARTPTR64
1181       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(z.ptr)) << 16;
1182 #else
1183       __ZINTptr = new ref_mpz_t(z.ptr);
1184 #endif
1185 #ifdef KHICAS
1186       if ((size_t) _ZINTptr > stackptr)
1187 	ctrl_c=interrupted=true;
1188 #endif
1189       type =_ZINT;
1190     }
1191     subtype=0;
1192   }
1193 
gen(const gen & e)1194   gen::gen(const gen & e) {
1195     if (e.type>_DOUBLE_ && e.type!=_FLOAT_
1196 #ifndef SMARTPTR64
1197 	&& e.type!=_FUNC
1198 #endif
1199 	) {
1200       if (
1201 #ifdef SMARTPTR64
1202 	  (*((ulonglong *) &e) >> 16)
1203 #else
1204 	  e.__ZINTptr
1205 #endif
1206 	  ){
1207 	ref_count_t * rc=(ref_count_t *)&e.ref_count();
1208 	if (*rc!=-1)
1209 	  ++(*rc);
1210       }
1211     }
1212 #ifdef DOUBLEVAL
1213     _DOUBLE_val = e._DOUBLE_val;
1214 #else
1215     * ((longlong *) this) = *((longlong * ) &e);
1216 #endif
1217 #ifndef SMARTPTR64
1218     __ZINTptr=e.__ZINTptr;
1219 #endif
1220     type=e.type;
1221     subtype=e.subtype;
1222   }
1223 
new_ref_complex(gen a,gen b)1224   inline ref_complex * new_ref_complex(gen a,gen b){
1225 #if defined(SMARTPTR64) || !defined(ALLOCSMALL)
1226     return new ref_complex(a,b);
1227 #else
1228     ref_complex * ptr= (ref_complex *) allocfast(sizeof(ref_complex));
1229     ptr->ref_count=1;
1230     ptr->display=0;
1231     ptr->re.type=0;
1232     ptr->re=a;
1233     ptr->im.type=0;
1234     ptr->im=b;
1235     return ptr;
1236 #endif
1237   }
1238 
gen(int a,int b)1239   gen::gen(int a,int b) {
1240     subtype=0;
1241     if (!b){
1242       type=_INT_;
1243       val=a;
1244     }
1245     else {
1246 #ifdef SMARTPTR64
1247       * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1248 #else
1249       __CPLXptr = new_ref_complex(a,b);
1250 #endif
1251       type =_CPLX;
1252       subtype=0;
1253     }
1254   }
1255 
1256 #ifndef DOUBLEVAL
gen(double d)1257   gen::gen(double d){
1258     opaque_double_copy(&d,this); type=_DOUBLE_;
1259   };
1260 #endif
1261 
gen(double a,double b)1262   gen::gen(double a,double b){
1263     subtype=0;
1264     // COUT << a << " " << b << " " << epsilon << '\n';
1265     if (fabs(b)<1e-12*fabs(a)){
1266 #ifdef DOUBLEVAL
1267       _DOUBLE_val=a;
1268 #else
1269       *((double *) this) = a;
1270 #endif
1271       type=_DOUBLE_;
1272     }
1273     else {
1274 #ifdef SMARTPTR64
1275       * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1276 #else
1277       __CPLXptr = new_ref_complex(a,b);
1278 #endif
1279       type =_CPLX;
1280       subtype=3;
1281     }
1282   }
1283 
gen(const gen & a,const gen & b)1284   gen::gen(const gen & a,const gen & b) { // a and b must be type <2!
1285     if ( (a.type>=_CPLX && a.type!=_FLOAT_) || (b.type>=_CPLX && b.type!=_FLOAT_) ){
1286       type=0;
1287       *this=a+cst_i*b; // gentypeerr(gettext("complex constructor"));
1288       return;
1289     }
1290     if (is_exactly_zero(b)){
1291       if (a.type==_FLOAT_){
1292 	type=0;
1293 	*this=a;
1294       }
1295       else {
1296 	type=a.type;
1297 	switch (type ) {
1298 	case _INT_:
1299 	  val=a.val;
1300 	  subtype=0;
1301 	  break;
1302 	case _DOUBLE_:
1303 #ifdef DOUBLEVAL
1304 	  _DOUBLE_val = a._DOUBLE_val;
1305 #else
1306 	  *((double *) this) = a._DOUBLE_val;
1307 	  type=_DOUBLE_;
1308 #endif
1309 	  break;
1310 	case _ZINT:
1311 #ifdef SMARTPTR64
1312 	  * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(*a._ZINTptr)) << 16;
1313 #else
1314 	  __ZINTptr=new ref_mpz_t(a.__ZINTptr->z); // a is a _ZINT
1315 #endif
1316 	  type=_ZINT;
1317 	  subtype=0;
1318 	  break;
1319 	case _REAL:
1320 	  subtype=0;
1321 #ifdef SMARTPTR64
1322 #ifndef NO_RTTI
1323 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr)){
1324 	    * ((ulonglong * ) this) = ulonglong(new ref_real_interval(*ptr)) << 16;
1325 	    subtype=1;
1326 	  }
1327 	  else
1328 #endif
1329 	    * ((ulonglong * ) this) = ulonglong(new ref_real_object(*a._REALptr)) << 16;
1330 #else
1331 #ifndef NO_RTTI
1332 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr)){
1333 	    __REALptr=(ref_real_object *) new ref_real_interval(*ptr);
1334 	    subtype=1;
1335 	  }
1336 	  else
1337 #endif
1338 	    __REALptr=new ref_real_object(a.__REALptr->r);
1339 #endif
1340 	  type=_REAL;
1341 	  break;
1342 	default:
1343 	  type=0;
1344 	  *this=gentypeerr(gettext("complex constructor"));
1345 	}
1346       }
1347     }
1348     else {
1349 #ifdef SMARTPTR64
1350       * ((ulonglong * ) this) = ulonglong(new ref_complex(a,b)) << 16;
1351 #else
1352       __CPLXptr = new_ref_complex(a,b);
1353 #endif
1354       type =_CPLX;
1355       subtype= (a.type==_DOUBLE_) + (b.type==_DOUBLE_)*2;
1356     }
1357   }
gen(const complex<double> & c)1358   gen::gen(const complex<double> & c) {
1359 #ifdef SMARTPTR64
1360       * ((ulonglong * ) this) = ulonglong(new ref_complex(c)) << 16;
1361 #else
1362       __CPLXptr = new ref_complex(c);
1363 #endif
1364     type=_CPLX;
1365     subtype=3;
1366   }
1367 
DOUBLE_val() const1368   double gen::DOUBLE_val() const {
1369 #ifdef DOUBLEVAL
1370     return _DOUBLE_val;
1371 #else
1372     return opaque_double_val(this);
1373 #endif
1374   }
1375 
FLOAT_val() const1376   giac_float gen::FLOAT_val() const {
1377 #ifdef DOUBLEVAL
1378     return _FLOAT_val;
1379 #else
1380     longlong r = * (longlong *)(this) ;
1381     // * (unsigned char *) (&r) = 0;
1382 #ifdef BCD
1383     return * (giac_float *)(&r);
1384 #else
1385     return giac_float(* (double *)(&r));
1386 #endif // BCD
1387 #endif // DOUBLEVAL
1388   }
1389 
makegen(int i) const1390   gen gen::makegen(int i) const {
1391     switch (type){
1392     case _INT_: case _ZINT: case _CPLX:
1393       return gen(i);
1394     case _VECT:
1395       return vecteur(1,i);
1396     case _USER:
1397       return _USERptr->makegen(i);
1398     default:
1399       return gensizeerr(gettext("makegen of type ")+print(context0));
1400     }
1401   }
1402 
gen2complex_d(const gen & e)1403   complex<double> gen2complex_d(const gen & e){
1404     if (e.type==_CPLX){
1405       if (e.subtype==3)
1406 	return complex<double>((*e._CPLXptr)._DOUBLE_val,(*(e._CPLXptr+1))._DOUBLE_val);
1407       gen ee=e.evalf_double(1,context0); // ok
1408       if (ee.type==_DOUBLE_) return complex<double>(ee._DOUBLE_val,0);
1409       if (ee.type!=_CPLX){
1410 #ifndef NO_STDEXCEPT
1411 	setsizeerr(gettext("complex<double>"));
1412 #endif
1413 	return complex<double>(nan(),nan());
1414       }
1415       return complex<double>((*ee._CPLXptr)._DOUBLE_val,(*(ee._CPLXptr+1))._DOUBLE_val);
1416     }
1417     if (e.type==_DOUBLE_)
1418       return complex<double>(e._DOUBLE_val,0);
1419     if (e.type==_INT_)
1420       return complex<double>(e.val,0);
1421     if (e.type==_ZINT)
1422       return complex<double>(e.evalf(1,context0)._DOUBLE_val,0); // ok
1423 #ifndef NO_STDEXCEPT
1424     setsizeerr(gettext("complex<double>"));
1425 #endif
1426     return complex<double>(nan(),nan());
1427   }
1428 
gen(const sparse_poly1 & p)1429   gen::gen(const sparse_poly1 & p){
1430     if (p.empty()){
1431       type=0;
1432       subtype=0;
1433       val=0;
1434     }
1435     else {
1436       if (is_undef(p.front().exponent)){
1437 	type=0;
1438 	*this=undef;
1439       }
1440       else {
1441 #ifdef SMARTPTR64
1442 	* ((ulonglong * ) this) = ulonglong(new ref_sparse_poly1(p)) << 16;
1443 #else
1444 	__SPOL1ptr= new ref_sparse_poly1(p);
1445 #endif
1446 #ifdef KHICAS
1447 	if ((size_t) _SPOL1ptr > stackptr)
1448 	  ctrl_c=interrupted=true;
1449 #endif
1450 	subtype=0;
1451 	type=_SPOL1;
1452       }
1453     }
1454   }
1455 
gen(const unary_function_ptr * f,int nargs)1456   gen::gen(const unary_function_ptr * f,int nargs){
1457 #if defined SMARTPTR64
1458     * ((ulonglong * ) this) = ulonglong(new ref_unary_function_ptr(*f)) << 16;
1459 #else
1460     _FUNC_ = (size_t) (* (size_t*) f);
1461     // __FUNCptr= new ref_unary_function_ptr(f);
1462 #endif
1463     type=_FUNC;
1464     subtype=nargs;
1465   }
1466 
gen(const unary_function_ptr & f,int nargs)1467   gen::gen(const unary_function_ptr & f,int nargs){
1468 #ifdef SMARTPTR64
1469     * ((ulonglong * ) this) = ulonglong(new ref_unary_function_ptr(f)) << 16;
1470 #else
1471     _FUNC_ = (size_t)(* (size_t *) &f);
1472     // __FUNCptr= new ref_unary_function_ptr(f);
1473 #endif
1474     type=_FUNC;
1475     subtype=nargs;
1476   }
1477 
gen(const giac_float & f)1478   gen::gen(const giac_float & f){
1479 #ifdef DOUBLEVAL
1480     _FLOAT_val=f;
1481 #else
1482 #ifdef BCD
1483     *((giac_float *) this) = f;
1484 #else // BCD
1485     *((double *) this) = f;
1486 #endif // BCD
1487 #endif // DOUBLEVAL
1488     type=_FLOAT_;
1489   }
1490 
1491 #ifdef BCD
gen(accurate_bcd_float * b)1492   gen::gen(accurate_bcd_float * b){
1493     giac_float f=fUnExpand(b);
1494 #ifdef DOUBLEVAL
1495     _FLOAT_val=f;
1496 #else
1497     *((giac_float *) this) = f;
1498 #endif // DOUBLEVAL
1499     type=_FLOAT_;
1500   }
1501 #endif // BCD
1502 
delete_gen()1503   void gen::delete_gen() {
1504     switch (type) {
1505 #ifdef SMARTPTR64
1506     case _ZINT:
1507       delete (ref_mpz_t *) (* ((ulonglong * ) this) >> 16);
1508       break;
1509     case _REAL:  {
1510       ref_real_object * ptr=(ref_real_object *) (* ((ulonglong * ) this) >> 16);
1511 #ifndef NO_RTTI
1512       if (dynamic_cast<real_interval *>(&ptr->r))
1513 	delete (ref_real_interval *) ptr;
1514       else
1515 #endif
1516 	delete ptr;
1517       break;
1518     }
1519     case _CPLX:
1520       delete (ref_complex *) (* ((ulonglong * ) this) >> 16);
1521       break;
1522     case _IDNT:
1523       delete (ref_identificateur *) (* ((ulonglong * ) this) >> 16);
1524       break;
1525     case _VECT:
1526       delete (ref_vecteur *) (* ((ulonglong * ) this) >> 16);
1527       break;
1528     case _SYMB:
1529       delete (ref_symbolic *) (* ((ulonglong * ) this) >> 16);
1530       break;
1531     case _USER:
1532       delete (ref_gen_user *) (* ((ulonglong * ) this) >> 16);
1533       break;
1534     case _EXT:
1535       delete (ref_algext *) (* ((ulonglong * ) this) >> 16);
1536       break;
1537     case _MOD:
1538       delete (ref_modulo *) (* ((ulonglong * ) this) >> 16);
1539       break;
1540     case _POLY:
1541       delete (ref_polynome *) (* ((ulonglong * ) this) >> 16);
1542       break;
1543     case _FRAC:
1544       delete (ref_fraction *) (* ((ulonglong * ) this) >> 16);
1545       break;
1546     case _SPOL1:
1547       delete (ref_sparse_poly1 *) (* ((ulonglong * ) this) >> 16);
1548       break;
1549     case _STRNG:
1550       delete (ref_string *) (* ((ulonglong * ) this) >> 16);
1551       break;
1552     case _FUNC:
1553       delete (ref_unary_function_ptr *) (* ((ulonglong * ) this) >> 16);
1554       break;
1555     case _MAP:
1556       delete (ref_gen_map *) (* ((ulonglong * ) this) >> 16);
1557       break;
1558     case _EQW:
1559       delete (ref_eqwdata *) (* ((ulonglong * ) this) >> 16);
1560       break;
1561     case _GROB:
1562       delete (ref_grob *) (* ((ulonglong * ) this) >> 16);
1563       break;
1564     case _POINTER_:
1565       if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1566 	fl_widget_delete_function(_POINTER_val);
1567       delete (ref_void_pointer *) (* ((ulonglong * ) this) >> 16);
1568       break;
1569 #else // SMARTPTR64
1570     case _ZINT:
1571       delete __ZINTptr;
1572       break;
1573     case _REAL: {
1574       ref_real_object * ptr=__REALptr;
1575 #ifndef NO_RTTI
1576       if (dynamic_cast<real_interval *>(&ptr->r))
1577 	delete (ref_real_interval *) __REALptr;
1578       else
1579 #endif
1580 	delete __REALptr;
1581       break;
1582     }
1583     case _CPLX:
1584       deletecomplex(__CPLXptr); // delete __CPLXptr;
1585       break;
1586     case _IDNT:
1587       delete __IDNTptr;
1588       break;
1589     case _VECT:
1590       delete_ref_vecteur(__VECTptr); // delete __VECTptr;
1591       break;
1592     case _SYMB:
1593       deletesymbolic(__SYMBptr); // delete __SYMBptr;
1594       break;
1595     case _USER:
1596       delete __USERptr;
1597       break;
1598     case _EXT:
1599       delete __EXTptr;
1600       break;
1601     case _MOD:
1602       delete __MODptr;
1603       break;
1604     case _POLY:
1605       delete __POLYptr;
1606       break;
1607     case _FRAC:
1608       delete __FRACptr;
1609       break;
1610     case _SPOL1:
1611       delete __SPOL1ptr;
1612       break;
1613     case _STRNG:
1614       delete __STRNGptr;
1615       break;
1616 #ifdef SMARTPTR64
1617     case _FUNC:
1618       delete __FUNCptr;
1619       break;
1620 #endif
1621     case _MAP:
1622       delete __MAPptr;
1623       break;
1624     case _EQW:
1625       delete __EQWptr;
1626       break;
1627     case _GROB:
1628       delete __GROBptr;
1629       break;
1630     case _POINTER_:
1631       if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1632 	fl_widget_delete_function(_POINTER_val);
1633       delete __POINTERptr;
1634       break;
1635 #endif // SMARTPTR64
1636     default:
1637 #ifndef NO_STDEXCEPT
1638       settypeerr(gettext("Gen Destructor"));
1639 #endif
1640       ;
1641     }
1642   }
1643 
delete_ptr(signed char subtype,short int type_save,ref_mpz_t * ptr_save)1644   void delete_ptr(signed char subtype,short int type_save,ref_mpz_t * ptr_save) {
1645 #if 0 // def COMPILE_FOR_STABILITY // commented (D.Alm) The call to delete_ptr() would sometimes get cancelled if ctrl_c was being set, which could cause the "Stopped by user interruption." exception somehow to be fired twice, with the second time not being caught properly by my exception handling code.
1646     control_c();
1647 #endif
1648     if (ptr_save && type_save!=_FLOAT_&& ptr_save->ref_count!=-1 && !--(ptr_save->ref_count)){
1649       switch (type_save) {
1650       case _ZINT:
1651 	delete ptr_save;
1652 	break;
1653       case _REAL: {
1654 	ref_real_object * ptr=(ref_real_object *) ptr_save;
1655 #ifndef NO_RTTI
1656 	if (dynamic_cast<real_interval *>(&ptr->r))
1657 	  delete (ref_real_interval *) ptr;
1658 	else
1659 #endif
1660 	  delete ptr;
1661 	break;
1662       }
1663       case _CPLX:
1664 	deletecomplex((ref_complex *) ptr_save);
1665 	break;
1666       case _IDNT:
1667 	delete (ref_identificateur *) ptr_save ;
1668 	break;
1669       case _SYMB:
1670 	deletesymbolic( (ref_symbolic *) ptr_save);
1671 	break;
1672       case _USER:
1673 	delete (ref_gen_user *) ptr_save;
1674 	break;
1675       case _EXT:
1676 	delete (ref_algext * ) ptr_save;
1677 	break;
1678       case _MOD:
1679 	delete (ref_modulo * ) ptr_save;
1680 	break;
1681       case _VECT:
1682 	delete_ref_vecteur((ref_vecteur *) ptr_save); // delete (ref_vecteur *) ptr_save;
1683 	break;
1684       case _POLY:
1685 	delete (ref_polynome *) ptr_save;
1686 	break;
1687       case _FRAC:
1688 	delete (ref_fraction *) ptr_save;
1689 	break;
1690       case _SPOL1:
1691 	delete (ref_sparse_poly1 *) ptr_save;
1692 	break;
1693       case _STRNG:
1694 	delete (ref_string *) ptr_save;
1695 	break;
1696 #ifdef SMARTPTR64
1697       case _FUNC:
1698 	delete (ref_unary_function_ptr *) ptr_save;
1699 	break;
1700 #endif
1701       case _MAP:
1702 	delete (ref_gen_map *) ptr_save;
1703 	break;
1704       case _EQW:
1705 	delete (ref_eqwdata *) ptr_save;
1706 	break;
1707       case _GROB:
1708 	delete (ref_grob *) ptr_save;
1709 	break;
1710       case _POINTER_:
1711 	if (subtype==_FL_WIDGET_POINTER && fl_widget_delete_function)
1712 	  fl_widget_delete_function( ((ref_void_pointer *)ptr_save)->p);
1713 	delete (ref_void_pointer *) ptr_save;
1714 	break;
1715       case _FLOAT_:
1716 	break;
1717       default:
1718 #ifndef NO_STDEXCEPT
1719 	settypeerr(gettext("Gen Operator ="));
1720 #endif
1721 	;
1722       }
1723     }
1724   }
1725 
1726 
to_double(GIAC_CONTEXT) const1727   double gen::to_double(GIAC_CONTEXT) const {
1728     if (type==_DOUBLE_)
1729       return _DOUBLE_val;
1730     if (type==_INT_)
1731       return double(val);
1732     gen tmp=evalf_double(1,contextptr);
1733     if (tmp.type==_DOUBLE_)
1734       return tmp._DOUBLE_val;
1735 #ifdef NAN
1736     return NAN;
1737 #else
1738     double d=1.0;
1739     d=d-d/double(1ULL<<53);
1740     return d*2.0/d;
1741 #endif
1742   }
1743 
is_vector_of_size(size_t n) const1744   bool gen::is_vector_of_size(size_t n) const {
1745     return type==_VECT && _VECTptr->size()==n;
1746   }
1747 
is_identificateur_with_name(const char * s) const1748   bool gen::is_identificateur_with_name(const char * s) const {
1749     return type==_IDNT && strcmp(_IDNTptr->id_name,s)==0;
1750   }
1751 
1752 
to_int() const1753   int gen::to_int() const {
1754     switch (type ) {
1755     case _INT_:
1756       return val;
1757     case _ZINT:
1758       return mpz_get_si(*_ZINTptr);
1759     case _CPLX:
1760       return _CPLXptr->to_int() ;
1761     default:
1762 #ifndef NO_STDEXCEPT
1763       settypeerr(gettext("To_int"));
1764 #endif
1765       return 0;
1766     }
1767     return 0;
1768   }
1769 
uncoerce(size_t s)1770   void gen::uncoerce(size_t s) {
1771     if (type==_INT_){
1772       int tmp =val;
1773 #ifdef SMARTPTR64
1774       * ((ulonglong * ) this) = ulonglong(new ref_mpz_t(s)) << 16;
1775 #else
1776       __ZINTptr = new ref_mpz_t(s);
1777 #endif
1778       type=_ZINT;
1779       mpz_set_si(*_ZINTptr,tmp);
1780     }
1781   }
1782 
_FRAC2_SYMB(const fraction & f)1783   gen _FRAC2_SYMB(const fraction & f){
1784     if (is_one(f.num))
1785       return symb_inv(f.den);
1786     if (is_minus_one(f.num))
1787       return -symb_inv(f.den);
1788     return symbolic(at_prod,makesequence(f.num,symb_inv(f.den)));
1789   }
1790 
_FRAC2_SYMB(const gen & e)1791   gen _FRAC2_SYMB(const gen & e){
1792 #ifdef DEBUG_SUPPORT
1793     if (e.type!=_FRAC) setsizeerr(gettext("gen.cc/_FRAC2_SYMB"));
1794 #endif
1795     return _FRAC2_SYMB(*e._FRACptr);
1796   }
1797 
_FRAC2_SYMB(const gen & n,const gen & d)1798   gen _FRAC2_SYMB(const gen & n,const gen & d){
1799     return symbolic(at_prod,makesequence(n,symb_inv(d)));
1800   }
1801 
1802 
1803   /* Eval, evalf */
evalf_VECT(const vecteur & v,int subtype,int level,const context * contextptr)1804   gen evalf_VECT(const vecteur & v,int subtype,int level,const context * contextptr){
1805     // bool save_is_inevalf=is_inevalf;
1806     // is_inevalf=true;
1807     vecteur w;
1808     vecteur::const_iterator it=v.begin(), itend=v.end();
1809     w.reserve(itend-it);
1810     for (;it!=itend;++it){
1811       gen tmp=it->evalf(level,contextptr);
1812       if (subtype){
1813 	if ((subtype==_SEQ__VECT)&&(tmp.type==_VECT) && (tmp.subtype==_SEQ__VECT)){
1814 	  const_iterateur jt=tmp._VECTptr->begin(),jtend=tmp._VECTptr->end();
1815 	  for (;jt!=jtend;++jt)
1816 	    w.push_back(*jt);
1817 	}
1818 	else {
1819 	  if ((subtype!=_SET__VECT) || (!equalposcomp(w,tmp)))
1820 	    w.push_back(tmp);
1821 	}
1822       }
1823       else
1824 	w.push_back(tmp);
1825     }
1826     // is_inevalf=save_is_inevalf;
1827     return gen(w,subtype);
1828   }
1829 
1830 
eval_VECT(const gen & g,gen & evaled,int subtype,int level,const context * contextptr)1831   bool eval_VECT(const gen & g,gen & evaled,int subtype,int level,const context * contextptr){
1832     //    const vecteur & v = *g._VECTptr;
1833     gen tmp;
1834     const gen * ansptr;
1835     ref_vecteur * vptr;
1836     const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(),jt,jtend;
1837     if (subtype!=_SET__VECT && subtype!=_SEQ__VECT){
1838       for (;it!=itend;++it){
1839 	if (it->in_eval(level,evaled,contextptr))
1840 	  break;
1841       }
1842       if (it==itend)
1843 	return false;
1844     }
1845     vptr = new_ref_vecteur(0);
1846     vptr->v.reserve(itend-g._VECTptr->begin());
1847     if (subtype!=_SET__VECT && subtype!=_SEQ__VECT){
1848       for (jt=g._VECTptr->begin();jt!=it;++jt)
1849 	vptr->v.push_back(*jt);
1850       if (evaled.type==_VECT && evaled.subtype==_SEQ__VECT){
1851 	jt=evaled._VECTptr->begin(); jtend=evaled._VECTptr->end();
1852 	for (;jt!=jtend;++jt){
1853 	  if ((subtype!=_SET__VECT) || (!equalposcomp(vptr->v,*jt)))
1854 	    vptr->v.push_back(*jt);
1855 	}
1856       }
1857       else {
1858 	if ( subtype!=_SET__VECT || (!equalposcomp(vptr->v,evaled)))
1859 	  vptr->v.push_back(evaled);
1860       }
1861       ++it;
1862     }
1863     evaled=gen(vptr,subtype);
1864     for (;it!=itend;++it){
1865       if (it->is_symb_of_sommet(at_comment))
1866 	continue;
1867       ansptr=(it->in_eval(level,tmp,contextptr))?&tmp:&*it;
1868       if (ansptr->type==_VECT && ansptr->subtype==_SEQ__VECT){
1869 	jt=ansptr->_VECTptr->begin(); jtend=ansptr->_VECTptr->end();
1870 	for (;jt!=jtend;++jt){
1871 	  if ((subtype!=_SET__VECT) || (!equalposcomp(vptr->v,*jt)))
1872 	    vptr->v.push_back(*jt);
1873 	}
1874       }
1875       else {
1876 	if ( subtype!=_SET__VECT || (!equalposcomp(vptr->v,*ansptr)))
1877 	  vptr->v.push_back(*ansptr);
1878       }
1879     }
1880     // CERR << "End " << v << " " << w << '\n';
1881     return true;
1882   }
1883 
1884   // evalf a real fraction
evalf_FRAC(const fraction & f,GIAC_CONTEXT)1885   gen evalf_FRAC(const fraction & f,GIAC_CONTEXT){
1886     gen n(f.num),d(f.den);
1887     if (n.type==_INT_ && d.type==_INT_)
1888       return evalf(n,1,contextptr)/evalf(d,1,contextptr);
1889     if (is_zero(n))
1890       return evalf(n,0,contextptr);
1891     bool npos=is_positive(n,contextptr),dpos=is_positive(d,contextptr);
1892     bool neg=npos?!dpos:dpos;
1893     if (!npos)
1894       n=-n;
1895     if (!dpos)
1896       d=-d;
1897     bool inf1=is_greater(d,n,contextptr);
1898 #ifdef FXCG
1899     gen m=gen(longlong(1)<<61);
1900     gen md=gen(1.0)/m;
1901 #else
1902 #ifdef BCD
1903     static gen m=gen(longlong(100000000000000));
1904 #else
1905     static gen m=gen(longlong(1)<<61);
1906 #endif
1907     static gen md=gen(1.0)/m;
1908 #endif
1909     if (absint(sizeinbase2(n)-sizeinbase2(d))>=53){
1910       gen a=inf1?iquo(d,n):iquo(n,d);
1911       gen res=evalf(a,1,contextptr);
1912       if (neg) res=-res;
1913       return inf1?inv(res,contextptr):res;
1914     }
1915     gen a=inf1?iquo(d*m,n):iquo(n*m,d);
1916     gen res=evalf(a,1,contextptr);
1917     if (neg) res=-res;
1918     res = md*res;
1919     return inf1?inv(res,contextptr):res;
1920   }
1921 
1922       // evaluate _FUNCndary in RPN mode, f must be of type _FUNC
rpneval_FUNC(const gen & f,GIAC_CONTEXT)1923   static gen rpneval_FUNC(const gen & f,GIAC_CONTEXT){
1924     // int s=history_out(contextptr).size();
1925       int nargs=giacmax(f.subtype,0);
1926       if (!nargs){
1927 	gen res=(*f._FUNCptr)(gen(history_out(contextptr),_RPN_STACK__VECT),contextptr);
1928 	if ( (res.type!=_VECT) || (res.subtype!=_RPN_STACK__VECT))
1929 	  res=gen(makenewvecteur(res),_RPN_STACK__VECT);
1930 	history_out(contextptr)=*res._VECTptr;
1931 	history_in(contextptr)=history_out(contextptr);
1932 	return res;
1933       }
1934       vecteur v(nargs);
1935       for (int i=nargs-1;i>=0;--i){
1936           v[i]=history_out(contextptr).back();
1937           history_out(contextptr).pop_back();
1938           history_in(contextptr).pop_back();
1939       }
1940       if (nargs==1)
1941           return (*f._FUNCptr)(v.front(),contextptr);
1942       else
1943           return (*f._FUNCptr)(v,contextptr);
1944   }
1945 
evalcomment(const vecteur & v,gen & evaled,int level,const context * contextptr)1946   static bool evalcomment(const vecteur & v,gen &evaled,int level,const context * contextptr){
1947     const_iterateur it=v.begin(),itend=v.end();
1948     for (;it!=itend;++it){
1949       if ( (it->type!=_SYMB) || (it->_SYMBptr->sommet!=at_comment) )
1950 	break;
1951     }
1952     if (it+1==itend){
1953       evaled=it->eval(level,contextptr);
1954       return true;
1955     }
1956     if (it!=itend){
1957       gen partial=vecteur(it,itend);
1958       if (eval_VECT(partial,evaled,_SEQ__VECT,level,contextptr))
1959 	return true;
1960       else {
1961 	evaled=partial;
1962 	return true;
1963       }
1964     }
1965     evaled=zero;
1966     return true;
1967   }
1968 
check_not_assume(const gen & not_evaled,gen & evaled,bool evalf_after,const context * contextptr)1969   bool check_not_assume(const gen & not_evaled,gen & evaled, bool evalf_after,const context * contextptr){
1970     if ( evaled.type==_VECT && evaled.subtype==_ASSUME__VECT ){
1971       if ( evalf_after && evaled._VECTptr->size()==2 && (evaled._VECTptr->back().type<=_CPLX || evaled._VECTptr->back().type==_FRAC || evaled._VECTptr->back().type==_FLOAT_) ){
1972 	evaled=evaled._VECTptr->back().evalf(1,contextptr);
1973 	return true;
1974       }
1975       if (not_evaled.type==_IDNT && evaled._VECTptr->size()==1 && evaled._VECTptr->front().type==_INT_){
1976 	gen tmp=not_evaled;
1977 	tmp.subtype=evaled._VECTptr->front().val;
1978 	evaled=tmp;
1979 	return true;
1980       }
1981       return false;
1982     }
1983     else {
1984       if (evalf_after && evaled.type!=_IDNT){
1985 	gen res;
1986 	if (has_evalf(evaled,res,0,contextptr)){
1987 	  evaled=res;
1988 	  return true;
1989 	}
1990       }
1991       return &evaled!=&not_evaled;
1992     }
1993     return false;
1994   }
1995 
1996 #if 0
1997   gen gen::eval(int level,const context * contextptr) const{
1998     // CERR << "eval " << *this << " " << level << '\n';
1999     gen res;
2000     // return in_eval(level,res,contextptr)?res:*this;
2001     if (in_eval(level,res,contextptr))
2002       return res;
2003     else
2004       return *this;
2005   }
2006 #endif
2007 
in_eval_mod(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2008   static bool in_eval_mod(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2009     evaled=makemod(g._MODptr->eval(level,contextptr),(g._MODptr+1)->eval(level,contextptr));
2010     return true;
2011   }
2012 
in_eval_user(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2013   static bool in_eval_user(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2014     evaled=g._USERptr->eval(level,contextptr);
2015     return true;
2016   }
2017 
in_eval_func(const gen & g,gen * evaledptr,GIAC_CONTEXT)2018   static bool in_eval_func(const gen & g,gen * evaledptr,GIAC_CONTEXT){
2019     if (rpn_mode(contextptr) && (history_out(contextptr).size()>=unsigned(g.subtype)))
2020       *evaledptr=rpneval_FUNC(g,contextptr);
2021     else {
2022       if (g.subtype)
2023 	return false;
2024       else
2025 	*evaledptr=(*g._FUNCptr)(gen(vecteur(0),_SEQ__VECT),contextptr);
2026     }
2027     return true;
2028   }
2029 
in_eval_idnt(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2030   static bool in_eval_idnt(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2031     identificateur * gptr=g._IDNTptr;
2032     if (strcmp(gptr->id_name,string_pi)==0 || strcmp(gptr->id_name,string_euler_gamma)==0 )
2033       return false;
2034     if (!contextptr && g.subtype==_GLOBAL__EVAL)
2035       evaled=global_eval(*gptr,level);
2036     else {
2037       if (!gptr->in_eval(level-1,g,evaled,contextptr))
2038 	return false;
2039     }
2040     if ( evaled.type!=_VECT || evaled.subtype!=_ASSUME__VECT ){
2041       if (evaled.is_symb_of_sommet(at_program))
2042 	lastprog_name(gptr->id_name,contextptr);
2043       return true;
2044     }
2045     return check_not_assume(g,evaled,false,contextptr);
2046   }
2047 
in_eval_vect(const gen & g,gen & evaled,int level,GIAC_CONTEXT)2048   static bool in_eval_vect(const gen & g,gen & evaled,int level,GIAC_CONTEXT){
2049 #ifdef HAVE_LIBMPFI
2050     if (g.subtype==_INTERVAL__VECT && g._VECTptr->size()==2){
2051       // convert to MPFI real_interval
2052       gen l=eval(g._VECTptr->front(),level,contextptr),u=eval(g._VECTptr->back(),level,contextptr);
2053       if (is_strictly_greater(l,u,contextptr)){
2054 	swapgen(l,u);
2055       }
2056       bool lexact=is_integer(l),uexact=is_integer(u);
2057       gen ul=u-l;
2058       if (is_exactly_zero(ul)){
2059 	if (u.type==_REAL)
2060 	  ul=int(mpfr_get_prec(u._REALptr->inf));
2061 	else
2062 	  ul=int(3.2*decimal_digits(contextptr));
2063       }
2064       else {
2065 	ul=u-l;
2066 	ul=2*ul/(abs(u,contextptr)+abs(l,contextptr));
2067 	ul=ln(abs(evalf(ul,1,contextptr),contextptr),contextptr);
2068 	ul=-_ceil(ul/ln(evalf(2,1,contextptr),contextptr),contextptr);
2069       }
2070       int nbits=53;
2071       if (ul.type==_INT_ && ul.val>48){
2072 	nbits=ul.val+4;
2073 	l=accurate_evalf(l,nbits);
2074 	u=accurate_evalf(u,nbits);
2075       }
2076       else {
2077 	l=evalf(l,level,contextptr); u=evalf(u,level,contextptr);
2078       }
2079       if (l.type==_DOUBLE_ && u.type==_REAL)
2080 	u=evalf_double(u,1,contextptr);
2081       if (u.type==_DOUBLE_ && l.type==_REAL)
2082 	l=evalf_double(l,1,contextptr);
2083       if (l.type==_DOUBLE_){
2084 	// adjust mantissa of l down and mantissa of u up
2085 	double epsilon=7e-15; // 2^(-47)
2086 	if (!lexact)
2087 	  l=(1.+(l._DOUBLE_val>0?(-epsilon):(epsilon)))*l;
2088 	if (!uexact)
2089 	  u=(1.+(u._DOUBLE_val>0?(epsilon):(-epsilon)))*u;
2090       }
2091       else { // do the same for MPFR
2092 	gen epsilon=pow(plus_two,nbits-2,contextptr); // nbits-3?
2093 	epsilon=fraction(1,epsilon);
2094 	if (!lexact){
2095 	  if (is_positive(l,contextptr))
2096 	    l=(1-epsilon)*l;
2097 	  else
2098 	    l=(1+epsilon)*l;
2099 	}
2100 	if (!uexact){
2101 	  if (is_positive(u,contextptr))
2102 	    u=(1+epsilon)*u;
2103 	  else
2104 	    u=(1-epsilon)*u;
2105 	}
2106       }
2107       if ( (l.type==_DOUBLE_ && u.type==_DOUBLE_) ||
2108 	   (l.type==_REAL && u.type==_REAL) ){
2109 	mpfi_t interv;
2110 	mpfi_init(interv);
2111 	mpfi_set_prec(interv,nbits);
2112 	if (l.type==_DOUBLE_)
2113 	  mpfi_interv_d(interv,l._DOUBLE_val,u._DOUBLE_val);
2114 	else
2115 	  mpfi_interv_fr(interv,l._REALptr->inf,u._REALptr->inf);
2116 	evaled=gen(real_interval(interv));
2117 	mpfi_clear(interv);
2118 	return true;
2119       }
2120     }
2121 #endif
2122     if (g.subtype==_SPREAD__VECT){
2123       makespreadsheetmatrice(*g._VECTptr,contextptr);
2124       spread_eval(*g._VECTptr,contextptr);
2125       return false;
2126     }
2127     if (g.subtype==_TABLE__VECT){
2128       eval_VECT(g,evaled,g.subtype,level,contextptr);
2129       evaled=_table(evaled,contextptr);
2130       return true;
2131     }
2132     if (g.subtype==_FOLDER__VECT || g.subtype==_RGBA__VECT)
2133       return false;
2134     if ( (g.subtype==_SEQ__VECT) && (!g._VECTptr->empty()) && (g._VECTptr->front().type==_SYMB)
2135 	 && (g._VECTptr->front().is_symb_of_sommet(at_comment))
2136 	 && (g._VECTptr->back().type==_SYMB)
2137 	 && (g._VECTptr->back().is_symb_of_sommet(at_return))
2138 	 ){
2139       return evalcomment(*g._VECTptr,evaled,level,contextptr);
2140     }
2141     if (g._VECTptr->size()==1 && g._VECTptr->front().is_symb_of_sommet(at_interval))
2142       return in_eval_vect(gen(makevecteur(g._VECTptr->front()[1],g._VECTptr->front()[2]),_INTERVAL__VECT),evaled,1,contextptr);
2143     return eval_VECT(g,evaled,g.subtype,level,contextptr);
2144   }
2145 
in_eval(int level,gen & evaled,const context * contextptr) const2146   bool gen::in_eval(int level,gen & evaled,const context * contextptr) const{
2147 #ifdef TIMEOUT
2148     control_c();
2149 #endif
2150     if (ctrl_c || interrupted) {
2151       interrupted = true; ctrl_c=false;
2152       *logptr(contextptr) << "Stopped in in_eval" << '\n';
2153       gensizeerr(gettext("Stopped by user interruption."),evaled);
2154       return true;
2155     }
2156     if (!level)
2157       return false;
2158     switch (type) {
2159     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _CPLX: case _POLY: case _FRAC: case _SPOL1: case _EXT: case _STRNG: case _MAP: case _EQW: case _GROB: case _POINTER_:
2160       return false;
2161     case _IDNT:
2162       return in_eval_idnt(*this,evaled,level,contextptr);
2163     case _VECT:
2164       return in_eval_vect(*this,evaled,level,contextptr);
2165     case _SYMB:
2166       if (subtype==_SPREAD__SYMB)
2167 	return false;
2168       {
2169 	symbolic * sptr=_SYMBptr;
2170 	unary_function_ptr & Sommet=sptr->sommet;
2171 	const gen & feuille=sptr->feuille;
2172 	bool is_ifte=false,is_of_local_ifte_bloc=false,is_plus=Sommet==at_plus,is_prod=false,is_pow=false;
2173 	if (is_plus || (is_prod=(Sommet==at_prod)) || (is_pow=(Sommet==at_pow)) || (is_of_local_ifte_bloc=(Sommet==at_of || Sommet==at_local || (is_ifte=Sommet==at_ifte) || Sommet==at_bloc)) ){
2174 	  int & elevel=eval_level(contextptr);
2175 	  short int slevel=elevel;
2176 	  // Check if we are not far from stack end
2177 #ifdef RTOS_THREADX
2178 	  if ((void *)&slevel<= (void *)&mainThreadStack[2048]){
2179 	    if ((void *)&slevel<= (void *)&mainThreadStack[1024]){
2180 	      gensizeerr(gettext("Too many recursion levels"),evaled); // two many recursion levels
2181 	      return true;
2182 	    }
2183 	    evaled=nr_eval(*this,level,contextptr);
2184 	    return true;
2185 	  }
2186 #else // rtos
2187 #if !defined(WIN32) && defined(HAVE_PTHREAD_H)
2188 	  void * stackaddr;
2189 	  if (contextptr && (stackaddr=thread_param_ptr(contextptr)->stackaddr)){
2190 	    // CERR << &slevel << " " << thread_param_ptr(contextptr)->stackaddr << '\n';
2191 	    if ( ((size_t) &slevel) < ((size_t) stackaddr)+65536){
2192 	      if ( ((size_t) &slevel) < ((size_t) stackaddr)+8192){
2193 		gensizeerr(gettext("Too many recursion levels"),evaled); // two many recursion levels
2194 		return true;
2195 	      }
2196 	      *logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2197 	      evaled=nr_eval(*this,level,contextptr);
2198 	      return true;
2199 	    }
2200 	  } else
2201 #endif // pthread
2202 	    {
2203 	      debug_struct * dbgptr=debug_ptr(contextptr);
2204 	      if ( int(dbgptr->sst_at_stack.size()) >= MAX_RECURSION_LEVEL){
2205 		if ( int(dbgptr->sst_at_stack.size()) >= MAX_RECURSION_LEVEL+10){
2206 		  gensizeerr(gettext("Too many recursions)"),evaled);
2207 		  return true;
2208 		}
2209 #ifdef KHICAS
2210 		if (warn_nr){
2211 		  *logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2212 		  warn_nr=false;
2213 		}
2214 #else
2215 		*logptr(contextptr) << gettext("Running non recursive evaluator") << '\n';
2216 #endif
2217 		evaled=nr_eval(*this,level,contextptr);
2218 		return true;
2219 	      }
2220 	    }
2221 #endif // rtos
2222 	  const vecteur * vptr;
2223 	  if ( (is_plus ||is_prod || is_pow) && feuille.type==_VECT && (vptr=feuille._VECTptr)->size()==2){
2224 	    const gen & vptrfront=vptr->front();
2225 	    const gen & vptrback=vptr->back();
2226 	    gen a;
2227 	    if (!vptrfront.in_eval(level,a,contextptr))
2228 	      a=vptrfront;
2229 	    if (a.type!=_VECT || a.subtype!=_SEQ__VECT){
2230 	      if (!vptrback.in_eval(level,evaled,contextptr))
2231 		evaled=vptrback;
2232 	      if (evaled.type!=_VECT || evaled.subtype!=_SEQ__VECT){
2233 		if (is_plus) evaled=operator_plus(a,evaled,contextptr);
2234 		else {
2235 		  if (is_prod) evaled=operator_times(a,evaled,contextptr);
2236 		  else evaled=pow(a,evaled,contextptr);
2237 		}
2238 		elevel=slevel;
2239 		return true;
2240 	      }
2241 	    }
2242 	  }
2243 	  if (is_of_local_ifte_bloc){
2244 	    elevel=level;
2245 	    evaled=feuille; // FIXME must also set eval_level to level
2246 	  }
2247 	  else {
2248 	    if (!feuille.in_eval(level,evaled,contextptr))
2249 	      evaled=feuille;
2250 	  }
2251 	  if (is_ifte)
2252 	    evaled=ifte(evaled,true,contextptr);
2253 	  else
2254 	    evaled=(*Sommet.ptr())(evaled,contextptr);
2255 	  elevel=slevel;
2256 	}
2257 	else
2258 	  evaled=sptr->eval(level,contextptr);
2259 	return true;
2260       }
2261     case _USER:
2262       return in_eval_user(*this,evaled,level,contextptr);
2263     case _MOD:
2264       return in_eval_mod(*this,evaled,level,contextptr);
2265     case _FUNC:
2266       return in_eval_func(*this,&evaled,contextptr);
2267     default:
2268       gentypeerr("Eval",evaled) ;
2269       return false;
2270     }
2271     return false;
2272   }
2273 
apply(const polynome & p,const gen_op & f)2274   polynome apply( const polynome & p, const gen_op & f){
2275     polynome res(p.dim);
2276     std::vector< monomial<gen> > :: const_iterator it=p.coord.begin(),itend=p.coord.end();
2277     res.coord.reserve(itend-it);
2278     for (;it!=itend;++it){
2279       gen tmp(f(it->value));
2280       if (!is_zero(tmp,context0))
2281 	res.coord.push_back(monomial<gen>(tmp,it->index));
2282     }
2283     return res;
2284   }
2285 
apply(const polynome & p,const context * contextptr,gen (* f)(const gen &,const context *))2286   polynome apply( const polynome & p, const context * contextptr, gen (* f) (const gen &, const context *)){
2287     polynome res(p.dim);
2288     std::vector< monomial<gen> > :: const_iterator it=p.coord.begin(),itend=p.coord.end();
2289     res.coord.reserve(itend-it);
2290     for (;it!=itend;++it){
2291       gen tmp(f(it->value,contextptr));
2292       if (!is_zero(tmp,contextptr))
2293 	res.coord.push_back(monomial<gen>(tmp,it->index));
2294     }
2295     return res;
2296   }
2297 
set_precision(const gen & g,int nbits)2298   static gen set_precision(const gen & g,int nbits){
2299     if (nbits<45)
2300       return evalf_double(g,1,context0);
2301 #ifdef HAVE_LIBMPFR
2302     return real_object(g,nbits);
2303 #else
2304     gen tmp=evalf_double(g,1,context0);
2305     gen G=g;
2306     if (tmp.type==_DOUBLE_ && tmp._DOUBLE_val!=0)
2307       round2(G,int(nbits-std::log(absdouble(tmp._DOUBLE_val))/std::log(2.0)));
2308     return evalf_double(G,1,context0);
2309 #endif
2310   }
2311 
accurate_evalf(const gen & g,int nbits)2312   gen accurate_evalf(const gen & g,int nbits){
2313     if (g.type==_FRAC && g._FRACptr->num.type==_VECT)
2314       return inv(accurate_evalf(g._FRACptr->den,nbits),context0)*accurate_evalf(g._FRACptr->num,nbits);
2315     if (g.type==_VECT)
2316       return gen(accurate_evalf(*g._VECTptr,nbits),g.subtype);
2317     gen r,i;reim(g,r,i,context0); // only called for numeric values
2318     if (is_zero(i,context0))
2319       return set_precision(r,nbits);
2320     else
2321       return gen(set_precision(r,nbits),set_precision(i,nbits));
2322   }
2323 
accurate_evalf(const vecteur & v,int nbits)2324   vecteur accurate_evalf(const vecteur & v,int nbits){
2325     vecteur res(v);
2326     iterateur it=res.begin(),itend=res.end();
2327     for (;it!=itend;++it)
2328       *it = accurate_evalf(*it,nbits);
2329     return res;
2330   }
2331 
evalf(const gen & e,int level,const context * contextptr)2332   gen evalf(const gen & e,int level,const context * contextptr){
2333     return e.evalf(level,contextptr);
2334   }
2335 
no_context_evalf(const gen & e)2336   gen no_context_evalf(const gen & e){
2337     gen tmp;
2338     if (has_evalf(e,tmp,1,context0))
2339       return tmp;
2340     else
2341       return e;
2342   }
2343 
2344   static const double double0_15[]={0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0};
_int2double(unsigned i)2345   static double _int2double(unsigned i){
2346     if (i<16)
2347       return double0_15[i];
2348     else
2349       return _int2double(i/16)*16.0+double0_15[i%16];
2350   }
2351   // double(int) does not seem to work under GNUWINCE
int2double(int i)2352   double int2double(int i){
2353     if (i<0)
2354       return -_int2double(-i);
2355     else
2356       return _int2double(i);
2357   }
2358 
2359 
evalf(int level,const context * contextptr) const2360   gen gen::evalf(int level,const context * contextptr) const{
2361     // CERR << "evalf " << *this << " " << level << '\n';
2362 #ifdef TIMEOUT
2363     control_c();
2364 #endif
2365     if (ctrl_c || interrupted) {
2366       interrupted = true; ctrl_c=false;
2367       return gensizeerr(gettext("Stopped by user interruption."));
2368     }
2369     if (level==0)
2370       return *this;
2371     gen evaled;
2372     if (in_evalf(level,evaled,contextptr))
2373       return evaled;
2374     else
2375       return *this;
2376   }
2377 
m_pi(GIAC_CONTEXT)2378   gen m_pi(GIAC_CONTEXT){
2379     int nbits=digits2bits(decimal_digits(contextptr));
2380     return m_pi(nbits);
2381   }
2382 
m_pi(int nbits)2383   gen m_pi(int nbits){
2384 #ifdef HAVE_LIBMPFR
2385     if (nbits>48){
2386 #ifdef HAVE_LIBPTHREAD
2387       int locked=pthread_mutex_lock(&mpfr_mutex);
2388 #else // HAVE_LIBPTHREAD
2389       int locked=0;
2390 #endif
2391       if (!locked)
2392 	mpfr_set_default_prec(nbits);
2393       mpfr_t pi;
2394       mpfr_init(pi);
2395       mpfr_const_pi(pi,MPFR_RNDN);
2396 #ifdef HAVE_LIBPTHREAD
2397       if (!locked)
2398 	pthread_mutex_unlock(&mpfr_mutex);
2399 #endif
2400       gen res=real_object(pi);
2401       mpfr_clear(pi);
2402       return res;
2403     }
2404 #endif
2405 #if 0 // def BCD
2406     return fpi();
2407 #else
2408     return M_PI;
2409 #endif
2410   }
2411 
m_gamma(int nbits)2412   gen m_gamma(int nbits){
2413 #ifdef HAVE_LIBMPFR
2414     if (nbits>15){
2415 #ifdef HAVE_LIBPTHREAD
2416       int locked=pthread_mutex_lock(&mpfr_mutex);
2417 #else // HAVE_LIBPTHREAD
2418       int locked=0;
2419 #endif
2420       if (!locked)
2421 	mpfr_set_default_prec(nbits);
2422       mpfr_t euler_gamma;
2423       mpfr_init(euler_gamma);
2424       mpfr_const_euler(euler_gamma,MPFR_RNDN);
2425 #ifdef HAVE_LIBPTHREAD
2426       if (!locked)
2427 	pthread_mutex_unlock(&mpfr_mutex);
2428 #endif
2429       gen res=real_object(euler_gamma);
2430       mpfr_clear(euler_gamma);
2431       return res;
2432     }
2433 #endif
2434     return .577215664901533;
2435   }
2436 
m_gamma(GIAC_CONTEXT)2437   gen m_gamma(GIAC_CONTEXT){
2438     int nbits=digits2bits(decimal_digits(contextptr));
2439     return m_gamma(nbits);
2440   }
2441 
approx_pnt(int level,const gen & g,gen & evaled,const context * contextptr)2442   static bool approx_pnt(int level,const gen & g,gen & evaled,const context * contextptr){
2443     vecteur v=*g._SYMBptr->feuille._VECTptr;
2444     if (!v[0].in_evalf(level,evaled,contextptr))
2445       return false;
2446     v[0]=evaled;
2447     evaled=symbolic(at_pnt,gen(v,g._SYMBptr->feuille.subtype));
2448     return true;
2449   }
2450 
has_evalf(const identificateur & g,int subtype,gen & res,int level,GIAC_CONTEXT)2451   static bool has_evalf(const identificateur & g,int subtype,gen & res,int level,GIAC_CONTEXT){
2452     if (strcmp(g.id_name,string_pi)==0){
2453       res=m_pi(contextptr);
2454       return true;
2455     }
2456     gen tmp=g;
2457     tmp.subtype=subtype;
2458     tmp=tmp.evalf(level,contextptr);
2459     if (tmp.type==_IDNT || tmp.type==_SYMB)
2460       return false;
2461     return has_evalf(tmp,res,0,contextptr);
2462   }
2463 
has_evalf(const gen & g,gen & res,int level,GIAC_CONTEXT)2464   bool has_evalf(const gen & g,gen & res,int level,GIAC_CONTEXT){
2465     switch (g.type){
2466     case _DOUBLE_: case _FLOAT_: case _REAL:
2467       res=g;
2468       return true;
2469     case _INT_: case _ZINT: case _CPLX:
2470       res=evalf(g,1,contextptr);
2471       return true;
2472     case _IDNT:
2473       return has_evalf(*g._IDNTptr,g.subtype,res,level,contextptr);
2474     case _SYMB:
2475       if (has_evalf(g._SYMBptr->feuille,res,level,contextptr)){
2476 	res=g._SYMBptr->sommet(res,contextptr);
2477 	if (res.type==_INT_ || res.type==_ZINT)
2478 	  res=evalf(res,1,contextptr);
2479 	return res.type==_DOUBLE_ || res.type==_FLOAT_ || res.type==_CPLX || res.type==_REAL;
2480       }
2481       else
2482 	return false;
2483     }
2484     if (g.type==_EXT){
2485       gen a,b;
2486       if (has_evalf(*g._EXTptr,a,level,contextptr) && has_evalf(*(g._EXTptr+1),b,level,contextptr)){
2487 	a=alg_evalf(a,b,contextptr);
2488 	return a.type==_EXT?false:has_evalf(a,res,level,contextptr);
2489       }
2490       return false;
2491     }
2492     if (g.type==_FRAC){
2493       if (is_cinteger(g._FRACptr->num) && is_cinteger(g._FRACptr->den)){
2494 	return g.in_evalf(1,res,contextptr);
2495       }
2496       gen num,den;
2497       if (has_evalf(g._FRACptr->num,num,level,contextptr) && has_evalf(g._FRACptr->den,den,level,contextptr)){
2498 	res=num/den;
2499 	return true;
2500       }
2501       else
2502 	return false;
2503     }
2504     if (g.type!=_VECT)
2505       return false;
2506     if (g.subtype==_ASSUME__VECT && !g._VECTptr->empty()){
2507       res=g._VECTptr->back();
2508       return true;
2509     }
2510     vecteur v;
2511     const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
2512     v.reserve(itend-it);
2513     for (;it!=itend;++it){
2514       if (!has_evalf(*it,res,level,contextptr))
2515 	return false;
2516       v.push_back(res);
2517     }
2518     res=gen(v,g.subtype);
2519     return true;
2520   }
2521 
in_evalf(int level,gen & evaled,const context * contextptr) const2522   bool gen::in_evalf(int level,gen & evaled,const context * contextptr) const{
2523     if (!level)
2524       return false;
2525     switch (type) {
2526     case _REAL:
2527 #if 0 // ndef NO_RTTI  // infinite recursion with has_evalf and real intervals
2528       if (real_interval * ptr=dynamic_cast<real_interval *>(_REALptr)){
2529 	evaled=real_object(ptr->inf);
2530 	return true;
2531       }
2532 #endif
2533       return false;
2534     case _DOUBLE_: case _FLOAT_: case _STRNG: case _MAP: case _EQW: case _GROB: case _POINTER_:
2535       return false;
2536     case _INT_:
2537       if (subtype)
2538 	return false;
2539       if (decimal_digits(contextptr)>14){
2540 	evaled=real_object(*this,digits2bits(decimal_digits(contextptr)));
2541 	return true;
2542       }
2543 #if 0 // def BCD
2544       evaled=giac_float(val);
2545 #else
2546       evaled=int2double(val);
2547 #endif
2548       return true;
2549     case _ZINT:
2550 #if 0 // def BCD
2551       evaled=giac_float(_ZINTptr);
2552 #else
2553       if (decimal_digits(contextptr)>14)
2554 	evaled=real_object(*this,digits2bits(decimal_digits(contextptr)));
2555       else
2556 	evaled=mpz_get_d(*_ZINTptr);
2557 #endif
2558       return true;
2559     case _CPLX:
2560       evaled=gen(_CPLXptr->evalf(level,contextptr),(_CPLXptr+1)->evalf(level,contextptr));
2561       return true;
2562     case _USER:
2563       evaled=_USERptr->evalf(level,contextptr);
2564       return true;
2565     case _IDNT:
2566       if (strcmp(_IDNTptr->id_name,string_pi)==0){
2567 	evaled=m_pi(contextptr);
2568 	return true;
2569       }
2570       if (strcmp(_IDNTptr->id_name,string_euler_gamma)==0){
2571 	evaled=m_gamma(contextptr);
2572 	return true;
2573       }
2574       if (!contextptr && subtype==_GLOBAL__EVAL)
2575 	evaled=global_evalf(*_IDNTptr,level-1);
2576       else {
2577 	if (!_IDNTptr->in_eval(level-1,*this,evaled,contextptr))
2578 	  return false;
2579       }
2580       return check_not_assume(*this,evaled,true,contextptr);
2581     case _VECT:
2582       evaled=evalf_VECT(*_VECTptr,subtype,level,contextptr);
2583       return true;
2584     case _SYMB:
2585       if (subtype==_SPREAD__SYMB)
2586 	return false;
2587       if (_SYMBptr->sommet==at_pow && _SYMBptr->feuille._VECTptr->back().type==_INT_){
2588 	evaled=pow(_SYMBptr->feuille._VECTptr->front().evalf(level,contextptr),_SYMBptr->feuille._VECTptr->back(),contextptr);
2589 	return true;
2590       }
2591       if (_SYMBptr->sommet==at_integrate || (_SYMBptr->sommet==at_int && xcas_mode(contextptr)!=3)){
2592 	evaled=_gaussquad(_SYMBptr->feuille,contextptr); // FIXME: take care of precision (romberg if >14 digits?)
2593 	return true;
2594       }
2595       if (_SYMBptr->sommet==at_rootof){
2596 	evaled=approx_rootof(_SYMBptr->feuille.evalf(level,contextptr),contextptr);
2597 	return true;
2598       }
2599       if (_SYMBptr->sommet==at_cell)
2600 	return false;
2601       if (_SYMBptr->sommet==at_pnt && _SYMBptr->feuille.type==_VECT && !_SYMBptr->feuille._VECTptr->empty())
2602 	return approx_pnt(level,*this,evaled,contextptr);
2603       evaled=_SYMBptr->evalf(level,contextptr);
2604       return true;
2605     case _FRAC:
2606 #ifdef HAVE_LIBMPFR
2607       if (decimal_digits(contextptr)>14)
2608 	evaled=rdiv(_FRACptr->num.evalf(level,contextptr),_FRACptr->den.evalf(level,contextptr),contextptr);
2609       else
2610 #endif
2611 	{
2612 	  if (is_zero(_FRACptr->num.im(contextptr)) && is_zero(_FRACptr->den.im(contextptr)))
2613 	    evaled=evalf_FRAC(*_FRACptr,contextptr);
2614 	  else
2615 	    evaled=re(contextptr).evalf(1,contextptr)+cst_i*im(contextptr).evalf(1,contextptr);
2616 	}
2617       return true;
2618 #ifdef HAVE_LIBMPFR
2619       if (decimal_digits(contextptr)<=14)
2620 	evaled=set_precision(re(contextptr),60).evalf_double(1,contextptr)+cst_i*set_precision(im(contextptr),60).evalf_double(1,contextptr);
2621       else
2622 #endif
2623 	evaled=rdiv(_FRACptr->num.evalf(level,contextptr),_FRACptr->den.evalf(level,contextptr),contextptr);
2624       return true;
2625     case _FUNC:
2626       return in_eval_func(*this,&evaled,contextptr);
2627     case _MOD: case _ROOT:
2628       return false; // replace in RPN mode
2629     case _EXT:
2630       evaled=alg_evalf(_EXTptr->eval(level,contextptr),(_EXTptr+1)->eval(level,contextptr),contextptr);
2631       return true;
2632     case _POLY:
2633       evaled=apply(*_POLYptr,no_context_evalf);
2634       return true;
2635     default:
2636       evaled=gentypeerr(gettext("Evalf")) ;
2637       return false;
2638     }
2639     return false;
2640   }
2641 
real2int(const gen & g,GIAC_CONTEXT)2642   gen real2int(const gen & g,GIAC_CONTEXT){
2643     if (g.type==_REAL){
2644       if (is_strictly_positive(-g,contextptr))
2645 	return -real2int(-g,contextptr);
2646       if (is_zero(g))
2647 	return 0;
2648 #ifdef HAVE_LIBMPFR
2649       ref_mpz_t * m=new ref_mpz_t;
2650       int n=int(mpfr_get_z_exp(m->z,g._REALptr->inf));
2651       gen res(m->z);
2652       if (n>=0)
2653 	return res*pow(plus_two,gen(n),contextptr);
2654       return _iquo(makesequence(res,pow(plus_two,gen(-n),contextptr)),contextptr);
2655 #else
2656       return g;
2657 #endif
2658     }
2659     if (g.type!=_VECT)
2660       return g;
2661     return apply(g,real2int,contextptr);
2662   }
2663 
real2double(const gen & g)2664   gen real2double(const gen & g){
2665     if (g.type==_REAL)
2666       return g._REALptr->evalf_double();
2667     if (g.type==_FLOAT_)
2668       return get_double(g._FLOAT_val);
2669     if (g.type!=_VECT)
2670       return g;
2671     return apply(g,real2double);
2672   }
2673 
evalf_double(int level,const context * contextptr) const2674   gen gen::evalf_double(int level,const context * contextptr) const{
2675     if (type==_DOUBLE_)
2676       return *this;
2677     if (type==_INT_ && subtype==_INT_BOOLEAN)
2678       return double(val);
2679     gen g;
2680     if (has_evalf(*this,g,level,contextptr)){
2681       if (g.type==_CPLX)
2682 	return gen(real2double(*g._CPLXptr),real2double(*(g._CPLXptr+1)));
2683       else
2684 	return real2double(g);
2685     }
2686     else
2687       return *this;
2688   }
2689 
evalf2double_nock(const gen & g0,int level,const context * contextptr)2690   gen evalf2double_nock(const gen & g0,int level,const context * contextptr){
2691     if (g0.type==_INT_)
2692       return double(g0.val);
2693     if (g0.type==_DOUBLE_)
2694       return g0;
2695     if (g0.is_symb_of_sommet(at_program))
2696       return g0;
2697     if (g0.type==_FLOAT_ || g0.type==_FRAC || g0.type==_ZINT || g0.type==_REAL)
2698       return evalf_double(g0,1,contextptr);
2699     if (storcl_38 && level && g0.type==_IDNT){
2700       if (!strcmp(g0._IDNTptr->id_name,"pi"))
2701 	return M_PI;
2702       gen res;
2703 //      if (storcl_38(res,0,g0._IDNTptr->id_name,undef,false,contextptr)) return evalf2double_nock(res,level-1,contextptr);
2704     }
2705     if (g0.type==_VECT){
2706       ref_vecteur *vptr = new_ref_vecteur(*g0._VECTptr);
2707       iterateur it=vptr->v.begin(),itend=vptr->v.end();
2708       for (;it!=itend;++it)
2709 	*it=evalf2double_nock(*it,level,contextptr);
2710       return gen(vptr,g0.subtype);
2711     }
2712     if (is_inf(g0)||is_undef(g0))
2713       return g0;
2714     if (g0.type==_SYMB){
2715       unary_function_ptr & s =g0._SYMBptr->sommet;
2716       gen f =g0._SYMBptr->feuille;
2717       if (s==at_integrate && f._VECTptr->size()==4)
2718 	return _gaussquad(f,contextptr);
2719       if (f.type==_VECT && !s.quoted()){
2720 	if (s==at_plus){
2721 	  double res(0);
2722 	  gen tmp;
2723 	  iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2724 	  for (;it!=itend;++it){
2725 	    tmp=evalf2double_nock(*it,level,contextptr);
2726 	    if (tmp.type!=_DOUBLE_)
2727 	      break;
2728 	    res=res+tmp._DOUBLE_val;
2729 	  }
2730 	  if (it==itend)
2731 	    return res;
2732 	}
2733 	if (s==at_prod){
2734 	  double res(1);
2735 	  gen tmp;
2736 	  iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2737 	  for (;it!=itend;++it){
2738 	    tmp=evalf2double_nock(*it,level,contextptr);
2739 	    if (tmp.type!=_DOUBLE_)
2740 	      break;
2741 	    res=res*tmp._DOUBLE_val;
2742 	  }
2743 	  if (it==itend)
2744 	    return res;
2745 	}
2746 	if (f._VECTptr->size()==2){
2747 	  gen tmp1=evalf2double_nock(f._VECTptr->front(),level,contextptr);
2748 	  gen tmp2=f._VECTptr->back();
2749 	  if (tmp1.type==_DOUBLE_ && tmp2.type==_INT_ && s==at_pow)
2750 	    return std::pow(tmp1._DOUBLE_val,double(tmp2.val));
2751 	  tmp2=evalf2double_nock(tmp2,level,contextptr);
2752 	  if (s==at_pow)
2753 	    return pow(tmp1,tmp2,contextptr);
2754 	  if (s==at_division)
2755 	    return rdiv(tmp1,tmp2,contextptr);
2756 	  if (s==at_minus)
2757 	    return operator_minus(tmp1,tmp2,contextptr);
2758 	  tmp1=s(gen(makenewvecteur(tmp1,tmp2),f.subtype),contextptr);
2759 	  if (tmp1.type<_IDNT || tmp1.type==_FRAC)
2760 	    tmp1=evalf2double_nock(tmp1,1,contextptr);
2761 	  return tmp1;
2762 	}
2763       }
2764       if (s.quoted()) {
2765 	if (s==at_quote)
2766 	  return f;
2767 	f=s(f,contextptr);
2768 	if (f.type<_IDNT || f.type==_FRAC || (f.type==_SYMB && contains(f,cst_pi)) )
2769 	  f=evalf2double_nock(f,1,contextptr);
2770 	return f;
2771       }
2772       f=s(evalf2double_nock(f,level,contextptr),contextptr);
2773       if (f.type<_IDNT || f.type==_FRAC)
2774 	f=evalf2double_nock(f,1,contextptr);
2775       return f;
2776     }
2777     if (g0.type==_CPLX){
2778       if (g0._CPLXptr->type==_DOUBLE_ && (g0._CPLXptr+1)->type==_DOUBLE_){
2779 #if 1
2780 	// maybe we should round complex numbers that are close to reals?
2781 	if (fabs((g0._CPLXptr+1)->_DOUBLE_val)<1e-12*fabs(g0._CPLXptr->_DOUBLE_val))
2782 	  return g0._CPLXptr->_DOUBLE_val;
2783 #endif
2784 	return g0;
2785       }
2786       return evalf2double_nock(*g0._CPLXptr,1,contextptr)+cst_i*evalf2double_nock(*(g0._CPLXptr+1),1,contextptr);
2787     }
2788     gen g=evalf(g0,level,contextptr);
2789     if (g.type==_FLOAT_)
2790       return evalf_double(g,1,contextptr);
2791     if (g.type==_CPLX)
2792       return evalf2double_nock(*g._CPLXptr,1,contextptr)+cst_i*evalf2double_nock(*(g._CPLXptr+1),1,contextptr);
2793     return g;
2794   }
2795 
2796 
evalf2double(int level,const context * contextptr) const2797   gen gen::evalf2double(int level,const context * contextptr) const{
2798     /*
2799     gen g=evalf(level,contextptr);
2800     return g.evalf_double(level,contextptr);
2801     */
2802     return evalf2double_nock(*this,level,contextptr);
2803   }
2804 
chk_inf_nan(const gen & g0)2805   gen chk_inf_nan(const gen & g0){
2806     if (g0.type==_FLOAT_){
2807       if (fis_nan(g0._FLOAT_val))
2808 	return undeferr(gettext("Undefined"));
2809       if (fis_inf_notmax(g0._FLOAT_val))
2810 	return undeferr(gettext("Infinity error"));
2811       return g0;
2812     }
2813     if (is_undef(g0)){
2814       if (g0.type==_STRNG)
2815 	return g0;
2816       if (g0.type==_VECT && !g0._VECTptr->empty())
2817 	return g0._VECTptr->front();
2818       return undeferr(gettext("Undefined"));
2819     }
2820     if (is_inf(g0))
2821       return undeferr(gettext("Infinity error"));
2822     return g0;
2823   }
2824 
evalf2bcd_nock(const gen & g0,int level,const context * contextptr)2825   gen evalf2bcd_nock(const gen & g0,int level,const context * contextptr){
2826     if (g0.type==_FLOAT_)
2827       return g0;
2828     if (g0.type==_FRAC)
2829       return evalf_FRAC(*g0._FRACptr,contextptr);
2830     if (g0.type==_INT_)
2831       return giac_float(g0.val);
2832     // FIXME _ZINT should be converted without being evalf-ed to double
2833 #ifdef BCD
2834     if (g0.type==_ZINT)
2835       return giac_float(g0._ZINTptr);
2836 #endif
2837     if (storcl_38 && level && g0.type==_IDNT){
2838 #ifdef BCD
2839       if (!strcmp(g0._IDNTptr->id_name,"pi"))
2840 	return fpi();
2841 #endif
2842       gen res;
2843       if (storcl_38(res,0,g0._IDNTptr->id_name,undef,false,contextptr,NULL,false))
2844 	return evalf2bcd_nock(res,level-1,contextptr);
2845     }
2846     if (g0.type==_VECT){
2847       ref_vecteur *vptr = new_ref_vecteur(*g0._VECTptr);
2848       iterateur it=vptr->v.begin(),itend=vptr->v.end();
2849       for (;it!=itend;++it)
2850 	*it=evalf2bcd_nock(*it,level,contextptr);
2851       return gen(vptr,g0.subtype);
2852     }
2853     if (is_inf(g0)||is_undef(g0))
2854       return g0;
2855     if (g0.type==_SYMB){
2856       /*
2857       if (g0._SYMBptr->sommet==at_unit){
2858 	gen f = g0._SYMBptr->feuille;
2859 	if (f.type==_VECT && f._VECTptr->size()==2){
2860 	  f=gen(makevecteur(evalf2bcd_nock(f._VECTptr->front(),level,contextptr),f._VECTptr->back()),f.subtype);
2861 	  return symbolic(at_unit,f);
2862 	}
2863 	else
2864 	  return g0;
2865       }
2866       */
2867       unary_function_ptr & s =g0._SYMBptr->sommet;
2868       gen f =g0._SYMBptr->feuille;
2869       if (s==at_integrate && f._VECTptr->size()==4)
2870 	return _gaussquad(f,contextptr);
2871       if (f.type==_VECT && !s.quoted()){
2872 	if (s==at_plus){
2873 	  giac_float res(0);
2874 	  gen tmp;
2875 	  iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2876 	  for (;it!=itend;++it){
2877 	    tmp=evalf2bcd_nock(*it,level,contextptr);
2878 	    if (tmp.type!=_FLOAT_)
2879 	      break;
2880 	    res=res+tmp._FLOAT_val;
2881 	  }
2882 	  if (it==itend)
2883 	    return res;
2884 	}
2885 	if (s==at_prod){
2886 	  giac_float res(1);
2887 	  gen tmp;
2888 	  iterateur it=f._VECTptr->begin(),itend=f._VECTptr->end();
2889 	  for (;it!=itend;++it){
2890 	    tmp=evalf2bcd_nock(*it,level,contextptr);
2891 	    if (tmp.type!=_FLOAT_)
2892 	      break;
2893 	    res=res*tmp._FLOAT_val;
2894 	  }
2895 	  if (it==itend)
2896 	    return res;
2897 	}
2898 	if (f._VECTptr->size()==2){
2899 	  gen tmp1=evalf2bcd_nock(f._VECTptr->front(),level,contextptr);
2900 	  gen tmp2=f._VECTptr->back();
2901 	  if (tmp1.type==_FLOAT_ && tmp2.type==_INT_ && s==at_pow)
2902 	    return fpow(tmp1._FLOAT_val,giac_float(tmp2.val));
2903 	  tmp2=evalf2bcd_nock(tmp2,level,contextptr);
2904 	  if (s==at_pow)
2905 	    return pow(tmp1,tmp2,contextptr);
2906 	  if (s==at_division)
2907 	    return rdiv(tmp1,tmp2,contextptr);
2908 	  if (s==at_minus)
2909 	    return operator_minus(tmp1,tmp2,contextptr);
2910 	  tmp1=s(gen(makenewvecteur(tmp1,tmp2),f.subtype),contextptr);
2911 	  if (tmp1.type<_IDNT || tmp1.type==_FRAC)
2912 	    tmp1=evalf2bcd_nock(tmp1,1,contextptr);
2913 	  return tmp1;
2914 	}
2915       }
2916       if (s.quoted()) {
2917 	if (s==at_quote)
2918 	  return f;
2919 	f=s(f,contextptr);
2920 	if (f.type<_IDNT || f.type==_FRAC)
2921 	  f=evalf2bcd_nock(f,1,contextptr);
2922 	return f;
2923       }
2924       f=s(evalf2bcd_nock(f,level,contextptr),contextptr);
2925       if (f.type<_IDNT || f.type==_FRAC)
2926 	f=evalf2bcd_nock(f,1,contextptr);
2927       return f;
2928     }
2929     if (g0.type==_CPLX){
2930       if (g0._CPLXptr->type==_FLOAT_ && (g0._CPLXptr+1)->type==_FLOAT_)
2931 	return g0;
2932       return evalf2bcd_nock(*g0._CPLXptr,1,contextptr)+cst_i*evalf2bcd_nock(*(g0._CPLXptr+1),1,contextptr);
2933     }
2934     gen g=evalf(g0,level,contextptr);
2935     if (g.type==_DOUBLE_)
2936       return giac_float(g._DOUBLE_val);
2937     if (g.type==_CPLX)
2938       return evalf2bcd_nock(*g._CPLXptr,1,contextptr)+cst_i*evalf2bcd_nock(*(g._CPLXptr+1),1,contextptr);
2939     return g;
2940   }
2941 
evalf2bcd(const gen & g0,int level,const context * contextptr)2942   gen evalf2bcd(const gen & g0,int level,const context * contextptr){
2943     return chk_inf_nan(evalf2bcd_nock(g0,level,contextptr));
2944   }
2945 
poly_is_real(const polynome & p)2946   bool poly_is_real(const polynome & p){
2947     vector< monomial<gen> >::const_iterator it=p.coord.begin(),itend=p.coord.end();
2948     for (;it!=itend;++it){
2949       if (!it->value.is_real(0)) // context is 0 since coeff do not depend on
2950 	return false;
2951     }
2952     return true;
2953   }
2954 
vect_is_real(const vecteur & v,GIAC_CONTEXT)2955   bool vect_is_real(const vecteur & v,GIAC_CONTEXT){
2956     const_iterateur it=v.begin(),itend=v.end();
2957     for (;it!=itend;++it){
2958       if (!it->is_real(contextptr))
2959 	return false;
2960     }
2961     return true;
2962   }
2963 
2964   /* Checking */
is_real(GIAC_CONTEXT) const2965   bool gen::is_real(GIAC_CONTEXT) const {
2966     switch (type) {
2967     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL:
2968       return true;
2969     case _CPLX:
2970       return (is_zero(*(_CPLXptr+1),contextptr));
2971     case _POLY:
2972       return poly_is_real(*_POLYptr);
2973     case _VECT:
2974       return vect_is_real(*_VECTptr,contextptr);
2975     default:
2976       return is_zero(im(contextptr),contextptr);
2977     }
2978   }
2979 
is_approx() const2980   bool gen::is_approx() const {
2981     switch(type){
2982     case _DOUBLE_: case _FLOAT_: case _REAL:
2983       return true;
2984     case _CPLX:
2985       return subtype==3 || (_CPLXptr->is_approx() && (_CPLXptr+1)->is_approx());
2986     case _VECT:
2987       return has_num_coeff(*this);
2988     default:
2989       return false;
2990     }
2991   }
2992 
is_cinteger() const2993   bool gen::is_cinteger() const {
2994     switch (type ) {
2995     case _INT_: case _ZINT:
2996       return true;
2997     case _CPLX:
2998       return _CPLXptr->is_integer() && (_CPLXptr+1)->is_integer();
2999     default:
3000       return false;
3001     }
3002   }
3003 
is_integer() const3004   bool gen::is_integer() const {
3005     switch (type ) {
3006     case _INT_: case _ZINT:
3007       return true;
3008     case _CPLX:
3009       return is_exactly_zero(*(_CPLXptr+1)) && _CPLXptr->is_integer();
3010     default:
3011       return false;
3012     }
3013   }
3014 
_VECT_is_constant(const vecteur & v)3015   bool _VECT_is_constant(const vecteur & v){
3016       const_iterateur it=v.begin(),itend=v.end();
3017       for (;it!=itend;++it)
3018           if (!(it->is_constant()))
3019               return false;
3020       return true;
3021   }
3022 
is_constant() const3023   bool gen::is_constant() const {
3024     switch (type ) {
3025     case _INT_: case _DOUBLE_: case _FLOAT_: case _REAL: case _ZINT: case _CPLX:
3026       return true;
3027     case _VECT:
3028       return _VECT_is_constant(*this->_VECTptr);
3029     case _EXT:
3030       return _EXTptr->is_constant() && (_EXTptr+1)->is_constant();
3031     case _POLY:
3032       return Tis_constant<gen>(*_POLYptr) && _POLYptr->coord.front().value.is_constant();
3033     default:
3034       return false;
3035     }
3036   }
3037 
is_atomic(const gen & e)3038   bool is_atomic(const gen & e){
3039     return e.type<_POLY || e.type==_FLOAT_ || e.type==_USER;
3040   }
3041 
giac_conj(const gen & g,GIAC_CONTEXT)3042   static gen giac_conj(const gen & g,GIAC_CONTEXT){
3043     return conj(g,contextptr);
3044   }
3045 
giac_re(const gen & g,GIAC_CONTEXT)3046   static gen giac_re(const gen & g,GIAC_CONTEXT){
3047     return re(g,contextptr);
3048   }
3049 
giac_im(const gen & g,GIAC_CONTEXT)3050   static gen giac_im(const gen & g,GIAC_CONTEXT){
3051     return im(g,contextptr);
3052   }
3053 
_VECTconj(const vecteur & a,GIAC_CONTEXT)3054   static vecteur _VECTconj(const vecteur & a,GIAC_CONTEXT){
3055     vecteur res;
3056     vecteur::const_iterator it=a.begin(),itend=a.end();
3057     for (;it!=itend;++it)
3058       res.push_back(it->conj(contextptr));
3059     return res;
3060   }
3061 
3062   // the complex pointed by res is modified despite being declared const
adjust_complex_display(const gen & res,const gen & a,const gen & b)3063   static gen adjust_complex_display(const gen & res,const gen & a,const gen & b){
3064     int * target = complex_display_ptr(res);
3065     int * aptr = complex_display_ptr(a);
3066     int * bptr = complex_display_ptr(b);
3067     if (target && aptr && bptr)
3068       *target = *aptr & *bptr;
3069     return res;
3070   }
3071 
3072   // the complex pointed by res is modified despite being declared const
adjust_complex_display(const gen & res,const gen & a)3073   static gen adjust_complex_display(const gen & res,const gen & a){
3074     int * target = complex_display_ptr(res);
3075     int * aptr = complex_display_ptr(a);
3076     if (target && aptr)
3077       *target = *aptr ;
3078     return res;
3079   }
3080 
3081   // change complex display type (in-place, true if changed, false otherwise)
3082   // modifies complex, vecteur and symbolics
adjust_complex_display(gen & res,int value)3083   int adjust_complex_display(gen & res,int value){
3084     if (res.type==_CPLX){
3085       if (value==3)
3086 	return 1;
3087       res=gen(*res._CPLXptr,*(res._CPLXptr+1));
3088       int * target = complex_display_ptr(res);
3089       if (value==2)
3090 	*target = 1 - (*target);
3091       else
3092 	* target = value;
3093       return 1;
3094     }
3095     if (res.type==_VECT){
3096       vecteur v(*res._VECTptr);
3097       int n=int(v.size());
3098       int r=0;
3099       for (int i=0;i<n;++i){
3100         r += adjust_complex_display(v[i],value);
3101       }
3102       if (!r || value==3)
3103 	return r;
3104       res = gen(v,res.subtype);
3105       return r;
3106     }
3107     if (res.type!=_SYMB)
3108       return 0;
3109     gen f=res._SYMBptr->feuille;
3110     int r=adjust_complex_display(f,value);
3111     if (!r || value==3)
3112       return r;
3113     res=symbolic(res._SYMBptr->sommet,f);
3114     return r;
3115   }
3116 
conj(GIAC_CONTEXT) const3117   gen gen::conj(GIAC_CONTEXT) const {
3118     switch (type ) {
3119     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3120       return *this;
3121     case _CPLX:
3122       return adjust_complex_display(gen(*_CPLXptr,-(*(_CPLXptr+1))),*this);
3123     case _VECT:
3124       return gen(_VECTconj(*_VECTptr,contextptr),subtype);
3125     case _MAP:
3126       return apply(*this,giac_conj,contextptr);
3127     case _USER:
3128       return _USERptr->conj(contextptr);
3129     case _IDNT:
3130       if (is_assumed_real(*this,contextptr))
3131 	return *this;
3132       /* if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(),contextptr)) )
3133 	 return *this; */
3134       return new_ref_symbolic(symbolic(at_conj,*this));
3135     case _SYMB:
3136       if (_SYMBptr->sommet==at_conj)
3137 	return _SYMBptr->feuille;
3138       if (_SYMBptr->sommet==at_re || _SYMBptr->sommet==at_im)
3139 	return *this;
3140       if (_SYMBptr->sommet==at_polar_complex && _SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
3141 	vecteur v=*_SYMBptr->feuille._VECTptr;
3142 	v[1]=-v[1];
3143 	return symbolic(at_polar_complex,gen(v,_SEQ__VECT));
3144       }
3145       if (_SYMBptr->sommet==at_rootof){
3146 	gen a;
3147 	if (has_evalf(*this,a,1,contextptr) && is_zero(a.im(contextptr),contextptr))
3148 	  return *this;
3149 	if (_SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
3150 	  vecteur tmp=*_SYMBptr->feuille._VECTptr;
3151 	  if (lidnt(tmp[1]).empty()){
3152 	    vecteur w=*tmp[1]._VECTptr;
3153 	    gen P;
3154 	    if (conj_in_nf(w,P,contextptr)){
3155 	      // P is a rootof such that conj(rootof(w))=P
3156 	      gen c=horner(tmp[0].conj(contextptr),P);
3157 	      c=normal(c,contextptr);
3158 	      return c;
3159 	    }
3160 	  }
3161 	}
3162       }
3163       if (equalposcomp(plot_sommets,_SYMBptr->sommet) || equalposcomp(analytic_sommets,_SYMBptr->sommet) || _SYMBptr->sommet==at_surd || _SYMBptr->sommet==at_erf)
3164 	return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.conj(contextptr)));
3165       else
3166 	return new_ref_symbolic(symbolic(at_conj,*this));
3167     case _FRAC:
3168       return fraction(_FRACptr->num.conj(contextptr),_FRACptr->den.conj(contextptr));
3169     case _MOD:
3170       return makemod(_MODptr->conj(contextptr),*(_MODptr+1));
3171     case _EXT:
3172       return algebraic_EXTension(_EXTptr->conj(contextptr),*(_EXTptr+1));
3173     default:
3174       return gentypeerr(gettext("Conj"));
3175     }
3176     return 0;
3177   }
3178 
_VECTre(const vecteur & a,GIAC_CONTEXT)3179   static vecteur _VECTre(const vecteur & a,GIAC_CONTEXT){
3180     vecteur res;
3181     vecteur::const_iterator it=a.begin(),itend=a.end();
3182     for (;it!=itend;++it)
3183       res.push_back(it->re(contextptr));
3184     return res;
3185   }
3186 
pascal_next_line(const vecteur & v)3187   vecteur pascal_next_line(const vecteur & v){
3188     if (v.empty())
3189       return vecteur(1,plus_one);
3190     const_iterateur it=v.begin(),itend=v.end();
3191     gen current(*it);
3192     vecteur w;
3193     w.reserve(itend-it+1);
3194     w.push_back(current);
3195     for (++it;it!=itend;++it){
3196       w.push_back(*it+current);
3197       current=*it;
3198     }
3199     w.push_back(plus_one);
3200     return w;
3201   }
3202 
pascal_nth_line(int n)3203   vecteur pascal_nth_line(int n){
3204     n=absint(n);
3205     vecteur v(1,plus_one);
3206     for (int i=0;i<n;++i)
3207       v=pascal_next_line(v);
3208     return v;
3209   }
3210 
algtrim(const gen & g)3211   static gen algtrim(const gen & g){
3212     if (g.type!=_VECT)
3213       return g;
3214     vecteur tmp=trim(*g._VECTptr,0);
3215     if (tmp.empty())
3216       return zero;
3217     if (tmp.size()==1)
3218       return tmp.front();
3219     return tmp;
3220   }
3221 
symb_reim(const symbolic & s,gen & r,gen & i,GIAC_CONTEXT)3222   static void symb_reim(const symbolic & s,gen & r,gen & i,GIAC_CONTEXT){
3223     unary_function_ptr u=s.sommet;
3224     gen f=s.feuille;
3225     if ( (u==at_re) || (u==at_im) || (u==at_abs) || (u==at_surd) || (u==at_NTHROOT) || (u==at_innertln)){
3226       r=s;
3227       i=0;
3228       return;
3229     }
3230     if (u==at_conj){
3231       reim(f,r,i,contextptr);
3232       i=-i;
3233       return;
3234     }
3235     if (u==at_plus){
3236       reim(f,r,i,contextptr);
3237       r=_plus(r,contextptr);
3238       i=_plus(i,contextptr);
3239       return;
3240     }
3241     if (u==at_neg){
3242       reim(f,r,i,contextptr);
3243       r=-r;
3244       i=-i;
3245       return;
3246     }
3247     if (u==at_polar_complex && f.type==_VECT && f._VECTptr->size()==2){
3248       i=f._VECTptr->back();
3249       f=f._VECTptr->front();
3250       r=f*cos(i,contextptr);
3251       i=f*sin(i,contextptr);
3252       return;
3253     }
3254     if (u==at_division){
3255       reim(f[0]*inv(f[1],contextptr),r,i,contextptr);
3256       return ;
3257     }
3258     if (u==at_sqrt){
3259       reim(pow(f,plus_one_half,contextptr),r,i,contextptr);
3260       return;
3261     }
3262     if (u==at_prod){
3263       if (f.type!=_VECT){
3264 	reim(f,r,i,contextptr);
3265 	return;
3266       }
3267       vecteur v(*f._VECTptr);
3268       if (v.empty()){
3269 	r=plus_one;
3270 	i=0;
3271 	return;
3272       }
3273       if (v.size()==1){
3274 	reim(v.front(),r,i,contextptr);
3275 	return;
3276       }
3277       // cut v in 2 parts and recursive call
3278       // re(a*b)=re(a)*re(b)-im(a)*im(b)
3279       const_iterateur it=v.begin(),itend=v.end();
3280       const_iterateur itm=it+(itend-it+1)/2;
3281       gen a(new_ref_symbolic(symbolic(u,vecteur(it,itm))));
3282       gen b(new_ref_symbolic(symbolic(u,vecteur(itm,itend))));
3283       gen ra,rb,ia,ib;
3284       reim(a,ra,ia,contextptr);
3285       reim(b,rb,ib,contextptr);
3286       r=ra*rb-ia*ib;
3287       i=ra*ib+ia*rb;
3288       return;
3289     }
3290     if (u==at_surd && is_integer(f._VECTptr->back())){
3291       reim(f._VECTptr->front(),r,i,contextptr);
3292       if (is_zero(i,contextptr)){
3293 	r=_surd(makesequence(r,f._VECTptr->back()),contextptr);
3294 	return;
3295       }
3296     }
3297     if (u==at_derive && f.type==_VECT && !f._VECTptr->empty()){
3298       vecteur v=*f._VECTptr;
3299       reim(v.front(),r,i,contextptr);
3300       v.front()=r;
3301       r=symbolic(at_derive,gen(v,f.subtype));
3302       if (is_zero(i))
3303 	return;
3304       v.front()=i;
3305       i=symbolic(at_derive,gen(v,f.subtype));
3306       return;
3307     }
3308     if (u==at_pow){
3309       gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3310       if (expo.type==_INT_){
3311 	int n=expo.val;
3312 	if (n==0){
3313 	  r=1;
3314 	  i=0;
3315 	  return;
3316 	}
3317 	reim(e,r,i,contextptr);
3318 	if (n==1)
3319 	  return ;
3320 	if (is_zero(i,contextptr)){
3321 	  r=pow(r,n);
3322 	  return;
3323 	}
3324 	if (is_zero(r,contextptr)){
3325 	  if (n%2){
3326 	    r=zero;
3327 	    i=pow(i,n);
3328 	    if (n%4==3)
3329 	      i=-i;
3330 	    return;
3331 	  }
3332 	  r=pow(i,n);
3333 	  i=0;
3334 	  if (n%4==2)
3335 	    r=-r;
3336 	  return;
3337 	}
3338 	bool n_pos=(n>0);
3339 	if (!n_pos){
3340 	  reim(inv(pow(e,-n),contextptr),r,i,contextptr);
3341 	  return;
3342 	}
3343 	vecteur v=pascal_nth_line(n);
3344 	vecteur sommer,sommei;
3345 	gen signer=1;
3346 	const_iterateur it=v.begin();
3347 	for (int j=0;j<=n;j+=2){
3348 	  sommer.push_back(signer*(*it)*pow(r,n-j)*pow(i,j));
3349 	  ++it;
3350 	  ++it;
3351 	  signer=-signer;
3352 	}
3353 	it=v.begin();
3354 	gen signei=1;
3355 	++it;
3356 	for (int j=1;j<=n;j+=2){
3357 	  sommei.push_back(signei*(*it)*pow(r,n-j)*pow(i,j));
3358 	  ++it;
3359 	  ++it;
3360 	  signei=-signei;
3361 	}
3362 	r=new_ref_symbolic(symbolic(at_plus,sommer));
3363 	i=new_ref_symbolic(symbolic(at_plus,sommei));
3364 	return ;
3365       } // end integer exponent
3366       if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3367 	if (!is_integer(expo) && is_positive(-e,contextptr)){
3368 	  r=pow(-e,expo,contextptr)*cos(cst_pi*expo,contextptr);
3369 	  i=pow(-e,expo,contextptr)*sin(cst_pi*expo,contextptr);
3370 	}
3371 	else {
3372 	  r=s;
3373 	  i=0;
3374 	}
3375 	return;
3376       }
3377       if (is_zero(im(expo,contextptr),contextptr)){
3378 	reim(e,r,i,contextptr);
3379 	gen abse=normal(pow(r,2,contextptr)+pow(i,2,contextptr),contextptr);
3380 	gen arge=arg(e,contextptr);
3381 	arge=expo*arge;
3382 	abse=sqrt(abse,contextptr);
3383 	abse=pow(abse,expo,contextptr);
3384 	r=abse*cos(arge,contextptr);
3385 	i=abse*sin(arge,contextptr);
3386 	return;
3387       }
3388     }
3389     if (u==at_rootof && f.type==_VECT && f._VECTptr->size()==2){
3390       vecteur tmp=*f._VECTptr;
3391       // check that the rootof is really real
3392       if (tmp[1].type==_VECT){
3393 	int nrealposroot=1;
3394 	if (lidnt(tmp[1]).empty()){
3395 	  vecteur w=*tmp[1]._VECTptr;
3396 	  gen pol(symb_horner(w,vx_var));
3397 	  nrealposroot=sturmab(pol,vx_var,0,plus_inf,contextptr);
3398 	  if (nrealposroot==0 && is_zero(im(tmp[1],contextptr))){
3399 	    // complex, perhaps the conjugate is in the same nf
3400 	    gen P;
3401 	    if (conj_in_nf(w,P,contextptr)){
3402 	      // P is a rootof such that conj(rootof(w))=P
3403 	      gen c=horner(conj(tmp[0],contextptr),P);
3404 	      r=normal((s+c)/2,contextptr);
3405 	      i=normal((s-c)/2/cst_i,contextptr);
3406 	      return;
3407 	    }
3408 	  }
3409 	}
3410 	if (nrealposroot>0){
3411 	  reim(tmp[0],r,i,contextptr);
3412 	  r=algtrim(r);
3413 	  if (r.type==_VECT){
3414 	    tmp[0]=r;
3415 	    r=new_ref_symbolic(symbolic(u,gen(tmp,f.subtype)));
3416 	  }
3417 	  i=algtrim(i);
3418 	  if (i.type==_VECT){
3419 	    tmp[0]=i;
3420 	    i=new_ref_symbolic(symbolic(u,gen(tmp,f.subtype)));
3421 	  }
3422 	  return;
3423 	}
3424       }
3425     }
3426     gen ref,imf;
3427     if (u==at_integrate){
3428       if (f.type!=_VECT){
3429 	reim(f,ref,imf,contextptr);
3430 	r=symbolic(at_integrate,ref);
3431 	i=is_exactly_zero(imf)?zero:symbolic(at_integrate,imf);
3432 	return;
3433       }
3434       vecteur v=*f._VECTptr;
3435       if (v.size()<=2 || (v.size()>=4 && is_exactly_zero(im(v[2],contextptr)) && is_exactly_zero(im(v[3],contextptr)))){
3436 	f=v[0];
3437 	reim(f,ref,imf,contextptr);
3438 	v[0]=ref;
3439 	r=is_exactly_zero(ref)?zero:symbolic(at_integrate,gen(v,_SEQ__VECT));
3440 	v[0]=imf;
3441 	i=is_exactly_zero(imf)?zero:symbolic(at_integrate,gen(v,_SEQ__VECT));
3442 	return;
3443       }
3444     }
3445     reim(f,ref,imf,contextptr);
3446     if (is_zero(imf,contextptr) && equalposcomp(reim_op,u)){
3447       r=s; i=0; return;
3448     }
3449     if (u==at_ln){ // FIXME?? might recurse
3450       if (do_lnabs(contextptr)){
3451 	r=ln(abs(f,contextptr),contextptr);
3452 	i=arg(f,contextptr);
3453       }
3454       else {
3455 	r=s; i=0;
3456       }
3457       return ;
3458     }
3459     if (u==at_tan){
3460       reim(rdiv(sin(f,contextptr),cos(f,contextptr),contextptr),r,i,contextptr);
3461       return;
3462     }
3463     if (u==at_tanh){
3464       reim(rdiv(sinh(f,contextptr),cosh(f,contextptr),contextptr),r,i,contextptr);
3465       return;
3466     }
3467     if ((u==at_asin || u==at_acos) && is_zero(imf,contextptr) && is_greater(1,f,contextptr) && is_greater(f,-1,contextptr)){
3468       r=s; i=0; return;
3469     }
3470     if (u==at_inv){
3471       gen tmp=inv(pow(ref,2)+pow(imf,2),contextptr);
3472       r=ref*tmp;
3473       i=-imf*tmp;
3474       return;
3475     }
3476     if (u==at_exp) {
3477       // FIXME?? exp might recurse
3478       r=exp(ref,contextptr)*cos(imf,contextptr);
3479       i=exp(ref,contextptr)*sin(imf,contextptr);
3480       return;
3481     }
3482     if (u==at_cos){
3483       r=cosh(imf,contextptr)*cos(ref,contextptr);
3484       i=-sinh(imf,contextptr)*sin(ref,contextptr);
3485       return;
3486     }
3487     if (u==at_sin){
3488       r=cosh(imf,contextptr)*sin(ref,contextptr);
3489       i=sinh(imf,contextptr)*cos(ref,contextptr);
3490       return;
3491     }
3492     if (u==at_cosh){
3493       r=cos(imf,contextptr)*cosh(ref,contextptr);
3494       i=sin(imf,contextptr)*sinh(ref,contextptr);
3495       return;
3496     }
3497     if (u==at_sinh){
3498       r=cos(imf,contextptr)*sinh(ref,contextptr);
3499       i=sin(imf,contextptr)*cosh(ref,contextptr);
3500       return;
3501     }
3502     if (u==at_floor || u==at_ceil || u==at_round){
3503       r=u(ref,contextptr);
3504       i=u(imf,contextptr);
3505       return;
3506     }
3507     if (u==at_Si && is_zero(imf)){
3508       r=_Si(ref,contextptr); return;
3509     }
3510     if (u==at_Ei && is_zero(imf)){
3511       r=_Ei(ref,contextptr); return;
3512     }
3513     if (u==at_Ci && is_zero(imf) && is_greater(ref,0,contextptr)){
3514       r=_Ci(ref,contextptr); return;
3515     }
3516     if (u==at_erf){ // works for analytic functions
3517       gen conjf=symbolic(u,ref-cst_i*imf);
3518       r=(s+conjf)/2;
3519       i=-cst_i*(s-conjf)/2;
3520       return;
3521     }
3522     r=new_ref_symbolic(symbolic(at_re,gen(s)));
3523     i=new_ref_symbolic(symbolic(at_im,gen(s)));
3524   }
3525 
reim_poly(const polynome & p,gen & r,gen & i,GIAC_CONTEXT)3526   static void reim_poly(const polynome & p,gen & r,gen & i,GIAC_CONTEXT){
3527     polynome R(p.dim),I(p.dim);
3528     vector< monomial<gen> >::const_iterator it=p.coord.begin(),itend=p.coord.end();
3529     for (;it!=itend;++it){
3530       reim(it->value,r,i,contextptr);
3531       if (!is_zero(r,contextptr))
3532 	R.coord.push_back(monomial<gen>(r,it->index));
3533       if (!is_zero(i,contextptr))
3534 	I.coord.push_back(monomial<gen>(i,it->index));
3535     }
3536     r=R;
3537     i=I;
3538   }
3539 
reim_vect(const vecteur & v,gen & r,gen & i,int subtype,GIAC_CONTEXT)3540   static void reim_vect(const vecteur & v,gen & r,gen & i,int subtype,GIAC_CONTEXT){
3541     const_iterateur it=v.begin(),itend=v.end();
3542     vecteur R,I;
3543     R.reserve(itend-it);
3544     I.reserve(itend-it);
3545     for (;it!=itend;++it){
3546       reim(*it,r,i,contextptr);
3547       R.push_back(r);
3548       I.push_back(i);
3549     }
3550     if (subtype==_POLY1__VECT){
3551       R=trim(R,0);
3552       I=trim(I,0);
3553     }
3554     r=gen(R,subtype);
3555     i=gen(I,subtype);
3556   }
3557 
reim_spol(const sparse_poly1 & p,gen & r,gen & i,GIAC_CONTEXT)3558   static void reim_spol(const sparse_poly1 & p,gen & r,gen & i,GIAC_CONTEXT){
3559     sparse_poly1 R,I;
3560     sparse_poly1::const_iterator it=p.begin(),itend=p.end();
3561     for (;it!=itend;++it){
3562       reim(it->coeff,r,i,contextptr);
3563       if (!is_zero(r,contextptr))
3564 	R.push_back(monome(r,it->exponent));
3565       if (!is_zero(i,contextptr))
3566 	I.push_back(monome(i,it->exponent));
3567     }
3568     r=R;
3569     i=I;
3570   }
3571 
frac_reim(const gen & n,const gen & d,bool findre,GIAC_CONTEXT)3572   static gen frac_reim(const gen & n,const gen & d,bool findre,GIAC_CONTEXT){
3573     gen dbar(conj(d,contextptr)),tmp(n*dbar);
3574     tmp=findre?re(tmp,contextptr):im(tmp,contextptr);
3575     return tmp/(d*dbar);
3576   }
3577 
3578   // compute simultaneously real and imaginary part
reim(const gen & g,gen & r,gen & i,GIAC_CONTEXT)3579   void reim(const gen & g,gen & r,gen & i,GIAC_CONTEXT){
3580     switch (g.type ) {
3581     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3582       r=g;
3583       i=0;
3584       break;
3585     case _CPLX:
3586       r=*g._CPLXptr;
3587       i=*(g._CPLXptr+1);
3588       break;
3589     case _VECT:
3590       reim_vect(*g._VECTptr,r,i,g.subtype,contextptr);
3591       break;
3592     case _IDNT:
3593       if (is_assumed_real(g,contextptr)){
3594 	r=g;
3595 	i=0;
3596       }
3597       else {
3598 	r=new_ref_symbolic(symbolic(at_re,g));
3599 	i=new_ref_symbolic(symbolic(at_im,g));
3600       }
3601       break;
3602     case _SYMB:
3603       if (equalposcomp(plot_sommets,g._SYMBptr->sommet)){
3604 	reim(g._SYMBptr->feuille,r,i,contextptr);
3605 	r=new_ref_symbolic(symbolic(g._SYMBptr->sommet,r));
3606 	i=new_ref_symbolic(symbolic(g._SYMBptr->sommet,i));
3607       }
3608       else {
3609 	if (expand_re_im(contextptr))
3610 	  symb_reim(*g._SYMBptr,r,i,contextptr);
3611 	else {
3612 	  r=new_ref_symbolic(symbolic(at_re,g));
3613 	  i=new_ref_symbolic(symbolic(at_im,g));
3614 	}
3615       }
3616       break;
3617     case _USER:
3618       r=g._USERptr->re(contextptr);
3619       i=g._USERptr->im(contextptr);
3620       break;
3621     case _FRAC:
3622       r=frac_reim(g._FRACptr->num,g._FRACptr->den,true,contextptr);
3623       i=frac_reim(g._FRACptr->num,g._FRACptr->den,false,contextptr);
3624       break;
3625     case _MOD:
3626       reim(*g._MODptr,r,i,contextptr);
3627       r=makemod(r,*(g._MODptr+1));
3628       i=makemod(i,*(g._MODptr+1));
3629       break;
3630     case _EXT:
3631       reim(*g._EXTptr,r,i,contextptr);
3632       r=algebraic_EXTension(r,*(g._EXTptr+1));
3633       i=algebraic_EXTension(i,*(g._EXTptr+1));
3634       break;
3635     case _POLY:
3636       reim_poly(*g._POLYptr,r,i,contextptr);
3637       break;
3638     case _SPOL1:
3639       reim_spol(*g._SPOL1ptr,r,i,contextptr);
3640       break;
3641     default:
3642       r=gentypeerr(gettext("reim"));
3643       i=r;
3644     }
3645   }
3646 
symb_re(const symbolic & s,GIAC_CONTEXT)3647   static gen symb_re(const symbolic & s,GIAC_CONTEXT){
3648     unary_function_ptr u=s.sommet;
3649     gen f=s.feuille;
3650     if ( (u==at_re) || (u==at_im) || (u==at_abs) )// re(re), re(im), re(abs)
3651       return s;
3652     if (u==at_conj)
3653       return re(f,contextptr);
3654     if (u==at_plus)
3655       return _plus(re(f,contextptr),contextptr);
3656     if (u==at_neg)
3657       return -re(f,contextptr);
3658     if (u==at_pow){
3659       gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3660       if (expo.type==_INT_){
3661 	int n=expo.val;
3662 	if (n==0)
3663 	  return plus_one;
3664 	// ? compute conj and use 1/2*(z+-zbar)?
3665 	gen r=re(e,contextptr);
3666 	if (n==1)
3667 	  return r;
3668 	gen i=im(e,contextptr);
3669 	if (n==2)
3670 	  return pow(r,2)-pow(i,2);
3671 	if (is_zero(i,contextptr))
3672 	  return pow(r,n);
3673 	if (is_zero(r,contextptr)){
3674 	  if (n%2)
3675 	    return zero;
3676 	  if (n%4==2)
3677 	    return -pow(i,n);
3678 	  else
3679 	    return pow(i,n);
3680 	}
3681 	bool n_pos=(n>0);
3682 	if (!n_pos)
3683 	  return re(inv(pow(e,-n),contextptr),contextptr);
3684 	vecteur v=pascal_nth_line(n);
3685 	vecteur somme;
3686 	gen signe=plus_one;
3687 	const_iterateur it=v.begin(); //,itend=v.end();
3688 	for (int j=0;j<=n;j+=2){
3689 	  somme.push_back(signe*(*it)*pow(r,n-j)*pow(i,j));
3690 	  ++it;
3691 	  ++it;
3692 	  signe=-signe;
3693 	}
3694 	gen res=new_ref_symbolic(symbolic(at_plus,somme));
3695 	return res;
3696       } // end integer exponent
3697       if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3698 	gen sgn=atan_tan_no_floor(contextptr)?1:sign(e,contextptr); // workaround for int(sqrt(x+sqrt(x)))
3699 	if (!is_integer(expo)){
3700 	  if (sgn==-1)
3701 	    return pow(-e,expo,contextptr)*cos(cst_pi*expo,contextptr);
3702 	  if (sgn!=1)
3703 	    return symbolic(at_re,s);
3704 	}
3705 	return s;
3706       }
3707     }
3708     if (u==at_ln) // FIXME?? might recurse
3709       return ln(abs(f,contextptr),contextptr);
3710     gen r,i;
3711     symb_reim(s,r,i,contextptr);
3712     return r;
3713   }
3714 
no_context_re(const gen & a)3715   gen no_context_re(const gen & a){
3716     return re(a,context0);
3717   }
3718 
no_context_im(const gen & a)3719   gen no_context_im(const gen & a){
3720     return im(a,context0);
3721   }
3722 
no_context_conj(const gen & a)3723   gen no_context_conj(const gen & a){
3724     return conj(a,context0);
3725   }
3726 
re(GIAC_CONTEXT) const3727   gen gen::re(GIAC_CONTEXT) const {
3728     switch (type ) {
3729     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3730       return *this;
3731     case _CPLX:
3732       return *_CPLXptr;
3733     case _VECT:
3734       return gen(subtype==_POLY1__VECT?trim(_VECTre(*_VECTptr,contextptr),0):_VECTre(*_VECTptr,contextptr),subtype);
3735     case _MAP:
3736       return apply(*this,giac_re,contextptr);
3737     case _IDNT:
3738       if (is_assumed_real(*this,contextptr))
3739 	return *this;
3740       if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(contextptr),contextptr)) )
3741 	return *this;
3742       return new_ref_symbolic(symbolic(at_re,*this));
3743     case _SYMB:
3744       if (equalposcomp(plot_sommets,_SYMBptr->sommet))
3745 	return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.re(contextptr)));
3746       if (expand_re_im(contextptr))
3747 	return symb_re(*_SYMBptr,contextptr);
3748       else
3749 	return new_ref_symbolic(symbolic(at_re,*this));
3750     case _USER:
3751       return _USERptr->re(contextptr);
3752     case _FRAC:
3753       return frac_reim(_FRACptr->num,_FRACptr->den,true,contextptr);
3754     case _MOD:
3755       return makemod(_MODptr->re(contextptr),*(_MODptr+1));
3756     case _EXT:
3757       return algebraic_EXTension(_EXTptr->re(contextptr),*(_EXTptr+1));
3758     case _POLY:
3759       return apply(*_POLYptr,contextptr,giac_re);
3760     default:
3761       return gentypeerr(gettext("Re"));
3762     }
3763     return 0;
3764   }
3765 
_VECTim(const vecteur & a,GIAC_CONTEXT)3766   static vecteur _VECTim(const vecteur & a,GIAC_CONTEXT){
3767     vecteur res;
3768     vecteur::const_iterator it=a.begin(),itend=a.end();
3769     for (;it!=itend;++it)
3770       res.push_back(it->im(contextptr));
3771     return res;
3772   }
3773 
symb_im(const symbolic & s,GIAC_CONTEXT)3774   static gen symb_im(const symbolic & s,GIAC_CONTEXT){
3775     unary_function_ptr u=s.sommet;
3776     gen f=s.feuille;
3777     if ( (u==at_re) || (u==at_im) || (u==at_abs) )// im of a real
3778       return zero;
3779     if (u==at_conj)
3780       return -im(f,contextptr);
3781     if (u==at_plus)
3782       return _plus(im(f,contextptr),contextptr);
3783     if (u==at_neg)
3784       return -im(f,contextptr);
3785     if (u==at_pow){
3786       gen e=f._VECTptr->front(),expo=f._VECTptr->back();
3787       if (expo.type==_INT_) {
3788 	// ? compute conj and use 1/2*(z+-zbar)?
3789 	gen r=re(e,contextptr);
3790 	gen i=im(e,contextptr);
3791 	int n=f._VECTptr->back().val;
3792 	if (n==0)
3793 	  return zero;
3794 	if (is_zero(i,contextptr))
3795 	  return zero;
3796 	if (is_zero(r,contextptr)){
3797 	  if (n%2==0)
3798 	    return zero;
3799 	  if (n%4==1)
3800 	    return pow(i,n);
3801 	  else
3802 	    return -pow(i,n);
3803 	}
3804 	bool n_pos=(n>0);
3805 	if (!n_pos)
3806 	  return im(inv(pow(e,-n),contextptr),contextptr);
3807 	vecteur v=pascal_nth_line(n);
3808 	vecteur somme;
3809 	gen signe=plus_one;
3810 	const_iterateur it=v.begin(); // ,itend=v.end();
3811 	++it;
3812 	for (int j=1;j<=n;j+=2){
3813 	  somme.push_back(signe*(*it)*pow(r,n-j)*pow(i,j));
3814 	  ++it;
3815 	  ++it;
3816 	  signe=-signe;
3817 	}
3818 	gen res=new_ref_symbolic(symbolic(at_plus,somme));
3819 	return res;
3820       } // end integer exponent
3821       if ( is_zero(im(expo,contextptr),contextptr) && is_zero(im(e,contextptr),contextptr) ){
3822 	// e must also be positive for non-integral power
3823 	if (!is_integer(expo)){
3824 	  gen sgn=atan_tan_no_floor(contextptr)?1:sign(e,contextptr); // workaround for int(sqrt(x+sqrt(x)))
3825 	  if (sgn==-1)
3826 	    return pow(-e,expo,contextptr)*sin(cst_pi*expo,contextptr);
3827 	  if (sgn!=1)
3828 	    return symbolic(at_im,s);
3829 	}
3830 	return zero;
3831       }
3832     }
3833     if (u==at_ln)
3834       return arg(f,contextptr);
3835     gen r,i;
3836     symb_reim(s,r,i,contextptr);
3837     return i;
3838   }
3839 
im(GIAC_CONTEXT) const3840   gen gen::im(GIAC_CONTEXT) const {
3841     switch (type) {
3842     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL: case _STRNG:
3843       return 0;
3844     case _CPLX:
3845       return *(_CPLXptr+1);
3846     case _VECT:
3847       return gen(subtype==_POLY1__VECT?trim(_VECTim(*_VECTptr,contextptr),0):_VECTim(*_VECTptr,contextptr),subtype);
3848     case _MAP:
3849       return apply(*this,giac_im,contextptr);
3850     case _IDNT:
3851       if (is_inf(*this) || is_undef(*this))
3852 	return undef;
3853       if (is_assumed_real(*this,contextptr))
3854 	return zero;
3855       if ( (_IDNTptr->value) && (is_zero(_IDNTptr->value->im(contextptr),contextptr)) )
3856 	return zero;
3857       return new_ref_symbolic(symbolic(at_im,*this));
3858     case _SYMB:
3859       if (equalposcomp(plot_sommets,_SYMBptr->sommet))
3860 	return new_ref_symbolic(symbolic(_SYMBptr->sommet,_SYMBptr->feuille.im(contextptr)));
3861       if (expand_re_im(contextptr))
3862 	return symb_im(*_SYMBptr,contextptr);
3863       else
3864 	return new_ref_symbolic(symbolic(at_im,*this));
3865     case _USER:
3866       return _USERptr->im(contextptr);
3867     case _FRAC:
3868       return frac_reim(_FRACptr->num,_FRACptr->den,false,contextptr);
3869     case _MOD:
3870       return makemod(_MODptr->im(contextptr),*(_MODptr+1));
3871     case _EXT:
3872       return algebraic_EXTension(_EXTptr->im(contextptr),*(_EXTptr+1));
3873     case _POLY:
3874       return apply(*_POLYptr,contextptr,giac_im);
3875     default:
3876       return gentypeerr(gettext("Im"));
3877     }
3878     return 0;
3879   }
3880 
_VECTabs(const vecteur & a,GIAC_CONTEXT)3881   static gen _VECTabs(const vecteur & a,GIAC_CONTEXT){
3882     gen res(0);
3883     vecteur::const_iterator it=a.begin(), itend=a.end();
3884     for (;it!=itend;++it){
3885       res=max(res,abs(*it,contextptr),contextptr);
3886     }
3887     return res;
3888   }
3889 
real_abs(const gen & s,GIAC_CONTEXT)3890   static gen real_abs(const gen & s,GIAC_CONTEXT){
3891     gen tmp=evalf_double(s,1,contextptr);
3892     if (tmp.type==_DOUBLE_){
3893       if (tmp._DOUBLE_val>epsilon(contextptr))
3894 	return s;
3895       if (tmp._DOUBLE_val<-epsilon(contextptr))
3896 	return -s;
3897       if (has_num_coeff(s))
3898 	return 0.0;
3899       else {
3900 #ifdef HAVE_LIBMPFR
3901 	tmp=accurate_evalf(s,ABS_NBITS_EVALF+10)*pow(2,ABS_NBITS_EVALF,contextptr);
3902 	if (!is_greater(1,abs(tmp,contextptr),contextptr)){
3903 	  if (is_positive(tmp,contextptr))
3904 	    return s;
3905 	  return -s;
3906 	}
3907 #else
3908 	return 0;
3909 #endif
3910       }
3911     }
3912     if (tmp.type==_FLOAT_){
3913       if (tmp._FLOAT_val>epsilon(contextptr))
3914 	return s;
3915       if (tmp._FLOAT_val<-epsilon(contextptr))
3916 	return -s;
3917       return 0.0;
3918     }
3919     int j=sturmsign(s,false,contextptr);
3920     if (!j || j==-2)
3921       return new_ref_symbolic(symbolic(at_abs,gen(s)));
3922     return j*s;
3923   }
3924 
idnt_abs(const gen & s,GIAC_CONTEXT)3925   static gen idnt_abs(const gen & s,GIAC_CONTEXT){
3926     if (is_inf(s))
3927       return plus_inf;
3928     if (is_undef(s))
3929       return s;
3930     if (!eval_abs(contextptr) || has_num_coeff(s))
3931       return new_ref_symbolic(symbolic(at_abs,s));
3932     gen r,i;
3933     reim(s,r,i,contextptr);
3934     if (is_zero(i,contextptr))
3935       return real_abs(s,contextptr);
3936     else {
3937       if (i.type==_SYMB && i._SYMBptr->sommet==at_im && !lop(r,at_re).empty())
3938 	return new_ref_symbolic(symbolic(at_abs,s));
3939       gen r2i2=pow(r,2)+pow(i,2);
3940       if (has_op(r2i2,*at_cos) || has_op(r2i2,*at_sin)){
3941 	r2i2=_tlin(r2i2,contextptr); // _tcollect?
3942 	vecteur l=lvar(r2i2);
3943 	unsigned count=0;
3944 	for (unsigned i=0;i<l.size();++i){
3945 	  if (l[i].is_symb_of_sommet(at_sin) || l[i].is_symb_of_sommet(at_cos))
3946 	    ++count;
3947 	}
3948 	if (count>=2)
3949 	  r2i2=_tcollect(r2i2,contextptr);
3950       }
3951       return sqrt(r2i2,contextptr);
3952     }
3953   }
3954 
symb_abs(const symbolic & s,GIAC_CONTEXT)3955   static gen symb_abs(const symbolic & s,GIAC_CONTEXT){
3956     unary_function_ptr u=s.sommet;
3957     gen f=s.feuille;
3958     if (u==at_abs) // abs(abs)
3959       return s;
3960     if (u==at_neg)
3961       return abs(f,contextptr);
3962     if (!complex_mode(contextptr)){
3963       if (u==at_ln)
3964 	return real_abs(s,contextptr);
3965       if (!has_i(s)){
3966 	if (u==at_exp || ( (u==at_sqrt && is_positive(f,contextptr)) || (u==at_pow && f[1]==plus_one_half && is_positive(f[0],contextptr)) ) )
3967 	  return s;
3968 	// if (calc_mode(contextptr)==1 && u==at_pow && f.type==_VECT && f._VECTptr->size()==2 && f._VECTptr->back()==plus_one_half && is_positive(f[0],contextptr)) return s;
3969       }
3970     }
3971     else {
3972       if (do_lnabs(contextptr) && u==at_ln)
3973 	return new_ref_symbolic(symbolic(at_abs,s));
3974       if (u==at_exp)
3975 	return exp(re(f,contextptr),contextptr);
3976     }
3977     if ( (u==at_pow) && (is_zero(im(f._VECTptr->back(),contextptr),contextptr))){
3978       gen fback=f._VECTptr->back();
3979       if (fback.type==_INT_ && (fback.val % 2==0))
3980 	return pow(abs(f._VECTptr->front(),contextptr),fback,contextptr);
3981       return new_ref_symbolic(symbolic(u,makesequence(abs(f._VECTptr->front(),contextptr),f._VECTptr->back())));
3982     }
3983     if (u==at_inv)
3984       return inv(abs(f,contextptr),contextptr);
3985     if (u==at_prod)
3986       return new_ref_symbolic(symbolic(u,apply(f,contextptr,abs)));
3987     return idnt_abs(s,contextptr);
3988   }
3989 
abs(const gen & a,GIAC_CONTEXT)3990   gen abs(const gen & a,GIAC_CONTEXT){
3991     switch (a.type ) {
3992     case _INT_:
3993       return(absint(a.val));
3994     case _ZINT:
3995       if (mpz_sgn(*a._ZINTptr)<0)
3996 	return(-a);
3997       else
3998 	return(a);
3999     case _REAL:
4000       return a._REALptr->abs();
4001     case _CPLX:
4002 #ifdef GIAC_HAS_STO_38
4003       {
4004         if (a._CPLXptr->type==_FLOAT_ && (a._CPLXptr+1)->type==_FLOAT_)
4005         {
4006           HP_gen r;
4007           cAbs_g(gen2HP(*a._CPLXptr), gen2HP(*(a._CPLXptr+1)), &r);
4008           return HP2gen(r);
4009         }
4010         return sqrt(sq(*a._CPLXptr)+sq(*(a._CPLXptr+1)),contextptr) ;
4011       }
4012 #else
4013       if (a.subtype==3){
4014 	gen * aptr=a._CPLXptr;
4015 	double ar=aptr->_DOUBLE_val,ai=(aptr+1)->_DOUBLE_val;
4016 	return gen(std::sqrt(ar*ar+ai*ai));
4017       }
4018       return sqrt(sq(*a._CPLXptr)+sq(*(a._CPLXptr+1)),contextptr) ;
4019 #endif
4020     case _DOUBLE_:
4021       return fabs(a._DOUBLE_val);
4022     case _FLOAT_:
4023       return fabs(a._FLOAT_val);
4024     case _VECT:
4025       if (a.subtype==_POINT__VECT || a.subtype==_GGBVECT)
4026 	return _l2norm(a,contextptr);
4027       return _VECTabs(*a._VECTptr,contextptr);
4028     case _IDNT:
4029       return idnt_abs(a,contextptr);
4030     case _SYMB:
4031       if (is_equal(a))
4032 	return apply_to_equal(a,abs,contextptr);
4033       if (a.is_symb_of_sommet(at_pnt)){
4034 	if (is3d(a))
4035 	  return _l2norm(_coordonnees(a,contextptr),contextptr);
4036 	return abs(_affixe(a,contextptr),contextptr);
4037       }
4038       return symb_abs(*a._SYMBptr,contextptr);
4039     case _USER:
4040       return a._USERptr->abs(contextptr);
4041     case _FRAC:
4042       if (is_integer(a._FRACptr->num) && is_integer(a._FRACptr->den))
4043 	return fraction(abs(a._FRACptr->num,contextptr),abs(a._FRACptr->den,contextptr));
4044       return rdiv(abs(a._FRACptr->num,contextptr),abs(a._FRACptr->den,contextptr),contextptr);
4045     default:
4046       return gentypeerr(gettext("Abs"));
4047     }
4048     return 0;
4049   }
4050 
linfnorm(const gen & a,GIAC_CONTEXT)4051   gen linfnorm(const gen & a,GIAC_CONTEXT){ // L^inf norm is |re|+|im| for a complex
4052     switch (a.type ) {
4053     case _INT_:
4054       return(absint(a.val));
4055     case _ZINT:
4056       if (mpz_sgn(*a._ZINTptr)<0)
4057 	return(-a);
4058       else
4059 	return(a);
4060     case _CPLX:
4061       return(abs(*a._CPLXptr,contextptr)+abs(*(a._CPLXptr+1),contextptr)) ;
4062     case _DOUBLE_:
4063       return fabs(a._DOUBLE_val);
4064     case _FLOAT_:
4065       return fabs(a._FLOAT_val);
4066     case _FRAC:
4067       return linfnorm(a._FRACptr->num)/linfnorm(a._FRACptr->den);
4068     case _VECT:
4069       return _VECTabs(*a._VECTptr,contextptr);
4070     case _USER:
4071       return a._USERptr->abs(contextptr);
4072     case _IDNT: case _SYMB:
4073       return new_ref_symbolic(symbolic(at_abs,a));
4074     default:
4075       return gentypeerr(gettext("Linfnorm"));
4076     }
4077     return 0;
4078   }
4079 
4080   // workaround for intervals
is_zero_or_contains(const gen & g,GIAC_CONTEXT)4081   static bool is_zero_or_contains(const gen & g,GIAC_CONTEXT){
4082 #ifdef NO_RTTI
4083     return is_zero(g,contextptr);
4084 #else
4085     if (is_zero(g,contextptr))
4086       return true;
4087     if (g.type!=_REAL)
4088       return false;
4089     if (real_interval * ptr=dynamic_cast<real_interval *>(g._REALptr))
4090       return ptr->maybe_zero();
4091     return false;
4092 #endif
4093   }
4094 
arg_CPLX(const gen & a,GIAC_CONTEXT)4095   gen arg_CPLX(const gen & a,GIAC_CONTEXT){
4096     gen realpart=normal(a.re(contextptr),contextptr),
4097       imagpart=normal(a.im(contextptr),contextptr);
4098     if (realpart.type==_FLOAT_ && imagpart.type==_FLOAT_){
4099 #ifdef GIAC_HAS_STO_38
4100       //grad
4101       return atan2f(realpart._FLOAT_val,imagpart._FLOAT_val,angle_mode(contextptr));
4102 #else
4103       return atan2f(realpart._FLOAT_val,imagpart._FLOAT_val,angle_radian(contextptr));
4104 #endif
4105     }
4106     if (is_zero_or_contains(realpart,contextptr)){
4107       if (is_zero_or_contains(imagpart,contextptr))
4108 	return undef;
4109       return (cst_pi_over_2-atan(realpart/imagpart,contextptr))*sign(imagpart,contextptr);
4110     }
4111     if (is_zero_or_contains(imagpart,contextptr))
4112       return (1-sign(realpart,contextptr))*cst_pi_over_2+atan(imagpart/realpart,contextptr);
4113     if ( (realpart.type==_DOUBLE_ || realpart.type==_FLOAT_) || (imagpart.type==_DOUBLE_ || imagpart.type==_FLOAT_) )
4114       return eval(atan(rdiv(imagpart,realpart,contextptr),contextptr)+(1-sign(realpart,contextptr))*sign(imagpart,contextptr)*evalf_double(cst_pi_over_2,1,contextptr),1,contextptr);
4115     else
4116       return atan(rdiv(imagpart,realpart,contextptr),contextptr)+(1-sign(realpart,contextptr))*sign(imagpart,contextptr)*cst_pi_over_2;
4117   }
4118 
_VECTarg(const vecteur & a,GIAC_CONTEXT)4119   static gen _VECTarg(const vecteur & a,GIAC_CONTEXT){
4120     vecteur res;
4121     vecteur::const_iterator it=a.begin(), itend=a.end();
4122     for (;it!=itend;++it){
4123       res.push_back(arg(*it,contextptr));
4124     }
4125     return res;
4126   }
4127 
arg(const gen & a,GIAC_CONTEXT)4128   gen arg(const gen & a,GIAC_CONTEXT){
4129     if (a.type==_CPLX && a._CPLXptr->type==_DOUBLE_ && (a._CPLXptr+1)->type==_DOUBLE_)
4130       return atan2((a._CPLXptr+1)->_DOUBLE_val,a._CPLXptr->_DOUBLE_val);
4131     if (!angle_radian(contextptr)){
4132       //grad
4133       int mode = get_mode_set_radian(contextptr); //get current mode
4134       gen res=evalf(arg(a,contextptr),1,contextptr);
4135       angle_mode(mode,contextptr); //set back to either degree or grads
4136       if(mode == 1) //if was in degrees
4137         return 180*res/cst_pi;
4138       else
4139         return 200 * res / cst_pi;
4140     }
4141     if (a.is_symb_of_sommet(at_pow)){
4142       gen af=a._SYMBptr->feuille;
4143       if (af.type==_VECT && af._VECTptr->size()==2){
4144 	gen res=im(ln(af._VECTptr->front(),contextptr)*af._VECTptr->back(),contextptr);
4145 	return _smod(makesequence(res,cst_two_pi),contextptr);
4146       }
4147     }
4148     if (a.is_symb_of_sommet(at_exp))
4149       return _smod(makesequence(im(a._SYMBptr->feuille,contextptr),cst_two_pi),contextptr);
4150     if (a.is_symb_of_sommet(at_prod)){
4151       const gen & af=a._SYMBptr->feuille;
4152       if (af.type==_VECT){
4153 	const_iterateur it=af._VECTptr->begin(),itend=af._VECTptr->end();
4154 	gen res;
4155 	int nonzero=0;
4156 	for (;it!=itend;++it){
4157 	  gen tmp(arg(*it,contextptr));
4158 	  if (!is_zero(tmp,contextptr)){
4159 	    res += tmp;
4160 	    ++nonzero;
4161 	  }
4162 	}
4163 	if (nonzero>1)
4164 	  return _smod(makesequence(res,cst_two_pi),contextptr);
4165 	return res;
4166       }
4167     }
4168     if (is_equal(a))
4169       return apply_to_equal(a,arg,contextptr);
4170     switch (a.type ) {
4171     case _INT_: case _ZINT: case _FLOAT_: case _REAL:
4172       if (is_positive(a,contextptr))
4173 	return 0;
4174       else
4175 	return cst_pi;
4176     case _DOUBLE_:
4177       return a._DOUBLE_val>=0?0.0:M_PI;
4178     case _CPLX:
4179       return arg_CPLX(a,contextptr);
4180     case _VECT:
4181       return _VECTarg(*a._VECTptr,contextptr);
4182     case _IDNT:
4183     case _SYMB:
4184       // if ( is_zero(im(a,contextptr),contextptr) || (evalf(a,eval_level(contextptr),contextptr).type==_CPLX) )
4185 	return arg_CPLX(a,contextptr);
4186 	// return new symbolic(at_arg,a);
4187     case _USER:
4188       return a._USERptr->arg(contextptr);
4189     case _FRAC:
4190       return arg(a._FRACptr->num*conj(a._FRACptr->den,contextptr),contextptr);
4191     default:
4192       return gentypeerr(gettext("Arg"));
4193     }
4194     return 0;
4195   }
4196 
squarenorm(GIAC_CONTEXT) const4197   gen gen::squarenorm(GIAC_CONTEXT) const {
4198     switch (type ) {
4199     case _INT_: case _DOUBLE_: case _FLOAT_: case _ZINT: case _REAL:
4200       return (*this) * (*this);
4201     case _CPLX:
4202       return ( (*_CPLXptr)*(*_CPLXptr)+(*(_CPLXptr+1)*(*(_CPLXptr+1))) );
4203     case _FRAC:
4204       return fraction(_FRACptr->num.squarenorm(contextptr),_FRACptr->den.squarenorm(contextptr));
4205     default:
4206       {
4207 	gen a,b;
4208 	reim(*this,a,b,contextptr);
4209 	return a*a+b*b;
4210       }
4211     }
4212   }
4213 
sq(const gen & a)4214   gen sq(const gen & a){
4215     return a*a;
4216   }
4217 
bindigits() const4218   int gen::bindigits() const{
4219     int res,valeur;
4220     switch (type ) {
4221     case _INT_:
4222       res=0;
4223       valeur=val;
4224       for (;valeur;res++)
4225 	valeur = valeur >> 1;
4226       return res;
4227     case _ZINT:
4228       return mpz_sizeinbase(*_ZINTptr,2)+1;
4229     case _CPLX:
4230       return giacmax(_CPLXptr->bindigits(),(_CPLXptr+1)->bindigits() ) ;
4231     default:
4232 #ifndef NO_STDEXCEPT
4233       settypeerr(gettext("Bindigits"));
4234 #endif
4235       return 0;
4236     }
4237     return 0;
4238   }
4239 
addpoly(const gen & th,const gen & other)4240   static gen addpoly(const gen & th, const gen & other){
4241     if ((th.type!=_POLY) || (other.type!=_POLY)){
4242 #ifndef NO_STDEXCEPT
4243       settypeerr(gettext("addpoly"));
4244 #endif
4245       return gentypeerr(gettext("addpoly"));
4246     }
4247     // Tensor addition
4248     vector< monomial<gen> >::const_iterator a=th._POLYptr->coord.begin();
4249     vector< monomial<gen> >::const_iterator a_end=th._POLYptr->coord.end();
4250     if (a == a_end) {
4251       return other;
4252     }
4253     vector< monomial<gen> >::const_iterator b=other._POLYptr->coord.begin();
4254     vector< monomial<gen> >::const_iterator b_end=other._POLYptr->coord.end();
4255     if (b==b_end){
4256       return th;
4257     }
4258     ref_polynome * resptr=new ref_polynome(th._POLYptr->dim);
4259     Add_gen(a,a_end,b,b_end,resptr->t.coord,th._POLYptr->is_strictly_greater);
4260     return resptr;
4261   }
4262 
addpoly(const polynome & p,const gen & c)4263   polynome addpoly(const polynome & p,const gen & c){
4264     if (is_exactly_zero(c))
4265       return p;
4266     polynome pcopy(p);
4267     if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
4268       pcopy.coord.back().value = pcopy.coord.back().value + c;
4269       if (is_exactly_zero(pcopy.coord.back().value))
4270 	pcopy.coord.pop_back();
4271     }
4272     else
4273       pcopy.coord.push_back(monomial<gen>(c,pcopy.dim));
4274     return pcopy;
4275   }
4276 
chkmod(const gen & a,const gen & b)4277   gen chkmod(const gen& a,const gen & b){
4278     if  ( (b.type!=_MOD) || ((a.type==_MOD) && (*(a._MODptr+1)==*(b._MODptr+1)) ))
4279       return a;
4280     return makemodquoted(a,*(b._MODptr+1));
4281   }
makemod(const gen & a,const gen & b)4282   gen makemod(const gen & a,const gen & b){
4283     if (a.type==_VECT)
4284       return apply1st(a,b,makemod);
4285     if (a.type==_POLY){
4286       polynome res(a._POLYptr->dim);
4287       vector< monomial<gen> >::const_iterator it=a._POLYptr->coord.begin(),itend=a._POLYptr->coord.end();
4288       res.coord.reserve(itend-it);
4289       for (;it!=itend;++it){
4290 	gen tmp=makemod(it->value,b);
4291 	if (!is_exactly_zero(tmp))
4292 	  res.coord.push_back(monomial<gen>(tmp,it->index));
4293       }
4294       return res;
4295     }
4296     if (a.type==_MOD){
4297       if (is_exactly_zero(b)) // unmodularize
4298 	return *a._MODptr;
4299       if (*(a._MODptr+1)==b) // avoid e.g. 7 % 5 % 5
4300 	return a;
4301     }
4302     if (a.type==_USER)
4303       return a;
4304     if (is_exactly_zero(b))
4305       return a;
4306     if (a.type==_DOUBLE_ || a.type==_REAL || a.type==_FLOAT_)
4307       return gensizeerr(context0);
4308     gen res=makemodquoted(0,0);
4309     if ( (b.type==_INT_) || (b.type==_ZINT) )
4310       *res._MODptr=smod(a,b);
4311     else {
4312       if (b.type!=_VECT){
4313 	res=0;
4314 #ifdef NO_STDEXCEPT
4315 	return gensizeerr(gettext("Bad mod:")+b.print(context0));
4316 #else
4317 	setsizeerr(gettext("Bad mod:")+b.print(context0));
4318 #endif
4319       }
4320       if (a.type==_VECT)
4321 	*res._MODptr=(*a._VECTptr)%(*b._VECTptr);
4322       else
4323 	*res._MODptr=a;
4324     }
4325     *(res._MODptr+1)=b;
4326     return res;
4327   }
4328 
makemodquoted(const gen & a,const gen & b)4329   gen makemodquoted(const gen & a,const gen & b){
4330     gen res;
4331 #ifdef SMARTPTR64
4332     * ((ulonglong * ) &res) = ulonglong(new ref_modulo(a,b)) << 16;
4333 #else
4334     res.__MODptr=new ref_modulo(a,b);
4335 #endif
4336     res.type=_MOD;
4337     return res;
4338   }
4339 
modadd(const ref_modulo * a,const ref_modulo * b)4340   static gen modadd(const ref_modulo * a,const ref_modulo *b){
4341     if (a->modulo!=b->modulo){
4342 #ifndef NO_STDEXCEPT
4343       setsizeerr(gettext("Mod are different"));
4344 #endif
4345     }
4346     return makemod(a->n+b->n,a->modulo);
4347   }
4348 
modsub(const ref_modulo * a,const ref_modulo * b)4349   static gen modsub(const ref_modulo * a,const ref_modulo *b){
4350 #ifndef NO_STDEXCEPT
4351     if (a->modulo!=b->modulo)
4352       setsizeerr(gettext("Mod are different"));
4353 #endif
4354     return makemod(a->n-b->n,a->modulo);
4355   }
4356 
modmul(const ref_modulo * a,const ref_modulo * b)4357   static gen modmul(const ref_modulo * a,const ref_modulo *b){
4358 #ifndef NO_STDEXCEPT
4359     if (a->modulo!=b->modulo)
4360       setsizeerr(gettext("Mod are different"));
4361 #endif
4362     return makemod(a->n*b->n,a->modulo);
4363   }
4364 
modinv(const gen & a)4365   static gen modinv(const gen & a){
4366     gen modu=*(a._MODptr+1);
4367     if ( ( (modu.type==_INT_) || (modu.type==_ZINT) ) &&
4368 	 a._MODptr->is_cinteger() )
4369       return makemod(invmod(*a._MODptr,modu),modu);
4370     if (modu.type==_VECT){
4371       modpoly polya,u,v,d;
4372       if (a._MODptr->type!=_VECT)
4373 	polya.push_back(*a._MODptr);
4374       else
4375 	polya=*a._MODptr->_VECTptr;
4376       egcd(polya,*modu._VECTptr,0,u,v,d);
4377       if (d.size()!=1){
4378 #ifndef NO_STDEXCEPT
4379 	setsizeerr(gettext("Not invertible"));
4380 #endif
4381 	return 0;
4382       }
4383       return makemod(u/d.front(),modu);
4384     }
4385     return fraction(makemod(plus_one,*(a._MODptr+1)),a);
4386   }
4387 
4388   // a and b must be dense univariate polynomials
4389   // WARNING: may modify a in place (suitable inside a += operator)
addgen_poly(const gen & a,const gen & b,bool inplace=false)4390   static gen addgen_poly(const gen & a,const gen & b,bool inplace=false){
4391     vecteur & av=*a._VECTptr;
4392     vecteur & bv=*b._VECTptr;
4393     if (inplace){
4394       /*
4395       int as=av.size(),bs=bv.size();
4396       if (as<bs)
4397 	av.insert(av.begin(),bs-as,0);
4398       */
4399       gen res(a);
4400       Addmodpoly(av.begin(),av.end(),bv.begin(),bv.end(),0,av);
4401       return res;
4402     }
4403     gen res(vecteur(0), _POLY1__VECT);
4404     addmodpoly(av,bv,0,*res._VECTptr);
4405     return res._VECTptr->empty()?0:res;
4406   }
4407 
operator_plus_eq(gen & a,const gen & b,GIAC_CONTEXT)4408   gen & operator_plus_eq(gen &a,const gen & b,GIAC_CONTEXT){
4409 #ifdef EMCC
4410     a=operator_plus(a,b,contextptr);
4411     return a;
4412 #endif
4413     if (a.type==b.type){
4414 
4415       if (a.type==_DOUBLE_){
4416 #ifdef DOUBLEVAL
4417 	a._DOUBLE_val += b._DOUBLE_val; return a;
4418 #else
4419 	*((double *) &a) += *((double *) &b);
4420 	a.type = _DOUBLE_;
4421 	return a;
4422 #endif
4423       }
4424       if (a.type==_FLOAT_){
4425 #ifdef DOUBLEVAL
4426 	a._FLOAT_val += b._FLOAT_val; return a;
4427 #else
4428 	*((giac_float *) &a) += *((giac_float *) &b);
4429 	a.type = _FLOAT_;
4430 	return a;
4431 #endif
4432       }
4433       if (a.type==_INT_){
4434 	longlong tmp=((longlong) a.val+b.val);
4435 	a.val=(int)tmp;
4436 	if (a.val==tmp)
4437 	  return a;
4438 	return a=tmp;
4439       }
4440       if (a.type==_ZINT && a.ref_count()==1){
4441 	mpz_t * ptr=a._ZINTptr;
4442 	mpz_add(*ptr,*ptr,*b._ZINTptr);
4443 	if (mpz_sizeinbase(*ptr,2)<32){
4444 	  return a=mpz_get_si(*ptr);
4445 	}
4446 	return a;
4447       }
4448       if (a.type==_VECT && a.subtype==_POLY1__VECT && a.ref_count()==1){
4449 	if (addgen_poly(a,b,true)._VECTptr->empty())
4450 	  a=0;
4451 	return a;
4452       }
4453     }
4454     if (a.type==_ZINT && b.type==_INT_ && a.ref_count()==1){
4455       mpz_t * ptr=a._ZINTptr;
4456       if (b.val<0)
4457 	mpz_sub_ui(*ptr,*ptr,-b.val);
4458       else
4459 	mpz_add_ui(*ptr,*ptr,b.val);
4460       if (mpz_sizeinbase(*ptr,2)<32){
4461 	return a=gen(*ptr);
4462       }
4463       return a;
4464     }
4465     // if (!( (++control_c_counter) & control_c_counter_mask))
4466 #ifdef TIMEOUT
4467     control_c();
4468 #endif
4469     if (ctrl_c || interrupted) {
4470       interrupted = true; ctrl_c=false;
4471       return a=gensizeerr(gettext("Stopped by user interruption."));
4472     }
4473     return a=operator_plus(a,b,contextptr);
4474   }
4475 
ck_evalf_double(const gen & g,GIAC_CONTEXT)4476   static gen ck_evalf_double(const gen & g,GIAC_CONTEXT){
4477     gen tmp=evalf_double(g,1,contextptr);
4478     if (tmp.type<=_CPLX)
4479       return tmp;
4480     return gensizeerr(contextptr);
4481   }
4482 
operator_plus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)4483   gen operator_plus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
4484     static bool warnextend=true;
4485     // if (!( (++control_c_counter) & control_c_counter_mask))
4486 #ifdef TIMEOUT
4487     control_c();
4488 #endif
4489     if (ctrl_c || interrupted) {
4490       interrupted = true; ctrl_c=false;
4491       return gensizeerr(gettext("Stopped by user interruption."));
4492     }
4493     register ref_mpz_t * e;
4494     switch ( t ) {
4495     case _ZINT__ZINT:
4496       e =new ref_mpz_t;
4497       mpz_add(e->z,*a._ZINTptr,*b._ZINTptr);
4498       return e;
4499     case _DOUBLE___DOUBLE_:
4500       return a._DOUBLE_val+b._DOUBLE_val;
4501     case _FLOAT___FLOAT_:
4502       return a._FLOAT_val+b._FLOAT_val;
4503     case _VECT__VECT:
4504       if (// abs_calc_mode(contextptr)==38 &&
4505 	  (a.subtype==_MATRIX__VECT ||b.subtype==_MATRIX__VECT)){
4506 	if (!ckmatrix(a) || !ckmatrix(b))
4507 	  return gensizeerr(contextptr);
4508 	if (a._VECTptr->size()!=b._VECTptr->size() || a._VECTptr->front()._VECTptr->size()!=b._VECTptr->front()._VECTptr->size())
4509 	  return gendimerr(contextptr);
4510       }
4511       if (a.subtype==_POLY1__VECT)
4512 	return addgen_poly(a,b);
4513       if (a.subtype==_PNT__VECT)
4514 	return gen(makenewvecteur(a._VECTptr->front()+b,a._VECTptr->back()),a.subtype);
4515       if (a.subtype!=_POINT__VECT && equalposcomp((int *) _GROUP__VECT_subtype,a.subtype))
4516 	return sym_add(a,b,contextptr);
4517       if (b.subtype!=_POINT__VECT && equalposcomp((int *)_GROUP__VECT_subtype,b.subtype))
4518 	return sym_add(b,a,contextptr);
4519       if (a.subtype==_POINT__VECT && b.subtype==_POINT__VECT)
4520 	return gen(addvecteur(*a._VECTptr,*b._VECTptr),0);
4521       if (a.subtype==0 && b.subtype==0 && python_compat(contextptr)==2)
4522 	return mergevecteur(*a._VECTptr,*b._VECTptr);
4523       if (warnextend && a.subtype==0 && b.subtype==0 && python_compat(contextptr)){
4524 	warnextend=false;
4525 	alert(gettext("Warning + is vector addition, run list1.extend(list2) for list concatenation"),contextptr);
4526       }
4527       return gen(addvecteur(*a._VECTptr,*b._VECTptr),a.subtype?a.subtype:b.subtype);
4528     case _MAP__MAP:
4529       {
4530 	int arows,acols,an,brows,bcols,bn;
4531 	if ( (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)) || (is_sparse_vector(a,arows,an) && is_sparse_vector(b,brows,bn)) ){
4532 	  gen_map res;
4533 	  gen g(res);
4534 	  sparse_add(*a._MAPptr,*b._MAPptr,*g._MAPptr);
4535 	  return g;
4536 	}
4537       }
4538     case _INT___ZINT:
4539       e = new ref_mpz_t;
4540       if (a.val<0)
4541 	mpz_sub_ui(e->z,*b._ZINTptr,-a.val);
4542       else
4543 	mpz_add_ui(e->z,*b._ZINTptr,a.val);
4544       return e;
4545     case _ZINT__INT_:
4546       e = new ref_mpz_t;
4547       if (b.val<0)
4548 	mpz_sub_ui(e->z,*a._ZINTptr,-b.val);
4549       else
4550 	mpz_add_ui(e->z,*a._ZINTptr,b.val);
4551       return e;
4552     case _DOUBLE___INT_:
4553       return a._DOUBLE_val+b.val;
4554     case _INT___DOUBLE_:
4555       return a.val+b._DOUBLE_val;
4556     case _FLOAT___DOUBLE_:
4557       return a._FLOAT_val+giac_float(b._DOUBLE_val);
4558     case _FLOAT___INT_:
4559       return a._FLOAT_val+giac_float(b.val);
4560     case _FLOAT___FRAC:
4561       return a+evalf2bcd(b,1,contextptr);
4562     case _DOUBLE___FRAC:
4563       return a+ck_evalf_double(b,contextptr);
4564     case _INT___FLOAT_:
4565       return b._FLOAT_val+giac_float(a.val);
4566     case _DOUBLE___FLOAT_:
4567       return b._FLOAT_val+giac_float(a._DOUBLE_val);
4568     case _DOUBLE___ZINT:
4569       return a._DOUBLE_val+mpz_get_d(*b._ZINTptr);
4570     case _DOUBLE___REAL:
4571       return a._DOUBLE_val+real2double(*b._REALptr);
4572     case _REAL__DOUBLE_:
4573       return b._DOUBLE_val+real2double(*a._REALptr);
4574     case _ZINT__DOUBLE_:
4575       return b._DOUBLE_val+mpz_get_d(*a._ZINTptr);
4576     case _CPLX__INT_:
4577       if (b.val==0) return a;
4578     case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
4579       return gen(*a._CPLXptr+b,*(a._CPLXptr+1));
4580     case _INT___CPLX:
4581       if (a.val==0) return b;
4582     case _ZINT__CPLX: case _FLOAT___CPLX: case _DOUBLE___CPLX: case _REAL__CPLX:
4583       return gen(a+*b._CPLXptr,*(b._CPLXptr+1));
4584     case _CPLX__CPLX: {
4585       gen * aptr=a._CPLXptr, *bptr=b._CPLXptr;
4586       if (aptr->type==_DOUBLE_ && (aptr+1)->type==_DOUBLE_ && bptr->type ==_DOUBLE_ && (bptr+1)->type ==_DOUBLE_)
4587 	return adjust_complex_display(gen(aptr->_DOUBLE_val + bptr->_DOUBLE_val, (aptr+1)->_DOUBLE_val + (bptr+1)->_DOUBLE_val),a,b);
4588       return adjust_complex_display(gen(*aptr + *bptr, *(aptr+1) + *(bptr+1)),a,b);
4589     }
4590     case _POLY__POLY:
4591       return addpoly(a,b);
4592     case _FRAC__FRAC:
4593       return (*a._FRACptr)+(*b._FRACptr);
4594     case _FRAC__FLOAT_:
4595       return evalf2bcd(a,1,contextptr)+b;
4596     case _INT___FRAC: case _ZINT__FRAC:
4597       return a+(*b._FRACptr);
4598     case _FRAC__INT_: case _FRAC_ZINT:
4599       return (*a._FRACptr)+b;
4600     case _FRAC__DOUBLE_:
4601       return ck_evalf_double(a,contextptr)+b;
4602     case _SPOL1__SPOL1:
4603       return spadd(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
4604     case _EXT__EXT:
4605       return ext_add(a,b,contextptr);
4606     case _STRNG__STRNG:
4607       if (is_undef(a)) return a;
4608       if (is_undef(b)) return b;
4609       return string2gen('"'+(*a._STRNGptr)+(*b._STRNGptr)+'"');
4610     case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__MOD: case _POLY__USER: case _POLY__REAL:
4611       return addpoly(*a._POLYptr,b);
4612     case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _MOD__POLY: case _USER__POLY: case _REAL__POLY:
4613       return addpoly(*b._POLYptr,a);
4614     case _MOD__MOD:
4615 #ifdef SMARTPTR64
4616       return modadd( (ref_modulo *) (* ((ulonglong * ) &a) >> 16),(ref_modulo *) (* ((ulonglong * ) &b) >> 16));
4617 #else
4618       return modadd(a.__MODptr,b.__MODptr);
4619 #endif
4620     case _REAL__REAL:
4621       return (*a._REALptr)+(*b._REALptr);
4622     case _IDNT__IDNT:
4623       if (a==unsigned_inf && b==unsigned_inf)
4624 	return undef;
4625       if (b==undef)
4626 	return b;
4627       if (a==undef || a==unsigned_inf)
4628 	return a;
4629       if (b==unsigned_inf)
4630 	return b;
4631       return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
4632     case _VECT__MAP:
4633       {
4634 	int brows,bcols,an;
4635 	if (is_sparse_matrix(b,brows,bcols,an)){
4636 	  matrice B;
4637 	  if (!convert(*b._MAPptr,B))
4638 	    return gendimerr(contextptr);
4639 	  return a+B;
4640 	}
4641       }
4642     case _MAP__VECT:
4643       {
4644 	int arows,acols,an;
4645 	if (is_sparse_matrix(a,arows,acols,an)){
4646 	  matrice A;
4647 	  if (!convert(*a._MAPptr,A))
4648 	    return gendimerr(contextptr);
4649 	  return A+b;
4650 	}
4651       }
4652     default:
4653       if (a.type==_INT_ && a.val==0 && b.type!=_STRNG)
4654 	return b;
4655       if (b.type==_INT_ && b.val==0 && a.type!=_STRNG)
4656 	return a;
4657       if (is_undef(a))
4658 	return a;
4659       if (is_undef(b))
4660 	return b;
4661       if (a.type==_FLOAT_){
4662 	if (is_inf(a))
4663 	  return a;
4664 	if (b.type==_VECT)
4665 	  return sym_add(b,a,contextptr);
4666 	gen b1;
4667 	if (has_evalf(b,b1,1,contextptr) && b.type!=b1.type)
4668 	  return operator_plus(a,b1,contextptr);
4669 	return operator_plus(evalf_double(a,1,contextptr),b,contextptr);
4670       }
4671       if (b.type==_FLOAT_){
4672 	if (is_inf(b))
4673 	  return b;
4674 	if (a.type==_VECT)
4675 	  return sym_add(a,b,contextptr);
4676 	gen a1;
4677 	if (has_evalf(a,a1,1,contextptr) && a.type!=a1.type)
4678 	  return operator_plus(a1,b,contextptr);
4679 	return operator_plus(a,evalf_double(b,1,contextptr),contextptr);
4680       }
4681       if (a.type==_STRNG)
4682 	return string2gen(*a._STRNGptr+b.print(contextptr),false);
4683       if (b.type==_STRNG)
4684 	return string2gen(a.print(contextptr)+*b._STRNGptr,false);
4685       if (a.type==_SPOL1)
4686 	return spadd(*a._SPOL1ptr,gen2spol1(b),contextptr);
4687       if (b.type==_SPOL1)
4688 	return spadd(gen2spol1(a),*b._SPOL1ptr,contextptr);
4689       if (a.type==_USER)
4690 	return (*a._USERptr)+b;
4691       if (b.type==_USER)
4692 	return (*b._USERptr)+a;
4693       if (a.type==_REAL)
4694 	return a._REALptr->addition(b,contextptr);
4695       if (b.type==_REAL){
4696 	return b._REALptr->addition(a,contextptr);
4697       }
4698       return sym_add(a,b,contextptr);
4699     }
4700   }
4701 
operator_plus(const gen & a,const gen & b,GIAC_CONTEXT)4702   gen operator_plus (const gen & a,const gen & b,GIAC_CONTEXT){
4703     register unsigned t=(a.type<< _DECALAGE) | b.type;
4704     if (!t)
4705       return((longlong) a.val+b.val);
4706     return operator_plus(a,b,t,contextptr);
4707   }
4708 
operator +(const gen & a,const gen & b)4709   gen operator + (const gen & a,const gen & b){
4710     register unsigned t=(a.type<< _DECALAGE) | b.type;
4711     if (!t)
4712       return ((longlong) a.val+b.val);
4713     return operator_plus(a,b,t,context0);
4714   }
4715 
4716   // specialization of Tfraction<gen> operator +
operator +(const Tfraction<gen> & a,const Tfraction<gen> & b)4717   Tfraction<gen> operator + (const Tfraction<gen> & a,const Tfraction<gen> &b){
4718     if (is_one(a.den))
4719       return(Tfraction<gen> (a.num+b));
4720     if (is_one(b.den))
4721       return(Tfraction<gen> (b.num+a));
4722     gen da(a.den),db(b.den);
4723     gen den=simplify3(da,db),num;
4724     if (a.num.type==_POLY && b.num.type==_POLY && db.type==_POLY && da.type==_POLY)
4725       num=foisplus(*a.num._POLYptr,*db._POLYptr,*b.num._POLYptr,*da._POLYptr);
4726     else
4727       num=foisplus(a.num,db,b.num,da) ; // (a.num*db+b.num*da);
4728     if (den.type==_FRAC){
4729       num=num * den._FRACptr->den;
4730       den=den._FRACptr->num;
4731     }
4732     if (is_exactly_zero(num))
4733       return Tfraction<gen>(num,1);
4734     simplify3(num,den);
4735     if (den.type==_CPLX){ // 3 jan 2020, avoid complex denominator
4736       gen & a=*den._CPLXptr;
4737       gen & b=*(den._CPLXptr+1);
4738       num=num*gen(a,-b);
4739       den=a*a+b*b;
4740     }
4741     den=den*da*db;
4742     return Tfraction<gen> (num,den);
4743   }
4744 
4745 
symbolic_plot_makevecteur(const unary_function_ptr & u,const gen & e,bool project,GIAC_CONTEXT)4746   static gen symbolic_plot_makevecteur(const unary_function_ptr & u,const gen & e,bool project,GIAC_CONTEXT){
4747     if ( (u!=at_pnt) || (e.type!=_VECT) || (e.subtype!=_PNT__VECT) )
4748       return symbolic(u,e);
4749     // e is a curve or a pnt
4750     vecteur w(*e._VECTptr);
4751     if ( (w.size()!=2) && (w.size()!=3))
4752       return symbolic(u,e);
4753     gen a0(w[0]);
4754     gen a1(w[1]);
4755     if ( a1.type==_VECT && a1._VECTptr->size()==3 )
4756       return symbolic(u,gen(makenewvecteur(a0,a1,a1._VECTptr->back()),_PNT__VECT));
4757     if ( a1.type==_VECT && a1._VECTptr->size()==2 ){
4758       if (project){
4759 	// we must project a0
4760 	gen param=a1._VECTptr->back(); // v= [ pnt() t ]
4761 	if (param.type==_VECT){
4762 	  vecteur v=*param._VECTptr;
4763 	  v[1]=projection(v[0],a0,contextptr);
4764 	  if (is_undef(v[1]))
4765 	    return v[1];
4766 	  a0=remove_at_pnt(parameter2point(v,contextptr)); // same
4767 	  a1=makenewvecteur(a1._VECTptr->front(),v);
4768 	}
4769       }
4770       else
4771 	a1=a1._VECTptr->front();
4772     }
4773     return symbolic(u,gen(makenewvecteur(a0,a1),_PNT__VECT));
4774   }
4775 
sym_add(const gen & a,const gen & b,GIAC_CONTEXT)4776   gen sym_add(const gen & a,const gen & b,GIAC_CONTEXT){
4777 #ifdef TIMEOUT
4778     control_c();
4779 #endif
4780     if (ctrl_c || interrupted) {
4781       interrupted = true; ctrl_c=false;
4782       return gensizeerr(gettext("Stopped by user interruption."));
4783     }
4784     bool adeuxpoints=a.is_symb_of_sommet(at_deuxpoints);
4785     if ( (a.is_symb_of_sommet(at_interval) || adeuxpoints)&& a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2)
4786       return symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->front()+b,a._SYMBptr->feuille._VECTptr->back()+b)); // removed +(adeuxpoints?minus_one:zero) otherwise slicing like v[1:4] does not work
4787     if (a.is_symb_of_sommet(at_unit)){
4788       if (is_zero(b))
4789 	return a;
4790       if (equalposcomp(lidnt(b),cst_pi)!=0)
4791 	return sym_add(a,evalf(b,1,contextptr),contextptr);
4792       if (b.is_symb_of_sommet(at_unit)){
4793 	vecteur & va=*a._SYMBptr->feuille._VECTptr;
4794 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
4795 	if (va[1]==vb[1])
4796 	  return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_plus(va[0],vb[0],contextptr),va[1])));
4797 	gen g=mksa_reduce(vb[1]/va[1],contextptr);
4798 	gen tmp=chk_not_unit(g);
4799 	if (is_undef(tmp)) return tmp;
4800 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_plus(va[0],operator_times(g,vb[0],contextptr),contextptr),va[1])));
4801       }
4802       if (lidnt(b).empty()){
4803 	gen g=mksa_reduce(a,contextptr);
4804 	gen tmp=chk_not_unit(g);
4805 	if (is_undef(tmp)) return tmp;
4806 	return g+b;
4807       }
4808     }
4809     if (b.is_symb_of_sommet(at_unit)){
4810       if (is_zero(a))
4811 	return b;
4812       if (equalposcomp(lidnt(a),cst_pi)!=0)
4813 	return sym_add(evalf(a,1,contextptr),b,contextptr);
4814       if (lidnt(a).empty()){
4815 	gen g=mksa_reduce(b,contextptr);
4816 	gen tmp=chk_not_unit(g);
4817 	if (is_undef(tmp)) return tmp;
4818 	return a+g;
4819       }
4820     }
4821     if (a.is_approx()){
4822       gen b1;
4823       if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
4824 #ifdef HAVE_LIBMPFR
4825 	if (a.type==_REAL){
4826 	  gen b2;
4827 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4828 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr))
4829 	    b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
4830 	  else
4831 #endif
4832 	    b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
4833 	  if (b2.is_approx())
4834 	    return a+b2;
4835 	}
4836 	if (a.type==_CPLX && a._CPLXptr->type==_REAL){
4837 	  gen b2;
4838 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4839 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._CPLXptr->_REALptr))
4840 	    b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
4841 	  else
4842 #endif
4843 	    b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
4844 	  if (b2.is_approx())
4845 	    return a+b2;
4846 	}
4847 #endif
4848 	return a+b1;
4849       }
4850     }
4851     if (b.is_approx()){
4852       gen a1;
4853       if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
4854 #ifdef HAVE_LIBMPFR
4855 	if (b.type==_REAL){
4856 	  gen a2;
4857 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4858 	  if (real_interval * ptr=dynamic_cast<real_interval *>(b._REALptr))
4859 	    a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
4860 	  else
4861 #endif
4862 	    a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
4863 	  if (a2.is_approx())
4864 	    return a2+b;
4865 	}
4866 	if (b.type==_CPLX && b._CPLXptr->type==_REAL){
4867 	  gen a2;
4868 #if defined HAVE_LIBMPFI && !defined NO_RTTI
4869 	  if (real_interval * ptr=dynamic_cast<real_interval *>(b._CPLXptr->_REALptr))
4870 	    a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
4871 	  else
4872 #endif
4873 	    a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
4874 	  if (a2.is_approx())
4875 	    return a2+b;
4876 	}
4877 #endif
4878 	return a1+b;
4879       }
4880     }
4881     if ( (a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet) ){
4882       if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
4883 	return a._SYMBptr->feuille._VECTptr->front()+b._SYMBptr->feuille._VECTptr->front();
4884       else {
4885 	if (b.type==_VECT)
4886 	  return translation(b,a,contextptr);
4887 	gen a_(a);
4888 	if (a.is_symb_of_sommet(at_curve) && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2 && a._SYMBptr->feuille._VECTptr->front().type==_VECT){
4889 	  // adjust param and cartesian eq
4890 	  vecteur v=*a._SYMBptr->feuille._VECTptr->front()._VECTptr;
4891 	  if (v.size()==7)
4892 	    v[6] += b;
4893 	  if (v.size()>=6){
4894 	    v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(x__IDNT_e-re(b,contextptr),y__IDNT_e-im(b,contextptr)),false,contextptr);
4895 	    a_=symbolic(at_curve,gen(makevecteur(gen(v,a._SYMBptr->feuille._VECTptr->front().subtype),a._SYMBptr->feuille._VECTptr->back()),a._SYMBptr->feuille.subtype));
4896 	  }
4897 	}
4898 	return symbolic_plot_makevecteur( a_._SYMBptr->sommet,a_._SYMBptr->feuille+b,true,contextptr);
4899       }
4900     }
4901     if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) ){
4902       if (a.type==_VECT)
4903 	return translation(a,b,contextptr);
4904       return symbolic_plot_makevecteur(b._SYMBptr->sommet,b._SYMBptr->feuille+a,true,contextptr);
4905     }
4906     gen var1,var2,res1,res2;
4907     if (is_algebraic_program(a,var1,res1)){
4908       if (is_algebraic_program(b,var2,res2)){
4909 	if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
4910 	  res2=subst(res2,var2,var1,false,contextptr);
4911 	  var2=var1;
4912 	}
4913 	if (var1==var2)
4914 	  return symbolic(at_program,gen(makevecteur(var1,0,operator_plus(res1,res2,contextptr)),_SEQ__VECT));
4915       }
4916       if (!is_constant_wrt(b,var1,contextptr))
4917 	*logptr(contextptr) << "Warning function+constant with constant dependant of mute variable" << '\n';
4918       return symbolic(at_program,gen(makevecteur(var1,0,operator_plus(res1,b,contextptr)),_SEQ__VECT));
4919     }
4920     if (is_algebraic_program(b,var2,res2)){
4921       if (!is_constant_wrt(a,var2,contextptr))
4922 	*logptr(contextptr) << "Warning constant+function with constant dependant of mute variable" << '\n';
4923       return symbolic(at_program,gen(makevecteur(var2,0,operator_plus(a,res2,contextptr)),_SEQ__VECT));
4924     }
4925     if (a.type==_VECT){
4926       if (is_zero(b,contextptr))
4927 	return a;
4928       if (a.subtype==_LIST__VECT)
4929 	return apply1st(a,b,contextptr,operator_plus);
4930       vecteur res=*a._VECTptr;
4931       if (res.empty())
4932 	return b;
4933       if (a.subtype==_VECTOR__VECT && a._VECTptr->size()==2){
4934 	if (b.type==_VECT && b._VECTptr->size()==2){
4935 	  vecteur & bv=*b._VECTptr;
4936 	  if (b.subtype==_VECTOR__VECT && res.front()==bv.back())
4937 	    return _vector(gen(makenewvecteur(bv.front(),bv.back()+res.back()-res.front()),_SEQ__VECT),contextptr);
4938 	  return _vector(gen(makenewvecteur(res.front(),res.back()+bv.back()-bv.front()),_SEQ__VECT),contextptr);
4939 	}
4940 	return _point(b+res.back()-res.front(),contextptr);
4941       }
4942       if (b.type==_VECT && b.subtype==_VECTOR__VECT && b._VECTptr->size()==2)
4943 	return a+vector2vecteur(*b._VECTptr);
4944       if (a.subtype==_POINT__VECT && a._VECTptr->size()==3 && b.type!=_VECT){
4945 	gen reb,imb; reim(b,reb,imb,contextptr);
4946 	res[0] += reb;
4947 	res[1] += imb;
4948 	return res;
4949       }
4950       if (equalposcomp((int *)_GROUP__VECT_subtype,a.subtype)){ // add to each element
4951 	iterateur it=res.begin(),itend=res.end();
4952 	for (;it!=itend;++it)
4953 	  *it=*it+b;
4954 	return gen(res,a.subtype);
4955       }
4956       if (a.subtype==_PNT__VECT){
4957 	res.front()=res.front()+b;
4958 	return gen(res,_PNT__VECT);
4959       }
4960       if (a.subtype!=_POLY1__VECT && ckmatrix(a)){ // matrix+cst
4961 	int s=int(res.size());
4962 	if (unsigned(s)==res.front()._VECTptr->size()){
4963 	  for (int i=0;i<s;i++){
4964 	    vecteur v = *res[i]._VECTptr;
4965 	    v[i] += b;
4966 	    res[i]=gen(v,res[i].subtype);
4967 	  }
4968 	  return gen(res,_MATRIX__VECT);
4969 	}
4970       }
4971       // polynomial+cst
4972       res.back()=res.back()+b;
4973       if ( (res.size()==1) && is_exactly_zero(res.back()))
4974           return zero;
4975       else
4976           return gen(res,_POLY1__VECT);
4977     }
4978     if (b.type==_VECT)
4979       return sym_add(b,a,contextptr);
4980     if (is_undef(a))
4981       return a;
4982     if (is_undef(b))
4983       return b;
4984     if (is_inf(a)){
4985       if (is_inf(b)){
4986 	if ((a==b) && (a!=unsigned_inf))
4987 	  return a;
4988 	else
4989 	  return undef;
4990       }
4991       if (a==unsigned_inf || is_zero(im(b,contextptr)))
4992 	return a;
4993       return unsigned_inf;
4994     }
4995     if (is_inf(b)){
4996       if (b==unsigned_inf || is_zero(im(a,contextptr)))
4997 	return b;
4998       return unsigned_inf;
4999     }
5000     if (b.is_symb_of_sommet(at_neg) && a==b._SYMBptr->feuille)
5001       return chkmod(zero,a);
5002     if (a.is_symb_of_sommet(at_neg) && b==a._SYMBptr->feuille)
5003       return chkmod(zero,b);
5004     if (is_exactly_zero(a))
5005       return b;
5006     if (is_exactly_zero(b))
5007       return a;
5008     if (a.type==_STRNG)
5009       return string2gen(*a._STRNGptr+b.print(context0),false);
5010     if (b.type==_STRNG)
5011       return string2gen(a.print(context0)+*b._STRNGptr,false);
5012     if (a.type==_FRAC){
5013       if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
5014 	return (*a._FRACptr)+b;
5015       if (b.is_symb_of_sommet(at_neg))
5016 	return a-b._SYMBptr->feuille;
5017       if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
5018 	return (*a._FRACptr)+fraction(1,b._SYMBptr->feuille);
5019       if (b.is_symb_of_sommet(at_prod) && b._SYMBptr->feuille.type==_VECT){
5020 	const vecteur & bf=*b._SYMBptr->feuille._VECTptr;
5021 	if (bf.size()==2 && is_integer(bf[0]) && bf[1].is_symb_of_sommet(at_inv) && is_cinteger(bf[1]._SYMBptr->feuille))
5022 	  return (*a._FRACptr)+fraction(bf[0],bf[1]._SYMBptr->feuille);
5023       }
5024       return sym_add(_FRAC2_SYMB(a),b,contextptr);
5025     }
5026     if (b.type==_FRAC){
5027       if ( (a.type!=_SYMB) && (a.type!=_IDNT) )
5028 	return a+(*b._FRACptr);
5029       if (a.is_symb_of_sommet(at_neg))
5030 	return b-a._SYMBptr->feuille;
5031       if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
5032 	return fraction(1,a._SYMBptr->feuille)+(*b._FRACptr);
5033       if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
5034 	const vecteur & af=*a._SYMBptr->feuille._VECTptr;
5035 	if (af.size()==2 && is_integer(af[0]) && af[1].is_symb_of_sommet(at_inv) && is_cinteger(af[1]._SYMBptr->feuille))
5036 	  return fraction(af[0],af[1]._SYMBptr->feuille)+(*b._FRACptr);
5037       }
5038       return sym_add(a,_FRAC2_SYMB(b),contextptr);
5039     }
5040     if (a.type==_EXT){
5041       if (a.is_constant() && (b.type==_POLY))
5042 	return addpoly(*b._POLYptr,a);
5043       /*
5044       if (b.type==_POLY && b.is_constant())
5045 	return a+b._POLYptr->coord.front().value;
5046       */
5047       else
5048 	return algebraic_EXTension(*a._EXTptr+b,*(a._EXTptr+1));
5049     }
5050     if (b.type==_EXT){
5051       if (b.is_constant() && (a.type==_POLY))
5052 	return addpoly(*a._POLYptr,b);
5053       /*
5054       if (a.type==_POLY && a.is_constant())
5055 	return a._POLYptr->coord.front().value+b;
5056       */
5057       else
5058 	return algebraic_EXTension(a+*b._EXTptr,*(b._EXTptr+1));
5059     }
5060     int ia=is_inequality(a),ib=is_inequality(b);
5061     if (ia){
5062       vecteur & va=*a._SYMBptr->feuille._VECTptr;
5063       if (ia==ib || (ia==1 && ib)){
5064 	if (ia==4) // <> + <>
5065 	  return undef;
5066 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5067 	return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(va.front()+vb.front(),va.back()+vb.back())));
5068       }
5069       if (ia==1 || !ib) // = +
5070 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(va.front()+b,va.back()+b)));
5071       if ( (ia==5 && ib==6) || (ia==6 && ib==5)){
5072 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5073 	return new_ref_symbolic(symbolic(at_superieur_strict,makesequence(va.front()+vb.front(),va.back()+vb.back())));
5074       }
5075     }
5076     if (ib)
5077       return b+a;
5078     if (a.is_symb_of_sommet(at_interval)){
5079       gen & f=a._SYMBptr->feuille;
5080       if (f.type==_VECT && f._VECTptr->size()==2){
5081 	vecteur & v=*f._VECTptr;
5082 	if (b.is_symb_of_sommet(at_interval)){
5083 	  gen & g=b._SYMBptr->feuille;
5084 	  if (g.type==_VECT && g._VECTptr->size()==2){
5085 	    vecteur & w=*g._VECTptr;
5086 	    return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(w[0]+v[0],w[1]+v[1]),_SEQ__VECT)));
5087 	  }
5088 	}
5089 	return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(b+v[0],b+v[1]),_SEQ__VECT)));
5090       }
5091     }
5092     if (b.is_symb_of_sommet(at_interval))
5093       return b+a;
5094     /* if (xcas_mode(contextptr) && (a.type==_SYMB|| b.type==_SYMB) )
5095        return liste2symbolique(fusion2liste(symbolique2liste(a),symbolique2liste(b))); */
5096     if ((a.type==_SYMB) && (b.type==_SYMB)){
5097       if (a._SYMBptr->sommet==at_plus) {
5098 	if (b._SYMBptr->sommet==at_plus)
5099 	  return new_ref_symbolic(symbolic(at_plus,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),*(b._SYMBptr->feuille._VECTptr)),_SEQ__VECT)));
5100 	else
5101 	  return new_ref_symbolic(symbolic(*a._SYMBptr,b));
5102       }
5103       else {
5104 	if (b._SYMBptr->sommet==at_plus)
5105 	  return new_ref_symbolic(symbolic(*(b._SYMBptr),a));
5106 	else
5107 	  return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5108       }
5109     }
5110     if (b.type==_SYMB){
5111       if (b._SYMBptr->sommet==at_plus)
5112 	return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
5113       else
5114 	return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5115     }
5116     if (a.type==_SYMB){
5117       if ( a._SYMBptr->sommet==at_plus && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()>1 &&
5118 	   ( (b==plus_one && a._SYMBptr->feuille._VECTptr->back()==minus_one) || (b==minus_one && a._SYMBptr->feuille._VECTptr->back()==plus_one) )
5119 	   )
5120 	{
5121 	vecteur v=*a._SYMBptr->feuille._VECTptr;
5122 	v.pop_back();
5123 	if (v.size()==1)
5124 	  return v.front();
5125 	else
5126 	  return new_ref_symbolic(symbolic(at_plus,gen(v,a._SYMBptr->feuille.subtype)));
5127       }
5128       if (a._SYMBptr->sommet==at_plus)
5129 	return new_ref_symbolic(symbolic(*a._SYMBptr,b));
5130       else
5131 	return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5132     }
5133     if ( (a.type==_IDNT) || (b.type==_IDNT))
5134       return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5135     if (a.type==_MOD)
5136       return a+makemod(b,*(a._MODptr+1));
5137     if (b.type==_MOD)
5138       return makemod(a,*(b._MODptr+1))+b;
5139     return new_ref_symbolic(symbolic(at_plus,makesequence(a,b)));
5140     // settypeerr(gettext("sym_add"));
5141   }
5142 
subpoly(const gen & th,const gen & other)5143   static gen subpoly(const gen & th, const gen & other){
5144     if ((th.type!=_POLY) || (other.type!=_POLY)){
5145 #ifndef NO_STDEXCEPT
5146       settypeerr(gettext("subpoly"));
5147 #endif
5148       return gentypeerr(gettext("subpoly"));
5149     }
5150     vector< monomial<gen> >::const_iterator a=th._POLYptr->coord.begin();
5151     vector< monomial<gen> >::const_iterator a_end=th._POLYptr->coord.end();
5152     vector< monomial<gen> >::const_iterator b=other._POLYptr->coord.begin();
5153     vector< monomial<gen> >::const_iterator b_end=other._POLYptr->coord.end();
5154     if (b==b_end){
5155       return th;
5156     }
5157     ref_polynome * resptr=new ref_polynome(th._POLYptr->dim);
5158     Sub_gen(a,a_end,b,b_end,resptr->t.coord,th._POLYptr->is_strictly_greater);
5159     return resptr;
5160   }
5161 
subpoly(const polynome & p,const gen & c)5162   polynome subpoly(const polynome & p,const gen & c){
5163     if (is_exactly_zero(c))
5164       return p;
5165     polynome pcopy(p);
5166     if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
5167       pcopy.coord.back().value = pcopy.coord.back().value - c;
5168       if (is_exactly_zero(pcopy.coord.back().value))
5169 	pcopy.coord.pop_back();
5170     }
5171     else
5172       pcopy.coord.push_back(monomial<gen>(-c,pcopy.dim));
5173     return pcopy;
5174   }
5175 
subpoly(const gen & c,const polynome & p)5176   static polynome subpoly(const gen & c,const polynome & p){
5177     if (is_exactly_zero(c))
5178       return -p;
5179     polynome pcopy(-p);
5180     if ( (!p.coord.empty()) && p.coord.back().index.is_zero() ) {
5181       pcopy.coord.back().value = pcopy.coord.back().value + c;
5182       if (is_exactly_zero(pcopy.coord.back().value))
5183 	pcopy.coord.pop_back();
5184     }
5185     else
5186       pcopy.coord.push_back(monomial<gen>(c,pcopy.dim));
5187     return pcopy;
5188   }
5189 
subgen_poly(const gen & a,const gen & b,bool inplace=false)5190   static gen subgen_poly(const gen & a,const gen & b,bool inplace=false){
5191     vecteur & av=*a._VECTptr;
5192     vecteur & bv=*b._VECTptr;
5193     if (inplace){
5194       /*
5195       int as=av.size(),bs=bv.size();
5196       if (as<bs)
5197 	av.insert(av.begin(),bs-as,0);
5198       */
5199       gen res(a);
5200       Submodpoly(av.begin(),av.end(),bv.begin(),bv.end(),0,av);
5201       return res;
5202     }
5203     gen res(vecteur(0), _POLY1__VECT);
5204     submodpoly(av,bv,0,*res._VECTptr);
5205     return res._VECTptr->empty()?0:res;
5206   }
5207 
operator_minus_eq(gen & a,const gen & b,GIAC_CONTEXT)5208   gen & operator_minus_eq (gen & a,const gen & b,GIAC_CONTEXT){
5209 #ifdef EMCC
5210     a=operator_minus(a,b,contextptr);
5211     return a;
5212 #endif
5213     if (a.type==b.type){
5214 #ifdef SMARTPTR64
5215       if (*(ulonglong *)&a==*(ulonglong *)&b && a.type<=_CPLX)
5216 	return a=0;
5217 #else
5218       if (&a==&b && a.type<=_CPLX)
5219 	return a=0;
5220 #endif
5221       if (a.type==_DOUBLE_){
5222 #ifdef DOUBLEVAL
5223 	a._DOUBLE_val -= b._DOUBLE_val; return a;
5224 #else
5225 	*((double *) &a) -= *((double *) &b);
5226 	a.type = _DOUBLE_;
5227 	return a;
5228 #endif
5229       }
5230       if (a.type==_FLOAT_){
5231 #ifdef DOUBLEVAL
5232 	a._FLOAT_val -= b._FLOAT_val; return a;
5233 #else
5234 	*((double *) &a) -= *((double *) &b);
5235 	a.type = _FLOAT_;
5236 	return a;
5237 #endif
5238       }
5239       if (a.type==_INT_){
5240 	longlong tmp=((longlong) a.val-b.val);
5241 	a.val=(int)tmp;
5242 	if (a.val==tmp)
5243 	  return a;
5244 	return a=tmp;
5245       }
5246       if (a.type==_ZINT && a.ref_count()==1){
5247 	mpz_t * ptr=a._ZINTptr;
5248 	mpz_sub(*ptr,*ptr,*b._ZINTptr);
5249 	if (mpz_sizeinbase(*ptr,2)<32){
5250 	  return a=mpz_get_si(*ptr);
5251 	}
5252 	return a;
5253       }
5254       if (a.type==_VECT && a.subtype==_POLY1__VECT && a.ref_count()==1){
5255 	if (subgen_poly(a,b,true)._VECTptr->empty())
5256 	  a=0;
5257 	return a;
5258       }
5259     }
5260     if (a.type==_ZINT && b.type==_INT_ && a.ref_count()==1){
5261       mpz_t * ptr=a._ZINTptr;
5262       if (b.val>0)
5263 	mpz_sub_ui(*ptr,*ptr,b.val);
5264       else
5265 	mpz_add_ui(*ptr,*ptr,-b.val);
5266       if (mpz_sizeinbase(*ptr,2)<32){
5267 	return a=mpz_get_si(*ptr);
5268       }
5269       return a;
5270     }
5271     // if (!( (++control_c_counter) & control_c_counter_mask))
5272 #ifdef TIMEOUT
5273     control_c();
5274 #endif
5275     if (ctrl_c || interrupted) {
5276       interrupted = true; ctrl_c=false;
5277       return a=gensizeerr(gettext("Stopped by user interruption."));
5278     }
5279     return a=operator_minus(a,b,contextptr);
5280   }
5281 
operator_minus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)5282   gen operator_minus(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
5283     // if (!( (++control_c_counter) & control_c_counter_mask))
5284 #ifdef TIMEOUT
5285     control_c();
5286 #endif
5287     if (ctrl_c || interrupted) {
5288       interrupted = true; ctrl_c=false;
5289       return gensizeerr(gettext("Stopped by user interruption."));
5290     }
5291     register ref_mpz_t * e;
5292     switch ( t) {
5293     case _ZINT__ZINT:
5294       e = new ref_mpz_t;
5295       mpz_sub(e->z,*a._ZINTptr,*b._ZINTptr);
5296       return e;
5297     case _DOUBLE___DOUBLE_:
5298       return a._DOUBLE_val-b._DOUBLE_val;
5299     case _FLOAT___FLOAT_:
5300       return a._FLOAT_val-b._FLOAT_val;
5301     case _VECT__VECT:
5302       if (// abs_calc_mode(contextptr)==38 &&
5303 	  (a.subtype==_MATRIX__VECT ||b.subtype==_MATRIX__VECT)){
5304 	if (!ckmatrix(a) || !ckmatrix(b))
5305 	  return gensizeerr(contextptr);
5306 	if (a._VECTptr->size()!=b._VECTptr->size() || a._VECTptr->front()._VECTptr->size()!=b._VECTptr->front()._VECTptr->size())
5307 	  return gendimerr(contextptr);
5308       }
5309       if (a.subtype==_POLY1__VECT)
5310 	return subgen_poly(a,b);
5311       if (a.subtype==_PNT__VECT)
5312 	return gen(makenewvecteur(a._VECTptr->front()-b,a._VECTptr->back()),a.subtype);
5313       if (a.subtype!=_POINT__VECT && equalposcomp((int *)_GROUP__VECT_subtype,a.subtype))
5314 	return sym_sub(a,b,contextptr);
5315       if (a.subtype==_POINT__VECT && b.subtype==_POINT__VECT)
5316 	return gen(subvecteur(*a._VECTptr,*b._VECTptr),0);
5317       return gen(subvecteur(*a._VECTptr,*b._VECTptr),a.subtype);
5318     case _MAP__MAP:
5319       {
5320 	int arows,acols,an,brows,bcols,bn;
5321 	if ( (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)) || (is_sparse_vector(a,arows,an) && is_sparse_vector(b,brows,bn)) ){
5322 	  gen_map res;
5323 	  gen g(res);
5324 	  sparse_sub(*a._MAPptr,*b._MAPptr,*g._MAPptr);
5325 	  return g;
5326 	}
5327       }
5328     case _INT___ZINT:
5329       e =  new ref_mpz_t;
5330       if (a.val<0)
5331 	mpz_add_ui(e->z,*b._ZINTptr,-a.val);
5332       else
5333 	mpz_sub_ui(e->z,*b._ZINTptr,a.val);
5334       mpz_neg(e->z,e->z);
5335       return(e);
5336     case _ZINT__INT_:
5337       e =  new ref_mpz_t;
5338       if (b.val<0)
5339 	mpz_add_ui(e->z,*a._ZINTptr,-b.val);
5340       else
5341 	mpz_sub_ui(e->z,*a._ZINTptr,b.val);
5342       return(e);
5343     case _INT___DOUBLE_:
5344       return a.val-b._DOUBLE_val;
5345     case _DOUBLE___INT_:
5346       return a._DOUBLE_val-b.val;
5347     case _INT___FLOAT_:
5348       return giac_float(a.val)-b._FLOAT_val;
5349     case _FLOAT___INT_:
5350       return a._FLOAT_val-giac_float(b.val);
5351     case _DOUBLE___FLOAT_:
5352       return giac_float(a._DOUBLE_val)-b._FLOAT_val;
5353     case _FLOAT___DOUBLE_:
5354       return a._FLOAT_val-giac_float(b._DOUBLE_val);
5355     case _FLOAT___FRAC:
5356       return a-evalf2bcd(b,1,contextptr);
5357     case _DOUBLE___FRAC:
5358       return a-ck_evalf_double(b,contextptr);
5359     case _FRAC__FLOAT_:
5360       return evalf2bcd(a,1,contextptr)-b;
5361     case _FRAC__DOUBLE_:
5362       return ck_evalf_double(a,contextptr)-b;
5363     case _ZINT__DOUBLE_:
5364       return mpz_get_d(*a._ZINTptr)-b._DOUBLE_val;
5365     case _DOUBLE___ZINT:
5366       return a._DOUBLE_val-mpz_get_d(*b._ZINTptr);
5367     case _DOUBLE___REAL:
5368       return a._DOUBLE_val-real2double(*b._REALptr);
5369     case _REAL__DOUBLE_:
5370       return real2double(*a._REALptr)-b._DOUBLE_val;
5371     case _CPLX__INT_: case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
5372       return gen(*a._CPLXptr-b,*(a._CPLXptr+1));
5373     case _INT___CPLX: case _ZINT__CPLX: case _DOUBLE___CPLX: case _FLOAT___CPLX: case _REAL__CPLX:
5374       return gen(a-*b._CPLXptr,-*(b._CPLXptr+1));
5375     case _CPLX__CPLX:
5376       return adjust_complex_display(gen(*a._CPLXptr - *b._CPLXptr, *(a._CPLXptr+1) - *(b._CPLXptr+1)),a,b);
5377     case _POLY__POLY:
5378       return subpoly(a,b);
5379     case _FRAC__FRAC:
5380         return (*a._FRACptr)-(*b._FRACptr);
5381     case _SPOL1__SPOL1:
5382       return spsub(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
5383     case _EXT__EXT:
5384       return ext_sub(a,b,contextptr);
5385     case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__MOD: case _POLY__REAL: case _POLY__USER:
5386       return subpoly(*a._POLYptr,b);
5387     case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _MOD__POLY:case _USER__POLY: case _REAL__POLY:
5388       return subpoly(a,*b._POLYptr);
5389     case _MOD__MOD:
5390 #ifdef SMARTPTR64
5391       return modsub( (ref_modulo *) (* ((ulonglong * ) &a) >> 16), (ref_modulo *) (* ((ulonglong * ) &b) >> 16) );
5392 #else
5393       return modsub(a.__MODptr,b.__MODptr);
5394 #endif
5395     case _REAL__REAL:
5396       return (*a._REALptr)-(*b._REALptr);
5397     default:
5398       if (is_undef(a))
5399 	return a;
5400       if (is_undef(b))
5401 	return b;
5402       if (a.type==_FLOAT_){
5403 	gen b1;
5404 	if (b.type==_VECT)
5405 	  return sym_sub(a,b,contextptr);
5406 	if (has_evalf(b,b1,1,contextptr) && b.type!=b1.type)
5407 	  return operator_minus(a,b1,contextptr);
5408 	return operator_minus(evalf_double(a,1,contextptr),b,contextptr);
5409       }
5410       if (b.type==_FLOAT_){
5411 	if (a.type==_VECT)
5412 	  return sym_sub(a,b,contextptr);
5413 	gen a1;
5414 	if (has_evalf(a,a1,1,contextptr) && a.type!=a1.type)
5415 	  return operator_minus(a1,b,contextptr);
5416 	return operator_minus(a,evalf_double(b,1,contextptr),contextptr);
5417       }
5418       if (a.type==_SPOL1)
5419 	return spsub(*a._SPOL1ptr,gen2spol1(b),contextptr);
5420       if (b.type==_SPOL1)
5421 	return spsub(gen2spol1(a),*b._SPOL1ptr,contextptr);
5422       if (a.type==_USER)
5423 	return (*a._USERptr)-b;
5424       if (b.type==_USER)
5425 	return (-b)+a;
5426       if (a.type==_REAL)
5427 	return a._REALptr->substract(b,contextptr);
5428       if (b.type==_REAL)
5429 	return operator_plus(-(*b._REALptr),a,contextptr);
5430       if (a.type==_STRNG)
5431 	return a;
5432       return sym_sub(a,b,contextptr);
5433     }
5434   }
5435 
operator_minus(const gen & a,const gen & b,GIAC_CONTEXT)5436   gen operator_minus (const gen & a,const gen & b,GIAC_CONTEXT){
5437     register unsigned t=(a.type<< _DECALAGE) | b.type;
5438     if (!t)
5439       return((longlong) a.val-b.val);
5440     return operator_minus(a,b,t,contextptr);
5441   }
5442 
operator -(const gen & a,const gen & b)5443   gen operator - (const gen & a,const gen & b){
5444     register unsigned t=(a.type<< _DECALAGE) | b.type;
5445     if (!t)
5446       return((longlong) a.val-b.val);
5447     return operator_minus(a,b,t,context0);
5448   }
5449 
sym_sub(const gen & a,const gen & b,GIAC_CONTEXT)5450   gen sym_sub(const gen & a,const gen & b,GIAC_CONTEXT){
5451 #ifdef TIMEOUT
5452     control_c();
5453 #endif
5454     if (ctrl_c || interrupted) {
5455       interrupted = true; ctrl_c=false;
5456       return gensizeerr(gettext("Stopped by user interruption."));
5457     }
5458     if (a.is_symb_of_sommet(at_unit) || b.is_symb_of_sommet(at_unit))
5459       return a+(-b);
5460     if ( a.is_approx()){
5461       gen b1;
5462       if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
5463 #ifdef HAVE_LIBMPFR
5464 	if (a.type==_REAL){
5465 	  gen b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
5466 	  if (b2.is_approx())
5467 	    return a-b2;
5468 	}
5469 #endif
5470 	return a-b1;
5471       }
5472     }
5473     if ( b.is_approx()){
5474       gen a1;
5475       if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
5476 #ifdef HAVE_LIBMPFR
5477 	if (a.type==_REAL){
5478 	  gen a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
5479 	  if (a2.is_approx())
5480 	    return a2-b;
5481 	}
5482 #endif
5483 	return a1-b;
5484       }
5485     }
5486     if ( (a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet) ){
5487       if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
5488 	return a._SYMBptr->feuille._VECTptr->front()-b._SYMBptr->feuille._VECTptr->front();
5489       else {
5490 	gen a_(a);
5491 	if (a.is_symb_of_sommet(at_curve) && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2 && a._SYMBptr->feuille._VECTptr->front().type==_VECT){
5492 	  // adjust param and cartesian eq
5493 	  vecteur v=*a._SYMBptr->feuille._VECTptr->front()._VECTptr;
5494 	  if (v.size()==7)
5495 	    v[6] -= b;
5496 	  if (v.size()>=6){
5497 	    v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(x__IDNT_e+re(b,contextptr),y__IDNT_e+im(b,contextptr)),false,contextptr);
5498 	    a_=symbolic(at_curve,gen(makevecteur(gen(v,a._SYMBptr->feuille._VECTptr->front().subtype),a._SYMBptr->feuille._VECTptr->back()),a._SYMBptr->feuille.subtype));
5499 	  }
5500 	}
5501 	return symbolic_plot_makevecteur(a_._SYMBptr->sommet,a_._SYMBptr->feuille-b,true,contextptr);
5502       }
5503     }
5504     if ( (b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet) )
5505       return sym_add(-b,a,contextptr);
5506     gen var1,var2,res1,res2;
5507     if (is_algebraic_program(a,var1,res1) && is_algebraic_program(b,var2,res2)){
5508       if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
5509 	res2=subst(res2,var2,var1,false,contextptr);
5510 	var2=var1;
5511       }
5512       if (var1==var2)
5513 	return symbolic(at_program,gen(makevecteur(var1,0,operator_minus(res1,res2,contextptr)),_SEQ__VECT));
5514     }
5515     if (a.type==_VECT)
5516       return sym_add(a,-b,contextptr);
5517     if (b.type==_VECT)
5518       return sym_add(-b,a,contextptr);
5519     if (is_undef(a))
5520       return a;
5521     if (is_undef(b))
5522       return b;
5523     if (is_inf(a)){
5524       if (is_inf(b)){
5525 	if ((a==plus_inf) && (b==minus_inf))
5526 	  return a;
5527 	if ((a==minus_inf) && (b==plus_inf))
5528 	  return a;
5529 	return undef;
5530       }
5531       else
5532 	return a;
5533     }
5534     if (a.type==_FRAC){
5535       if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
5536         return (*a._FRACptr)-b;
5537       if (b.is_symb_of_sommet(at_neg))
5538 	return a+b._SYMBptr->feuille;
5539       if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
5540 	return (*a._FRACptr)-fraction(1,b._SYMBptr->feuille);
5541       return sym_sub(_FRAC2_SYMB(a),b,contextptr);
5542     }
5543     if (b.type==_FRAC){
5544       if ( (a.type!=_SYMB) && (a.type!=_IDNT) )
5545         return a-(*b._FRACptr);
5546       if (a.is_symb_of_sommet(at_neg))
5547 	return -(a._SYMBptr->feuille+b);
5548       if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
5549 	return fraction(1,a._SYMBptr->feuille)-(*b._FRACptr);
5550       return sym_sub(a,_FRAC2_SYMB(b),contextptr);
5551     }
5552     if (a.type==_EXT){
5553         if (a.is_constant() && (b.type==_POLY))
5554             return subpoly(a,*b._POLYptr);
5555         else
5556             return algebraic_EXTension(*a._EXTptr-b,*(a._EXTptr+1));
5557     }
5558     if (b.type==_EXT){
5559         if (b.is_constant() && (a.type==_POLY))
5560             return subpoly(*a._POLYptr,b);
5561         else
5562             return algebraic_EXTension(a-*b._EXTptr,*(b._EXTptr+1));
5563     }
5564     if (a==b)
5565       return chkmod(zero,a);
5566     if (is_inf(b))
5567       return -b;
5568     if (is_exactly_zero(b))
5569       return a;
5570     if (is_exactly_zero(a))
5571       return -b;
5572     /*
5573     if (a.type==_SYMB && a._SYMBptr->sommet==at_equal){
5574       vecteur & va=*a._SYMBptr->feuille._VECTptr;
5575       if (b.type==_SYMB && b._SYMBptr->sommet==at_equal){
5576 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5577 	return new_ref_symbolic(symbolic(at_equal,makesequence(va.front()-vb.front(),va.back()-vb.back())));
5578       }
5579       else
5580 	return new_ref_symbolic(symbolic(at_equal,makesequence(va.front()-b,va.back()-b)));
5581     }
5582     if (b.type==_SYMB && b._SYMBptr->sommet==at_equal){
5583       vecteur & vb=*b._SYMBptr->feuille._VECTptr;
5584       return new_ref_symbolic(symbolic(at_equal,makesequence(a-vb.front(),a-vb.back())));
5585     }
5586     */
5587     if (is_inequality(a) || is_inequality(b))
5588       return a+(-b);
5589     if ((a.type==_SYMB) && (b.type==_SYMB)){
5590       if (a._SYMBptr->sommet==at_plus) {
5591 	if (b._SYMBptr->sommet==at_plus)
5592 	  return new_ref_symbolic(symbolic(at_plus,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),negvecteur(*(b._SYMBptr->feuille._VECTptr))),_SEQ__VECT)));
5593 	else
5594 	  return new_ref_symbolic(symbolic(*a._SYMBptr,-b));
5595       }
5596       else {
5597 	if (b._SYMBptr->sommet==at_plus)
5598 	  return new_ref_symbolic(symbolic(*(-b)._SYMBptr,a));
5599 	else
5600 	  return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5601       }
5602     }
5603     if (b.type==_SYMB){
5604       if (b._SYMBptr->sommet==at_plus)
5605 	return new_ref_symbolic(symbolic(*(-b)._SYMBptr,a));
5606       else
5607 	return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5608     }
5609     if (a.type==_SYMB){
5610       if (a._SYMBptr->sommet==at_plus)
5611 	return new_ref_symbolic(symbolic(*a._SYMBptr,-b));
5612       else
5613 	return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5614     }
5615     if ((a.type==_IDNT) || (b.type==_IDNT))
5616       return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5617     if (a.type==_MOD)
5618       return a-makemod(b,*(a._MODptr+1));
5619     if (b.type==_MOD)
5620       return makemod(a,*(b._MODptr+1))-b;
5621     return new_ref_symbolic(symbolic(at_plus,makesequence(a,-b)));
5622     // settypeerr(gettext("sym_sub"));
5623   }
5624 
negfirst(const vecteur & v)5625   static vecteur negfirst(const vecteur & v){
5626     vecteur w(v);
5627     if (!w.empty())
5628       w.front()=-w.front();
5629     return w;
5630   }
5631 
operator -(const gen & a)5632   gen operator -(const gen & a){
5633     ref_mpz_t *e ;
5634     switch (a.type ) {
5635     case _INT_:
5636       return(-a.val);
5637     case _ZINT:
5638       e=new ref_mpz_t;
5639       mpz_neg(e->z,*a._ZINTptr);
5640       return(e);
5641     case _DOUBLE_:
5642       return -(a._DOUBLE_val);
5643     case _FLOAT_:
5644       return -(a._FLOAT_val);
5645     case _CPLX: {
5646       const gen * aptr=a._CPLXptr;
5647       if (a.subtype==3)
5648 	return adjust_complex_display(gen(-aptr->_DOUBLE_val,-(aptr+1)->_DOUBLE_val),a);
5649       return adjust_complex_display(gen(-*aptr,-*(aptr+1)),a);
5650     }
5651     case _IDNT:
5652       if ((a==undef) || (a==unsigned_inf))
5653 	return a;
5654       return new_ref_symbolic(symbolic(at_neg,a));
5655     case _SYMB:
5656       if (a==plus_inf)
5657 	return minus_inf;
5658       if (a==minus_inf)
5659 	return plus_inf;
5660       if (a._SYMBptr->sommet==at_neg)
5661 	return a._SYMBptr->feuille;
5662       if (a._SYMBptr->sommet==at_unit){
5663 	// if (equalposcomp(lidnt(a),cst_pi)!=0) return -evalf(b,1,context0);
5664 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(-a._SYMBptr->feuille._VECTptr->front(),a._SYMBptr->feuille._VECTptr->back())));
5665       }
5666       if (a._SYMBptr->sommet==at_plus)
5667 	return new_ref_symbolic(symbolic(at_plus,gen(negvecteur(*a._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
5668       if (a._SYMBptr->sommet==at_interval && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2){
5669 	return new_ref_symbolic(symbolic(at_interval,gen(makenewvecteur(-a._SYMBptr->feuille._VECTptr->back(),-a._SYMBptr->feuille._VECTptr->front()),_SEQ__VECT)));
5670       }
5671       if (equalposcomp(plot_sommets,a._SYMBptr->sommet)){
5672 	return symbolic_plot_makevecteur(a._SYMBptr->sommet,-a._SYMBptr->feuille,false,context0);
5673       }
5674       if (a.is_symb_of_sommet(at_program)){
5675 	gen a1,b;
5676 	if (is_algebraic_program(a,a1,b))
5677 	  return symbolic(at_program,gen(makevecteur(a1,0,-b),_SEQ__VECT));
5678       }
5679       if (a._SYMBptr->sommet==at_equal || a._SYMBptr->sommet==at_equal2 || a._SYMBptr->sommet==at_different || a._SYMBptr->sommet==at_same)
5680 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(-a._SYMBptr->feuille._VECTptr->front(),-a._SYMBptr->feuille._VECTptr->back())));
5681       if (is_inequality(a))
5682 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(-a._SYMBptr->feuille._VECTptr->back(),-a._SYMBptr->feuille._VECTptr->front())));
5683       return new_ref_symbolic(symbolic(at_neg,a));
5684     case _VECT:
5685       if (a.subtype==_VECTOR__VECT && a._VECTptr->size()==2)
5686 	return gen(makenewvecteur(a._VECTptr->back(),a._VECTptr->front()),_VECTOR__VECT);
5687       if (a.subtype==_PNT__VECT)
5688 	return gen(negfirst(*a._VECTptr),a.subtype);
5689       return gen(negvecteur(*a._VECTptr),a.subtype);
5690     case _MAP:{
5691       gen_map res;
5692       gen g(res);
5693       *g._MAPptr=*a._MAPptr;
5694       sparse_neg(*g._MAPptr);
5695       return g;
5696     }
5697     case _POLY:
5698       return -(*a._POLYptr);
5699     case _EXT:
5700       return algebraic_EXTension(-(*a._EXTptr),*(a._EXTptr+1));
5701     case _USER:
5702       return -(*a._USERptr);
5703     case _MOD:
5704       return makemod(-*a._MODptr,*(a._MODptr+1));
5705     case _FRAC:
5706       return fraction(-(a._FRACptr->num),a._FRACptr->den);
5707     case _SPOL1:
5708       return spneg(*a._SPOL1ptr,context0);
5709     case _STRNG:
5710       if (is_undef(a)) return a;
5711       return string2gen("-"+(*a._STRNGptr),false);
5712     case _REAL:
5713       return -*a._REALptr;
5714     default:
5715       return new_ref_symbolic(symbolic(at_neg,a));
5716     }
5717   }
5718 
mulpoly(const gen & th,const gen & other)5719   static gen mulpoly(const gen & th,const gen & other){
5720     if ((th.type!=_POLY) || (other.type!=_POLY)){
5721 #ifndef NO_STDEXCEPT
5722       settypeerr(gettext("mulpoly"));
5723 #endif
5724       return gentypeerr(gettext("mulpoly"));
5725     }
5726     vector< monomial<gen> >::const_iterator ita = th._POLYptr->coord.begin();
5727     vector< monomial<gen> >::const_iterator ita_end = th._POLYptr->coord.end();
5728     vector< monomial<gen> >::const_iterator itb = other._POLYptr->coord.begin();
5729     vector< monomial<gen> >::const_iterator itb_end = other._POLYptr->coord.end();
5730     // first some trivial cases
5731     if (ita==ita_end)
5732       return(th);
5733     if (itb==itb_end)
5734       return(other);
5735     if (is_one(*th._POLYptr))
5736       return other;
5737     if (is_one(*other._POLYptr))
5738       return th;
5739     // Now look if length a=1 or length b=1, happens frequently
5740     // think of x^3*y^2*z translated to internal form
5741     int c1=int(th._POLYptr->coord.size());
5742     if (c1==1)
5743       return other._POLYptr->shift(th._POLYptr->coord.front().index,th._POLYptr->coord.front().value);
5744     int c2=int(other._POLYptr->coord.size());
5745     if (c2==1)
5746       return th._POLYptr->shift(other._POLYptr->coord.front().index,other._POLYptr->coord.front().value);
5747     ref_polynome * resptr = new ref_polynome(th._POLYptr->dim);
5748     mulpoly(*th._POLYptr,*other._POLYptr,resptr->t,0);
5749     return resptr;
5750   }
5751 
multfirst(const gen & a,const vecteur & v)5752   static vecteur multfirst(const gen & a,const vecteur & v){
5753     vecteur w(v);
5754     if (!w.empty())
5755       w.front()=v.front()*a;
5756     return w;
5757   }
5758 
multgen_poly(const gen & a,const vecteur & b,int subtype)5759   static gen multgen_poly(const gen & a,const vecteur & b,int subtype){
5760     gen res(vecteur(0),subtype);
5761     multvecteur(a,b,*res._VECTptr);
5762     return res;
5763   }
5764 
multgen_poly(const vecteur & a,const vecteur & b)5765   static gen multgen_poly(const vecteur & a,const vecteur & b){
5766     gen res(vecteur(0), _POLY1__VECT);
5767     operator_times(a,b,0,*res._VECTptr);
5768     return res;
5769   }
5770 
5771   // a*b -> tmp, modifies tmp in place
type_operator_times(const gen & a,const gen & b,gen & tmp)5772   void type_operator_times(const gen & a,const gen &b,gen & tmp){
5773     register unsigned t=(a.type<< _DECALAGE) | b.type;
5774 #ifndef EMCC
5775     if (tmp.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5776 #ifdef DOUBLEVAL
5777       tmp._DOUBLE_val=a._DOUBLE_val*b._DOUBLE_val;
5778 #else
5779       *((double *) &tmp) = (*((double *) &a)) * (*((double *) &b));
5780       tmp.type = _DOUBLE_;
5781 #endif
5782       return ;
5783     }
5784 #endif
5785     if (!t && tmp.type==_INT_ ){
5786       register longlong ab=longlong(a.val)*b.val;
5787       tmp.val=(int)ab;
5788 #if 1
5789       if (ab>>31)
5790 	tmp=ab;
5791 #else
5792       if (tmp.val!=ab)
5793 	tmp=ab;
5794 #endif
5795       return;
5796     }
5797     if (tmp.type==_ZINT && tmp.ref_count()==1){
5798       mpz_t * ptr=tmp._ZINTptr;
5799       switch (t){
5800       case _INT___INT_:
5801 	tmp=longlong(a.val)*b.val;
5802 	return;
5803       case _ZINT__ZINT:
5804 	mpz_mul(*ptr,*a._ZINTptr,*b._ZINTptr);
5805 	return ;
5806       case _ZINT__INT_:
5807 	if (b.val<0){
5808 	  mpz_mul_ui(*ptr,*a._ZINTptr,-b.val);
5809 	  mpz_neg(*ptr,*ptr);
5810 	}
5811 	else
5812 	  mpz_mul_ui(*ptr,*a._ZINTptr,b.val);
5813 	return;
5814       case _INT___ZINT:
5815 	if (a.val<0){
5816 	  mpz_mul_ui(*ptr,*b._ZINTptr,-a.val);
5817 	  mpz_neg(*ptr,*ptr);
5818 	}
5819 	else
5820 	  mpz_mul_ui(*ptr,*b._ZINTptr,a.val);
5821 	return;
5822       }
5823     }
5824     tmp=a*b;
5825   }
5826 
is_int_zint_vecteur(const vecteur & m)5827   bool is_int_zint_vecteur(const vecteur & m){
5828     const_iterateur it=m.begin(),itend=m.end();
5829     for (;it!=itend;++it){
5830       int t=it->type;
5831       if (t!=_INT_ && t!=_ZINT) return false;
5832     }
5833     return true;
5834   }
5835 
type_operator_plus_times(const gen & a,const gen & b,gen & c)5836   void type_operator_plus_times(const gen & a,const gen & b,gen & c){
5837     register unsigned t=(a.type<< _DECALAGE) | b.type;
5838 #ifndef EMCC
5839     if (c.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5840 #ifdef DOUBLEVAL
5841       c._DOUBLE_val += a._DOUBLE_val*b._DOUBLE_val;
5842 #else
5843       *((double *) &c) += (*((double *) &a)) * (*((double *) &b));
5844       c.type = _DOUBLE_;
5845 #endif
5846       return ;
5847     }
5848 #endif
5849     if (c.type==_ZINT && c.ref_count()==1){
5850       switch (t){
5851       case _ZINT__ZINT:
5852 	mpz_addmul(*c._ZINTptr,*a._ZINTptr,*b._ZINTptr);
5853 	return;
5854       case _ZINT__INT_:
5855 	if (b.val<0)
5856 	  mpz_submul_ui(*c._ZINTptr,*a._ZINTptr,-b.val);
5857 	else
5858 	  mpz_addmul_ui(*c._ZINTptr,*a._ZINTptr,b.val);
5859 	return;
5860       case _INT___ZINT:
5861 	if (a.val<0){
5862 	  mpz_submul_ui(*c._ZINTptr,*b._ZINTptr,-a.val);
5863 	}
5864 	else
5865 	  mpz_addmul_ui(*c._ZINTptr,*b._ZINTptr,a.val);
5866 	return;
5867       }
5868     }
5869     if (c.type==_EXT && a.type==_EXT && b.type==_EXT){
5870       if ((c._EXTptr+1)->type==_VECT && *(a._EXTptr+1)==*(c._EXTptr+1) && *(b._EXTptr+1)==*(c._EXTptr+1) && a._EXTptr->type==_VECT && b._EXTptr->type==_VECT && c._EXTptr->type==_VECT){
5871 	vecteur & v = *(c._EXTptr+1)->_VECTptr;
5872 	if (v.size()==3 && v[0]==1 && v[1]==0 && a._EXTptr->_VECTptr->size()==2 && b._EXTptr->_VECTptr->size()==2 && c._EXTptr->_VECTptr->size()==2){
5873 	  gen a1=a._EXTptr->_VECTptr->front(),a0=a._EXTptr->_VECTptr->back(),b1=b._EXTptr->_VECTptr->front(),b0=b._EXTptr->_VECTptr->back(),c1=c._EXTptr->_VECTptr->front(),c0=c._EXTptr->_VECTptr->back();
5874 	  gen d1=a1*b0+a0*b1+c1,d0=a0*b0-v[2]*a1*b1+c0;
5875 	  if (is_zero(d1)){ c=d0; return; }
5876 	  gen d=new ref_vecteur(2);
5877 	  d._VECTptr->front()=d1;
5878 	  d._VECTptr->back()=d0;
5879 	  if (c.ref_count()==1)
5880 	    *c._EXTptr=d;
5881 	  else
5882 	    c=algebraic_EXTension(d,*(c._EXTptr+1));
5883 	}
5884 	else {
5885 	  gen d=new ref_vecteur;
5886 	  vecteur ab,rem;
5887 	  operator_times(*a._EXTptr->_VECTptr,*b._EXTptr->_VECTptr,0,ab);
5888 	  addmodpoly(ab,*c._EXTptr->_VECTptr,*d._VECTptr);
5889 	  if (c.ref_count()==1){
5890 	    DivRem(*d._VECTptr,v,0,ab,rem); // take remainder!
5891 	    if (rem.size()<2){ if (rem.empty()) c=0; else c=rem.front();}
5892 	    else {
5893 	      //gen dbg=ext_reduce(d,*(c._EXTptr+1));
5894 	      d._VECTptr->swap(rem);
5895 	      *c._EXTptr=d;
5896 	      //if (dbg!=c) CERR << "error" << '\n';
5897 	    }
5898 	  }
5899 	  else
5900 	    c=ext_reduce(d,*(c._EXTptr+1));
5901 	}
5902 	return;
5903       }
5904     }
5905     if (c.type==_VECT && c.ref_count()==1 && a.type==_VECT && b.type==_VECT && a._VECTptr->size()<KARAMUL_SIZE && b._VECTptr->size()<KARAMUL_SIZE && is_int_zint_vecteur(*a._VECTptr) && is_int_zint_vecteur(*b._VECTptr) && is_int_zint_vecteur(*c._VECTptr)){
5906       add_mulmodpoly(a._VECTptr->begin(),a._VECTptr->end(),b._VECTptr->begin(),b._VECTptr->end(),0,*c._VECTptr);
5907       return;
5908     }
5909     gen g;
5910     type_operator_times(a,b,g);
5911     if (g.type==_ZINT)
5912       swapgen(c,g);
5913     c += g;
5914   }
5915 
type_operator_minus_times(const gen & a,const gen & b,gen & c)5916   void type_operator_minus_times(const gen & a,const gen & b,gen & c){
5917     register unsigned t=(a.type<< _DECALAGE) | b.type;
5918 #ifndef EMCC
5919     if (c.type==_DOUBLE_ && t==_DOUBLE___DOUBLE_){
5920 #ifdef DOUBLEVAL
5921       c._DOUBLE_val -= a._DOUBLE_val*b._DOUBLE_val;
5922 #else
5923       *((double *) &c) -= (*((double *) &a)) * (*((double *) &b));
5924       c.type = _DOUBLE_;
5925 #endif
5926       return ;
5927     }
5928 #endif
5929     if (c.type==_ZINT && c.ref_count()==1){
5930       switch (t){
5931       case _ZINT__ZINT:
5932 	mpz_submul(*c._ZINTptr,*a._ZINTptr,*b._ZINTptr);
5933 	return;
5934       case _ZINT__INT_:
5935 	if (b.val<0)
5936 	  mpz_addmul_ui(*c._ZINTptr,*a._ZINTptr,-b.val);
5937 	else
5938 	  mpz_submul_ui(*c._ZINTptr,*a._ZINTptr,b.val);
5939 	return;
5940       case _INT___ZINT:
5941 	if (a.val<0){
5942 	  mpz_addmul_ui(*c._ZINTptr,*b._ZINTptr,-a.val);
5943 	}
5944 	else
5945 	  mpz_submul_ui(*c._ZINTptr,*b._ZINTptr,a.val);
5946 	return;
5947       }
5948     }
5949     gen g;
5950     type_operator_times(a,b,g);
5951     c -= g;
5952   }
5953 
double_times_frac(const gen & a,const fraction & b,GIAC_CONTEXT)5954   static gen double_times_frac(const gen & a,const fraction & b,GIAC_CONTEXT){
5955     gen n=a*b.num,d=b.den;
5956     return rdiv(n,d,contextptr);
5957   }
5958 
mult_cplx(const gen & a,const gen & b,GIAC_CONTEXT)5959   static gen mult_cplx(const gen & a,const gen & b,GIAC_CONTEXT){
5960     gen * aptr=a._CPLXptr,*bptr=b._CPLXptr;
5961     unsigned t= (aptr->type | ((aptr+1)->type << 8) | (bptr->type << 16) | ((bptr+1)->type << 24));
5962     if (t==(_DOUBLE_ | (_DOUBLE_<<8) | (_DOUBLE_ <<16) | (_DOUBLE_ <<24))){
5963       double ar=aptr->_DOUBLE_val,ai=(aptr+1)->_DOUBLE_val,
5964 	br=bptr->_DOUBLE_val,bi=(bptr+1)->_DOUBLE_val;
5965       return gen(ar*br-ai* bi, br*ai+ar*bi);
5966     }
5967     if (t==(_ZINT | (_ZINT<<8) | (_ZINT <<16) | (_ZINT <<24))){
5968       mpz_t & ax=*aptr->_ZINTptr;
5969       mpz_t & ay=*((aptr+1)->_ZINTptr);
5970       mpz_t & bx=*bptr->_ZINTptr;
5971       mpz_t & by=*((bptr+1)->_ZINTptr);
5972       // (ax+i*ay)*(bx+i*by)=ax*bx-ay*by+i*(ax*by+ay*bx)
5973       // imaginary part is also (ax+ay)*(bx+by)-ax*bx-ay*by, Karatsuba trick
5974       mpz_t axbx,ayby,r;
5975 #ifdef USE_GMP_REPLACEMENTS
5976       mpz_init(axbx); mpz_init(ayby); mpz_init(r);
5977 #else
5978       int n1=mpz_size(ax)+mpz_size(bx),n2=mpz_size(ay)+mpz_size(by);
5979       mpz_init2(axbx,n1); mpz_init2(ayby,n2); mpz_init2(r,giacmax(n1,n2)+2);
5980 #endif
5981       mpz_mul(axbx,ax,bx);
5982       mpz_add(r,ax,ay);
5983       mpz_add(ayby,bx,by); // temporary use
5984       mpz_mul(r,r,ayby);
5985       mpz_sub(r,r,axbx);
5986       mpz_mul(ayby,ay,by);
5987       mpz_sub(r,r,ayby);
5988       gen I=r;
5989       mpz_sub(r,axbx,ayby);
5990       gen R=r;
5991       R=gen(R,I);
5992       mpz_clear(r); mpz_clear(ayby); mpz_clear(axbx);
5993       return R;
5994     }
5995 #if defined HAVE_LIBMPFR && !defined NO_RTTI
5996     if (t==(_REAL | (_REAL<<8) | (_REAL <<16) | (_REAL <<24))){
5997       real_object & ax=*aptr->_REALptr;
5998       real_object & ay=*((aptr+1)->_REALptr);
5999       real_object & bx=*bptr->_REALptr;
6000       real_object & by=*((bptr+1)->_REALptr);
6001       if (!dynamic_cast<real_interval *>(&ax) ||
6002 	  !dynamic_cast<real_interval *>(&ay) ||
6003 	  !dynamic_cast<real_interval *>(&bx) ||
6004 	  !dynamic_cast<real_interval *>(&by) ){
6005 	mpfr_t axbx,ayby,r;
6006 	int nbits=mpfr_get_prec(ax.inf);
6007 	nbits=giacmin(nbits,mpfr_get_prec(bx.inf));
6008 	mpfr_init2(axbx,nbits); mpfr_init2(ayby,nbits); mpfr_init2(r,nbits);
6009 	mpfr_mul(axbx,ax.inf,bx.inf,MPFR_RNDN);
6010 	mpfr_add(r,ax.inf,ay.inf,MPFR_RNDN);
6011 	mpfr_add(ayby,bx.inf,by.inf,MPFR_RNDN); // temporary use
6012 	mpfr_mul(r,r,ayby,MPFR_RNDN);
6013 	mpfr_sub(r,r,axbx,MPFR_RNDN);
6014 	mpfr_mul(ayby,ay.inf,by.inf,MPFR_RNDN);
6015 	mpfr_sub(r,r,ayby,MPFR_RNDN);
6016 	gen I=real_object(r);
6017 	mpfr_sub(r,axbx,ayby,MPFR_RNDN);
6018 	gen R=real_object(r);
6019 	R=gen(R,I);
6020 	mpfr_clear(r); mpfr_clear(ayby); mpfr_clear(axbx);
6021 	return R;
6022       }
6023     }
6024 #endif
6025     return gen(*aptr * (*bptr) - *(aptr+1)* (*(bptr+1)),
6026 	       (*bptr) * (*(aptr+1)) + *(bptr+1) * (*aptr));
6027   }
6028 
operator_times(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT)6029   static gen operator_times(const gen & a,const gen & b,unsigned t,GIAC_CONTEXT){
6030     static bool warnpy=true;
6031     // COUT << a << "*" << b << '\n';
6032     // if (!( (++control_c_counter) & control_c_counter_mask))
6033 #ifdef TIMEOUT
6034     control_c();
6035 #endif
6036     if (ctrl_c || interrupted) {
6037       interrupted = true; ctrl_c=false;
6038       return gensizeerr(gettext("Stopped by user interruption."));
6039     }
6040     register ref_mpz_t * e;
6041     switch (t) {
6042     case _ZINT__ZINT:
6043       e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // ((mpz_size(*b._ZINTptr)+mpz_size(*b._ZINTptr))*mp_bits_per_limb);
6044       mpz_mul(e->z,*a._ZINTptr,*b._ZINTptr);
6045       return e;
6046     case _DOUBLE___DOUBLE_:
6047       return a._DOUBLE_val*b._DOUBLE_val;
6048     case _FLOAT___FLOAT_:
6049       return a._FLOAT_val*b._FLOAT_val;
6050     case _INT___ZINT:
6051       if (a.val==1) return b;
6052       e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // (mpz_size(*b._ZINTptr)*mp_bits_per_limb);
6053       if (a.val<0){
6054 	mpz_mul_ui(e->z,*b._ZINTptr,-a.val);
6055 	mpz_neg(e->z,e->z);
6056       }
6057       else
6058 	mpz_mul_ui(e->z,*b._ZINTptr,a.val);
6059       return gen(e);
6060     case _ZINT__INT_:
6061       if (b.val==1) return a;
6062       e=new ref_mpz_t(GIAC_MPZ_INIT_SIZE); // (mpz_size(*a._ZINTptr)*mp_bits_per_limb);
6063       if (b.val<0){
6064 	mpz_mul_ui(e->z,*a._ZINTptr,-b.val);
6065 	mpz_neg(e->z,e->z);
6066       }
6067       else
6068 	mpz_mul_ui(e->z,*a._ZINTptr,b.val);
6069       return gen(e);
6070     case _INT___DOUBLE_:
6071       return a.val*b._DOUBLE_val;
6072     case _DOUBLE___INT_:
6073       return a._DOUBLE_val*b.val;
6074     case _INT___FLOAT_:
6075       return giac_float(a.val)*b._FLOAT_val;
6076     case _FLOAT___INT_:
6077       return a._FLOAT_val*giac_float(b.val);
6078     case _DOUBLE___FLOAT_:
6079       return giac_float(a._DOUBLE_val)*b._FLOAT_val;
6080     case _FLOAT___DOUBLE_:
6081       return a._FLOAT_val*giac_float(b._DOUBLE_val);
6082     case _FLOAT___FRAC: case _DOUBLE___FRAC:
6083       return double_times_frac(a,*b._FRACptr,contextptr);
6084     case _FRAC__FLOAT_: case _FRAC__DOUBLE_:
6085       return double_times_frac(b,*a._FRACptr,contextptr);
6086     case _INT___FRAC: case _ZINT__FRAC:
6087       return a*(*b._FRACptr);
6088     case _FRAC__INT_: case _FRAC_ZINT:
6089       return (*a._FRACptr)*b;
6090     case _DOUBLE___ZINT:
6091       return a._DOUBLE_val*mpz_get_d(*b._ZINTptr);
6092     case _DOUBLE___REAL:
6093       return a._DOUBLE_val*real2double(*b._REALptr);
6094     case _REAL__DOUBLE_:
6095       return b._DOUBLE_val*real2double(*a._REALptr);
6096     case _ZINT__DOUBLE_:
6097       return mpz_get_d(*a._ZINTptr)*b._DOUBLE_val;
6098     case _CPLX__INT_:
6099       if (b.val==1) return a;
6100     case _CPLX__ZINT: case _CPLX__DOUBLE_: case _CPLX__FLOAT_: case _CPLX__REAL:
6101       return gen(*a._CPLXptr*b,*(a._CPLXptr+1)*b);
6102     case _INT___CPLX:
6103       return a.val==1?b:gen(a*(*b._CPLXptr),a*(*(b._CPLXptr+1)));
6104     case _ZINT__CPLX: case _DOUBLE___CPLX: case _FLOAT___CPLX: case _REAL__CPLX:
6105       return is_one(a)?b:gen(a*(*b._CPLXptr),a*(*(b._CPLXptr+1)));
6106     case _CPLX__CPLX:
6107       return adjust_complex_display(mult_cplx(a,b,contextptr),a,b);
6108 #if 1 //ndef GIAC_GGB
6109     case _INT___STRNG:{
6110       if (b.subtype==-1) return b;
6111       string res;
6112       for (int i=0;i<a.val;++i)
6113 	res += *b._STRNGptr;
6114       return string2gen(res,false);
6115     }
6116     case _STRNG__INT_:{
6117       if (a.subtype==-1) return a;
6118       string res;
6119       for (int i=0;i<b.val;++i)
6120 	res += *a._STRNGptr;
6121       return string2gen(res,false);
6122     }
6123 #endif
6124     case _VECT__INT_:
6125       if (b.val>=0 && python_compat(contextptr)==2){
6126 	vecteur res;
6127 	res.reserve(a._VECTptr->size()*b.val);
6128 	const_iterateur it,itend=a._VECTptr->end();
6129 	int n=b.val;
6130 	for (int i=0;i<n;++i){
6131 	  for (it=a._VECTptr->begin();it!=itend;++it)
6132 	    res.push_back(*it);
6133 	}
6134 	return gen(res,a.subtype);
6135       }
6136     case _VECT__ZINT: case _VECT__DOUBLE_: case _VECT__FLOAT_: case _VECT__CPLX: case _VECT__SYMB: case _VECT__IDNT: case _VECT__POLY: case _VECT__EXT: case _VECT__MOD: case _VECT__FRAC: case _VECT__REAL: {
6137       gen A(a),B(b);
6138       if (A.is_approx() && !is_fully_numeric(B))
6139 	B=evalf(b,1,contextptr);
6140       else {
6141 	if (B.is_approx() && !is_fully_numeric(A)){
6142 	  A=evalf(a,1,contextptr);
6143 	  if (A.type!=_VECT)
6144 	    A=a;
6145 	}
6146       }
6147       // matrix * point -> point
6148       if (B.is_symb_of_sommet(at_pnt)){
6149 	gen tmp=complex2vecteur(remove_at_pnt(B),contextptr);
6150 	if (ckmatrix(A)){
6151 	  tmp=multmatvecteur(*A._VECTptr,*tmp._VECTptr);
6152 	  return _point(tmp,contextptr);
6153 	}
6154 	if (A._VECTptr->size()==tmp._VECTptr->size())
6155 	  return dotvecteur(*A._VECTptr,*tmp._VECTptr);
6156       }
6157       if (A.subtype==_VECTOR__VECT && A._VECTptr->size()==2)
6158 	return vector2vecteur(*A._VECTptr)*B;
6159       if (A.subtype==_PNT__VECT)
6160 	return gen(multfirst(B,*A._VECTptr),_PNT__VECT);
6161       if (A.subtype==_POLY1__VECT){
6162 	if (is_zero(B,contextptr))
6163 	  return B;
6164 	//if (b.type==_POLY) return a*(*b._POLYptr);
6165       }
6166       return multgen_poly(B,*A._VECTptr,A.subtype); // gen(multvecteur(b,*a._VECTptr),a.subtype);
6167     }
6168     case _INT___VECT:
6169       if (a.val>=0 && python_compat(contextptr)==2)
6170 	return operator_times(b,a,contextptr);
6171       if (warnpy && a.val>=0 && python_compat(contextptr)){
6172 	alert(gettext("Python compatibility, integer*list will do vector multiplication, run list*integer to duplicate list"),contextptr);
6173 	warnpy=false;
6174       }
6175     case _ZINT__VECT: case _DOUBLE___VECT: case _FLOAT___VECT: case _CPLX__VECT: case _SYMB__VECT: case _IDNT__VECT: case _POLY__VECT: case _EXT__VECT: case _MOD__VECT: case _FRAC__VECT: case _REAL__VECT: {
6176       gen A(a),B(b);
6177       if (A.is_approx() && !is_fully_numeric(B)){
6178 	B=evalf(b,1,contextptr);
6179 	if (B.type!=_VECT)
6180 	  B=b;
6181       }
6182       else {
6183 	if (B.is_approx() && !is_fully_numeric(A)){
6184 	  A=evalf(a,1,contextptr);
6185 	}
6186       }
6187       if (A.is_symb_of_sommet(at_pnt)){
6188 	gen tmp=complex2vecteur(remove_at_pnt(A),contextptr);
6189 	if (ckmatrix(B))
6190 	  return _point(multvecteurmat(*tmp._VECTptr,*B._VECTptr),contextptr);
6191 	if (tmp._VECTptr->size()==B._VECTptr->size())
6192 	  return dotvecteur(*tmp._VECTptr,*B._VECTptr,contextptr);
6193       }
6194       if (B.subtype==_VECTOR__VECT && B._VECTptr->size()==2)
6195 	return A*vector2vecteur(*B._VECTptr);
6196       if (B.subtype==_PNT__VECT)
6197 	return gen(multfirst(A,*B._VECTptr),_PNT__VECT);
6198       if (B.subtype==_POLY1__VECT){
6199 	if (is_zero(A,contextptr))
6200 	  return A;
6201 	// if (a.type==_POLY) return b*(*a._POLYptr);
6202       }
6203       return multgen_poly(A,*B._VECTptr,B.subtype); // gen(multvecteur(a,*b._VECTptr),b.subtype);
6204     }
6205     case _VECT__VECT: {
6206       gen A(a),B(b);
6207       if (A.subtype==_SET__VECT && B.subtype==_SET__VECT){
6208 	vecteur res; res.reserve(A._VECTptr->size()*B._VECTptr->size());
6209 	const_iterateur at=A._VECTptr->begin(),aend=A._VECTptr->end(),bt=B._VECTptr->begin(),bend=B._VECTptr->end();
6210 	for (;at!=aend;++at){
6211 	  for (bt=B._VECTptr->begin();bt!=bend;++bt){
6212 	    if (at->type==_VECT && at->subtype==_TUPLE__VECT){
6213 	      if (bt->type==_VECT && bt->subtype==_TUPLE__VECT){
6214 		res.push_back(gen(mergevecteur(*at->_VECTptr,*bt->_VECTptr),_TUPLE__VECT));
6215 	      }
6216 	      else {
6217 		vecteur tmp(*at->_VECTptr);
6218 		tmp.push_back(*bt);
6219 		res.push_back(gen(tmp,_TUPLE__VECT));
6220 	      }
6221 	    }
6222 	    else {
6223 	      if (bt->type==_VECT && bt->subtype==_TUPLE__VECT){
6224 		vecteur tmp(*bt->_VECTptr);
6225 		tmp.insert(tmp.begin(),*at);
6226 		res.push_back(gen(tmp,_TUPLE__VECT));
6227 	      }
6228 	      else
6229 		res.push_back(gen(makevecteur(*at,*bt),_TUPLE__VECT));
6230 	    }
6231 	  }
6232 	}
6233 	return gen(res,_SET__VECT);
6234       }
6235       // FIXME should not convert 0 in B if A has intervals
6236       if (A.is_approx() && !is_fully_numeric(B)){
6237 	bool done=false;
6238 #if defined HAVE_LIBMPFI && !defined NO_RTTI
6239 	// workaround for lu e.g. a:=ranm(4,4); b:=convert(a,interval); p,l,u:=lu(b):; l*u;
6240 	if (!A._VECTptr->empty() && A._VECTptr->back().type==_VECT && !A._VECTptr->back()._VECTptr->empty() && A._VECTptr->back()._VECTptr->front().type==_REAL){
6241 	  if (real_interval * ptr=dynamic_cast<real_interval *>(A._VECTptr->back()._VECTptr->front()._REALptr)){
6242 	    B=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
6243 	    done=true;
6244 	  }
6245 	}
6246 #endif
6247 	if (!done)
6248 	  B=evalf(b,1,contextptr);
6249 	if (B.type!=_VECT)
6250 	  B=b;
6251       }
6252       else {
6253 	if (B.is_approx() && !is_fully_numeric(A)){
6254 	  A=evalf(a,1,contextptr);
6255 	  if (A.type!=_VECT)
6256 	    A=a;
6257 	}
6258       }
6259       if (// abs_calc_mode(contextptr)==38 &&
6260 	  (A.subtype==_MATRIX__VECT ||B.subtype==_MATRIX__VECT) && ckmatrix(A) && ckmatrix(B)){
6261 	if (A._VECTptr->front()._VECTptr->size()!=B._VECTptr->size())
6262 	  return gendimerr(contextptr);
6263 	gen res(new ref_vecteur(0),_MATRIX__VECT);
6264 	mmult(*A._VECTptr,*B._VECTptr,*res._VECTptr);
6265 	return res;
6266       }
6267       if ( (A.subtype==_POLY1__VECT) || (B.subtype==_POLY1__VECT) )
6268 	return multgen_poly(*A._VECTptr,*B._VECTptr);
6269       if ( (A.subtype==_LIST__VECT) || (B.subtype==_LIST__VECT) )
6270 	return matrix_apply(A,B,contextptr,operator_times);
6271       if (A.subtype==_GGBVECT || (b.subtype==_GGBVECT && !ckmatrix(A))){
6272 	gen res=dotvecteur(a,b);
6273 	if (res.type==_VECT) res.subtype=_GGBVECT;
6274 	return res;
6275       }
6276       { gen res=ckmultmatvecteur(*A._VECTptr,*B._VECTptr,contextptr);
6277 	if ( (calc_mode(contextptr)==1 || abs_calc_mode(contextptr)==38) && res.type==_VECT){
6278 	  res.subtype=B.subtype;
6279 	  if (res.subtype==0)
6280 	    res.subtype=A.subtype;
6281 	}
6282 	return res;
6283       }
6284     }
6285     case _POLY__POLY:
6286       return mulpoly(a,b);
6287     case _FRAC__FRAC:
6288       if (a._FRACptr->num.type==_EXT && b._FRACptr->num.type==_EXT)
6289 	return ((*a._FRACptr)*(*b._FRACptr)).normal();
6290       return (*a._FRACptr)*(*b._FRACptr);
6291     case _SPOL1__SPOL1:
6292       return spmul(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
6293     case _EXT__EXT:
6294       return ext_mul(a,b,contextptr);
6295     case _MAP__MAP:
6296       {
6297 	int arows,acols,an,brows,bcols,bn;
6298 	if (is_sparse_matrix(a,arows,acols,an) && is_sparse_matrix(b,brows,bcols,bn)){
6299 	  gen_map res;
6300 	  gen g(res);
6301 	  sparse_mult(*a._MAPptr,*b._MAPptr,*g._MAPptr);
6302 	  return g;
6303 	}
6304       }
6305     case _MAP__VECT:
6306       {
6307 	int arows,acols,an;
6308 	if (is_sparse_matrix(a,arows,acols,an)){
6309 	  if (acols>b._VECTptr->size())
6310 	    return gendimerr(contextptr);
6311 	  if (ckmatrix(b)){
6312 	    vecteur A;
6313 	    convert(*a._MAPptr,A);
6314 	    return A*b;
6315 	  }
6316 	  smatrix as;
6317 	  if (convert(*a._MAPptr,as)){
6318 	    vecteur res;
6319 	    sparse_mult(as,*b._VECTptr,res);
6320 	    return res;
6321 	  }
6322 	  gen_map res;
6323 	  gen g(res);
6324 	  if (!sparse_mult(*a._MAPptr,*b._VECTptr,*g._MAPptr))
6325 	    return gendimerr(contextptr);
6326 	  // Should probably check if g is dense or not
6327 	  return g;
6328 	}
6329       }
6330     case _VECT__MAP:
6331       {
6332 	int brows,bcols,an;
6333 	if (is_sparse_matrix(b,brows,bcols,an)){
6334 	  if (brows>a._VECTptr->size())
6335 	    return gendimerr(contextptr);
6336 	  if (ckmatrix(a)){
6337 	    vecteur B;
6338 	    convert(*b._MAPptr,B);
6339 	    return a*B;
6340 	  }
6341 	  smatrix bs;
6342 	  if (convert(*b._MAPptr,bs)){
6343 	    vecteur res;
6344 	    sparse_mult(*a._VECTptr,bs,res);
6345 	    return res;
6346 	  }
6347 	  gen_map res;
6348 	  gen g(res);
6349 	  if (!sparse_mult(*a._VECTptr,*b._MAPptr,*g._MAPptr))
6350 	    return gendimerr(contextptr);
6351 	  // Should probably check if g is dense or not
6352 	  return g;
6353 	}
6354       }
6355     case _INT___MAP: case _ZINT__MAP: case _DOUBLE___MAP: case _FLOAT___MAP: case _CPLX__MAP: case _SYMB__MAP: case _IDNT__MAP: case _POLY__MAP: case _EXT__MAP: case _MOD__MAP: case _FRAC__MAP: case _REAL__MAP: {
6356       if (is_one(a))
6357 	return b;
6358       int brows,bcols,bn;
6359       if (is_sparse_matrix(b,brows,bcols,bn)){
6360 	gen_map res;
6361 	gen g(res);
6362 	if (is_zero(a))
6363 	  return g;
6364 	*g._MAPptr=*b._MAPptr;
6365 	sparse_mult(a,*g._MAPptr);
6366 	return g;
6367       }
6368       break;
6369     }
6370     case _POLY__INT_: case _POLY__ZINT: case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__CPLX: case _POLY__USER: case _POLY__REAL:
6371       if (is_one(b))
6372 	return a;
6373       return (*a._POLYptr) * b;
6374     case _POLY__MOD:
6375       return (*a._POLYptr) * b;
6376     case _INT___POLY: case _ZINT__POLY: case _DOUBLE___POLY: case _FLOAT___POLY: case _CPLX__POLY: case _USER__POLY: case _REAL__POLY:
6377       if (is_one(a))
6378 	return b;
6379       return a * (*b._POLYptr);
6380     case _MOD__POLY:
6381       return a * (*b._POLYptr);
6382     case _MOD__MOD:
6383 #ifdef SMARTPTR64
6384       return modmul( (ref_modulo *) (* ((ulonglong * ) &a) >> 16),(ref_modulo *) (* ((ulonglong * ) &b) >> 16) );
6385 #else
6386       return modmul(a.__MODptr,b.__MODptr);
6387 #endif
6388     case _MOD__INT_: case _MOD__ZINT:
6389       return makemod(*a._MODptr*b,*(a._MODptr+1));
6390     case _INT___MOD: case _ZINT__MOD:
6391       return makemod(*b._MODptr*a,*(b._MODptr+1));
6392     case _REAL__REAL:
6393       return (*a._REALptr)*(*b._REALptr);
6394     default:
6395       if (is_undef(a))
6396 	return a;
6397       if (is_undef(b))
6398 	return b;
6399       if (a.type==_FLOAT_){
6400 	gen b1;
6401 	if (has_evalf(b,b1,1,contextptr)&& (b.type!=b1.type || b!=b1))
6402 	  return a*b1;
6403 	return operator_times(evalf_double(a,1,contextptr),b,contextptr);
6404       }
6405       if (b.type==_FLOAT_){
6406 	gen a1;
6407 	if (has_evalf(a,a1,1,contextptr)&& (a.type!=a1.type || a!=a1))
6408 	  return a1*b;
6409 	return operator_times(a,evalf_double(b,1,contextptr),contextptr);
6410       }
6411       if (a.type==_SPOL1)
6412 	return spmul(*a._SPOL1ptr,gen2spol1(b),contextptr);
6413       if (b.type==_SPOL1)
6414 	return spmul(gen2spol1(a),*b._SPOL1ptr,contextptr);
6415       if (a.type==_USER)
6416 	return (*a._USERptr)*b;
6417       if (b.type==_USER)
6418 	return (*b._USERptr)*a;
6419       if (a.type==_REAL)
6420 	return a._REALptr->multiply(b,contextptr);
6421       if (b.type==_REAL)
6422 	return b._REALptr->multiply(a,contextptr);
6423       if (a.type==_STRNG || b.type==_STRNG)
6424 	return gensizeerr(contextptr);
6425       return sym_mult(a,b,contextptr);
6426     }
6427     return undef;
6428   }
6429 
operator_times(const gen & a,const gen & b,GIAC_CONTEXT)6430   gen operator_times(const gen & a,const gen & b,GIAC_CONTEXT){
6431     register unsigned t=(a.type<< _DECALAGE) | b.type;
6432     if (!t)
6433       return gen((longlong) a.val*b.val);
6434     return operator_times(a,b,t,contextptr);
6435   }
6436 
operator *(const gen & a,const gen & b)6437   gen operator * (const gen & a,const gen & b){
6438     register unsigned t=(a.type<< _DECALAGE) | b.type;
6439     if (!t)
6440       return gen((longlong) a.val*b.val);
6441     return operator_times(a,b,t,context0);
6442   }
6443 
has_i(const gen & g)6444   bool has_i(const gen & g){
6445     if (g.type==_CPLX)
6446       return true;
6447     if (g.type==_FRAC)
6448       return g._FRACptr->num.type==_CPLX || g._FRACptr->den.type==_CPLX;
6449     if (g.type==_VECT){
6450       const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
6451       for (;it!=itend;++it){
6452 	if (has_i(*it))
6453 	  return true;
6454       }
6455       return false;
6456     }
6457     if (g.type==_SPOL1){
6458       sparse_poly1::const_iterator it=g._SPOL1ptr->begin(),itend=g._SPOL1ptr->end();
6459       for (;it!=itend;++it){
6460 	if (has_i(it->coeff))
6461 	  return true;
6462       }
6463       return false;
6464     }
6465     if (g.type==_EXT)
6466       return has_i(*g._EXTptr);
6467     if (g.type!=_SYMB)
6468       return false;
6469     return has_i(g._SYMBptr->feuille);
6470   }
6471 
giac_pow(const gen & base,const gen & exponent,GIAC_CONTEXT)6472   gen giac_pow(const gen & base,const gen & exponent,GIAC_CONTEXT){
6473     return pow(base,exponent,contextptr);
6474   }
6475 
6476   // (-1)^n
minus1pow(const gen & exponent,GIAC_CONTEXT,bool allow_recursion=true)6477   static gen minus1pow(const gen & exponent,GIAC_CONTEXT,bool allow_recursion=true){
6478     if (exponent.type==_INT_)
6479       return (exponent.val%2)?-1:1;
6480     if (exponent.type==_ZINT){
6481       gen q,g=irem(exponent,2,q);
6482       if (is_zero(g,contextptr))
6483 	return 1;
6484       return -1;
6485     }
6486     if (is_inf(exponent))
6487       return undef;
6488     if (is_undef(exponent))
6489       return exponent;
6490     if (exponent.is_symb_of_sommet(at_neg)){
6491       gen tmp=minus1pow(exponent._SYMBptr->feuille,contextptr);
6492       if (is_assumed_integer(exponent,contextptr))
6493 	return tmp;
6494       //else return symb_inv(tmp);
6495     }
6496     if (exponent.is_symb_of_sommet(at_plus)){
6497       gen res(1);
6498       gen & f=exponent._SYMBptr->feuille;
6499       if (f.type!=_VECT)
6500 	return minus1pow(f,contextptr);
6501       vecteur & v = *f._VECTptr;
6502       int s=int(v.size());
6503       for (int i=0;i<s;++i)
6504 	res = res * minus1pow(v[i],contextptr);
6505       return res;
6506     }
6507     if (exponent.is_symb_of_sommet(at_prod)){
6508       gen & f =exponent._SYMBptr->feuille;
6509       if (f.type==_VECT){
6510 	vecteur & v = *f._VECTptr;
6511 	int i,s=int(v.size());
6512 	bool even=false,perhapsone=true;
6513 	gen num=1,den=1;
6514 	for (i=0;i<s;++i){
6515 	  if (v[i].is_symb_of_sommet(at_inv))
6516 	    den=den*v[i]._SYMBptr->feuille;
6517 	  else
6518 	    num=num*v[i];
6519 	  if (is_integer(v[i]) && is_zero(smod(v[i],2),contextptr))
6520 	    even=true;
6521 	  if (!is_assumed_integer(v[i],contextptr))
6522 	    perhapsone=false;
6523 	}
6524 #ifndef NO_STDEXCEPT
6525 	if (allow_recursion && perhapsone){
6526 	  gen num1=undef;
6527 	  try {
6528 	    num1=_irem(makesequence(num,2*den),contextptr);
6529 	  } catch (std::runtime_error & err){
6530 	    num1=undef;
6531 	  }
6532 	  if (!is_undef(num1) && num1!=num) return minus1pow(symb_prod(num1,symb_inv(den)),contextptr,false);
6533 	}
6534 #endif
6535 	if (even && perhapsone)
6536 	  return 1;
6537 	if (num.type==_INT_ && den.type==_INT_ && den.val<=MAX_ALG_EXT_ORDER_SIZE){
6538 	  return exp(cst_i*exponent*cst_pi,contextptr);
6539 	}
6540       }
6541     }
6542     return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(-1,exponent),_SEQ__VECT)));
6543   }
6544 
pow_iterative(const gen & base,const gen & exponent,GIAC_CONTEXT)6545   static gen pow_iterative(const gen & base,const gen & exponent,GIAC_CONTEXT){
6546     if (is_positive(-exponent,contextptr))
6547       return pow_iterative(inv(base,contextptr),-exponent,contextptr);
6548     gen res=1,expo=exponent;
6549     gen basepow=base;
6550     while (!is_zero(expo)){
6551       gen q,r=irem(expo,2,q);
6552       if (!is_zero(r))
6553 	res = res*basepow;
6554       expo=q;
6555       if ( !is_zero(expo) )
6556 	basepow=basepow*basepow;
6557     }
6558     return res;
6559   }
6560 
pow(const gen & base,const gen & exponent,GIAC_CONTEXT)6561   gen pow(const gen & base,const gen & exponent,GIAC_CONTEXT){
6562     // if (!( (++control_c_counter) & control_c_counter_mask))
6563 #ifdef TIMEOUT
6564     control_c();
6565 #endif
6566     if (ctrl_c || interrupted) {
6567       interrupted = true; ctrl_c=false;
6568       return gensizeerr(gettext("Stopped by user interruption."));
6569     }
6570     if (exponent.type==_INT_){
6571       if (exponent.val==1) return base;
6572       if (exponent.val==2 && base.type<=_CPLX){
6573 	if (base.type==_CPLX && base.subtype==3){
6574 	  double a=base._CPLXptr->_DOUBLE_val,b=(base._CPLXptr+1)->_DOUBLE_val;
6575 	  return gen(a*a-b*b,2.0*a*b);
6576 	}
6577 	return operator_times(base,base,contextptr);
6578       }
6579     }
6580     if (is_undef(base))
6581       return base;
6582     if (is_undef(exponent))
6583       return exponent;
6584     {
6585       gen a,b;
6586       if (is_algebraic_program(base,a,b))
6587 	return symbolic(at_program,gen(makevecteur(a,0,pow(b,exponent,contextptr)),_SEQ__VECT));
6588       if (is_algebraic_program(exponent,a,b))
6589 	return symbolic(at_program,gen(makevecteur(a,0,pow(base,b,contextptr)),_SEQ__VECT));
6590     }
6591     if (base.type==_VECT && base.subtype!=_POLY1__VECT && !is_squarematrix(base)){
6592       *logptr(contextptr) << gettext("Warning, ^ is ambiguous on non square matrices. Use .^ to apply ^ element by element.") << '\n';
6593       if (exponent.type==_VECT)
6594 	return apply(base,exponent,contextptr,giac_pow);
6595       if (base.subtype!=_LIST__VECT && (exponent.type==_INT_ && exponent.val %2==0) )
6596 	return pow(dotvecteur(*base._VECTptr,*base._VECTptr,contextptr),exponent.val/2,contextptr);
6597       return apply1st(base,exponent,contextptr,&giac_pow);
6598     }
6599     if (exponent.type==_VECT)
6600       return apply2nd(base,exponent,contextptr,&giac_pow);
6601     if (exponent.type==_FRAC){
6602       if (base.type<_POLY || base.type==_FLOAT_){
6603 	if (exponent==plus_one_half)
6604 	  return sqrt(base,contextptr);
6605 	if (exponent==minus_one_half)
6606 	  return inv(sqrt(base,contextptr),contextptr);
6607       }
6608       if (exponent._FRACptr->num==1 && exponent._FRACptr->den==2 && base.type==_SYMB){
6609 	vecteur v=lvar(base);
6610 	if (v.size()==1 && v.front().is_symb_of_sommet(at_pow) && v.front()._SYMBptr->feuille[1]==plus_one_half && is_integer(v.front()._SYMBptr->feuille[0])){
6611 	  gen a,b,c=v.front()._SYMBptr->feuille[0];
6612 	  if (is_linear_wrt(base,v.front(),b,a,contextptr) && (is_integer(a) ||a.type==_FRAC) && (is_integer(b) || b.type==_FRAC)){
6613 	    gen d=a*a-b*b*c;
6614 	    if (is_positive(d,contextptr)){
6615 	      d=sqrt(d,contextptr);
6616 	      if (is_integer(d) || d.type==_FRAC){
6617 		return sqrt((a+d)/2,contextptr)+sign(b,contextptr)*sqrt((a-d)/2,contextptr);
6618 	      }
6619 	    }
6620 	  }
6621 	}
6622       }
6623       return pow(base,new_ref_symbolic(symbolic(at_prod,makesequence(exponent._FRACptr->num,symb_inv(exponent._FRACptr->den)))),contextptr);
6624     }
6625     if (is_inf(base)){
6626       if (is_zero(exponent,contextptr))
6627 	return undef;
6628       if (exponent==plus_inf){
6629 	if (base==plus_inf)
6630 	  return base;
6631 	return unsigned_inf;
6632       }
6633       if (exponent==minus_inf)
6634 	return 0;
6635       gen d;
6636       bool b=has_evalf(exponent,d,1,contextptr);
6637       if (b && is_strictly_positive(-exponent,contextptr) )
6638 	return 0;
6639       if (b && base==plus_inf &&is_strictly_positive(exponent,contextptr))
6640 	return plus_inf;
6641       if ( (exponent.type==_INT_) ){
6642 	if (exponent.val % 2)
6643 	  return base;
6644 	else
6645 	  return plus_inf; // for unsigned_inf in _DOUBLE_ mode only!!
6646       }
6647       if (b && is_strictly_positive(exponent,contextptr))
6648 	return unsigned_inf;
6649       return undef;
6650     }
6651     if (base.type==_SYMB){
6652       unary_function_ptr & u =base._SYMBptr->sommet;
6653       if (u==at_unit){
6654 	vecteur & v=*base._SYMBptr->feuille._VECTptr;
6655 	gen v1=v[1];
6656 	vecteur w;
6657 	if (v1.is_symb_of_sommet(at_prod))
6658 	  w=gen2vecteur(v1._SYMBptr->feuille);
6659 	else
6660 	  w.push_back(v1);
6661 	for (unsigned i=0;i<w.size();++i){
6662 	  gen & v1=w[i];
6663 	  if (v1.is_symb_of_sommet(at_pow))
6664 	    v1=pow(v1._SYMBptr->feuille[0],v1._SYMBptr->feuille[1]*exponent,contextptr);
6665 	  else
6666 	    v1=pow(v1,exponent,contextptr);
6667 	}
6668 	if (w.size()==1) v1=w.front(); else v1=symbolic(at_prod,gen(w,_SEQ__VECT));
6669 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(pow(v[0],exponent,contextptr),v1)));
6670       }
6671       if (u==at_abs && exponent.type==_INT_ && !complex_mode(contextptr) && !has_i(base)){
6672 	int n=exponent.val,m;
6673 	if (n<0 && n%2)
6674 	  m=n-1;
6675 	else
6676 	  m=(n/2)*2; // or m=n%2?n-1:n;
6677 	gen basep=pow(base._SYMBptr->feuille,m);
6678 	if (n%2)
6679 	  return base*basep;
6680 	else
6681 	  return basep;
6682       }
6683       if (u==at_pnt && exponent.type==_INT_ && exponent.val%2==0){
6684 	return pow(abs_norm2(remove_at_pnt(base),contextptr),exponent.val/2,contextptr);
6685       }
6686       if (u==at_sign && exponent.type==_INT_ && !complex_mode(contextptr) && !has_i(base)){
6687 	int n=exponent.val;
6688 	if (n%2)
6689 	  return base;
6690 	else
6691 	  return 1;
6692       }
6693       if (u==at_exp){
6694 	// (e^a)^b=e^(a*b)
6695 	// but we keep (e^a)^b if b is integer and e^(a*b) is not simplified
6696 	// for rational dependance
6697 	gen res=exp(base._SYMBptr->feuille*exponent,contextptr);
6698 	if (exponent.type!=_INT_ || !res.is_symb_of_sommet(at_exp))
6699 	  return res;
6700       }
6701       if (u==at_inv && base._SYMBptr->feuille.type==_SYMB && (base._SYMBptr->feuille._SYMBptr->sommet==at_exp ||base._SYMBptr->feuille._SYMBptr->sommet==at_pow))
6702 	return inv(pow(base._SYMBptr->feuille,exponent,contextptr),contextptr);
6703       if (u==at_pow && !has_i(base)){
6704 	vecteur & v=*base._SYMBptr->feuille._VECTptr;
6705 	gen & v1=v[1];
6706 	gen new_exp=v1*exponent;
6707 	if (new_exp.type>_IDNT)
6708 	  new_exp=normal(new_exp,contextptr);
6709 	if ( v1.type==_INT_ && v1.val%2==0
6710 	     && (new_exp.type!=_INT_ || new_exp.val%2 )
6711 	     && !complex_mode(contextptr) )
6712 	  return pow(abs(v[0],contextptr),new_exp,contextptr);
6713 	else
6714 	  return pow(v[0],new_exp,contextptr);
6715       }
6716       if (u==at_equal || u==at_equal2){
6717 	vecteur & vb=*base._SYMBptr->feuille._VECTptr;
6718 	return new_ref_symbolic(symbolic(base._SYMBptr->sommet,makesequence(pow(vb.front(),exponent,contextptr),pow(vb.back(),exponent,contextptr))));
6719       }
6720       if (exponent.type==_INT_){
6721 	if (exponent.val==0)
6722 	  return 1;
6723 	if (exponent.val==1)
6724 	  return base;
6725 	return new_ref_symbolic(symbolic(at_pow,gen(makevecteur(base,exponent),_SEQ__VECT)));
6726       }
6727     }
6728     if (abs_calc_mode(contextptr)==38 && !complex_mode(contextptr) && is_exactly_zero(base) && is_exactly_zero(exponent)) // was is_zero(,.contextptr) changed so that MINREAL^0 is not undef but 1
6729       return undef;
6730     switch ( (base.type<< _DECALAGE) | exponent.type ) {
6731     case _INT___INT_: case _ZINT__INT_: case _REAL__INT_: case _CPLX__INT_: case _IDNT__INT_:
6732       return pow(base,exponent.val);
6733     case _DOUBLE___DOUBLE_:
6734       if (exponent._DOUBLE_val==int(std::floor(exponent._DOUBLE_val+.25)))
6735 	return pow(base,int(std::floor(exponent._DOUBLE_val+.25)));
6736       if (base._DOUBLE_val>=0)
6737 #ifdef _SOFTMATH_H
6738 	return std::giac_gnuwince_pow(base._DOUBLE_val,exponent._DOUBLE_val);
6739 #else
6740 	return std::pow(base._DOUBLE_val,exponent._DOUBLE_val);
6741 #endif
6742       else
6743 	return exp(exponent*log(base,contextptr),contextptr);
6744     case _FRAC__DOUBLE_:
6745       return exp(exponent*log(base,contextptr),contextptr);
6746     case _FLOAT___FLOAT_:
6747       if (exponent._FLOAT_val==get_int(exponent._FLOAT_val))
6748 	return pow(base,get_int(exponent._FLOAT_val));
6749       if (is_strictly_positive(-base,contextptr))
6750 	return exp(exponent*ln(base,contextptr),contextptr);
6751       return fpow(base._FLOAT_val,exponent._FLOAT_val);
6752     case _INT___FLOAT_:
6753       if (exponent._FLOAT_val==get_int(exponent._FLOAT_val))
6754 	return pow(base,get_int(exponent._FLOAT_val));
6755       if (is_strictly_positive(-base,contextptr))
6756 	return exp(exponent*ln(base,contextptr),contextptr);
6757       return fpow(giac_float(base.val),exponent._FLOAT_val);
6758     case _FLOAT___INT_:
6759       return fpow(base._FLOAT_val,giac_float(exponent.val));
6760     case _DOUBLE___INT_:
6761       if (base._DOUBLE_val>=0)
6762 #ifdef _SOFTMATH_H
6763 	return std::giac_gnuwince_pow(base._DOUBLE_val,exponent.val);
6764 #else
6765       return std::pow(base._DOUBLE_val,exponent.val);
6766 #endif
6767       else
6768 	return (exponent.val%2?-1:1)*std::pow(-base._DOUBLE_val,exponent.val);//exp(exponent*log(-base,contextptr),contextptr);
6769     case _INT___DOUBLE_:
6770 #ifdef _SOFTMATH_H
6771       return std::giac_gnuwince_pow(base.val,exponent._DOUBLE_val);
6772 #else
6773       return std::pow(double(base.val),exponent._DOUBLE_val);
6774 #endif
6775     case _ZINT__DOUBLE_:
6776 #ifdef _SOFTMATH_H
6777       return std::giac_gnuwince_pow(mpz_get_d(*base._ZINTptr),exponent._DOUBLE_val);
6778 #else
6779       return std::pow(mpz_get_d(*base._ZINTptr),exponent._DOUBLE_val);
6780 #endif
6781     case _DOUBLE___ZINT:
6782       if (base._DOUBLE_val>=0)
6783 #ifdef _SOFTMATH_H
6784 	return std::giac_gnuwince_pow(base._DOUBLE_val,mpz_get_d(*exponent._ZINTptr));
6785 #else
6786       return std::pow(base._DOUBLE_val,mpz_get_d(*exponent._ZINTptr));
6787 #endif
6788       else
6789 	return exp(exponent*log(base,contextptr),contextptr);
6790     case _POLY__INT_:
6791       if (exponent.val<0)
6792 	return fraction(1,pow(*base._POLYptr,-exponent.val));
6793       else
6794 	return pow(*base._POLYptr,exponent.val);
6795     case _MAP__INT_:
6796       if (exponent.val>=0)
6797 	return pow(base,exponent.val);
6798     case _FRAC__INT_:
6799       return pow(*base._FRACptr,exponent.val);
6800     case _EXT__INT_: case _MOD__INT_: case _VECT__INT_: case _USER__INT_:
6801       return pow(base,exponent.val);
6802     case _MOD__ZINT:
6803       return makemod(powmod(*base._MODptr,exponent,*(base._MODptr+1)),*(base._MODptr+1));
6804     default:
6805       if (is_undef(base))
6806 	return base;
6807       if (is_undef(exponent))
6808 	return exponent;
6809       if (base.type==_STRNG || exponent.type==_STRNG)
6810 	return gensizeerr(contextptr);
6811       if (is_one(base) && !is_inf(exponent))
6812 	return base;
6813       if (exponent.is_symb_of_sommet(at_prod) && exponent._SYMBptr->feuille.type==_VECT && exponent._SYMBptr->feuille._VECTptr->size()==2){
6814 	gen e1=exponent._SYMBptr->feuille._VECTptr->front();
6815 	gen e2=exponent._SYMBptr->feuille._VECTptr->back();
6816 	if (e1.is_symb_of_sommet(at_ln) && e2.is_symb_of_sommet(at_inv) && e2._SYMBptr->feuille.is_symb_of_sommet(at_ln) && base==e2._SYMBptr->feuille._SYMBptr->feuille)
6817 	  return e1._SYMBptr->feuille;
6818       }
6819       if (is_squarematrix(base)){
6820 	if ((exponent.type==_REAL || exponent.type==_DOUBLE_ || exponent.type==_FLOAT_))
6821 	  return matpow(*base._VECTptr,exponent,contextptr);
6822 	if (exponent.type>=_IDNT)
6823 	  *logptr(contextptr) << gettext("Use matpow to force computation of a power of matrix via jordanisation") << '\n';
6824       }
6825       if (base.type==_REAL || base.type==_DOUBLE_ ||
6826 	  (base.type==_CPLX
6827 	   // && base.subtype==3
6828 	   )
6829 	  || base.type==_FLOAT_ || ( (base.type<_POLY || base.type==_FLOAT_) && (exponent.type==_REAL || exponent.type==_DOUBLE_ || exponent.type==_FLOAT_)))
6830 	return exp(exponent*log(base,contextptr),contextptr);
6831       /*
6832 	 if (base.is_symb_of_sommet(at_neg))
6833 	 return minus1pow(exponent)*pow(base._SYMBptr->feuille,exponent);
6834       */
6835       if ((base.type==_INT_) && (base.val<0)){
6836 	if (exponent==plus_one_half)
6837 	  return cst_i*sqrt(-base.val,contextptr);
6838 	// if (exponent==-one_half)
6839 	//  return rdiv(cst_i,sqrt(-base.val));
6840       }
6841       if (is_exactly_zero(base)){
6842 	gen d;
6843 #if 1
6844 	// 0^k should return 0 if k is assumed to be positive
6845 	d=sign(exponent,contextptr);
6846 	if (is_one(d))
6847 	  return base;
6848 	if (is_minus_one(d))
6849 	  return unsigned_inf;
6850 #else
6851 	bool b=has_evalf(exponent,d,1,contextptr);
6852 	if (b && is_positive(exponent,contextptr))
6853 	  return base;
6854 	if (b && is_positive(-exponent,contextptr))
6855 	  return unsigned_inf;
6856 #endif
6857 	return undef;
6858       }
6859       if (base.type==_SPOL1)
6860 	return sppow(*base._SPOL1ptr,exponent,contextptr);
6861       if (is_integer(base) && is_positive(-base,contextptr)){
6862 #if 0
6863 	if (abs_calc_mode(contextptr)==38 && !complex_mode(contextptr))
6864 	  return gensizeerr(gettext("Negative to a fractional power"));
6865 #endif
6866 	return minus1pow(exponent,contextptr)*pow(-base,exponent,contextptr);
6867       }
6868       if (is_inf(exponent)){
6869 	if (base.type==_VECT)
6870 	  return gensizeerr(contextptr);
6871 	return exp(exponent*ln(base,contextptr),contextptr);
6872       }
6873       // extract integral powers in a product exponent
6874       if ((exponent.type==_SYMB) && (exponent._SYMBptr->sommet==at_prod)){
6875 	gen subexponent_num(1),subexponent_deno(1);
6876 	gen superexponent(1);
6877 	const_iterateur it=exponent._SYMBptr->feuille._VECTptr->begin(),itend=exponent._SYMBptr->feuille._VECTptr->end();
6878 	for (;it!=itend;++it){
6879 	  if (it->type==_INT_){
6880 	    superexponent = superexponent * (*it);
6881 	    continue;
6882 	  }
6883 	  if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_inv))
6884 	    subexponent_deno = subexponent_deno * (it->_SYMBptr->feuille);
6885 	  else
6886 	    subexponent_num = subexponent_num * (*it);
6887 	}
6888 	if (superexponent.type!=_INT_
6889 	    || (!lidnt(exponent).empty() && absint(superexponent.val)>MAX_COMMON_ALG_EXT_ORDER_SIZE)
6890 	    )
6891 	  return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,exponent),_SEQ__VECT)));
6892 	if (subexponent_deno.type!=_INT_){
6893 	  if (is_one(superexponent))
6894 	    return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,_FRAC2_SYMB(subexponent_num,subexponent_deno)),_SEQ__VECT)));
6895 	  return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,_FRAC2_SYMB(subexponent_num,subexponent_deno)),_SEQ__VECT))),superexponent),_SEQ__VECT)));
6896 	}
6897 	int q=superexponent.val / subexponent_deno.val;
6898 	int r=superexponent.val % subexponent_deno.val;
6899 	gen res(1);
6900 	if (r){
6901 	  if (complex_mode(contextptr) && fastsign(base,contextptr)==-1){ // is_strictly_positive(-base,contextptr)){
6902 	    gen base1=-base;
6903 	    res=exp((cst_i*cst_pi*subexponent_num)/subexponent_deno,contextptr);
6904 	    res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base1,subexponent_num,contextptr),inv(subexponent_deno,contextptr)),_SEQ__VECT)))*res;
6905 	  }
6906 	  else
6907 	    res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base,subexponent_num,contextptr),inv(subexponent_deno,contextptr)),_SEQ__VECT)));
6908 	  if (r!=1)
6909 	    res=new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(res,r),_SEQ__VECT)));
6910 	}
6911 	if (!q)
6912 	  return res;
6913 	if (q==1){
6914 	  if (is_one(subexponent_num))
6915 	    return res*base;
6916 	  return res*new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,subexponent_num),_SEQ__VECT)));
6917 	}
6918 	if (q==-1)
6919 	  return res*inv(pow(base,subexponent_num,contextptr),contextptr);
6920 	return res*new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(pow(base,subexponent_num,contextptr),q),_SEQ__VECT)));
6921       }
6922       gen var1,var2,res1,res2;
6923       if (is_algebraic_program(base,var1,res1) && is_algebraic_program(exponent,var2,res2)){
6924 	if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
6925 	  res2=subst(res2,var2,var1,false,contextptr);
6926 	  var2=var1;
6927 	}
6928 	if (var1==var2)
6929 	  return symbolic(at_program,gen(makevecteur(var1,0,pow(res1,res2,contextptr)),_SEQ__VECT));
6930       }
6931       if (exponent.type==_ZINT){
6932 	if (base.type==_USER)
6933 	  return pow_iterative(base,exponent,contextptr);
6934 	return exp(exponent*log(base,contextptr),contextptr);
6935       }
6936       return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,exponent),_SEQ__VECT)));
6937     }
6938   }
6939 
sym_mult(const gen & a,const gen & b,GIAC_CONTEXT)6940   gen sym_mult(const gen & a,const gen & b,GIAC_CONTEXT){
6941 #ifdef TIMEOUT
6942     control_c();
6943 #endif
6944     if (ctrl_c || interrupted) {
6945       interrupted = true; ctrl_c=false;
6946       return gensizeerr(gettext("Stopped by user interruption."));
6947     }
6948     if (is_undef(a))
6949       return a;
6950     if (is_undef(b))
6951       return b;
6952     if (is_inequality(a) && !is_equal(a)){
6953       int bs=fastsign(b,contextptr);
6954       if (bs==-1)
6955 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->back()*b,a._SYMBptr->feuille._VECTptr->front()*b)));
6956       if (bs==1)
6957 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(a._SYMBptr->feuille._VECTptr->front()*b,a._SYMBptr->feuille._VECTptr->back()*b)));
6958     }
6959     if (is_inequality(b) && !is_equal(b)){
6960       int bs=fastsign(a,contextptr);
6961       if (bs==-1)
6962 	return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(a*b._SYMBptr->feuille._VECTptr->back(),a*b._SYMBptr->feuille._VECTptr->front())));
6963       if (bs==1)
6964 	return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(a*b._SYMBptr->feuille._VECTptr->front(),a*b._SYMBptr->feuille._VECTptr->back())));
6965     }
6966     if (a.is_symb_of_sommet(at_unit)){
6967       if (equalposcomp(lidnt(b),cst_pi)!=0)
6968 	return sym_mult(a,evalf(b,1,contextptr),contextptr);
6969       vecteur & va=*a._SYMBptr->feuille._VECTptr;
6970       if (b.is_symb_of_sommet(at_unit)){
6971 	vecteur & v=*b._SYMBptr->feuille._VECTptr;
6972 	gen res=va[1]*v[1];
6973 	res=ratnormal(res,contextptr);
6974 	if (is_one(res))
6975 	  return va[0]*v[0];
6976 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(va[0],v[0],contextptr),res)));
6977       }
6978       else {
6979 	if (lidnt(b).empty())
6980 	  return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(va[0],b,contextptr),va[1])));
6981       }
6982     }
6983     if (b.is_symb_of_sommet(at_unit)){
6984       if (equalposcomp(lidnt(a),cst_pi)!=0)
6985 	return sym_mult(evalf(a,1,contextptr),b,contextptr);
6986       if (lidnt(a).empty()){
6987 	vecteur & v=*b._SYMBptr->feuille._VECTptr;
6988 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(operator_times(a,v[0],contextptr),v[1])));
6989       }
6990     }
6991     gen var1,var2,res1,res2;
6992     if (is_algebraic_program(a,var1,res1)){
6993       if (is_algebraic_program(b,var2,res2)){
6994 	if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
6995 	  res2=subst(res2,var2,var1,false,contextptr);
6996 	  var2=var1;
6997 	}
6998 	if (var1==var2)
6999 	  return symbolic(at_program,gen(makevecteur(var1,0,operator_times(res1,res2,contextptr)),_SEQ__VECT));
7000       }
7001       if (!is_constant_wrt(b,var1,contextptr))
7002 	*logptr(contextptr) << "Warning function*constant with constant dependant of mute variable" << '\n';
7003       return symbolic(at_program,gen(makevecteur(var1,0,operator_times(res1,b,contextptr)),_SEQ__VECT));
7004     }
7005     if (is_algebraic_program(b,var2,res2)){
7006       if (!is_constant_wrt(a,var2,contextptr))
7007 	*logptr(contextptr) << "Warning constant*function with constant dependant of mute variable" << '\n';
7008       return symbolic(at_program,gen(makevecteur(var2,0,operator_times(a,res2,contextptr)),_SEQ__VECT));
7009     }
7010     if (is_inf(a)){
7011       if (is_exactly_zero(normal(b,contextptr)))
7012 	return undef;
7013       int s=fastsign(a,contextptr)*fastsign(b,contextptr);
7014       if (s==1)
7015 	return plus_inf;
7016       if (s)
7017 	return minus_inf;
7018       return unsigned_inf;
7019     }
7020     if (is_inf(b)){
7021       if (is_exactly_zero(normal(a,contextptr)))
7022 	return undef;
7023       int s=fastsign(a,contextptr)*fastsign(b,contextptr);
7024       if (s==1)
7025 	return plus_inf;
7026       if (s)
7027 	return minus_inf;
7028       return unsigned_inf;
7029     }
7030     if (a.type==_INT_ && a.val==0 )
7031       return a;
7032     if (a.type==_DOUBLE_ && a._DOUBLE_val==0 )
7033       return a;
7034     if (a.type==_FLOAT_ && is_zero(a._FLOAT_val) )
7035       return a;
7036     if (b.type==_INT_ && b.val==0)
7037       return b;
7038     if (b.type==_DOUBLE_ && b._DOUBLE_val==0 )
7039       return b;
7040     if (b.type==_FLOAT_ && is_zero(b._FLOAT_val) )
7041       return b;
7042     if ( a.is_approx()){
7043       gen b1;
7044       if (has_evalf(b,b1,1,contextptr)&& (b.type!=b1.type || b!=b1)){
7045 #ifdef HAVE_LIBMPFR
7046 	if (a.type==_REAL){
7047 	  gen b2;
7048 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7049 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._REALptr))
7050 	    b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
7051 	  else
7052 #endif
7053 	    b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
7054 	  if (b2.is_approx())
7055 	    return (*a._REALptr)*b2;
7056 	}
7057 	if (a.type==_CPLX && a._CPLXptr->type==_REAL){
7058 	  gen b2;
7059 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7060 	  if (real_interval * ptr=dynamic_cast<real_interval *>(a._CPLXptr->_REALptr))
7061 	    b2=convert_interval(b,mpfi_get_prec(ptr->infsup),contextptr);
7062 	  else
7063 #endif
7064 	    b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
7065 	  if (b2.is_approx())
7066 	    return a*b2;
7067 	}
7068 #endif
7069 	return a*b1;
7070       }
7071     }
7072     if ( b.is_approx()){
7073       gen a1;
7074       if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
7075 #ifdef HAVE_LIBMPFR
7076 	if (b.type==_REAL){
7077 	  gen a2;
7078 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7079 	  if (real_interval * ptr=dynamic_cast<real_interval *>(b._REALptr))
7080 	    a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
7081 	  else
7082 #endif
7083 	    a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
7084 	  if (a2.is_approx())
7085 	    return a2*b;
7086 	}
7087 	if (b.type==_CPLX && b._CPLXptr->type==_REAL){
7088 	  gen a2;
7089 #if defined HAVE_LIBMPFI && !defined NO_RTTI
7090 	  if (real_interval * ptr=dynamic_cast<real_interval *>(b._CPLXptr->_REALptr))
7091 	    a2=convert_interval(a,mpfi_get_prec(ptr->infsup),contextptr);
7092 	  else
7093 #endif
7094 	    a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
7095 	  if (a2.is_approx())
7096 	    return a2*b;
7097 	}
7098 #endif
7099 	return a1*b;
7100       }
7101     }
7102     if (is_one(a) && ((a.type!=_MOD) || (b.type==_MOD) ))
7103       return b;
7104     if (is_one(b) && ((b.type!=_MOD) || (a.type==_MOD) ))
7105       return a;
7106     if ((a.type==_SYMB) && equalposcomp(plot_sommets,a._SYMBptr->sommet)){
7107       gen tmp=remove_at_pnt(a);
7108       if (tmp.type==_VECT && tmp.subtype==_VECTOR__VECT){
7109 	if (b.type==_SYMB && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7110 	  gen tmpb=remove_at_pnt(b);
7111 	  return dotvecteur(vector2vecteur(*tmp._VECTptr),vector2vecteur(*tmpb._VECTptr));
7112 	}
7113 	return _vector(vector2vecteur(*tmp._VECTptr)*b,contextptr);
7114       }
7115       if ((b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7116 	gen tmpb=complex2vecteur(remove_at_pnt(b),contextptr);
7117 	tmp=complex2vecteur(tmp,contextptr);
7118 	if (tmpb._VECTptr->size()==tmp._VECTptr->size())
7119 	  return dotvecteur(*tmp._VECTptr,*tmpb._VECTptr,contextptr);
7120 	return gensizeerr(gettext("Unable to multiply two graphic objects"));
7121       }
7122       return symbolic_plot_makevecteur(a._SYMBptr->sommet,a._SYMBptr->feuille*b,false,contextptr);
7123     }
7124     if ((b.type==_SYMB) && equalposcomp(plot_sommets,b._SYMBptr->sommet)){
7125       gen tmp=remove_at_pnt(b);
7126       if (tmp.type==_VECT && tmp.subtype==_VECTOR__VECT)
7127 	return _vector(a*vector2vecteur(*tmp._VECTptr),contextptr);
7128       gen b_(b);
7129       if (b_.is_symb_of_sommet(at_curve) && b_._SYMBptr->feuille.type==_VECT && b_._SYMBptr->feuille._VECTptr->size()==2 && b_._SYMBptr->feuille._VECTptr->front().type==_VECT){
7130 	  // adjust param and cartesian eq
7131 	vecteur v=*b_._SYMBptr->feuille._VECTptr->front()._VECTptr;
7132 	if (v.size()==7)
7133 	  v[6] =v[6]*a;
7134 	if (v.size()>=6){
7135 	  gen ax,ay;
7136 	  reim(inv(a,contextptr),ax,ay,contextptr);
7137 	  v[5]=subst(v[5],makevecteur(x__IDNT_e,y__IDNT_e),makevecteur(ax*x__IDNT_e-ay*y__IDNT_e,ax*y__IDNT_e+ay*x__IDNT_e),false,contextptr);
7138 	  b_=symbolic(at_curve,gen(makevecteur(gen(v,b_._SYMBptr->feuille._VECTptr->front().subtype),b_._SYMBptr->feuille._VECTptr->back()),b_._SYMBptr->feuille.subtype));
7139 	}
7140       }
7141       return symbolic_plot_makevecteur(b_._SYMBptr->sommet,b_._SYMBptr->feuille*a,false,contextptr);
7142     }
7143     if (a.is_symb_of_sommet(at_neg)){
7144       if (b.is_symb_of_sommet(at_neg))
7145 	return operator_times(a._SYMBptr->feuille,b._SYMBptr->feuille,contextptr);
7146       return -operator_times(a._SYMBptr->feuille,b,contextptr);
7147     }
7148     if (b.is_symb_of_sommet(at_neg))
7149       return -operator_times(a,b._SYMBptr->feuille,contextptr);
7150     if (a.type==_FRAC){
7151       if (b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
7152 	return (*a._FRACptr)*fraction(1,b._SYMBptr->feuille);
7153       if ( (b.type!=_SYMB) && (b.type!=_IDNT) ) {
7154 	if (b.type==_EXT)
7155 	  return fraction(a._FRACptr->num*b,a._FRACptr->den).normal();
7156         return (*a._FRACptr)*b;
7157       }
7158       return sym_mult(_FRAC2_SYMB(a),b,contextptr);
7159     }
7160     if (b.type==_FRAC){
7161       if (a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
7162 	return fraction(1,a._SYMBptr->feuille)*(*b._FRACptr);
7163       if ( (a.type!=_SYMB) && (a.type!=_IDNT) ){
7164 	if (a.type==_EXT)
7165 	  return fraction(a*b._FRACptr->num,b._FRACptr->den).normal();
7166         return a*(*b._FRACptr);
7167       }
7168       return sym_mult(a,_FRAC2_SYMB(b),contextptr);
7169     }
7170     if (is_cinteger(a) && b.is_symb_of_sommet(at_inv) && is_cinteger(b._SYMBptr->feuille))
7171       return a/b._SYMBptr->feuille;
7172     if (is_cinteger(b) && a.is_symb_of_sommet(at_inv) && is_cinteger(a._SYMBptr->feuille))
7173       return b/a._SYMBptr->feuille;
7174     if (a.type<=_CPLX && b.is_symb_of_sommet(at_inv)&& b._SYMBptr->feuille.type<=_CPLX)
7175       return fraction(a,b._SYMBptr->feuille).normal();
7176     if (b.type<=_CPLX && a.is_symb_of_sommet(at_inv)&& a._SYMBptr->feuille.type<=_CPLX)
7177       return fraction(b,a._SYMBptr->feuille).normal();
7178     if ((a.type<=_REAL || a.type==_FLOAT_) && is_strictly_positive(-a,contextptr))
7179       return -sym_mult(-a,b,contextptr);
7180     if ((b.type<=_REAL || b.type==_FLOAT_) && is_strictly_positive(-b,contextptr))
7181       return -sym_mult(a,-b,contextptr);
7182     if (a.type==_EXT){
7183       if (a.is_constant() && (b.type==_POLY))
7184 	return a*(*b._POLYptr);
7185       else
7186 	return algebraic_EXTension(b*(*a._EXTptr),*(a._EXTptr+1));
7187     }
7188     if (b.type==_EXT){
7189       if (b.is_constant() && (a.type==_POLY))
7190 	return (*a._POLYptr)*b;
7191       else
7192 	return algebraic_EXTension(a*(*b._EXTptr),*(b._EXTptr+1));
7193     }
7194     if ( (a.type==_INT_) && (a.val<0) && (a.val!=1<<31)){
7195       if (b.is_symb_of_sommet(at_inv) && (b._SYMBptr->feuille.type<_POLY || b._SYMBptr->feuille.is_symb_of_sommet(at_neg)))
7196 	return sym_mult(-a,inv(-b._SYMBptr->feuille,contextptr),contextptr);
7197       else
7198 	return -sym_mult(-a,b,contextptr);
7199     }
7200     if ( (b.type==_INT_) && (b.val<0) && (b.val!=1<<31)){
7201       if (a.is_symb_of_sommet(at_inv))
7202 	return sym_mult(-b,inv(-a._SYMBptr->feuille,contextptr),contextptr);
7203       else
7204 	return -sym_mult(-b,a,contextptr);
7205     }
7206     if (is_equal(a)){
7207       vecteur & va=*a._SYMBptr->feuille._VECTptr;
7208       if (is_equal(b)){
7209 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7210 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,gen(makenewvecteur(va.front()*vb.front(),va.back()*vb.back()),_SEQ__VECT)));
7211       }
7212       else
7213 	return new_ref_symbolic(symbolic(a._SYMBptr->sommet,gen(makenewvecteur(va.front()*b,va.back()*b),_SEQ__VECT)));
7214     }
7215     if (is_equal(b)){
7216       vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7217       return new_ref_symbolic(symbolic(b._SYMBptr->sommet,gen(makenewvecteur(a*vb.front(),a*vb.back()),_SEQ__VECT)));
7218     }
7219     if ((a.type==_SYMB)&& (b.type==_SYMB)){
7220       if ((a._SYMBptr->sommet==at_prod) && (b._SYMBptr->sommet==at_prod))
7221 	return new_ref_symbolic(symbolic(at_prod,gen(mergevecteur(*(a._SYMBptr->feuille._VECTptr),*(b._SYMBptr->feuille._VECTptr)),_SEQ__VECT)));
7222       else {
7223 	if (a._SYMBptr->sommet==at_prod)
7224 	  return new_ref_symbolic(symbolic(*a._SYMBptr,b));
7225 	else {
7226 	  if (b._SYMBptr->sommet==at_prod)
7227 	    return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
7228 	  else
7229 	    return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7230 	}
7231       }
7232     }
7233     if (b.type==_SYMB){
7234       if (b._SYMBptr->sommet==at_prod)
7235 	return new_ref_symbolic(symbolic(a,b._SYMBptr->sommet,b._SYMBptr->feuille));
7236       else
7237 	return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7238     }
7239     if (a.type==_SYMB){
7240       if (a._SYMBptr->sommet==at_prod)
7241 	return new_ref_symbolic(symbolic(*a._SYMBptr,b));
7242       else
7243 	return new_ref_symbolic(symbolic(at_prod,gen(b.type==_INT_?makenewvecteur(b,a):makenewvecteur(a,b),_SEQ__VECT)));
7244     }
7245     if ((a.type==_IDNT) || (b.type==_IDNT))
7246       return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7247     if (a.type==_MOD)
7248       return a*makemod(b,*(a._MODptr+1));
7249     if (b.type==_MOD)
7250       return b*makemod(a,*(b._MODptr+1));
7251     return new_ref_symbolic(symbolic(at_prod,gen(makenewvecteur(a,b),_SEQ__VECT)));
7252     // settypeerr(gettext("sym_mult"));
7253   }
7254 
inv__VECT(const vecteur & v,GIAC_CONTEXT)7255   static vecteur inv__VECT(const vecteur & v,GIAC_CONTEXT){
7256     vecteur w;
7257     if (is_squarematrix(v))
7258       w=minv(v,contextptr);
7259     else {
7260       vecteur::const_iterator it=v.begin(),itend=v.end();
7261       for (;it!=itend;++it)
7262 	w.push_back(inv(*it,contextptr));
7263     }
7264     return w;
7265   }
7266 
invfirst(const vecteur & v)7267   static vecteur invfirst(const vecteur & v){
7268     vecteur w(v);
7269     if (!w.empty())
7270       w.front()=inv(w.front(),context0);
7271     return w;
7272   }
7273 
invdistrib(const gen & g,GIAC_CONTEXT)7274   static gen invdistrib(const gen & g,GIAC_CONTEXT){
7275     if (g.type!=_SYMB)
7276       return inv(g,contextptr);
7277     gen & f=g._SYMBptr->feuille;
7278     if (g._SYMBptr->sommet==at_inv)
7279       return f;
7280     if (g._SYMBptr->sommet==at_pow)
7281       return symbolic(at_pow,gen(makevecteur(f[0],-f[1]),_SEQ__VECT));
7282     if (g._SYMBptr->sommet==at_prod && f.type==_VECT){
7283       vecteur v = *f._VECTptr;
7284       iterateur it=v.begin(),itend=v.end();
7285       for (;it!=itend;++it)
7286 	*it=invdistrib(*it,contextptr);
7287       return symbolic(at_prod,gen(v,_SEQ__VECT));
7288     }
7289     return inv(g,contextptr);
7290   }
7291 
inv_distrib(const gen & b,GIAC_CONTEXT)7292   gen inv_distrib(const gen & b,GIAC_CONTEXT){
7293     if (b.is_symb_of_sommet(at_prod)){
7294       gen f=b._SYMBptr->feuille;
7295       return symbolic(at_prod,inv_distrib(f,contextptr));
7296     }
7297     if (b.is_symb_of_sommet(at_pow))
7298       return pow(b._SYMBptr->feuille[0],-b._SYMBptr->feuille[1],contextptr);
7299     if (b.is_symb_of_sommet(at_inv))
7300       return b._SYMBptr->feuille;
7301     if (b.type==_VECT){
7302       vecteur v(*b._VECTptr);
7303       for (unsigned i=0;i<v.size();++i){
7304 	v[i]=inv_distrib(v[i],contextptr);
7305       }
7306       return gen(v,b.subtype);
7307     }
7308     return unitpow(b,-1);
7309   }
7310 
inv(const gen & a,GIAC_CONTEXT)7311   gen inv(const gen & a,GIAC_CONTEXT){
7312 #ifdef TIMEOUT
7313     control_c();
7314 #endif
7315     if (ctrl_c || interrupted) {
7316       interrupted = true; ctrl_c=false;
7317       return gensizeerr(gettext("Stopped by user interruption."));
7318     }
7319     if ( (a.type==_DOUBLE_ || a.type==_FLOAT_ )? a==0 : is_exactly_zero(a))
7320       return unsigned_inf;
7321     switch (a.type ) {
7322     case _INT_: case _ZINT:
7323       if (is_one(a) || (is_minus_one(a)) )
7324 	return a;
7325       else
7326 	return fraction(1,a);
7327     case _REAL:
7328       return a._REALptr->inv();
7329     case _DOUBLE_:
7330       return 1/a._DOUBLE_val;
7331     case _FLOAT_:
7332       return finv(a._FLOAT_val);
7333     case _CPLX:
7334       if (is_exactly_zero(*a._CPLXptr)){
7335 	if (is_one(abs(*(a._CPLXptr+1),contextptr)))
7336 	  return -a;
7337       }
7338       if ( a._CPLXptr->type==_DOUBLE_ || a._CPLXptr->type==_FLOAT_ ||a._CPLXptr->type==_REAL || (a._CPLXptr+1)->type==_DOUBLE_ || (a._CPLXptr+1)->type==_FLOAT_ || (a._CPLXptr+1)->type==_REAL ){
7339 	gen a2=no_context_evalf(a.squarenorm(contextptr));
7340 	if (is_inf(a2)){
7341 	  gen theta=arg(a,contextptr);
7342 	  theta=cos(theta,contextptr)-cst_i*sin(theta,contextptr);
7343 	  a2=re(a*theta,contextptr);
7344 	  return inv(a2,contextptr)*theta;
7345 	}
7346 	return gen(rdiv(no_context_evalf(a.re(contextptr)),a2,contextptr),rdiv(no_context_evalf(-a.im(contextptr)),a2,contextptr));
7347       }
7348       return fraction(1,a);
7349     case _IDNT:
7350       if (a==undef)
7351 	return undef;
7352       if (a==unsigned_inf)
7353 	return 0;
7354       return new_ref_symbolic(symbolic(at_inv,a));
7355     case _SYMB:
7356       if ((a==plus_inf) || (a==minus_inf))
7357 	return 0;
7358       {
7359 	vecteur v=alg_lvar(a); // change for limit(1/(1+sqrt(2)*cos(x))*sin(x-3*pi/4),x=3*pi/4); maybe we should only do evalf test and return undef
7360 	if (v.size()==1 && v.front().type==_VECT && v.front()._VECTptr->empty() && is_zero(evalf(a,1,contextptr)) && is_exactly_zero(recursive_normal(a,contextptr)))
7361 	return unsigned_inf;
7362       }
7363       if (a.is_symb_of_sommet(at_unit)){
7364 	if (equalposcomp(lidnt(a),cst_pi)!=0)
7365 	  return inv(evalf(a,1,contextptr),contextptr);
7366 	return new_ref_symbolic(symbolic(at_unit,makenewvecteur(inv(a._SYMBptr->feuille._VECTptr->front(),contextptr),inv_distrib(a._SYMBptr->feuille._VECTptr->back(),contextptr))));
7367       }
7368       if (equalposcomp(plot_sommets,a._SYMBptr->sommet))
7369 	return symbolic_plot_makevecteur( a._SYMBptr->sommet,inv(a._SYMBptr->feuille,contextptr),false,contextptr);
7370       if (a._SYMBptr->sommet==at_inv)
7371 	return a._SYMBptr->feuille;
7372       if (a._SYMBptr->sommet==at_NTHROOT && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2){
7373 	return symbolic(at_NTHROOT,makesequence(-a._SYMBptr->feuille._VECTptr->front(),a._SYMBptr->feuille._VECTptr->back()));
7374       }
7375       if (a._SYMBptr->sommet==at_neg)
7376 	return -inv(a._SYMBptr->feuille,contextptr);
7377       else {
7378 	if (a._SYMBptr->sommet==at_prod)
7379 	  return new_ref_symbolic(symbolic(at_prod,gen(inv__VECT(*(a._SYMBptr->feuille._VECTptr),contextptr),a._SYMBptr->feuille.subtype)));
7380 	else
7381 	  return new_ref_symbolic(symbolic(at_inv,a));
7382       }
7383     case _VECT:
7384       if (a.subtype==_PNT__VECT)
7385 	return gen(invfirst(*a._VECTptr),a.subtype);
7386       if (a.subtype==_POLY1__VECT)
7387 	return fraction(gen(vecteur(1,plus_one),_POLY1__VECT),a);
7388       if (a.subtype==_MATRIX__VECT && !is_squarematrix(a))
7389 	return gensizeerr(gettext("Inv of non-square matrix"));
7390       return gen(inv__VECT(*a._VECTptr,contextptr),a.subtype);
7391     case _EXT:
7392       return inv_EXT(a);
7393     case _SPOL1:
7394       return spdiv(gen2spol1(1),*a._SPOL1ptr,contextptr);
7395     case _USER:
7396       return a._USERptr->inv();
7397     case _MOD:
7398       return modinv(a);
7399     case _FRAC:
7400       if (a._FRACptr->num.type==_CPLX)
7401 	return fraction(a._FRACptr->den,a._FRACptr->num).normal();
7402       if (is_positive(a._FRACptr->num,contextptr))
7403 	return fraction(a._FRACptr->den,a._FRACptr->num);
7404       else
7405 	return fraction(-a._FRACptr->den,-a._FRACptr->num);
7406     default:
7407       if (is_undef(a))
7408 	return a;
7409       return new_ref_symbolic(symbolic(at_inv,a));
7410       // settypeerr(gettext("Inv"));
7411     }
7412 
7413   }
7414 
7415   /*
7416   gen inv(const gen & a,GIAC_CONTEXT){
7417     return inv(a,context0);
7418   }
7419   */
7420 
inverse(GIAC_CONTEXT) const7421   gen gen::inverse(GIAC_CONTEXT) const  { return inv(*this,contextptr); }
7422 
inpow(const gen & base,unsigned long int exponent,gen & res)7423   static void inpow(const gen & base,unsigned long int exponent,gen & res){
7424 #if 0
7425     res=1;
7426     gen basepow=base;
7427     while (exponent){
7428       if (exponent%2)
7429 	res = res*basepow;
7430       if ( (exponent /=2) )
7431 	basepow=basepow*basepow;
7432     }
7433 #else
7434     if (exponent==1)
7435       res=base;
7436     else {
7437       inpow(base,exponent/2,res);
7438       res=res*res;
7439       if (exponent %2)
7440 	res=res*base;
7441     }
7442 #endif
7443   }
7444 
pow(const gen & base,unsigned long int exponent)7445   gen pow(const gen & base, unsigned long int exponent){
7446     // if (!( (++control_c_counter) & control_c_counter_mask))
7447 #ifdef TIMEOUT
7448     control_c();
7449 #endif
7450     if (ctrl_c || interrupted) {
7451       interrupted = true; ctrl_c=false;
7452       return gensizeerr(gettext("Stopped by user interruption."));
7453     }
7454     ref_mpz_t * e;
7455     gen res;
7456     switch (base.type ) {
7457     case _INT_:
7458       if (base.val<0 && (exponent % 2))
7459 	return(-pow(-base.val,exponent));
7460       else
7461 	return(pow(absint(base.val),exponent));
7462     case _DOUBLE_:
7463 #ifdef _SOFTMATH_H
7464       return std::giac_gnuwince_pow(base._DOUBLE_val,double(exponent));
7465 #else
7466       return std::pow(base._DOUBLE_val,double(exponent));
7467 #endif
7468     case _FLOAT_:
7469       return fpow(base._FLOAT_val,giac_float(double(exponent)));
7470     case _ZINT:
7471       e=new ref_mpz_t;
7472       mpz_pow_ui(e->z,*base._ZINTptr,exponent);
7473       return e;
7474     case _VECT:
7475       if (base.subtype==_POLY1__VECT && base._VECTptr->size()<5){
7476 	vecteur res;
7477 	if (miller_pow(*base._VECTptr,exponent,res))
7478 	  return gen(res,_POLY1__VECT);
7479       }
7480       /* no break, _VECT handled by next case */
7481     case _CPLX: case _REAL: case _EXT: case _MOD: case _USER:
7482       // gauss integer power
7483       if (!exponent){
7484 	if (ckmatrix(base))
7485 	  return midn(int(base._VECTptr->size()));
7486 	if (base.type==_USER)
7487 	  return base*inv(base,context0);
7488 	return 1;
7489       }
7490       inpow(base,exponent,res);
7491       return(res);
7492     case _IDNT:
7493       if (is_undef(base))
7494 	return base;
7495       if (!exponent)
7496 	return 1;
7497       if (exponent==1)
7498 	return base;
7499       return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,(longlong)exponent),_SEQ__VECT)));
7500     case _SYMB:
7501       if (!exponent)
7502 	return 1;
7503       if (exponent==1)
7504 	return base;
7505       if (base._SYMBptr->sommet==at_pow){
7506 	res= (*((base._SYMBptr->feuille)._VECTptr))[1];
7507 	return pow( (base._SYMBptr->feuille)._VECTptr->front(),gen((longlong) (exponent)) * res,context0) ;
7508       }
7509       if ((exponent % 2==0) && base._SYMBptr->sommet==at_abs)
7510 	return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base._SYMBptr->feuille,(longlong) exponent),_SEQ__VECT)));
7511       return new_ref_symbolic(symbolic(at_pow,gen(makenewvecteur(base,(longlong) exponent),_SEQ__VECT)));
7512     case _POLY:
7513       return pow(*base._POLYptr,(int) exponent);
7514     case _FRAC:
7515       return pow(*base._FRACptr,(int) exponent);
7516     case _MAP:{
7517       gen res;
7518       inpow(base,exponent,res);
7519       return res;
7520     }
7521     default:
7522       if (is_undef(base))
7523 	return base;
7524       return gentypeerr(gettext("Pow")) ;
7525     }
7526     return 0;
7527   }
7528 
pow(const gen & base,int exponent)7529   gen pow(const gen & base, int exponent){
7530     if (base==zero){
7531       if (exponent>0)
7532 	return base;
7533       if (!exponent)
7534 	return undef;
7535       if (exponent %2)
7536 	return unsigned_inf;
7537       return plus_inf;
7538     }
7539     if (exponent<0){
7540       if (-exponent<0)
7541 	return gensizeerr("pow: int exponent underflow");
7542       return inv(pow(base,-exponent),context0);
7543     }
7544     if (is_one(base))
7545       return base;
7546     if (is_minus_one(base))
7547       return exponent%2?-1:1;
7548     unsigned long int expo=exponent;
7549     gen b;
7550     if (base.type<=_ZINT && has_evalf(base,b,0,context0) && !is_inf(b) &&
7551 	is_greater(abs(exponent*log(abs(b,context0),context0),context0),powlog2float,context0)){
7552       return gensizeerr("Exponent overflow");
7553       *logptr(context0) << "Exponent overflow" << '\n';
7554       if (is_strictly_greater(1,abs(b,context0),context0))
7555 	return 0;
7556       return (exponent%2==0 || is_greater(b,0,context0))?plus_inf:minus_inf; // overflow
7557       // return pow(b,expo);
7558     }
7559     return(pow(base,expo));
7560   }
7561 
pow(unsigned long int base,unsigned long int exponent)7562   gen pow(unsigned long int base, unsigned long int exponent){
7563     ref_mpz_t *e=new ref_mpz_t;
7564 #ifdef EMCC
7565     if (base==int(base)){
7566       mpz_set_si(e->z,1);
7567       for (unsigned long int i=0;i<exponent;++i){
7568 	mpz_mul_ui(e->z,e->z,int(base));
7569       }
7570       return e;
7571     }
7572 #endif
7573     mpz_ui_pow_ui(e->z,base,exponent);
7574     return e;
7575   }
7576 
_ZINTdiv(const gen & a,const gen & b,ref_mpz_t * & quo)7577   static void _ZINTdiv (const gen & a,const gen & b,ref_mpz_t * & quo){
7578     // at least one is not an int, uncoerce remaining int
7579     ref_mpz_t *aptr,*bptr;
7580     if (a.type!=_INT_)
7581 #ifdef SMARTPTR64
7582       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
7583 #else
7584       aptr=a.__ZINTptr;
7585 #endif
7586     else {
7587       aptr=new ref_mpz_t;
7588       mpz_set_si(aptr->z,a.val);
7589     }
7590     if (b.type!=_INT_)
7591 #ifdef SMARTPTR64
7592       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
7593 #else
7594       bptr=b.__ZINTptr;
7595 #endif
7596     else {
7597       bptr=new ref_mpz_t;
7598       mpz_set_si(bptr->z,b.val);
7599     }
7600     quo=new ref_mpz_t;
7601     mpz_tdiv_q(quo->z,aptr->z,bptr->z);
7602     if (a.type==_INT_){
7603       delete aptr;
7604     }
7605     if (b.type==_INT_){
7606       delete bptr;
7607     }
7608   }
7609 
7610   // a and b must be integers or Gaussian integers
iquobest(const gen & a,const gen & b)7611   static gen iquobest(const gen & a,const gen & b){
7612     if (is_strictly_positive(-a,0))
7613       return -iquobest(-a,b);
7614     return iquo(a+iquo(b,2),b);
7615   }
7616 
7617   // a and b must be integers or Gaussian integers
iquocmplx(const gen & a,const gen & b)7618   static gen iquocmplx(const gen & a,const gen & b){
7619     gen b2=b.squarenorm(0);
7620     gen ab=a*b.conj(0);
7621     gen res(iquobest(re(ab,context0),b2),iquobest(im(ab,context0),b2)); // ok
7622     return res;
7623   }
7624 
iquopoly(const polynome & a,const gen & b)7625   static polynome iquopoly(const polynome & a,const gen & b){
7626     polynome res(a);
7627     vector< monomial<gen> >::iterator it=res.coord.begin(),itend=res.coord.end();
7628     for (;it!=itend;++it)
7629       it->value=iquo(it->value,b);
7630     return res;
7631   }
7632 
7633   // integer quotient, use rdiv for symbolic division
iquo(const gen & a,const gen & b)7634   gen iquo(const gen & a,const gen & b){
7635     if ((b.type==_INT_)){
7636       switch (b.val){
7637       case 1:
7638 	return a;
7639       case -1:
7640 	return -a;
7641       case 0:
7642 	return gensizeerr(gettext("Division by 0"));
7643       }
7644     }
7645     if (a.type==_POLY) // may be called by resulant interpolation
7646       return iquopoly(*a._POLYptr,b);
7647     ref_mpz_t * quo;
7648     switch ( (a.type<< _DECALAGE) | b.type ) {
7649     case _INT___INT_:
7650       return(a.val/b.val);
7651     case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
7652       _ZINTdiv(a,b,quo);
7653       return quo;
7654     case _CPLX__INT_:  case _CPLX__ZINT:
7655       return gen(iquo(*a._CPLXptr,b),iquo(*(a._CPLXptr+1),b));
7656     case _INT___CPLX: case _ZINT__CPLX:
7657       return iquocmplx(a,b);
7658     case _CPLX__CPLX:
7659       return adjust_complex_display(iquocmplx(a,b),a,b);
7660     default:
7661       return gentypeerr(gettext("iquo"));
7662     }
7663     return 0;
7664   }
7665 
7666   // a and b must be integer or Gaussian integers
rdivsimp(const gen & a,const gen & b)7667   static gen rdivsimp(const gen & a,const gen & b){
7668     if (is_positive(-b,context0)) // ok
7669       return rdivsimp(-a,-b);
7670     gen c(gcd(a,b,context0));
7671     if (c.type==_CPLX)
7672       c=gcd(c.re(context0),c.im(context0),context0); // ok
7673     return fraction(iquo(a,c),iquo(b,c));
7674   }
7675 
divpoly(const polynome & p,const gen & e)7676   static gen divpoly(const polynome & p, const gen & e){
7677     if (p.coord.empty())
7678       return zero;
7679     gen coefft; int pt=coefftype(p,coefft);
7680     if (pt==_MOD || pt==_USER){
7681       polynome res(p);
7682       mulpoly(res,coefft/(e*coefft),res);
7683       return res;
7684     }
7685     gen d=gcd(Tcontent<gen>(p),e,context0);
7686     if (d.type==_EXT)
7687       d=_gcd(*d._EXTptr,context0);
7688     if (is_one(d)){
7689       if (e==cst_i || e==minus_one || e==-cst_i)
7690 	return p/e;
7691       return fraction(p,e);
7692     }
7693     gen den(rdiv(e,d,context0));
7694     gen iden(inv(den,context0));
7695     if ( (iden.type!=_SYMB) && (iden.type!=_FRAC))
7696       return (p/d)*iden;
7697     else
7698       return fraction(p/d,den);
7699   }
7700 
divpoly(const gen & e,const polynome & p)7701   static gen divpoly(const gen & e,const polynome & p){
7702     if (is_exactly_zero(e))
7703       return e;
7704     if (Tis_constant<gen>(p)&& p.coord.front().value.type<_POLY)
7705       return rdiv(e,p.coord.front().value,context0);
7706     gen d=gcd(Tcontent<gen>(p),e,context0);
7707     gen tmp=polynome(rdiv(e,d,context0),p.dim);
7708     return fraction(tmp,p/d);
7709   }
7710 
divpolypoly(const gen & a,const gen & b)7711   static gen divpolypoly(const gen & a,const gen &b){
7712     polynome ap(*a._POLYptr),bp(*b._POLYptr);
7713     polynome q(ap.dim),r(ap.dim);
7714     if (divrem1(ap,bp,q,r) && r.coord.empty())
7715       return q;
7716     return normal(fraction(a,b),context0); // ok
7717   }
7718 
rdiv(const gen & a,const gen & b,GIAC_CONTEXT)7719   gen rdiv(const gen &a,const gen &b,GIAC_CONTEXT){
7720     // if (!( (++control_c_counter) & control_c_counter_mask))
7721 #ifdef TIMEOUT
7722     control_c();
7723 #endif
7724     if (ctrl_c || interrupted) {
7725       interrupted = true; ctrl_c=false;
7726       return gensizeerr(gettext("Stopped by user interruption."));
7727     }
7728     if (b.type==_MOD)
7729       return a*inv(b,contextptr);
7730     switch ( (a.type<< _DECALAGE) | b.type ) {
7731     case _INT___INT_: case _ZINT__INT_: case _ZINT__ZINT:
7732       if (is_exactly_zero(b)){
7733 	if (is_exactly_zero(a))
7734 	  return undef;
7735 	return unsigned_inf;
7736       }
7737       if (a==b)
7738 	return 1;
7739       if (a==-b)
7740 	return -1;
7741       if (is_exactly_zero(a%b))
7742 	return iquo(a,b);
7743       else
7744 	return rdivsimp(a,b);
7745     case _CPLX__INT_: case _CPLX__ZINT:
7746       if ( (a._CPLXptr->type==_DOUBLE_ || a._CPLXptr->type==_FLOAT_) || ((a._CPLXptr+1)->type==_DOUBLE_ || (a._CPLXptr+1)->type==_FLOAT_) )
7747 	return rdiv(no_context_evalf(a),no_context_evalf(b),contextptr);
7748       if (a._CPLXptr->type==_REAL){
7749 	if ((a._CPLXptr+1)->type==_REAL)
7750 	  return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7751 #ifdef HAVE_LIBMPFR
7752 	return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(real_object(*(a._CPLXptr+1),mpfr_get_prec(a._CPLXptr->_REALptr->inf)),b,contextptr);
7753 #else
7754 	return rdiv(*a._CPLXptr,b,contextptr)+cst_i*rdiv(real_object(*(a._CPLXptr+1)),b,contextptr);
7755 #endif
7756       }
7757       if ((a._CPLXptr+1)->type==_REAL){
7758 #ifdef HAVE_LIBMPFR
7759 	return rdiv(real_object(*a._CPLXptr,mpfr_get_prec((a._CPLXptr+1)->_REALptr->inf)),b,contextptr)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7760 #else
7761 	return rdiv(real_object(*a._CPLXptr),b)+cst_i*rdiv(*(a._CPLXptr+1),b,contextptr);
7762 #endif
7763       }
7764       if (is_exactly_zero(b))
7765 	return unsigned_inf;
7766       if (is_exactly_zero(a%b))
7767 	return iquo(a,b);
7768       else
7769 	return rdivsimp(a,b);
7770     case _CPLX__CPLX:
7771       return adjust_complex_display(rdiv(a*conj(b,contextptr),b.squarenorm(contextptr),contextptr),a,b);
7772     case _DOUBLE___CPLX: case _FLOAT___CPLX: case _INT___CPLX: case _ZINT__CPLX: case _REAL__CPLX:
7773       if (is_one(a))
7774 	return inv(b,contextptr);
7775       return rdiv(a*conj(b,contextptr),b.squarenorm(contextptr),contextptr);
7776     case _DOUBLE___DOUBLE_:
7777       return a._DOUBLE_val/b._DOUBLE_val;
7778     case _DOUBLE___INT_:
7779       return a._DOUBLE_val/b.val;
7780     case _INT___DOUBLE_:
7781       return a.val/b._DOUBLE_val;
7782     case _FLOAT___FLOAT_:
7783       return a._FLOAT_val/b._FLOAT_val;
7784     case _FLOAT___INT_:
7785       return a._FLOAT_val/giac_float(b.val);
7786     case _INT___FLOAT_:
7787       return giac_float(a.val)/b._FLOAT_val;
7788 #ifdef BCD
7789     case _FLOAT___ZINT:
7790       return a._FLOAT_val/giac_float(b._ZINTptr);
7791     case _ZINT__FLOAT_:
7792       return giac_float(a._ZINTptr)/b._FLOAT_val;
7793 #endif
7794     case _FLOAT___DOUBLE_:
7795       return a._FLOAT_val/giac_float(b._DOUBLE_val);
7796     case _DOUBLE___FLOAT_:
7797       return giac_float(a._DOUBLE_val)/b._FLOAT_val;
7798     case _ZINT__DOUBLE_:
7799       return mpz_get_d(*a._ZINTptr)/b._DOUBLE_val;
7800     case _CPLX__DOUBLE_: case _CPLX__REAL:
7801       return gen(rdiv(*a._CPLXptr,b,contextptr),rdiv(*(a._CPLXptr+1),b,contextptr));
7802     case _DOUBLE___ZINT:
7803       return a._DOUBLE_val/mpz_get_d(*b._ZINTptr);
7804       // _CPLX__DOUBLE_, _DOUBLE___CPLX, _CPLX__CPLX, _ZINT__CPLX, _INT___CPLX
7805     case _VECT__INT_: case _VECT__ZINT: case _VECT__DOUBLE_: case _VECT__FLOAT_: case _VECT__CPLX: case _VECT__FRAC:
7806     case _VECT__SYMB: case _VECT__IDNT: case _VECT__POLY: case _VECT__EXT:
7807       if (a.subtype==_VECTOR__VECT)
7808 	return a*inv(b,contextptr);
7809       return gen(divvecteur(*a._VECTptr,b),a.subtype);
7810     case _MAP__INT_: case _MAP__ZINT: case _MAP__DOUBLE_: case _MAP__FLOAT_: case _MAP__CPLX:
7811     case _MAP__SYMB: case _MAP__IDNT: case _MAP__POLY: case _MAP__EXT: {
7812       gen_map m;
7813       gen g(m);
7814       *g._MAPptr=*a._MAPptr;
7815       sparse_div(*g._MAPptr,b);
7816       return g;
7817     }
7818     case _VECT__VECT:
7819       if (a.subtype==_POLY1__VECT || b.subtype==_POLY1__VECT)
7820 	return fraction(a,b).normal();
7821       if (is_squarematrix(b)){
7822 	if (abs_calc_mode(contextptr)==38){
7823 	  *logptr(contextptr) << gettext("Warning: A/B with B a square matrix is a misleading notation interpreted as inv(B)*A") << '\n';
7824 	  return inv(b,contextptr)*a;
7825 	}
7826 	*logptr(contextptr) << gettext("Warning, pointwise division of a by b. For matrix division, please use inv(b)*a or a*inv(b)") << '\n';
7827       }
7828       if (b._VECTptr->size()==1)
7829 	return rdiv(a,b._VECTptr->front(),contextptr);
7830       return apply(a,b,contextptr,rdiv);
7831     case _POLY__POLY:
7832       return divpolypoly(a,b);
7833     case _FRAC__FRAC:
7834       if (a._FRACptr->num.type==_CPLX || a._FRACptr->den.type==_CPLX ||
7835 	  b._FRACptr->num.type==_CPLX || b._FRACptr->den.type==_CPLX){
7836 	gen d=gcd(a._FRACptr->den,b._FRACptr->den,contextptr);
7837 	return (a._FRACptr->num*(b._FRACptr->den/d))/((a._FRACptr->den/d)*b._FRACptr->num);
7838       }
7839       return (*a._FRACptr)/(*b._FRACptr);
7840     case _SPOL1__SPOL1:
7841       return spdiv(*a._SPOL1ptr,*b._SPOL1ptr,contextptr);
7842     case _POLY__DOUBLE_: case _POLY__FLOAT_: case _POLY__REAL:
7843       return (*a._POLYptr)/b;
7844     case _POLY__INT_:
7845       if (b.val==1) return a;
7846     case _POLY__ZINT: case _POLY__CPLX:
7847       return divpoly(*a._POLYptr,b);
7848     case _INT___POLY: case _ZINT__POLY: case _CPLX__POLY:
7849       return divpoly(a,*b._POLYptr);
7850     case _INT___FRAC: case _ZINT__FRAC:
7851       if (is_positive(-b._FRACptr->num,contextptr)){
7852 	// if (is_one(a)) return fraction(-b._FRACptr->den,-b._FRACptr->num);
7853 	return (-b._FRACptr->den*a)/(-b._FRACptr->num);
7854       }
7855       // if (is_one(a)) return fraction(b._FRACptr->den,b._FRACptr->num);
7856       return (b._FRACptr->den*a)/b._FRACptr->num;
7857     case _INT___VECT: case _ZINT__VECT: case _CPLX__VECT: case _DOUBLE___VECT: case _FLOAT___VECT: case _SYMB__VECT:
7858       if (b.subtype==_LIST__VECT)
7859 	return apply2nd(a,b,contextptr,rdiv);
7860       if (ckmatrix(b))
7861 	return a*inv(b,contextptr);
7862       if (calc_mode(contextptr)==1 && b.subtype!=_POLY1__VECT)
7863 	return apply2nd(a,b,contextptr,rdiv);
7864       return fraction(a,b);
7865     default:
7866 #ifdef TIMEOUT
7867       control_c();
7868 #endif
7869       if (ctrl_c || interrupted) {
7870 	interrupted = true; ctrl_c=false;
7871 	return gensizeerr(gettext("Stopped by user interruption."));
7872       }
7873       if (is_undef(a))
7874 	return a;
7875       if (is_undef(b))
7876 	return b;
7877       if (a.type==_STRNG || b.type==_STRNG)
7878 	return gensizeerr("string /");
7879       {
7880 	gen var1,var2,res1,res2;
7881 	if (is_algebraic_program(a,var1,res1)){
7882 	  if (is_algebraic_program(b,var2,res2)){
7883 	    if (var1!=var2 && is_constant_wrt(res2,var1,contextptr)){
7884 	      res2=subst(res2,var2,var1,false,contextptr);
7885 	      var2=var1;
7886 	    }
7887 	    if (var1==var2)
7888 	      return symbolic(at_program,gen(makevecteur(var1,0,rdiv(res1,res2,contextptr)),_SEQ__VECT));
7889 	  }
7890 	  if (!is_constant_wrt(b,var1,contextptr))
7891 	    *logptr(contextptr) << "Warning function/constant with constant dependant of mute variable" << '\n';
7892 	  return symbolic(at_program,gen(makevecteur(var1,0,rdiv(res1,b,contextptr)),_SEQ__VECT));
7893 	}
7894 	if (is_algebraic_program(b,var2,res2)){
7895 	  if (!is_constant_wrt(a,var2,contextptr))
7896 	    *logptr(contextptr) << "Warning constant/function with constant dependant of mute variable" << '\n';
7897 	  return symbolic(at_program,gen(makevecteur(var2,0,rdiv(a,res2,contextptr)),_SEQ__VECT));
7898 	}
7899       }
7900       if (a.type==_FLOAT_)
7901 	return rdiv(evalf_double(a,1,contextptr),b,contextptr);
7902       if (b.type==_FLOAT_)
7903 	return rdiv(a,evalf_double(b,1,contextptr),contextptr);
7904       if (a.is_symb_of_sommet(at_unit) || b.is_symb_of_sommet(at_unit))
7905 	return operator_times(a,inv(b,contextptr),contextptr);
7906       if (is_one(b))
7907 	return chkmod(a,b);
7908       if (is_minus_one(b))
7909 	return chkmod(-a,b);
7910       if (is_exactly_zero(a)){
7911 	if (!is_exactly_zero(normal(b,contextptr)))
7912 	  return a;
7913 	else
7914 	  return undef;
7915       }
7916       if (is_exactly_zero(b))
7917 	return unsigned_inf;
7918       if (is_inf(a)){
7919 	if (is_inf(b))
7920 	  return undef;
7921 	if (is_zero(b))
7922 	  return unsigned_inf;
7923 	return a*b;
7924       }
7925       if (is_inf(b)){
7926 	if (is_inf(a))
7927 	  return undef;
7928 	else
7929 	  return zero;
7930       }
7931       if (a==b && a.type!=_REAL && b.type!=_REAL)
7932 	return chkmod(plus_one,a);
7933       if (a.is_approx()){
7934 	gen b1;
7935 	if (has_evalf(b,b1,1,contextptr) && (b.type!=b1.type || b!=b1)){
7936 #ifdef HAVE_LIBMPFR
7937 	if (a.type==_REAL){
7938 	  gen b2=accurate_evalf(b,mpfr_get_prec(a._REALptr->inf));
7939 	  if (b2.is_approx())
7940 	    return rdiv(a,b2,contextptr);
7941 	}
7942 	if (a.type==_CPLX && a._CPLXptr->type==_REAL){
7943 	  gen b2=accurate_evalf(b,mpfr_get_prec(a._CPLXptr->_REALptr->inf));
7944 	  if (b2.is_approx())
7945 	    return rdiv(a,b2,contextptr);
7946 	}
7947 #endif
7948 	  return rdiv(a,b1,contextptr);
7949 	}
7950       }
7951       if (b.is_approx()){
7952 	gen a1;
7953 	if (has_evalf(a,a1,1,contextptr) && (a.type!=a1.type || a!=a1)){
7954 #ifdef HAVE_LIBMPFR
7955 	  if (b.type==_REAL){
7956 	    gen a2=accurate_evalf(a,mpfr_get_prec(b._REALptr->inf));
7957 	    if (a2.is_approx())
7958 	      return rdiv(a2,b,contextptr);
7959 	  }
7960 	  if (b.type==_CPLX && b._CPLXptr->type==_REAL){
7961 	    gen a2=accurate_evalf(a,mpfr_get_prec(b._CPLXptr->_REALptr->inf));
7962 	    if (a2.is_approx())
7963 	      return rdiv(a2,b,contextptr);
7964 	  }
7965 #endif
7966 	  return rdiv(a1,b,contextptr);
7967 	}
7968       }
7969       if (a.type==_REAL)
7970 	return (*a._REALptr)*inv(b,contextptr);
7971       if (b.type==_REAL)
7972 	return a*b._REALptr->inv();
7973       if (a.type==_SPOL1)
7974 	return spdiv(*a._SPOL1ptr,gen2spol1(b),contextptr);
7975       if (b.type==_SPOL1)
7976 	return spdiv(gen2spol1(a),*b._SPOL1ptr,contextptr);
7977       if (a.type==_USER && b.type!=_USER)
7978 	return (*a._USERptr)/b;
7979       if (a.type==_USER || b.type==_USER)
7980 	return a*inv(b,contextptr);
7981       if (a.type==_FRAC){
7982 	if ( (b.type!=_SYMB) && (b.type!=_IDNT) )
7983 	  return (*a._FRACptr)/b;
7984 	return rdiv(_FRAC2_SYMB(a),b,contextptr);
7985       }
7986       if (b.type==_FRAC){
7987 	if ( a.type!=_SYMB && a.type!=_IDNT && !(a.type==_VECT && a.subtype==_POLY1__VECT) ) // POLY1__VECT check added feb 2017 for poly hermite normal form
7988 	  return a/(*b._FRACptr);
7989 	//return rdiv(a,_FRAC2_SYMB(b),contextptr);
7990 	// return symbolic(at_prod,makesequence(a,b._FRACptr->den,symbolic(at_inv,b._FRACptr->num)));
7991 	return (b._FRACptr->den*a)/b._FRACptr->num;
7992       }
7993       if (is_equal(a)){
7994 	vecteur & va=*a._SYMBptr->feuille._VECTptr;
7995 	if (is_equal(b)){
7996 	  vecteur & vb=*b._SYMBptr->feuille._VECTptr;
7997 	  return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(rdiv(va.front(),vb.front(),contextptr),rdiv(va.back(),vb.back(),contextptr))));
7998 	}
7999 	else
8000 	  return new_ref_symbolic(symbolic(a._SYMBptr->sommet,makesequence(rdiv(va.front(),b,contextptr),rdiv(va.back(),b,contextptr))));
8001       }
8002       if (is_equal(b)){
8003 	vecteur & vb=*b._SYMBptr->feuille._VECTptr;
8004 	return new_ref_symbolic(symbolic(b._SYMBptr->sommet,makesequence(rdiv(a,vb.front(),contextptr),rdiv(a,vb.back(),contextptr))));
8005       }
8006       /* commented since * is not always commutative
8007       if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
8008 	int i=equalposcomp(*a._SYMBptr->feuille._VECTptr,b);
8009 	if (i){
8010 	  vecteur v(*a._SYMBptr->feuille._VECTptr);
8011 	  v.erase(v.begin()+i-1);
8012 	  if (v.size()==1)
8013 	    return v.front();
8014 	  else
8015 	    return new_ref_symbolic(symbolic(at_prod,v));
8016 	}
8017       }
8018       */
8019       if (b.is_symb_of_sommet(at_neg))
8020 	return -rdiv(a,b._SYMBptr->feuille,contextptr);
8021       if ((b.type<=_REAL || b.type==_FLOAT_) && is_strictly_positive(-b,context0))
8022 	return -rdiv(a,-b,contextptr);
8023       if ( (a.type==_SYMB) || (a.type==_IDNT) || (a.type==_FUNC) || (b.type==_SYMB) || (b.type==_IDNT) || (b.type==_FUNC) ){
8024 	if (is_one(a)) return symb_inv(b);
8025 	if (is_minus_one(a)) return -symb_inv(b);
8026 	if (a.is_symb_of_sommet(at_prod) && a._SYMBptr->feuille.type==_VECT){
8027 	  ref_vecteur * vptr = new_ref_vecteur(0);
8028 	  vptr->v.reserve(a._SYMBptr->feuille._VECTptr->size()+1);
8029 	  vptr->v=*a._SYMBptr->feuille._VECTptr;
8030 	  vptr->v.push_back(symb_inv(b));
8031 	  return symbolic(at_prod,gen(vptr,_SEQ__VECT));
8032 	}
8033 	return operator_times(a,symb_inv(b),contextptr);
8034       }
8035       if (a.type==_STRNG || b.type==_STRNG)
8036 	return gentypeerr(gettext("rdiv"));
8037       return fraction(a,b).normal();
8038     }
8039   }
8040 
8041   /* Tests */
8042   // 0 if unknown, 1 if >0, -1 if <0
8043   // no test for symbolics if context_ptr=0
fastsign(const gen & a,GIAC_CONTEXT)8044   int fastsign(const gen & a,GIAC_CONTEXT){
8045     if (is_zero(a,contextptr) || is_undef(a))
8046       return 0;
8047     if (is_inf(a)){
8048       if (a==plus_inf)
8049 	return 1;
8050       if (a==minus_inf)
8051 	return -1;
8052       return 0;
8053     }
8054     switch (a.type) {
8055     case _INT_:
8056       if (a.val>0)
8057 	return 1;
8058       else
8059 	return -1;
8060     case _ZINT:
8061       return signint(mpz_cmp_si(*a._ZINTptr,0));
8062     case _FRAC:
8063       return fastsign(a._FRACptr->num,contextptr)*fastsign(a._FRACptr->den,contextptr);
8064     case _CPLX:
8065       return 0;
8066     case _DOUBLE_:
8067       if (a._DOUBLE_val>0)
8068 	return 1;
8069       else
8070 	return -1;
8071     case _FLOAT_:
8072       return fsign(a._FLOAT_val);
8073     case _REAL:
8074       if (a._REALptr->maybe_zero())
8075 	return 0;
8076       return a._REALptr->is_positive(); // this is the sign
8077     case _SYMB:
8078       if (a._SYMBptr->sommet==at_neg)
8079 	return -fastsign(a._SYMBptr->feuille,contextptr);
8080       if (a._SYMBptr->sommet==at_inv)
8081 	return fastsign(a._SYMBptr->feuille,contextptr);
8082       if (a._SYMBptr->sommet==at_abs || (a._SYMBptr->sommet==at_exp && is_real(a._SYMBptr->feuille,contextptr)))
8083 	return 1;
8084     }
8085     if (a.type==_SYMB){
8086       bool aplus=a.is_symb_of_sommet(at_plus);
8087       if (aplus || a.is_symb_of_sommet(at_prod)){
8088 	gen f=a._SYMBptr->feuille;
8089 	if (f.type==_VECT){
8090 	  vecteur & v=*f._VECTptr;
8091 	  int i=0,fs=v.size(),curs=0;
8092 	  for (;i<fs;++i){
8093 	    int news=fastsign(v[i],contextptr);
8094 	    if (news==0)
8095 	      break;
8096 	    if (i==0) {
8097 	      curs=news;
8098 	      continue;
8099 	    }
8100 	    if (aplus && curs!=news)
8101 	      break;
8102 	    if (!aplus)
8103 	      curs=curs*news;
8104 	  }
8105 	  if (i==fs)
8106 	    return curs;
8107 	}
8108      }
8109      if (a.is_symb_of_sommet(at_pow)){
8110 	gen & f =a._SYMBptr->feuille;
8111 	if (f.type==_VECT && f._VECTptr->size()==2){
8112 	  gen & ex = f._VECTptr->back();
8113 	  if (ex.type==_INT_){
8114 	    if (ex.val%2==0)
8115 	      return 1;
8116 	    return fastsign(f._VECTptr->front(),contextptr);
8117 	  }
8118 	  if (ex.type==_FRAC && ex._FRACptr->den.type==_INT_ && ex._FRACptr->den.val % 2 ==0 )
8119 	    return 1;
8120 	}
8121       }
8122     }
8123     if (is_inf(a)){
8124       if (a==plus_inf)
8125 	return 1;
8126       if (a==minus_inf)
8127 	return -1;
8128       return 0;
8129     }
8130     if (a.type==_IDNT){
8131       vecteur v;
8132       if (find_range(a,v,contextptr) && v.size()==1 && v.front().type==_VECT && v.front()._VECTptr->size()==2){
8133 	if (is_positive(v.front()._VECTptr->front(),contextptr))
8134 	  return 1;
8135 	if (is_positive(-v.front()._VECTptr->back(),contextptr))
8136 	  return -1;
8137       }
8138     }
8139     gen approx;
8140     if (has_evalf(a,approx,1,contextptr) && (a.type!=approx.type ||a!=approx))
8141       return fastsign(approx,contextptr);
8142     // FIXME GIAC_CONTEXT??
8143     /*
8144     if (contextptr){
8145       gen test=superieur_strict(a,0,contextptr);
8146       if (test.type==_INT_){
8147 	if (test.val)
8148 	  return test.val;
8149 	test=inferieur_strict(a,0,contextptr);
8150 	if (test.type==_INT_)
8151 	  return -test.val;
8152       }
8153     }
8154     */
8155     return 0;
8156   }
8157 
is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8158   bool is_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8159     gen test=superieur_egal(a,b,contextptr);
8160     if ((test.type==_INT_) && (test.val==1))
8161       return true;
8162     else
8163       return false;
8164   }
8165 
is_strictly_greater(const gen & a,const gen & b,GIAC_CONTEXT)8166   bool is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8167     gen test=superieur_strict(a,b,contextptr);
8168     if ((test.type==_INT_) && (test.val==1))
8169       return true;
8170     else
8171       return false;
8172   }
8173 
is_positive(const gen & a,GIAC_CONTEXT)8174   bool is_positive(const gen & a,GIAC_CONTEXT){
8175     switch (a.type){
8176     case _INT_:
8177       return a.val>=0;
8178     case _CPLX:
8179       return is_zero(*(a._CPLXptr+1)) && is_positive(*a._CPLXptr,contextptr);
8180     case _REAL:
8181       return (a._REALptr->is_positive()>0) || a._REALptr->is_zero();
8182     case _ZINT:
8183       if (mpz_sgn(*a._ZINTptr)==-1)
8184 	return false;
8185       else
8186 	return true;
8187     case _POLY:
8188       return is_positive(a._POLYptr->coord.front());
8189     case _FRAC:
8190       return (is_positive(a._FRACptr->num,contextptr) && is_positive(a._FRACptr->den,contextptr)) || (is_positive(-a._FRACptr->num,contextptr) && is_positive(-a._FRACptr->den,contextptr));
8191     case _EXT:
8192       return false;
8193     case _SYMB:
8194       if (a==plus_inf)
8195 	return true;
8196       if (a==minus_inf)
8197 	return false;
8198       if (a._SYMBptr->sommet==at_exp)
8199 	return true;
8200       if (a._SYMBptr->sommet==at_ln)
8201 	return is_positive(a._SYMBptr->feuille-1,contextptr);
8202       if (a._SYMBptr->sommet==at_program)
8203 	return true;
8204       return is_greater(a,0,contextptr);
8205     case _FUNC:
8206       return true;
8207     default:
8208       return is_greater(a,0,contextptr);
8209     }
8210   }
8211 
is_strictly_positive(const gen & a,GIAC_CONTEXT)8212   bool is_strictly_positive(const gen & a,GIAC_CONTEXT){
8213     if (a.type==_REAL){
8214       if (a._REALptr->maybe_zero())
8215 	return false;
8216     } else {
8217       if (is_exactly_zero(a))
8218 	return false;
8219     }
8220     return is_positive(a,contextptr);
8221   }
8222 
ck_is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8223   bool ck_is_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8224     if (a==b)
8225       return true;
8226     gen test=superieur_strict(a,b,contextptr);
8227     if (test.type!=_INT_)
8228       cksignerr(test);
8229     if (test.val==1)
8230       return true;
8231     else
8232       return false;
8233   }
8234 
ck_is_strictly_greater(const gen & a,const gen & b,GIAC_CONTEXT)8235   bool ck_is_strictly_greater(const gen & a,const gen &b,GIAC_CONTEXT){
8236     gen test=superieur_strict(a,b,contextptr);
8237     if (test.type!=_INT_)
8238       cksignerr(test);
8239     if (test.val==1)
8240       return true;
8241     else
8242       return false;
8243   }
8244 
ck_is_positive(const gen & a,GIAC_CONTEXT)8245   bool ck_is_positive(const gen & a,GIAC_CONTEXT){
8246     switch (a.type){
8247     case _INT_:
8248       return a.val>=0;
8249     case _ZINT:
8250       if (mpz_sgn(*a._ZINTptr)==-1)
8251 	return false;
8252       else
8253 	return true;
8254     case _SYMB:
8255       if (a==plus_inf)
8256 	return true;
8257       if (a==minus_inf)
8258 	return false;
8259       if (a._SYMBptr->sommet==at_exp)
8260 	return true;
8261       if (a._SYMBptr->sommet==at_ln)
8262 	return ck_is_positive(a._SYMBptr->feuille-1,contextptr);
8263       return ck_is_greater(a,0,contextptr);
8264     default:
8265       return ck_is_greater(a,0,contextptr);
8266     }
8267   }
8268 
ck_is_strictly_positive(const gen & a,GIAC_CONTEXT)8269   bool ck_is_strictly_positive(const gen & a,GIAC_CONTEXT){
8270     if (is_zero(a,contextptr))
8271       return false;
8272     return ck_is_positive(a,contextptr);
8273   }
8274 
min(const gen & a,const gen & b,GIAC_CONTEXT)8275   gen min(const gen & a, const gen & b,GIAC_CONTEXT){
8276     if (a.type==_DOUBLE_ && b.type==_DOUBLE_)
8277       return a._DOUBLE_val<b._DOUBLE_val?a._DOUBLE_val:b._DOUBLE_val;
8278     if (a.type==_REAL && b.type==_REAL){
8279       gen s=sign(a-b,contextptr);
8280       if (s==1) return b;
8281       if (s==-1) return a;
8282     }
8283     if (a==b)
8284       return a;
8285     if (is_inf(a)){
8286       if (a==plus_inf)
8287 	return b;
8288       if (a==minus_inf)
8289 	return a;
8290       if (!is_inf(b))
8291 	return undef;
8292     }
8293     if (is_inf(b)){
8294       if (b==plus_inf)
8295 	return a;
8296       if (b==minus_inf)
8297 	return b;
8298       return undef;
8299     }
8300     if (is_undef(a))
8301       return a;
8302     if (is_undef(b))
8303       return b;
8304     gen test=superieur_strict(a,b,contextptr);
8305     if (test.type==_INT_){
8306       if (test.val==1)
8307 	return b;
8308       else
8309 	return a;
8310     }
8311     return new_ref_symbolic(symbolic(at_min,makesequence(a,b)));
8312   }
8313 
max(const gen & a,const gen & b,GIAC_CONTEXT)8314   gen max(const gen & a, const gen & b,GIAC_CONTEXT){
8315     if (a.type==_INT_ && b.type==_INT_)
8316       return a.val<b.val?b.val:a.val;
8317     if (a.type==_DOUBLE_ && b.type==_DOUBLE_)
8318       return a._DOUBLE_val<b._DOUBLE_val?b._DOUBLE_val:a._DOUBLE_val;
8319     if (a.type==_REAL && b.type==_REAL){
8320       gen s=sign(a-b,contextptr);
8321       if (s==1) return a;
8322       if (s==-1) return b;
8323     }
8324     if (a==b)
8325       return a;
8326     if (is_inf(a)){
8327       if (a==plus_inf)
8328 	return a;
8329       if (a==minus_inf)
8330 	return b;
8331       if (!is_inf(b))
8332 	return undef;
8333     }
8334     if (is_inf(b)){
8335       if (b==plus_inf)
8336 	return b;
8337       if (b==minus_inf)
8338 	return a;
8339       return undef;
8340     }
8341     if (is_undef(a))
8342       return a;
8343     if (is_undef(b))
8344       return b;
8345     gen test=superieur_strict(a,b,contextptr);
8346     if (test.type==_INT_){
8347       if (test.val==1)
8348 	return a;
8349       else
8350 	return b;
8351     }
8352     return new_ref_symbolic(symbolic(at_max,makesequence(a,b)));
8353   }
8354 
operator !(const gen & a)8355   gen operator !(const gen & a){
8356     if (is_undef(a)) return a;
8357     switch (a.type){
8358     case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _FLOAT_:
8359       return change_subtype(is_zero(a,context0),_INT_BOOLEAN);
8360     default:
8361       bool as=a.is_symb_of_sommet(at_superieur_strict);
8362       bool ae=a.is_symb_of_sommet(at_superieur_egal);
8363       if (as || ae){
8364 	gen f=a._SYMBptr->feuille;
8365 	if (f.type==_VECT && f._VECTptr->size()==2){
8366 	  return symbolic(ae?at_superieur_strict:at_superieur_egal,makesequence(f._VECTptr->back(),f._VECTptr->front()));
8367 	}
8368       }
8369       if (a.is_symb_of_sommet(at_and)){
8370 	gen f=_not(a._SYMBptr->feuille,context0);
8371 	return symbolic(at_ou,f);
8372       }
8373       if (a.is_symb_of_sommet(at_ou)){
8374 	gen f=_not(a._SYMBptr->feuille,context0);
8375 	return symbolic(at_and,f);
8376       }
8377       return symb_not(a);
8378     }
8379   }
8380 
8381   struct islesscomplexthanf_compare {
islesscomplexthanf_comparegiac::islesscomplexthanf_compare8382     islesscomplexthanf_compare() {}
operator ()giac::islesscomplexthanf_compare8383     bool operator ()(const gen & a,const gen &b){ return islesscomplexthanf(a,b); }
8384   };
8385 
islesscomplexthanf_sort(iterateur it,iterateur itend)8386   void islesscomplexthanf_sort(iterateur it,iterateur itend){
8387     islesscomplexthanf_compare m;
8388     sort(it,itend,m);
8389   }
8390 
8391   struct f_compare {
8392     bool (*f)(const gen &a,const gen &b);
f_comparegiac::f_compare8393     f_compare():f(islesscomplexthanf){}
f_comparegiac::f_compare8394     f_compare(bool (*f_)(const gen &a,const gen &b)):f(f_){}
operator ()giac::f_compare8395     inline bool operator () (const gen & a,const gen &b){ return f(a,b); }
8396   };
8397 
gen_sort_f(iterateur it,iterateur itend,bool (* f)(const gen & a,const gen & b))8398   void gen_sort_f(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b)){
8399     f_compare m(f);
8400     sort(it,itend,m);
8401   }
8402 
8403 
8404   // equality of vecteurs representing geometrical lines
geo_equal(const vecteur & v,const vecteur & w,int subtype,GIAC_CONTEXT)8405   static bool geo_equal(const vecteur &v,const vecteur & w,int subtype,GIAC_CONTEXT){
8406     int vs=int(v.size()),ws=int(w.size());
8407     if (vs!=ws)
8408       return false;
8409     if (v==w)
8410       return true;
8411     if ( (subtype==_LINE__VECT)  && (vs==2)){
8412       if (v[1]==v[0])
8413 	return v==w;
8414       // v[1]!=v[0]
8415       if (!is_zero(im(rdiv(w[0]-v[0],v[1]-v[0],contextptr),contextptr),contextptr))
8416 	return false;
8417       if (!is_zero(im(rdiv(w[1]-v[0],v[1]-v[0],contextptr),contextptr),contextptr))
8418 	return false;
8419       return true;
8420     }
8421     if (subtype==_SET__VECT){
8422       vecteur w1(w),v1(v);
8423 #if 1
8424       islesscomplexthanf_sort(w1.begin(),w1.end());
8425       islesscomplexthanf_sort(v1.begin(),v1.end());
8426 #else
8427       sort(w1.begin(),w1.end(),islesscomplexthanf);
8428       sort(v1.begin(),v1.end(),islesscomplexthanf);
8429 #endif
8430       return w1==v1;
8431     }
8432     return false;
8433   }
8434 
operator_equal(const gen & a,const gen & b,GIAC_CONTEXT)8435   bool operator_equal(const gen & a,const gen & b,GIAC_CONTEXT){
8436     switch ( (a.type<< _DECALAGE) | b.type ) {
8437     case _INT___INT_:
8438       return (a.val==b.val);
8439     case _INT___MOD: case _ZINT__MOD:
8440       return a==*b._MODptr;
8441     case _MOD__INT_: case _MOD__ZINT:
8442       return b==*a._MODptr;
8443     case _INT___ZINT:
8444       return (mpz_cmp_si(*b._ZINTptr,a.val)==0);
8445     case _INT___DOUBLE_:
8446       return double(a.val)==b._DOUBLE_val;
8447     case _DOUBLE___INT_:
8448       return a._DOUBLE_val==double(b.val);
8449     case _REAL__INT_: case _INT___REAL: case _REAL__ZINT: case _ZINT__REAL: case _REAL__FRAC: case _FRAC__REAL: case _DOUBLE___FRAC: case _FRAC__DOUBLE_: case _FRAC__FLOAT_: case _FLOAT___FRAC:
8450       return is_exactly_zero(a-b);
8451     case _INT___FLOAT_:
8452       return giac_float(a.val)==b._FLOAT_val;
8453     case _FLOAT___INT_:
8454       return a._FLOAT_val==giac_float(b.val);
8455     case _ZINT__INT_:
8456       return (mpz_cmp_si(*a._ZINTptr,b.val)==0);
8457     case _ZINT__ZINT:
8458       return (mpz_cmp(*a._ZINTptr,*b._ZINTptr)==0);
8459     case _INT___CPLX: case _ZINT__CPLX:
8460       return ( operator_equal(a,re(b,contextptr),contextptr) && is_zero(im(b,contextptr),contextptr));
8461     case _CPLX__ZINT: case _CPLX__INT_:
8462       return ( operator_equal(re(a,contextptr),b,contextptr) && is_zero(im(a,contextptr),contextptr)) ;
8463     case _CPLX__CPLX:
8464       return( operator_equal(*a._CPLXptr,*b._CPLXptr,contextptr) && operator_equal(*(a._CPLXptr+1),*(b._CPLXptr+1),contextptr) );
8465     case _DOUBLE___DOUBLE_:
8466       if (a._DOUBLE_val==b._DOUBLE_val)
8467 	return true;
8468       if (my_isnan(a._DOUBLE_val) && my_isnan(b._DOUBLE_val))
8469 	return true; // avoid infinite loop in evalf
8470       return  absdouble(a._DOUBLE_val-b._DOUBLE_val)<absdouble(a._DOUBLE_val)*epsilon(contextptr);
8471     case _FLOAT___FLOAT_:
8472       if (a._FLOAT_val==b._FLOAT_val)
8473 	return true;
8474 #ifdef BCD
8475       if (fis_nan(a._FLOAT_val) && fis_nan(b._FLOAT_val))
8476 	return true; // avoid infinite loop in evalf
8477       return false;
8478 #else
8479       if (my_isnan(a._FLOAT_val) && my_isnan(b._FLOAT_val))
8480 	return true; // avoid infinite loop in evalf
8481 #endif
8482       return fabs(a._FLOAT_val-b._FLOAT_val)<giac_float(epsilon(contextptr));
8483     case _IDNT__IDNT:
8484       // return a.subtype==b.subtype && (a._IDNTptr->name==b._IDNTptr->name || *a._IDNTptr->name==*b._IDNTptr->name);
8485       return a._IDNTptr->id_name==b._IDNTptr->id_name || strcmp(a._IDNTptr->id_name,b._IDNTptr->id_name)==0;
8486     case _SYMB__SYMB:
8487       if (a._SYMBptr==b._SYMBptr)
8488 	return true;
8489       if (a._SYMBptr->sommet!=b._SYMBptr->sommet)
8490 	return false;
8491       return (a._SYMBptr->feuille==b._SYMBptr->feuille);
8492     case _VECT__VECT:
8493       if (a._VECTptr==b._VECTptr)
8494 	return true;
8495       if (a.subtype!=b.subtype){
8496 	if ( (a.subtype==_MATRIX__VECT && b.subtype==0) ||
8497 	     (b.subtype==_MATRIX__VECT && a.subtype==0) )
8498 	  ; // don't consider them different
8499 	else
8500 	  return false;
8501       }
8502       if (a.subtype)
8503 	return geo_equal(*a._VECTptr,*b._VECTptr,a.subtype,contextptr);
8504       return *a._VECTptr==*b._VECTptr;
8505     case _POLY__POLY:
8506       if (a._POLYptr==b._POLYptr)
8507 	return true;
8508       return (a._POLYptr->dim==b._POLYptr->dim) && (a._POLYptr->coord==b._POLYptr->coord);
8509     case _FRAC__FRAC:
8510       return (a._FRACptr->num==b._FRACptr->num) && (a._FRACptr->den==b._FRACptr->den);
8511     case _STRNG__STRNG:
8512       if (is_undef(a)) return false;
8513       if (is_undef(b)) return false;
8514       return (a._STRNGptr==b._STRNGptr) || (*a._STRNGptr==*b._STRNGptr);
8515     case _FUNC__FUNC:
8516       return (a._FUNCptr==b._FUNCptr) || (*a._FUNCptr==*b._FUNCptr);
8517     case _MOD__MOD:
8518       return ( (*a._MODptr==*b._MODptr) && (*(a._MODptr+1)==*(b._MODptr+1)) );
8519     case _EXT__EXT:
8520       return ( change_subtype(*a._EXTptr,_POLY1__VECT)==change_subtype(*b._EXTptr,_POLY1__VECT) && (*(a._EXTptr+1)==*(b._EXTptr+1)) );
8521     case _SPOL1__SPOL1:
8522       return *a._SPOL1ptr==*b._SPOL1ptr;
8523     default: // Check pointers, type subtype
8524       if ((a.type==b.type) && (a.subtype==b.subtype) && (a.val==b.val) && a._ZINTptr==b._ZINTptr)
8525 	return true;
8526       if (a.type<=_REAL && b.type<=_REAL)
8527 	return is_zero(a-b,contextptr);
8528       if ( (a.type==_FLOAT_ || a.type==_DOUBLE_ || a.type==_REAL) && (b.type<=_REAL || b.type==_FRAC || b.type==_FLOAT_))
8529 	return is_zero(a-evalf(b,1,contextptr));
8530       if ( (b.type==_FLOAT_ || b.type==_DOUBLE_ || b.type==_REAL) && (a.type<=_REAL || a.type==_FRAC || a.type==_FLOAT_))
8531 	return is_zero(evalf(a,1,contextptr)-b);
8532       if (a.type==_USER)
8533 	return *a._USERptr==b;
8534       if (b.type==_USER)
8535 	return *b._USERptr==a;
8536       if (a.type==_INT_ && a.subtype==_INT_TYPE && b.type==_FUNC){
8537 	if (a==_STRNG && b==at_string) return true;
8538 	if (a==_VECT && b==at_vector) return true;
8539 	if (a==_FLOAT_ && b==at_float) return true;
8540 	if (a==_DOUBLE_ && b==at_real) return true;
8541 	if (a==_CPLX && b==at_complex) return true;
8542 	if ( (a==_INT_||a==_ZINT) && b==at_int) return true;
8543       }
8544       if (b.type==_INT_ && b.subtype==_INT_TYPE && a.type==_FUNC)
8545 	return operator_equal(b,a,contextptr);
8546       return false;
8547     }
8548   }
8549 
operator ==(const identificateur & i)8550   bool identificateur::operator ==(const identificateur & i){
8551     return id_name==i.id_name || !strcmp(id_name,i.id_name);
8552   }
8553 
operator ==(const gen & a,const identificateur & i)8554   bool operator ==(const gen & a,const identificateur & i){
8555     return a.type==_IDNT && (a._IDNTptr->id_name==i.id_name || !strcmp(a._IDNTptr->id_name,i.id_name));
8556   }
8557 
operator ==(const gen & i)8558   bool identificateur::operator ==(const gen & i){
8559     return i.type==_IDNT && (id_name==i._IDNTptr->id_name || !strcmp(id_name,i._IDNTptr->id_name));
8560   }
8561 
operator ==(const gen & a,const gen & b)8562   bool operator ==(const gen & a,const gen & b){
8563     return operator_equal(a,b,context0);
8564   }
8565 
operator !=(const gen & a,const gen & b)8566   bool operator !=(const gen & a,const gen & b){
8567     return !(a==b);
8568   }
8569 
equal(const gen & a,const gen & b,GIAC_CONTEXT)8570   gen equal(const gen & a,const gen &b,GIAC_CONTEXT){
8571     if (a.type==_VECT && b.type==_VECT && !b._VECTptr->empty()){
8572       if (calc_mode(contextptr)==1 && a.subtype==_GGBVECT && b.subtype==_GGBVECT){
8573 	return symbolic(at_equal,makesequence(a,b));
8574       }
8575       else {
8576 	if (a._VECTptr->size()==b._VECTptr->size())
8577 	  return apply(a,b,contextptr,equal);
8578 	return apply2nd(a,b,contextptr,equal);
8579       }
8580     }
8581     if (is_equal(a)) // so that equal(a=0 ,1) returns a=1, used for fsolve
8582       return equal(a._SYMBptr->feuille[0],b,contextptr);
8583     // only in ggb mode, because we want to be able to do subst(x[1],x=[1,2])
8584     if (calc_mode(contextptr)==1 && a.type==_IDNT && b.type==_VECT && b.subtype!=_SEQ__VECT && b.subtype!=_GGB__VECT){
8585       vecteur v=*b._VECTptr;
8586       for (unsigned i=0;i<v.size();++i){
8587 	v[i]=symbolic(at_equal,makesequence(a,v[i]));
8588       }
8589       return gen(v,b.subtype);
8590     }
8591     gen res=symbolic(at_equal,makesequence(a,b));
8592     if (a.type==_INT_ && a.subtype==_INT_PLOT && io_graph(contextptr))
8593       __interactive.op(res,contextptr);
8594     return res;
8595   }
8596 
equal2(const gen & a,const gen & b,GIAC_CONTEXT)8597   gen equal2(const gen & a,const gen &b,GIAC_CONTEXT){
8598     if (is_equal(a)) // so that equal(a=0 ,1) returns a=1, used for fsolve
8599       return equal(a._SYMBptr->feuille[0],b,contextptr);
8600     // only in ggb mode, because we want to be able to do subst(x[1],x=[1,2])
8601     if (calc_mode(contextptr)==1 && a.type==_IDNT && b.type==_VECT){
8602       vecteur v=*b._VECTptr;
8603       for (unsigned i=0;i<v.size();++i){
8604 	v[i]=symbolic(at_equal2,makesequence(a,v[i]));
8605       }
8606       return gen(v,b.subtype);
8607     }
8608     gen res=symbolic(at_equal2,makesequence(a,b));
8609     if (a.type==_INT_ && a.subtype==_INT_PLOT && io_graph(contextptr))
8610       __interactive.op(res,contextptr);
8611     return res;
8612   }
8613 
sign(const gen & a,GIAC_CONTEXT)8614   gen sign(const gen & a,GIAC_CONTEXT){
8615     if (is_equal(a))
8616       return apply_to_equal(a,sign,contextptr);
8617     if (complex_mode(contextptr)==0 && !has_i(a)){
8618       if (a.is_symb_of_sommet(at_exp))
8619 	return 1;
8620       if (a.is_symb_of_sommet(at_pow)){
8621 	gen f=a._SYMBptr->feuille[1];
8622 	if (f.type==_FRAC && f._FRACptr->den.type==_INT_ && f._FRACptr->den.val %2==0)
8623 	  return 1;
8624       }
8625     }
8626     if (a.is_symb_of_sommet(at_neg) && !is_inf(a))
8627       return -sign(a._SYMBptr->feuille,contextptr);
8628     if (a.is_symb_of_sommet(at_inv))
8629       return sign(a._SYMBptr->feuille,contextptr);
8630     if (a.is_symb_of_sommet(at_prod)){
8631       vecteur v=gen2vecteur(a._SYMBptr->feuille);
8632       gen res=1;
8633       for (int i=0;i<int(v.size());++i){
8634 	res=res*sign(v[i],contextptr);
8635       }
8636       return res;
8637     }
8638     if (is_exactly_zero(a)){
8639       if (a.type==_DOUBLE_ || a.type==_FLOAT_)
8640 	return 0.0;
8641       else
8642 	return 0;
8643     }
8644     if (a==plus_inf)
8645       return 1;
8646     if (a==minus_inf)
8647       return -1;
8648     if (is_undef(a))
8649       return a;
8650     if (is_inf(a))
8651       return undef;
8652     double eps=epsilon(contextptr);
8653     if (eps>1e-6)
8654       *logptr(contextptr) << gettext("Warning, sign might return 0 incorrectly because the value of eps is too large ") << eps << '\n';
8655     switch (a.type){
8656     case _INT_: case _ZINT:
8657       if (is_positive(a,contextptr))
8658 	return 1;
8659       else
8660 	return -1;
8661     case _DOUBLE_:
8662       if (a._DOUBLE_val>eps)
8663 	return 1.0;
8664       if (a._DOUBLE_val<-eps)
8665 	return -1.0;
8666       return 0.0;
8667     case _FLOAT_: // NOTE: does not follow eps rule
8668       if (a._FLOAT_val>0)
8669 	return giac_float(1.0);
8670       if (a._FLOAT_val<0)
8671 	return giac_float(-1.0);
8672       return giac_float(0.0);
8673     case _REAL:
8674       {
8675 	if (a._REALptr->is_zero())
8676 	  return 0;
8677 	if (a._REALptr->maybe_zero())
8678 	  return undef;
8679 	int res=a._REALptr->is_positive();
8680 	if (res)
8681 	  return res;
8682 	return undef;
8683       }
8684       return -1;
8685     case _CPLX:
8686       return a/abs(a,contextptr);
8687     case _FRAC:
8688       return sign(a._FRACptr->num,contextptr)*sign(a._FRACptr->den,contextptr);
8689     }
8690     int fs=fastsign(a,contextptr);
8691     if (fs)
8692       return fs;
8693     gen b=evalf_double(a,1,contextptr);
8694     if (b.type==_DOUBLE_){
8695       if (b._DOUBLE_val>eps)
8696 	return plus_one;
8697       if (b._DOUBLE_val<-eps)
8698 	return minus_one;
8699 #ifdef HAVE_LIBMPFR // FIXME try to avoid rounding errors
8700       b=accurate_evalf(eval(a,1,contextptr),1000);
8701       if (is_greater(b,1e-250,contextptr))
8702 	return plus_one;
8703       if (is_greater(-1e-250,b,contextptr))
8704 	return minus_one;
8705 #endif
8706       // return zero; // returning 0 is wrong, sign(a) is much better!
8707     }
8708     if (b.type==_FLOAT_){
8709       if (b._FLOAT_val>eps)
8710 	return plus_one;
8711       if (b._FLOAT_val<-eps)
8712 	return minus_one;
8713       return zero;
8714     }
8715     if (is_zero(im(a,contextptr),contextptr)){
8716       int s=sturmsign(a,true,contextptr);
8717       if (s && s!=-2)
8718 	return s;
8719     }
8720     return new_ref_symbolic(symbolic(at_sign,a));
8721   }
8722 
sym_is_greater(const gen & a,const gen & b,GIAC_CONTEXT)8723   static gen sym_is_greater(const gen & a,const gen & b,GIAC_CONTEXT){
8724     if (is_undef(a))
8725       return a;
8726     if (is_undef(b))
8727       return b;
8728     if (a==unsigned_inf || b==unsigned_inf || a.type==_VECT || b.type==_VECT)
8729       return undef;
8730     if (a==b)
8731       return false;
8732     if ( (b==plus_inf) || (a==minus_inf) )
8733       return false;
8734     if ( (b==minus_inf) || (a==plus_inf) )
8735       return true;
8736     if (is_equal(a) && is_equal(b) ){
8737       gen & af=a._SYMBptr->feuille;
8738       gen & bf=b._SYMBptr->feuille;
8739       if (af.type==_VECT && bf.type==_VECT && af._VECTptr->size()==2 && bf._VECTptr->size()==2 && af._VECTptr->front()==bf._VECTptr->front())
8740 	return sym_is_greater(af._VECTptr->back(),bf._VECTptr->back(),contextptr);
8741     }
8742     if (a.type==_STRNG && b.type==_STRNG)
8743       return *a._STRNGptr>=*b._STRNGptr;
8744     if (a.type==_USER)
8745       return (*a._USERptr>b);
8746     if (b.type==_USER)
8747       return (*b._USERptr<=a);
8748     if (a.is_symb_of_sommet(at_superieur_strict) || a.is_symb_of_sommet(at_superieur_egal) || a.is_symb_of_sommet(at_inferieur_strict) || a.is_symb_of_sommet(at_inferieur_egal) )
8749       return false;
8750     if (b.is_symb_of_sommet(at_superieur_strict) || b.is_symb_of_sommet(at_superieur_egal) || b.is_symb_of_sommet(at_inferieur_strict) || b.is_symb_of_sommet(at_inferieur_egal) )
8751       return false;
8752     if (a.type==_CPLX || b.type==_CPLX)
8753       return symb_superieur_strict(a,b);
8754     gen approx;
8755     if (has_evalf(a,approx,1,contextptr) && approx.type==_CPLX && !is_zero(im(approx,contextptr)/re(approx,contextptr),contextptr))
8756       return symb_superieur_strict(a,b);
8757     if (has_evalf(a-b,approx,1,contextptr)){
8758       if (approx.type==_CPLX && is_zero(im(approx,contextptr)/re(approx,contextptr),contextptr))
8759 	approx=re(approx,contextptr);
8760       if (approx.type==_DOUBLE_ ){
8761 #ifdef HAVE_LIBMPFR
8762 	// FIXME?? try to avoid rounding error with more digits
8763 	if (fabs(approx._DOUBLE_val)<1e-5 && (a-b).type!=_FRAC){
8764 	  gen tmp=accurate_evalf(eval(a-b,1,contextptr),1000);
8765 	  tmp=evalf_double(tmp,1,contextptr);
8766 	  if (tmp.type==_DOUBLE_)
8767 	    approx=tmp;
8768 	}
8769 #endif
8770 	return (approx._DOUBLE_val>0);
8771       }
8772       if (approx.type==_REAL)
8773 	return is_strictly_positive(approx,contextptr);
8774       if (approx.type==_FLOAT_ )
8775 	return (approx._FLOAT_val>0);
8776     }
8777     gen g=sign(a-b,contextptr);
8778     if (is_one(g))
8779       return plus_one;
8780     if (is_minus_one(g))
8781       return false;
8782     return symb_superieur_strict(a,b);
8783   }
8784 
superieur_strict(const gen & a,const gen & b,GIAC_CONTEXT)8785   gen superieur_strict(const gen & a,const gen & b,GIAC_CONTEXT){
8786     switch ( (a.type<< _DECALAGE) | b.type ) {
8787     case _INT___INT_:
8788       return (a.val>b.val);
8789     case _INT___ZINT:
8790       return (mpz_cmp_si(*b._ZINTptr,a.val)<0);
8791     case _ZINT__INT_:
8792       return (mpz_cmp_si(*a._ZINTptr,b.val)>0);
8793     case _ZINT__ZINT:
8794       return (mpz_cmp(*a._ZINTptr,*b._ZINTptr)>0);
8795     case _DOUBLE___DOUBLE_:
8796       return a._DOUBLE_val>b._DOUBLE_val;
8797     case _FRAC__FRAC:
8798       if (is_positive(a._FRACptr->den,contextptr) && is_positive(b._FRACptr->den,contextptr))
8799 	return superieur_strict(a._FRACptr->num*b._FRACptr->den,a._FRACptr->den*b._FRACptr->num,contextptr);
8800       break;
8801     case _FRAC__INT_:
8802       if (is_positive(a._FRACptr->den,contextptr))
8803 	return superieur_strict(a._FRACptr->num,a._FRACptr->den*b,contextptr);
8804       break;
8805     case _INT___FRAC:
8806       if (is_positive(b._FRACptr->den,contextptr))
8807 	return superieur_strict(b._FRACptr->den*a,b._FRACptr->num,contextptr);
8808       break;
8809     case _DOUBLE___INT_:
8810       return a._DOUBLE_val>b.val;
8811     case _INT___DOUBLE_:
8812       return a.val>b._DOUBLE_val;
8813     case _FLOAT___FLOAT_:
8814       return a._FLOAT_val>b._FLOAT_val;
8815     case _FLOAT___INT_:
8816       return a._FLOAT_val>b.val;
8817     case _INT___FLOAT_:
8818       return a.val>b._FLOAT_val;
8819     case _DOUBLE___ZINT:
8820       return a._DOUBLE_val>mpz_get_d(*b._ZINTptr);
8821     case _ZINT__DOUBLE_:
8822       return mpz_get_d(*a._ZINTptr)>b._DOUBLE_val;
8823     }
8824     if (a.type<=_REAL && b.type<=_REAL)
8825       return is_strictly_positive(a-b,contextptr);
8826     return sym_is_greater(a,b,contextptr);
8827   }
8828 
inferieur_strict(const gen & a,const gen & b,GIAC_CONTEXT)8829   gen inferieur_strict(const gen & a,const gen & b,GIAC_CONTEXT){
8830     return superieur_strict(b,a,contextptr);
8831   }
8832 
superieur_egal(const gen & a,const gen & b,GIAC_CONTEXT)8833   gen superieur_egal(const gen & a,const gen & b,GIAC_CONTEXT){
8834     if ( (a.type==_REAL && b.type<=_REAL) ||
8835 	 (b.type==_REAL && a.type<=_REAL) ){
8836       if (is_positive(a-b,contextptr))
8837 	return 1;
8838       return 0;
8839     }
8840     gen g=!superieur_strict(b,a,contextptr);
8841     if (is_undef(g)) return g;
8842     if (g.type==_INT_)
8843       return g;
8844     return symb_superieur_egal(a,b);
8845   }
8846 
inferieur_egal(const gen & a,const gen & b,GIAC_CONTEXT)8847   gen inferieur_egal(const gen & a,const gen & b,GIAC_CONTEXT){
8848     return superieur_egal(b,a,contextptr);
8849   }
8850 
has_inf_or_undef(const gen & g)8851   bool has_inf_or_undef(const gen & g){
8852     if (g.type!=_VECT)
8853       return is_inf(g) || is_undef(g);
8854     const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
8855     for (;it!=itend;++it){
8856       if (has_inf_or_undef(*it))
8857 	return true;
8858     }
8859     return false;
8860   }
8861 
is_inf(const gen & e)8862   bool is_inf(const gen & e){
8863     switch (e.type){
8864     case _IDNT:
8865       return !strcmp(e._IDNTptr->id_name,string_infinity);
8866     case _SYMB:
8867       return is_inf(e._SYMBptr->feuille);
8868     case _DOUBLE_:
8869       return my_isinf(e._DOUBLE_val);
8870     case _FLOAT_:
8871       return fis_inf(e._FLOAT_val);
8872     default:
8873       return false;
8874     }
8875   }
is_undef(const vecteur & v)8876   bool is_undef(const vecteur & v){
8877     return !v.empty() && is_undef(v.front());
8878   }
is_undef(const polynome & p)8879   bool is_undef(const polynome & p){
8880     return !p.coord.empty() && is_undef(p.coord.front());
8881   }
8882   // we are using exponent as undef marker because coeff=undef is used
8883   // for Landau notation O(x^exponent)
is_undef(const sparse_poly1 & s)8884   bool is_undef(const sparse_poly1 & s){
8885     return !s.empty() && is_undef(s.front().exponent);
8886   }
is_undef(const gen & e)8887   bool is_undef(const gen & e){
8888     switch (e.type){
8889     case _IDNT:
8890       return !strcmp(e._IDNTptr->id_name,string_undef);
8891     case _STRNG:
8892       return e.subtype==-1;
8893     case _VECT:
8894       return !e._VECTptr->empty() && is_undef(e._VECTptr->front());
8895     case _POLY:
8896       return !e._POLYptr->coord.empty() && is_undef(e._POLYptr->coord.front().value);
8897     case _SPOL1:
8898       return !e._SPOL1ptr->empty() && is_undef(e._SPOL1ptr->front().exponent);
8899     case _FLOAT_:
8900       return fis_nan(e._FLOAT_val);
8901     case _DOUBLE_:
8902       return my_isnan(e._DOUBLE_val);
8903     case _CPLX:
8904       return is_undef(*e._CPLXptr) || is_undef(*(e._CPLXptr+1));
8905     case _FRAC:
8906       return is_undef(e._FRACptr->num);
8907     default:
8908       return false;
8909     }
8910   }
8911 
is_zero__VECT(const vecteur & v,GIAC_CONTEXT)8912   bool is_zero__VECT(const vecteur & v,GIAC_CONTEXT){
8913     vecteur::const_iterator it=v.begin(),itend=v.end();
8914     for (;it!=itend;++it){
8915       if (!is_zero(*it,contextptr))
8916 	return false;
8917     }
8918     return true;
8919   }
8920 
is_zero(const gen & a,GIAC_CONTEXT)8921   bool is_zero(const gen & a,GIAC_CONTEXT){
8922     switch (a.type ) {
8923     case _INT_:
8924       return !a.val;
8925     case _ZINT:
8926       return (!mpz_sgn(*a._ZINTptr));
8927     case _REAL:
8928       return fabs(evalf_double(a,1,contextptr)._DOUBLE_val)<=epsilon(contextptr);// return a._REALptr->is_zero();
8929     case _CPLX:
8930       return (is_zero(*a._CPLXptr,contextptr) && is_zero(*(a._CPLXptr+1),contextptr));
8931     case _DOUBLE_:
8932       return (fabs(a._DOUBLE_val)<=epsilon(contextptr));
8933     case _FLOAT_:
8934       return is_exactly_zero(a._FLOAT_val);
8935     case _VECT:
8936       return is_zero__VECT(*a._VECTptr,contextptr);
8937     case _POLY:
8938       return a._POLYptr->coord.empty();
8939     case _FRAC:
8940       return is_zero(a._FRACptr->num,contextptr);
8941     case _MOD:
8942       return is_zero(*a._MODptr,contextptr);
8943     case _USER:
8944       return a._USERptr->is_zero();
8945     case _SYMB:
8946       if (a._SYMBptr->sommet==at_unit)
8947 	return is_zero(a._SYMBptr->feuille[0]);
8948     default:
8949       return false;
8950     }
8951   }
8952 
is_exactly_zero(const gen & a)8953   bool is_exactly_zero(const gen & a){
8954     switch (a.type ) {
8955     case _INT_:
8956       return !a.val;
8957     case _ZINT:
8958       return (!mpz_sgn(*a._ZINTptr));
8959     case _REAL:
8960       return a._REALptr->is_zero();
8961     case _CPLX:
8962       return (is_exactly_zero(*a._CPLXptr) && is_exactly_zero(*(a._CPLXptr+1)));
8963     case _DOUBLE_:
8964       return a._DOUBLE_val==0;
8965     case _FLOAT_:
8966       return fis_exactly_zero(a._FLOAT_val);
8967     case _POLY:
8968       return a._POLYptr->coord.empty();
8969     case _FRAC:
8970       return is_exactly_zero(a._FRACptr->num);
8971     case _MOD:
8972       return is_exactly_zero(*a._MODptr);
8973     case _USER:
8974       return a._USERptr->is_zero();
8975     default:
8976       return false;
8977     }
8978   }
8979 
is_one(const gen & a)8980   bool is_one(const gen & a){
8981     switch (a.type ) {
8982     case _INT_:
8983       return a.val==1;
8984     case _ZINT:
8985       return mpz_cmp_si(*a._ZINTptr,1)==0;
8986     case _CPLX:
8987       return is_one(*a._CPLXptr) && is_zero(*(a._CPLXptr+1));
8988     case _DOUBLE_:
8989       return a._DOUBLE_val==1;
8990     case _FLOAT_:
8991       return a._FLOAT_val==giac_float(1);
8992     case _REAL:
8993       return is_exactly_zero(a-1);
8994     case _VECT:
8995       return a._VECTptr->size()==1 && is_one(a._VECTptr->front());
8996     case _POLY:
8997       return Tis_constant(*a._POLYptr) && (is_one(a._POLYptr->coord.front().value));
8998     case _FRAC:
8999       return a._FRACptr->num == a._FRACptr->den;
9000     case _MOD:
9001       return is_one(*a._MODptr);
9002     case _USER:
9003       return a._USERptr->is_one();
9004     default:
9005       return false;
9006     }
9007   }
9008 
is_minus_one(const gen & a)9009   bool is_minus_one(const gen & a){
9010     switch (a.type ) {
9011     case _INT_:
9012       return a.val==-1;
9013     case _ZINT:
9014       return mpz_cmp_si(*a._ZINTptr,-1)==0;
9015     case _CPLX:
9016       return (is_minus_one(*a._CPLXptr) && is_zero(*(a._CPLXptr+1),context0));
9017     case _DOUBLE_:
9018       return a._DOUBLE_val==-1;
9019     case _FLOAT_:
9020       return a._FLOAT_val==giac_float(-1);
9021     case _REAL:
9022       return is_exactly_zero(a+1);
9023     case _VECT:
9024       return a._VECTptr->size()==1 && is_minus_one(a._VECTptr->front());
9025     case _POLY:
9026       return Tis_constant(*a._POLYptr) && (is_minus_one(a._POLYptr->coord.front().value));
9027     case _FRAC:
9028       return a._FRACptr->num == -a._FRACptr->den;
9029     case _MOD:
9030       if (*(a._MODptr+1)==plus_two)
9031 	return is_one(*a._MODptr);
9032       else
9033 	return is_minus_one(*a._MODptr);
9034     case _SYMB:
9035       return a._SYMBptr->sommet==at_neg && is_one(a._SYMBptr->feuille);
9036     case _USER:
9037       return a._USERptr->is_minus_one();
9038     default:
9039       return false;
9040     }
9041   }
9042 
is_sq_minus_one(const gen & a)9043   bool is_sq_minus_one(const gen & a){
9044     switch (a.type ) {
9045     case _CPLX: case _MOD: case _USER:
9046       return is_minus_one(a*a);
9047     case _VECT:
9048       return a._VECTptr->size()==1 && is_sq_minus_one(a._VECTptr->front());
9049     case _POLY:
9050       return Tis_constant(*a._POLYptr) && (is_sq_minus_one(a._POLYptr->coord.front().value));
9051     default:
9052       return false;
9053     }
9054   }
9055 
operator [](int i) const9056   gen gen::operator [] (int i) const{
9057     return operator_at(i,context0);
9058   }
9059 
operator_at(int i,GIAC_CONTEXT) const9060   gen gen::operator_at(int i,GIAC_CONTEXT) const{
9061     if (type==_SYMB){
9062       if (!i)
9063 	return _SYMBptr->sommet;
9064       if (_SYMBptr->feuille.type!=_VECT){
9065 	if (i==1)
9066 	  return _SYMBptr->feuille;
9067 	else
9068 	  return gendimerr(contextptr);
9069       }
9070       if (unsigned(i)>_SYMBptr->feuille._VECTptr->size())
9071 	return gendimerr(contextptr);
9072       return (*(_SYMBptr->feuille._VECTptr))[i-1];
9073     }
9074     if (type==_MOD){
9075       if (!i)
9076 	return _MOD;
9077       if (i==1)
9078 	return *_MODptr;
9079       if (i==2)
9080 	return *(_MODptr+1);
9081       return gendimerr(contextptr);
9082     }
9083     if (type==_IDNT)
9084       return symb_at(makesequence(*this,i));
9085     if (type==_FUNC){
9086       if (*this==at_ln){
9087 	i=i+array_start(contextptr); // (xcas_mode(contextptr)!=0);
9088 	return inv(ln(i,contextptr),contextptr)*(*this);
9089       }
9090       if (*this==at_maple_root){
9091 	identificateur tmp(" x");
9092 	gen g=symb_program(tmp,zero,new_ref_symbolic(symbolic(at_makesuite,i,tmp)),contextptr);
9093 	g=makesequence(at_maple_root,g);
9094 	return symb_compose(g);
9095       }
9096     }
9097     if (this->type!=_VECT){
9098       if (calc_mode(contextptr)==1)
9099 	return *this;
9100       return gentypeerr(gettext("Gen [int]"));
9101     }
9102     if (i<0) i+=_VECTptr->size();
9103     if (unsigned(i)>=_VECTptr->size()){
9104       if (array_start(contextptr))//(xcas_mode(contextptr)!=0 || abs_calc_mode(contextptr)==38)
9105 	++i;
9106       return gendimerr(gettext("Index outside range : ")+ print_INT_(i)+", vector size is "+print_INT_(int(_VECTptr->size()))
9107 #ifndef GIAC_HAS_STO_38
9108 		       +", syntax compatibility mode "+print_program_syntax(xcas_mode(contextptr))
9109 #endif
9110 		       +"\n");
9111     }
9112     return (*(this->_VECTptr))[i];
9113   }
9114 
operator [](const gen & i) const9115   gen gen::operator [] (const gen & i) const {
9116     return operator_at(i,context0);
9117   }
9118 
operator_at(const gen & i,GIAC_CONTEXT) const9119   gen gen::operator_at(const gen & i,GIAC_CONTEXT) const {
9120     if (type==_STRNG && subtype==-1) return *this;
9121     if (i.type==_DOUBLE_){
9122       double id=i._DOUBLE_val;
9123       if (int(id)==id)
9124 	return (*this)[int(id)];
9125     }
9126     if (i.type==_FLOAT_){
9127       giac_float id=i._FLOAT_val;
9128       if (giac_float(get_int(id))==id)
9129 	return (*this)[get_int(id)];
9130     }
9131     if (i.type==_REAL){
9132       double id=i.evalf_double(1,contextptr)._DOUBLE_val;
9133       if (int(id)==id)
9134 	return (*this)[int(id)];
9135     }
9136     if ((type==_STRNG) && (i.type==_INT_)){
9137       int s=int(_STRNGptr->size()),I=i.val;
9138       if (I<0) I+=s;
9139       if ( (I<s) && (I>=0))
9140 	return string2gen(string()+'"'+(*_STRNGptr)[I]+'"');
9141     }
9142     if (type==_IDNT)
9143       return new_ref_symbolic(symbolic(at_at,gen(makenewvecteur(*this,i),_SEQ__VECT)));
9144     if (type==_USER)
9145       return (*_USERptr)[i];
9146     if (type==_MAP){
9147       gen_map::const_iterator it=_MAPptr->find(i),itend=_MAPptr->end();
9148       if (it!=itend)
9149 	return it->second;
9150       if (subtype==_SPARSE_MATRIX)
9151 	return 0;
9152     }
9153     if (type==_SPOL1){
9154       sparse_poly1::const_iterator it=_SPOL1ptr->begin(),itend=_SPOL1ptr->end();
9155       for (;it!=itend;++it){
9156 	if (it->exponent==i)
9157 	  return it->coeff;
9158       }
9159       return 0;
9160     }
9161     if (is_symb_of_sommet(at_at)){ // add i at the end of the index
9162       if (_SYMBptr->feuille.type==_VECT && _SYMBptr->feuille._VECTptr->size()==2){
9163 	gen operand=_SYMBptr->feuille._VECTptr->front();
9164 	vecteur indice=makevecteur(_SYMBptr->feuille._VECTptr->back());
9165 	indice.push_back(i);
9166 	return symb_at(makenewvecteur(operand,gen(indice,_SEQ__VECT)));
9167       }
9168     }
9169     if (i.type==_DOUBLE_)
9170       return (*this)[(int) i._DOUBLE_val];
9171     if (i.type==_FLOAT_)
9172       return (*this)[ get_int(i._FLOAT_val) ];
9173     if (i.type==_SYMB){
9174       bool ideuxpoints=i._SYMBptr->sommet==at_deuxpoints;
9175       if (i._SYMBptr->sommet==at_interval || ideuxpoints) {
9176 	gen i1=_ceil(i._SYMBptr->feuille._VECTptr->front(),contextptr);
9177 	gen iback=i._SYMBptr->feuille._VECTptr->back();
9178 	int step=1;
9179 	if (ideuxpoints && iback.is_symb_of_sommet(at_deuxpoints)){
9180 	  gen istep=iback._SYMBptr->feuille;
9181 	  iback=istep[0];
9182 	  istep=istep[1]+array_start(contextptr);
9183 	  if (!is_integral(istep) || istep.type!=_INT_ || istep.val==0)
9184 	    return gendimerr(contextptr);
9185 	  step=istep.val;
9186 	  if (step<0 && is_zero(i1))
9187 	    i1=minus_one;
9188 	  if (0 && step<0 && is_zero(iback)){ // detected during translation
9189 	    *logptr(contextptr) << gettext("Warning, using :0:-step, use :-1:-step for ::") << '\n';
9190 	  }
9191 	}
9192 	gen i2=_floor(iback,contextptr);
9193 	if (is_integral(i1) && is_integral(i2)){
9194 	  int debut=i1.val,fin=i2.val+(ideuxpoints?(step<0?1:-1):0);
9195 	  int S=1;
9196 	  if (type==_STRNG) S=int(_STRNGptr->size());
9197 	  if (type==_VECT) S=int(_VECTptr->size());
9198 	  if (debut>=S)
9199 	    return (type==_STRNG)?string2gen("",false):gen(vecteur(0),subtype);
9200 	  if (debut<0) debut+=S;
9201 	  if (fin<0) fin+=S;
9202 	  fin=giacmin(fin,S-1);
9203 	  debut=giacmin(debut,S-1);
9204 	  if (debut<0 || step*double(fin-debut)<0 )
9205 	    return (type==_STRNG)?string2gen("",false):gen(vecteur(0),subtype); // swap(debut,fin);
9206 	  if (step==1){
9207 	    if (type==_STRNG)
9208 	      return string2gen('"'+_STRNGptr->substr(debut,fin-debut+1)+'"');
9209 	    if (type==_VECT)
9210 	      return gen(vecteur(_VECTptr->begin()+debut,_VECTptr->begin()+fin+1),subtype);
9211 	  }
9212 	  if (type==_STRNG){
9213 	    const string & s=*_STRNGptr;
9214 	    string res;
9215 	    if (step<0){
9216 	      for (;debut>=fin;debut+=step)
9217 		res += s[debut];
9218 	    }
9219 	    else {
9220 	      for (;debut<=fin;debut+=step)
9221 		res += s[debut];
9222 	    }
9223 	    return string2gen(res,false);
9224 	  }
9225 	  if (type==_VECT){
9226 	    const vecteur & v=*_VECTptr;
9227 	    vecteur res;
9228 	    res.reserve(absint(fin-debut)/step+1);
9229 	    if (step<0){
9230 	      for (;debut>=fin;debut+=step)
9231 		res.push_back(v[debut]);
9232 	    }
9233 	    else {
9234 	      for (;debut<=fin;debut+=step)
9235 		res.push_back(v[debut]);
9236 	    }
9237 	    return gen(res,subtype);
9238 	  }
9239 	}
9240       }
9241     }
9242     if (i.type==_VECT){
9243       const_iterateur it=i._VECTptr->begin(),itend=i._VECTptr->end();
9244       gen res (*this);
9245       for (;it!=itend;++it){
9246 	if (it->type==_VECT){
9247 	  vecteur tmp;
9248 	  const_iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end();
9249 	  for (;jt!=jtend;++jt){
9250 	    tmp.push_back(res[*jt]);
9251 	  }
9252 	  return gen(tmp,it->subtype);
9253 	}
9254 	bool itdeuxpoints=it->type==_SYMB && it->_SYMBptr->sommet==at_deuxpoints;
9255 	if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_interval || itdeuxpoints) && (it+1!=itend) ){
9256 	  // submatrix extraction
9257 	  gen i1=it->_SYMBptr->feuille._VECTptr->front(),iback=it->_SYMBptr->feuille._VECTptr->back();
9258 	  int step=1;
9259 	  if (itdeuxpoints && iback.is_symb_of_sommet(at_deuxpoints)){
9260 	    gen istep=iback._SYMBptr->feuille;
9261 	    iback=istep[0];
9262 	    istep=istep[1]+array_start(contextptr);
9263 	    if (!is_integral(istep) || istep.type!=_INT_ || istep==0)
9264 	      return gendimerr(contextptr);
9265 	    step=istep.val;
9266 	    if (step<0 && is_zero(i1))
9267 	      i1=minus_one;
9268 	    if (step<0 && is_zero(iback)){
9269 	      *logptr(contextptr) << gettext("Warning, using :0:-step, use :-1:-step for ::") << '\n';
9270 	    }
9271 	  }
9272 	  if (i1.type==_INT_ && iback.type==_INT_){
9273 	    int debut=i1.val,fin=iback.val+(itdeuxpoints?(step<0?1:-1):0);
9274 	    if (res.type==_VECT){
9275 	      int S=int(res._VECTptr->size());
9276 	      if (debut<0) debut +=S;
9277 	      if (fin<0) fin +=S;
9278 	      fin=giacmin(fin,S-1);
9279 	      debut=giacmin(debut,S-1);
9280 	      if (debut<0 || step*double(fin-debut)<0 )
9281 		return gendimerr(contextptr);
9282 	      iterateur jt=res._VECTptr->begin()+debut,jtend=_VECTptr->begin()+fin;
9283 	      gen fin_it(vecteur(it+1,itend),_SEQ__VECT);
9284 	      vecteur v;
9285 	      v.reserve(absint(jtend-jt)/step+1);
9286 	      if (step<0){
9287 		for (;jt>=jtend;jt+=step)
9288 		  v.push_back((*jt)[fin_it]);
9289 	      }
9290 	      else {
9291 		for (;jt<=jtend;jt+=step)
9292 		  v.push_back((*jt)[fin_it]);
9293 	      }
9294 	      if (res.subtype==_MATRIX__VECT && !ckmatrix(v))
9295 		return v;
9296 	      return gen(v,res.subtype);
9297 	    }
9298 	  }
9299 	}
9300 	res = res[*it];
9301       }
9302       return res;
9303     }
9304     if (i.type!=_INT_)
9305       return symb_at(makesequence(*this,i));
9306     return this->operator_at(i.val,contextptr);
9307   }
9308 
9309   /*
9310   gen & gen::operator [](int i){
9311     if (this->type!=_VECT)
9312       return gentypeerr(gettext("Gen [int]"));
9313     if (i>=_VECTptr->size())
9314       return gendimerr(contextptr);
9315     return (*(this->_VECTptr))[i];
9316   }
9317 
9318   gen & gen::operator [] (const gen & i) {
9319     if (i.type==_DOUBLE_)
9320       return (*this)[(int) i._DOUBLE_val];
9321     if (i.type!=_INT_)
9322       return gentypeerr(gettext("Gen [gen]"));
9323     if (this->type!=_VECT)
9324       return gentypeerr(gettext("Gen [gen]"));
9325     if (i.val>=_VECTptr->size())
9326       return gendimerr(gettext("Gen [_VECT]"));
9327     return (*(this->_VECTptr))[i.val];
9328   }
9329   */
9330 
operator ()(const gen & i,const context * contextptr) const9331   gen gen::operator () (const gen & i,const context * contextptr) const{
9332     return (*this)(i,undef,contextptr);
9333   }
9334 
operator ()(const gen & i,const gen & progname,const context * contextptr) const9335   gen gen::operator () (const gen & i,const gen & progname,const context * contextptr) const{
9336     bool isprog=type==_FUNC || this->is_symb_of_sommet(at_program) || this->is_symb_of_sommet(*at_program);
9337     if (!isprog){
9338       if (i.is_symb_of_sommet(at_equal))
9339 	return _subst(makesequence(*this,i),contextptr);
9340       if (i.type==_VECT){
9341 	vecteur & v = *i._VECTptr;
9342 	vecteur vin,vout;
9343 	for (unsigned j=0;j<v.size();++j){
9344 	  if (!v[j].is_symb_of_sommet(at_equal))
9345 	    break;
9346 	  vin.push_back(v[j]._SYMBptr->feuille[0]);
9347 	  vout.push_back(v[j]._SYMBptr->feuille[1]);
9348 	}
9349 	if (vin.size()==v.size())
9350 	  return subst(*this,vin,vout,false,contextptr);
9351       }
9352     }
9353     if (type==_SYMB){
9354       // Functional case for sommet
9355       if (_SYMBptr->sommet==at_program) {
9356 	gen tmp=_SYMBptr->feuille;
9357 	if (tmp.type!=_VECT)
9358 	  return gensizeerr(contextptr);
9359 	vecteur tmpv=*tmp._VECTptr; tmpv[1]=i;
9360 	return _program(gen(tmpv,tmp.subtype),progname,contextptr);
9361       }
9362 #ifndef RTOS_THREADX
9363       if (_SYMBptr->sommet==at_rpn_prog){
9364 	vecteur pile;
9365 	if (rpn_mode(contextptr))
9366 	  pile=history_out(contextptr);
9367 	if ( (i.type!=_VECT) || (i.subtype!=_SEQ__VECT))
9368 	  pile.push_back(i);
9369 	else
9370 	  pile=mergevecteur(pile,*i._VECTptr);
9371 	vecteur prog;
9372 	if (_SYMBptr->feuille.type==_VECT)
9373 	  prog=*_SYMBptr->feuille._VECTptr;
9374 	else
9375 	  prog=vecteur(1,_SYMBptr->feuille);
9376 	return gen(rpn_eval(prog,pile,contextptr),_RPN_STACK__VECT);
9377       }
9378 #endif
9379       if (_SYMBptr->sommet==at_compose){
9380 	gen tmp=_SYMBptr->feuille;
9381 	if (tmp.type!=_VECT)
9382 	  return tmp(i,contextptr);
9383 	gen res=i;
9384 	const_iterateur it=tmp._VECTptr->begin(),itend=tmp._VECTptr->end();
9385 	for (;itend!=it;){
9386 	  --itend;
9387 	  res=(*itend)(res,contextptr);
9388 	}
9389 	return res;
9390       }
9391       if (_SYMBptr->sommet==at_composepow){
9392 	gen tmp=_SYMBptr->feuille;
9393 	if (tmp.type!=_VECT || tmp._VECTptr->size()!=2 || tmp._VECTptr->back().type!=_INT_)
9394 	  return symb_of(tmp,i);
9395 	gen res=i;
9396 	int n=tmp._VECTptr->back().val;
9397 	if (n<0){
9398 	  // try to invert the function
9399 	  gen x(identificateur("xinvert")),y(identificateur("yinvert"));
9400 	  gen f=tmp._VECTptr->front();
9401 	  gen s=_solve(makesequence(symb_equal(f(x,contextptr),y),x),contextptr);
9402 	  if (s.type!=_VECT || s._VECTptr->size()<1 || is_undef(s._VECTptr->front()))
9403 	    return gensizeerr("Unable to invert function");
9404 	  if (s._VECTptr->size()>1)
9405 	    *logptr(contextptr) << "Choosing first solution in "<<s<<'\n';
9406 	  f=symb_program(y,0,s._VECTptr->front(),contextptr);
9407 	  n=-n;
9408 	  tmp=makesequence(f,n);
9409 	}
9410 	if (!n)
9411 	  return i;
9412 	int ratnormal_test=MAX_RECURSION_LEVEL/2;
9413 	// otherwise f(x):=-3x+2; g:=(f@@300)(x):; simplifier(g); might segfault
9414 	tmp=tmp._VECTptr->front();
9415 	for (int j=0;j<n;++j){
9416 	  res=tmp(res,contextptr);
9417 	  if (j%ratnormal_test==ratnormal_test-1)
9418 	    res=ratnormal(res);
9419 	}
9420 	return res;
9421       }
9422       if (_SYMBptr->sommet==at_derive || _SYMBptr->sommet==at_function_diff || _SYMBptr->sommet==at_of || _SYMBptr->sommet==at_at)
9423 	return new_ref_symbolic(symbolic(at_of,makesequence(*this,i)));
9424       gen & f=_SYMBptr->feuille;
9425       // distributions laws: add arguments and reeval
9426       if (is_distribution(_SYMBptr->sommet)){
9427 	vecteur args(gen2vecteur(f));
9428 	if (i.type==_VECT && i.subtype==_SEQ__VECT)
9429 	  args=mergevecteur(args,*i._VECTptr);
9430 	else
9431 	  args.push_back(i);
9432 	return _SYMBptr->sommet(gen(args,_SEQ__VECT),contextptr);
9433       }
9434       if (string(_SYMBptr->sommet.ptr()->s)=="pari"){
9435 	vecteur argv(gen2vecteur(f));
9436 	if (i.type==_VECT && i.subtype!=_SEQ__VECT)
9437 	  argv=mergevecteur(argv,vecteur(1,i));
9438 	else
9439 	  argv=mergevecteur(argv,gen2vecteur(i));
9440 	return _SYMBptr->sommet(gen(argv,_SEQ__VECT),contextptr);
9441       }
9442       if (f==makenewvecteur(zero)){
9443 	return _SYMBptr->sommet(i,contextptr);
9444       }
9445       // other case, apply feuille to i then apply sommet
9446       if (f.type!=_VECT)
9447 	return _SYMBptr->sommet(f(i,contextptr),contextptr);
9448       vecteur lid(lidnt(*this));
9449       if (lid.size()==1 && !has_algebraic_program(*this)){
9450 	if (lid.front()==vx_var)
9451 	// suspect something like P:=x^3+1 then P(2)
9452 	  *logptr(contextptr) << "Warning, evaluating univariate expression of x(value) like if expression was a function.\nYou should write subst(" << *this << "," << lid.front() << "," << i << ")" << '\n';
9453 	else
9454 	  return gensizeerr("Expression used like a function "+this->print(contextptr)+"\nYou should write subst("+this->print(contextptr)+","+lid.front().print(contextptr)+","+i.print(contextptr)+")");
9455 	return subst(*this,lid.front(),i,false,contextptr);
9456       }
9457       vecteur res(*f._VECTptr);
9458       iterateur it=res.begin(),itend=res.end();
9459       bool warn=false;
9460       for (;it!=itend;++it){
9461 	if (it->type==_IDNT)
9462 	  warn=true;
9463 	*it=(*it)(i,contextptr);
9464       }
9465       if (warn)
9466 	*logptr(contextptr) << gettext("Warning, evaluating (") << *this << ")(" << i << ") as a function not as a product" << '\n';
9467       return _SYMBptr->sommet(res,contextptr);
9468     }
9469     if (type==_FUNC){
9470       if ( (i.type==_VECT) && (i.subtype==_SEQ__VECT) && (i._VECTptr->size()==1))
9471 	return (*_FUNCptr)(i._VECTptr->front(),contextptr);
9472       else
9473 	return (*_FUNCptr)(i,contextptr);
9474     }
9475     if (i.type==_DOUBLE_ && giac_floor(i._DOUBLE_val)==i._DOUBLE_val )
9476       return (*this)((int) i._DOUBLE_val,contextptr);
9477     if (i.type==_FLOAT_ && ffloor(i._FLOAT_val)==i._FLOAT_val )
9478       return (*this)(get_int(i._FLOAT_val),contextptr);
9479     if (type==_INT_ && subtype==_INT_TYPE && i.type==_VECT){
9480       return gen(*i._VECTptr,type);
9481     }
9482     if (type<_IDNT )
9483       return *this;
9484     if (type==_USER)
9485       return (*_USERptr)(i,contextptr);
9486     if (type==_STRNG){
9487       gen ii(i);
9488       if (!is_integral(ii))
9489 	return gensizeerr(gettext("Bad index"));
9490       if (ii.val<1 || ii.val>int(_STRNGptr->size()))
9491 	return gendimerr(gettext("Index out of range"));
9492       return string2gen(string(1,(*_STRNGptr)[ii.val-1]),false);
9493     }
9494     if (type==_VECT){
9495       if (of_pointer_38 && _VECTptr->size()==2 && _VECTptr->front().type==_POINTER_ && _VECTptr->front().subtype==_APPLET_POINTER && _VECTptr->back().type==_POINTER_ && _VECTptr->back().subtype==_VARFUNCDEF_POINTER )
9496 	return of_pointer_38(_VECTptr->front()._POINTER_val,_VECTptr->back()._POINTER_val,i);
9497       if (1 ||
9498 	  abs_calc_mode(contextptr)==38){
9499 	if (i.type==_VECT){
9500 	  gen res=*this;
9501 	  int is=int(i._VECTptr->size());
9502 	  for (int k=0;k<is;++k){
9503 	    res=res(i[k],contextptr);
9504 	  }
9505 	  return res;
9506 	}
9507 	if (i.is_symb_of_sommet(at_interval)){
9508 	  const gen & ife =i._SYMBptr->feuille;
9509 	  if (ife.type==_VECT && ife._VECTptr->size()==2){
9510 	    const gen & if1=ife._VECTptr->front();
9511 	    const gen & if2=ife._VECTptr->back();
9512 	    if (if1.type==_INT_ && if2.type==_INT_ && if1.val>=1 && if2.val>=1 && if1.val<=if2.val && if1.val<=int(_VECTptr->size()) && if2.val<=int(_VECTptr->size()))
9513 	      return gen(vecteur(_VECTptr->begin()+if1.val-1,_VECTptr->begin()+if2.val),subtype);
9514 	  }
9515 	}
9516 	gen tmp=_floor(i,contextptr);
9517 	if (tmp.type!=_INT_)
9518 	  return gendimerr(contextptr);
9519 	if (tmp.val<1 || tmp.val>int(_VECTptr->size()) )
9520 	  return gendimerr(contextptr);
9521 	return (*_VECTptr)[tmp.val-1];
9522       }
9523       // Old code for _VECT type was just return (*this)[i];
9524       vecteur w(*_VECTptr);
9525       iterateur it=w.begin(),itend=w.end();
9526       for (;it!=itend;++it)
9527 	*it=(*it)(i,contextptr);
9528       return gen(w,subtype);
9529     }
9530     else {
9531       if (has_inf_or_undef(i))
9532 	return undef;
9533       return symb_of(*this,i);
9534     }
9535   }
9536 
compare_VECT(const vecteur & v,const vecteur & w)9537   static bool compare_VECT(const vecteur & v,const vecteur & w){
9538     int s1=int(v.size()),s2=int(w.size());
9539     if (s1!=s2)
9540       return s1<s2;
9541     const_iterateur it=v.begin(),itend=v.end(),jt=w.begin();
9542     for (;it!=itend;++it,++jt){
9543       if (*it!=*jt){
9544 	return it->islesscomplexthan(*jt);
9545       }
9546     }
9547     // setsizeerr(); should not happen... commented because it happens!
9548     return false;
9549   }
9550 
9551   // return true if *this is "strictly less complex" than other
islesscomplexthan(const gen & other) const9552   bool gen::islesscomplexthan (const gen & other ) const {
9553     // FIXME it is not the natural order, but used for pivot selection
9554     if (type<_IDNT && is_zero(*this,context0)){
9555       // if (type==_INT_ && other.type==_INT_) return val<other.val;
9556       return false;
9557     }
9558     if (other.type<_IDNT && is_zero(other,context0))
9559       return true;
9560     if (type != other.type)
9561       return type < other.type;
9562     if (*this==other)
9563       return false;
9564     if (type<_POLY && type!=_CPLX && *this==-other)
9565       return is_strictly_positive(*this,context0);
9566     switch ( type) {
9567     case _INT_:
9568       return absint(val)<absint(other.val);
9569     case _ZINT:
9570       return is_greater(abs(other,context0),abs(*this,context0),context0);
9571     case _DOUBLE_: case _FLOAT_: case _REAL:
9572       return is_greater(abs(*this,context0),abs(other,context0),context0);
9573     case _CPLX:
9574       {
9575 	gen a1=abs(*this,context0),a2=abs(other,context0);
9576 	if (a1!=a2)
9577 	  return is_strictly_greater(a1,a2,context0);
9578 	a1=re(context0);
9579 	a2=other.re(context0);
9580 	if (a1!=a2)
9581 	  return is_strictly_greater(a1,a2,context0);
9582 	a1=im(context0);
9583 	a2=other.im(context0);
9584 	return is_greater(a1,a2,context0);
9585       }
9586     case _IDNT:
9587       return strcmp(_IDNTptr->id_name,other._IDNTptr->id_name)<0;
9588     case _POLY:
9589       if (_POLYptr->coord.size()!=other._POLYptr->coord.size())
9590 	return _POLYptr->coord.size()<other._POLYptr->coord.size();
9591       return _POLYptr->coord.front().value.islesscomplexthan(other._POLYptr->coord.front().value);
9592     case _MOD:
9593       if (*(_MODptr+1)!=*(other._MODptr+1)){
9594 #ifndef NO_STDEXCEPT
9595 	setsizeerr(gettext("islesscomplexthan mod"));
9596 #endif
9597       }
9598       return _MODptr->islesscomplexthan(*other._MODptr);
9599     case _SYMB:
9600       if (_SYMBptr->sommet !=other._SYMBptr->sommet ){
9601 #ifdef GIAC_HAS_STO_38 // otherwise 1 test of chk_xavier fails, needs to check
9602 	int c=strcmp(_SYMBptr->sommet.ptr()->s,other._SYMBptr->sommet.ptr()->s);
9603 	if (c) return c<0;
9604 #endif
9605 	return (alias_type) _SYMBptr->sommet.ptr() <(alias_type) other._SYMBptr->sommet.ptr();
9606       }
9607       return _SYMBptr->feuille.islesscomplexthan(other._SYMBptr->feuille);
9608       // return false;
9609     case _VECT:
9610       return compare_VECT(*_VECTptr,*other._VECTptr);
9611     case _EXT:
9612       if (*(_EXTptr+1)!=*(other._EXTptr+1))
9613 	return (_EXTptr+1)->islesscomplexthan(*(other._EXTptr+1));
9614       return _EXTptr->islesscomplexthan(*(other._EXTptr));
9615     case _STRNG:
9616       return *_STRNGptr<*other._STRNGptr;
9617     default:
9618       return this->print(context0)< other.print(context0);
9619     }
9620   }
9621 
islesscomplexthanf(const gen & a,const gen & b)9622   bool islesscomplexthanf(const gen & a,const gen & b){
9623     return a.islesscomplexthan(b);
9624   }
9625 
monomial_degree(const gen & a)9626   static gen monomial_degree(const gen & a){
9627     if (a.type<_IDNT)
9628       return 0;
9629     if (a.type==_IDNT){
9630       // detect constants of integration
9631       if (strlen(a._IDNTptr->id_name)>=3 && a._IDNTptr->id_name[0]=='c' && a._IDNTptr->id_name[1]=='_')
9632 	return 0;
9633       return 1;
9634     }
9635     if (a.type!=_SYMB)
9636       return 0;
9637     if (a._SYMBptr->sommet==at_neg)
9638       return monomial_degree(a._SYMBptr->feuille);
9639     if (a._SYMBptr->sommet==at_inv)
9640       return -monomial_degree(a._SYMBptr->feuille);
9641     if (a._SYMBptr->sommet==at_pow && a._SYMBptr->feuille.type==_VECT && a._SYMBptr->feuille._VECTptr->size()==2)
9642       return (*a._SYMBptr->feuille._VECTptr)[1];
9643     if (a._SYMBptr->sommet==at_plus){
9644       gen af=a._SYMBptr->feuille;
9645       if (af.type!=_VECT)
9646 	return monomial_degree(af);
9647       gen res(0);
9648       for (unsigned i=0;i<af._VECTptr->size();++i){
9649 	res = max(res,monomial_degree((*af._VECTptr)[i]),context0);
9650       }
9651       return res;
9652     }
9653     if (a._SYMBptr->sommet!=at_prod)
9654       return 0;
9655     gen af=a._SYMBptr->feuille;
9656     if (af.type!=_VECT)
9657       return monomial_degree(af);
9658     gen res(0);
9659     for (unsigned i=0;i<af._VECTptr->size();++i){
9660       res += monomial_degree((*af._VECTptr)[i]);
9661     }
9662     return res;
9663   }
9664 
is_monomial(const gen & a)9665   static bool is_monomial(const gen & a){
9666     if (a.type<=_IDNT)
9667       return true;
9668     if (a.type!=_SYMB)
9669       return false;
9670     if (a._SYMBptr->sommet==at_pow)
9671       return true;
9672     if (a._SYMBptr->sommet!=at_prod && a._SYMBptr->sommet!=at_plus && a._SYMBptr->sommet!=at_neg && a._SYMBptr->sommet!=at_inv)
9673       return false;
9674     gen af=a._SYMBptr->feuille;
9675     if (af.type!=_VECT)
9676       return is_monomial(af);
9677     for (unsigned i=0;i<af._VECTptr->size();++i){
9678       if (!is_monomial((*af._VECTptr)[i]))
9679 	return false;
9680     }
9681     return true;
9682   }
9683 
islesscomplexthanf2(const gen & a,const gen & b,GIAC_CONTEXT)9684   static bool islesscomplexthanf2(const gen & a,const gen & b,GIAC_CONTEXT){
9685     if (a==b)
9686       return false;
9687     if (a.type==_VECT && b.type==_VECT && a._VECTptr->size()==2 && b._VECTptr->size()==2){
9688       gen & a2=a._VECTptr->back();
9689       gen & b2=b._VECTptr->back();
9690       if (a2!=b2)
9691 	return islesscomplexthanf2(a2,b2,contextptr);
9692     }
9693     if (is_monomial(a) && is_monomial(b)){
9694       gen da=monomial_degree(a);
9695       gen db=monomial_degree(b);
9696       if (da!=db)
9697 	return increasing_power(contextptr)?is_greater(db,da,contextptr):is_greater(da,db,contextptr);
9698     }
9699     if (a.type==b.type)
9700       return a.islesscomplexthan(b);
9701     if (a.type==_FRAC && b.type>=_POLY)
9702       return false;
9703     if (a.type>=_POLY && b.type==_FRAC)
9704       return true;
9705     return !a.islesscomplexthan(b);
9706   }
9707 
9708   struct f_compare_context {
9709     bool (*f)(const gen &a,const gen &b,GIAC_CONTEXT);
9710     const context * ptr;
f_compare_contextgiac::f_compare_context9711     f_compare_context():f(islesscomplexthanf2),ptr(context0){}
f_compare_contextgiac::f_compare_context9712     f_compare_context(bool (*f_)(const gen &a,const gen &b,GIAC_CONTEXT),GIAC_CONTEXT):f(f_),ptr(contextptr){}
operator ()giac::f_compare_context9713     inline bool operator () (const gen & a,const gen &b){ return f(a,b,ptr); }
9714   };
9715 
gen_sort_f_context(iterateur it,iterateur itend,bool (* f)(const gen & a,const gen & b,GIAC_CONTEXT),GIAC_CONTEXT)9716   void gen_sort_f_context(iterateur it,iterateur itend,bool (*f)(const gen &a,const gen &b,GIAC_CONTEXT),GIAC_CONTEXT){
9717     f_compare_context m(f,contextptr);
9718     sort(it,itend,m);
9719   }
9720 
symb_size() const9721   int gen::symb_size () const {
9722     if (type==_SYMB)
9723       return _SYMBptr->size();
9724     else
9725       return 1;
9726   }
9727 
symb_size_less(const gen & a,const gen & b)9728   bool symb_size_less(const gen & a,const gen & b){
9729     return a.symb_size() < b.symb_size();
9730   }
9731 
is_symb_of_sommet(const unary_function_ptr & u) const9732   bool gen::is_symb_of_sommet(const unary_function_ptr & u) const {
9733     return type==_SYMB && _SYMBptr->sommet==u;
9734   }
9735 
is_symb_of_sommet(const unary_function_ptr * u) const9736   bool gen::is_symb_of_sommet(const unary_function_ptr * u) const {
9737     return type==_SYMB && _SYMBptr->sommet==u;
9738   }
9739 
operator &&(const gen & a,const gen & b)9740   gen operator && (const gen & a,const gen & b){
9741     if (is_zero(a,context0)){
9742       if (b.type==_DOUBLE_)
9743 	return 0.0;
9744       if (b.type==_FLOAT_)
9745 	return giac_float(0);
9746       return change_subtype(!is_zero(a),_INT_BOOLEAN);
9747     }
9748     if (is_zero(b,context0)){
9749       if (a.type==_DOUBLE_ )
9750 	return 0.0;
9751       if (a.type==_FLOAT_)
9752 	return giac_float(0);
9753       return change_subtype(!is_zero(b),_INT_BOOLEAN);
9754     }
9755     if (a.type<=_CPLX || a.type==_FLOAT_ || a.type==_FRAC){
9756       if (b.type<=_CPLX || b.type==_FLOAT_ || b.type==_FRAC)
9757 	return change_subtype(!is_zero(b),_INT_BOOLEAN);
9758       return b;
9759     }
9760     if (b.type<=_CPLX || b.type==_FLOAT_ || b.type==_FRAC){
9761       if (a.type<=_CPLX || a.type==_FLOAT_ || a.type==_FRAC)
9762 	return change_subtype(!is_zero(a),_INT_BOOLEAN);
9763       return a;
9764     }
9765     if (a.is_symb_of_sommet(at_and)){
9766       if (b.is_symb_of_sommet(at_and))
9767 	return new_ref_symbolic(symbolic(at_and,gen(mergevecteur(*a._SYMBptr->feuille._VECTptr,*b._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
9768       vecteur v=*a._SYMBptr->feuille._VECTptr;
9769       v.push_back(b);
9770       return new_ref_symbolic(symbolic(at_and,v));
9771     }
9772     if (b.is_symb_of_sommet(at_and)){
9773       vecteur v=*b._SYMBptr->feuille._VECTptr;
9774       v.push_back(a);
9775       return new_ref_symbolic(symbolic(at_and,v));
9776     }
9777     if ( ((a.type==_IDNT) || (a.type==_SYMB)) || ((b.type==_IDNT) || (b.type==_SYMB)) )
9778       return symb_and(a,b);
9779     if ( (a.type==_DOUBLE_) || (b.type==_DOUBLE_) )
9780       return 1.0;
9781     if ( (a.type==_FLOAT_) || (b.type==_FLOAT_) )
9782       return giac_float(1);
9783     return change_subtype(plus_one,_INT_BOOLEAN);
9784   }
9785 
operator ||(const gen & a,const gen & b)9786   gen operator || (const gen & a,const gen & b){
9787     if (is_zero(a,context0))
9788       return change_subtype(!is_zero(b),_INT_BOOLEAN);
9789     if (is_zero(b,context0))
9790       return change_subtype(!is_zero(a),_INT_BOOLEAN);
9791     if (a.is_symb_of_sommet(at_ou)){
9792       if (b.is_symb_of_sommet(at_ou))
9793 	return new_ref_symbolic(symbolic(at_ou,gen(mergevecteur(*a._SYMBptr->feuille._VECTptr,*b._SYMBptr->feuille._VECTptr),_SEQ__VECT)));
9794       vecteur v=*a._SYMBptr->feuille._VECTptr;
9795       v.push_back(b);
9796       return new_ref_symbolic(symbolic(at_ou,v));
9797     }
9798     if (b.is_symb_of_sommet(at_ou)){
9799       vecteur v=*b._SYMBptr->feuille._VECTptr;
9800       v.push_back(a);
9801       return new_ref_symbolic(symbolic(at_ou,v));
9802     }
9803     if ( ((a.type==_IDNT) || (a.type==_SYMB)) || ((b.type==_IDNT) || (b.type==_SYMB)) )
9804       return symb_ou(a,b);
9805     if ( (a.type==_DOUBLE_) || (b.type==_DOUBLE_) )
9806       return 1.0;
9807     if ( (a.type==_FLOAT_) || (b.type==_FLOAT_) )
9808       return giac_float(1);
9809     return change_subtype(plus_one,_INT_BOOLEAN);
9810   }
9811 
collect(const gen & g,GIAC_CONTEXT)9812   gen collect(const gen & g,GIAC_CONTEXT){
9813     if (g.type==_VECT)
9814       return apply(g,collect,contextptr);
9815     if (is_inf(g))
9816       return g;
9817     return liste2symbolique(symbolique2liste(g,contextptr));
9818   }
9819 
modified_islesscomplexthanf(const gen & a,const gen & b)9820   static bool modified_islesscomplexthanf(const gen& a,const gen& b){
9821     if (a.type!=b.type && (a.type<=_CPLX || b.type<=_CPLX))
9822       return a.type<b.type;
9823     if (a.is_symb_of_sommet(at_neg)){
9824       if (b.is_symb_of_sommet(at_neg))
9825 	return modified_islesscomplexthanf(a._SYMBptr->feuille,b._SYMBptr->feuille);
9826       return modified_islesscomplexthanf(a._SYMBptr->feuille,b);
9827     }
9828     if (b.is_symb_of_sommet(at_neg))
9829       return modified_islesscomplexthanf(a,b._SYMBptr->feuille);
9830     if (a.is_symb_of_sommet(at_inv)){
9831       if (b.is_symb_of_sommet(at_inv))
9832 	return modified_islesscomplexthanf(a._SYMBptr->feuille,b._SYMBptr->feuille);
9833       if (a._SYMBptr->feuille.type<_IDNT)
9834 	return modified_islesscomplexthanf(a._SYMBptr->feuille,b);
9835       return false;
9836     }
9837     if (b.is_symb_of_sommet(at_inv)){
9838       if (b._SYMBptr->feuille.type<_IDNT)
9839 	return modified_islesscomplexthanf(a,b._SYMBptr->feuille);
9840       return true;
9841     }
9842     if (a.is_symb_of_sommet(at_pow)){
9843       if (b.is_symb_of_sommet(at_pow))
9844 	return modified_islesscomplexthanf(a._SYMBptr->feuille[0],b._SYMBptr->feuille[0]);
9845       return modified_islesscomplexthanf(a._SYMBptr->feuille[0],b);
9846     }
9847     if (b.is_symb_of_sommet(at_pow))
9848       return modified_islesscomplexthanf(a,b._SYMBptr->feuille[0]);
9849     if (a.type!=b.type){
9850       if (a.type==_FRAC && b.type>=_POLY)
9851 	return true;
9852       if (b.type==_FRAC && a.type>=_POLY)
9853 	return false;
9854     }
9855     return islesscomplexthanf(a,b);
9856   }
9857 
9858   class modified_compare {
9859   public:
modified_compare()9860     modified_compare(){}
operator ()(const gen & a,const gen & b)9861     bool operator ()(const gen &a,const gen &b){ return modified_islesscomplexthanf(a,b);}
9862   };
9863 
9864   // return true if a is -basis^exp
power_basis_exp(const gen & a,gen & basis,gen & expa)9865   static bool power_basis_exp(const gen& a,gen & basis,gen & expa){
9866     if (a.is_symb_of_sommet(at_neg))
9867       return !power_basis_exp(a._SYMBptr->feuille,basis,expa);
9868     if (a.is_symb_of_sommet(at_inv)){
9869       gen & tmp=a._SYMBptr->feuille;
9870       bool b=power_basis_exp(tmp,basis,expa);
9871       expa=-expa;
9872       return b;
9873     } // de-commented 2/2/2013 so that regrouper(x^2/x) works
9874     if (a.is_symb_of_sommet(at_pow)){
9875       gen & tmp=a._SYMBptr->feuille;
9876       if (tmp.type!=_VECT || tmp._VECTptr->size()!=2){
9877 #ifndef NO_STDEXCEPT
9878 	setsizeerr(gettext("power_basis_exp"));
9879 #endif
9880 	return false;
9881       }
9882       expa=tmp._VECTptr->back();
9883       basis=tmp._VECTptr->front();
9884     }
9885     else {
9886       basis=a;
9887       expa=plus_one;
9888     }
9889     return false;
9890   }
9891 
regroup_inv(const vecteur & vtmp)9892   static gen regroup_inv(const vecteur & vtmp){
9893     vecteur vtmp1,vtmp2;
9894     gen tt(1);
9895     for (unsigned i=0;i<vtmp.size();++i){
9896       if (vtmp[i].is_symb_of_sommet(at_inv))
9897 	vtmp2.push_back(vtmp[i]._SYMBptr->feuille);
9898       else
9899 	vtmp1.push_back(vtmp[i]);
9900     }
9901     if (!vtmp1.empty()){
9902       if (vtmp1.size()==1)
9903 	tt=vtmp1.front();
9904       else
9905 	tt=new_ref_symbolic(symbolic(at_prod,gen(vtmp1,_SORTED__VECT)));
9906     }
9907     if (!vtmp2.empty()){
9908       if (vtmp2.size()==1)
9909 	tt=tt/vtmp2.front();
9910       else
9911 	tt=tt/new_ref_symbolic(symbolic(at_prod,gen(vtmp2,_SORTED__VECT)));
9912     }
9913     return tt;
9914   }
9915 
9916   // Helpers for symbolic addition
9917   // from a product returns a list with the numeric coeff and the monomial
terme2unitaire(const gen & x,bool sorted,GIAC_CONTEXT)9918   static vecteur terme2unitaire(const gen & x,bool sorted,GIAC_CONTEXT){
9919     if (x.type<_POLY)
9920       return makevecteur(x,plus_one);
9921     gen tmp;
9922     if (x.type!=_SYMB || x._SYMBptr->sommet==at_program || x._SYMBptr->sommet==at_when)
9923       return makevecteur(1,x);
9924     if (x._SYMBptr->sommet==at_neg){
9925       vecteur v=terme2unitaire(x._SYMBptr->feuille,sorted,contextptr);
9926       v[0]=-v[0];
9927       return v;
9928     }
9929     if (x._SYMBptr->sommet==at_binary_minus){
9930       vecteur v=terme2unitaire(x._SYMBptr->feuille,sorted,contextptr);
9931       v[1]=-v[1];
9932       return v;
9933     }
9934     if (x._SYMBptr->sommet==at_prod && (tmp=x._SYMBptr->feuille).type==_VECT && !tmp._VECTptr->empty() ){
9935       vecteur & v = *tmp._VECTptr;
9936       int s=int(v.size());
9937       if (s==2 && (sorted || tmp.subtype==_SORTED__VECT))
9938 	return makevecteur(v[0],v[1]);
9939       vecteur vtmp(v.begin(),v.end());
9940       for (unsigned i=0;i<vtmp.size();++i){
9941 	vtmp[i]=simplifier(vtmp[i],contextptr);
9942 	if (vtmp[i].is_symb_of_sommet(at_inv) && vtmp[i]._SYMBptr->feuille.is_symb_of_sommet(at_pow)){
9943 	  gen f= vtmp[i]._SYMBptr->feuille._SYMBptr->feuille;
9944 	  if (f.type==_VECT && f._VECTptr->size()==2)
9945 	    vtmp[i]=symbolic(at_pow,makesequence(f._VECTptr->front(),-f._VECTptr->back()));
9946 	}
9947       }
9948       if (equalposcomp(vtmp,undef))
9949 	return makevecteur(1,undef);
9950       if (equalposcomp(vtmp,0)){
9951 	if (equalposcomp(vtmp,unsigned_inf))
9952 	  return makevecteur(1,undef);
9953 	return makevecteur(0,plus_one);
9954       }
9955 #if 1 // def NSPIRE
9956       // COUT << "modified " << (int) modified_islesscomplexthanf << '\n'; wait_key_pressed() ;
9957       modified_compare m;
9958       sort(vtmp.begin(),vtmp.end(),m);
9959       // COUT << "after modified " << '\n'; wait_key_pressed() ;
9960 #else
9961       sort(vtmp.begin(),vtmp.end(),modified_islesscomplexthanf);
9962 #endif
9963       // collect term with the same power
9964       const_iterateur it=vtmp.begin(),itend=vtmp.end();
9965       vecteur vsorted;
9966       vsorted.reserve(itend-it);
9967       gen precbasis,precexpo,basis,expo,constcoeff(plus_one);
9968       for (;it!=itend;++it){
9969 	if (it->type<=_CPLX)
9970 	  constcoeff=constcoeff*(*it);
9971 	else {
9972 	  if (it->is_symb_of_sommet(at_inv) && it->_SYMBptr->feuille.type<=_CPLX)
9973 	    constcoeff=constcoeff/it->_SYMBptr->feuille;
9974 	  else
9975 	    break;
9976 	}
9977       }
9978       if (!is_one(constcoeff))
9979 	vsorted.push_back(constcoeff);
9980       bool isneg(false),hasneg(false);
9981       if (it!=itend){
9982 	power_basis_exp(*it,precbasis,precexpo);
9983 	precexpo=zero;
9984 	for (;it!=itend;++it){
9985 	  if (power_basis_exp(*it,basis,expo)){
9986 	    isneg=!isneg;
9987 	    hasneg=true;
9988 	  }
9989 	  if (!vsorted.empty() && basis==vsorted.back()){
9990 	    vsorted.pop_back();
9991 	    expo+=1;
9992 	  }
9993 	  if (basis==precbasis)
9994 	    precexpo=precexpo+expo;
9995 	  else {
9996 	    if (!is_zero(precexpo,contextptr)){
9997 	      if (is_strictly_positive(-precexpo,contextptr))
9998 		vsorted.push_back(inv(pow(precbasis,-precexpo,contextptr),contextptr));
9999 	      else
10000 		vsorted.push_back(pow(precbasis,precexpo,contextptr));
10001 	    }
10002 	      // vsorted.push_back(pow(precbasis,precexpo,contextptr));
10003 	    precbasis=basis;
10004 	    precexpo=expo;
10005 	  }
10006 	}
10007 	if (!is_zero(precexpo,contextptr)){
10008 	  if (is_strictly_positive(-precexpo,contextptr)){
10009 	    gen tmp=pow(precbasis,-precexpo,contextptr);
10010 	    if (tmp.is_symb_of_sommet(at_prod))
10011 	      tmp=symbolic(at_inv,tmp);
10012 	    else
10013 	      tmp=inv(tmp,contextptr);
10014 	    vsorted.push_back(tmp);
10015 	  }
10016 	  else
10017 	    vsorted.push_back(pow(precbasis,precexpo,contextptr));
10018 	}
10019       }
10020       vecteur res;
10021       if (hasneg){
10022 	res=terme2unitaire(_prod(vsorted,contextptr),sorted,contextptr);
10023 	if (isneg)
10024 	  res[0]=-res[0];
10025 	return res;
10026       }
10027       if (vsorted.empty())
10028 	vsorted.push_back(1);
10029       if (vsorted.front().type<_POLY || vsorted.front().type==_FRAC){
10030 	vtmp=vecteur(vsorted.begin()+1,vsorted.end());
10031 	gen tt(1);
10032 	if (!vtmp.empty()){
10033 	  if (vtmp.size()==1)
10034 	    tt=vtmp.front();
10035 	  else
10036 	    tt=regroup_inv(vtmp);
10037 	}
10038 	res=makevecteur(vsorted.front(),tt);
10039       }
10040       else
10041 	res=makevecteur(plus_one,regroup_inv(vsorted));
10042       return res;
10043     }
10044     // recurse
10045     if (x._SYMBptr->sommet==at_pow)
10046       return makevecteur(plus_one,x._SYMBptr->sommet(collect(x._SYMBptr->feuille,contextptr),contextptr));
10047     tmp=collect(x._SYMBptr->feuille,contextptr);
10048     if (x._SYMBptr->sommet==at_inv){
10049       if (is_zero(tmp))
10050 	return makevecteur(1,unsigned_inf);
10051     }
10052     return makevecteur(plus_one,new_ref_symbolic(symbolic(x._SYMBptr->sommet,tmp)));
10053   }
10054 
10055   // assumes v is a sorted list, shrink it
10056   // should be written to a gen of type _VECT and subtype _SORTED__VECT
fusionliste(const vecteur & v)10057   static vecteur fusionliste(const vecteur & v){
10058     const_iterateur it=v.begin(),itend=v.end();
10059     if (itend-it<2)
10060       return v;
10061     vecteur res;
10062     gen current=(*it)[1];
10063     gen current_coeff=(*it)[0];
10064     ++it;
10065     for (;it!=itend;++it){
10066       if ((*it)[1].type!=current.type || (current.type==_DOUBLE_ && current._DOUBLE_val!=(*it)[1]._DOUBLE_val) || (*it)[1]!=current ){
10067 	res.push_back(makenewvecteur(current_coeff,current));
10068 	current_coeff=(*it)[0];
10069 	current=(*it)[1];
10070       }
10071       else
10072 	current_coeff=current_coeff+(*it)[0];
10073     }
10074     res.push_back(makenewvecteur(current_coeff,current));
10075     return res;
10076   }
10077 
10078   struct tri_context {
10079     const context * contextptr;
operator ()giac::tri_context10080     bool operator()(const gen & a,const gen &b){ return islesscomplexthanf2(a,b,contextptr); }
tri_contextgiac::tri_context10081     tri_context(const context * ptr):contextptr(ptr){};
tri_contextgiac::tri_context10082     tri_context():contextptr(0){};
10083   };
10084 
10085   // from a sum in x returns a list of [coeff monomial]
10086   // e.g. 5+2x+3*x*y -> [ [5 1] [2 x] [ 3 x*y] ]
symbolique2liste(const gen & x,GIAC_CONTEXT)10087   vecteur symbolique2liste(const gen & x,GIAC_CONTEXT){
10088     if (!x.is_symb_of_sommet(at_plus))
10089       return vecteur(1,terme2unitaire(x,false,contextptr));
10090     bool sorted=x._SYMBptr->feuille.subtype==_SORTED__VECT;
10091     gen number;
10092     vecteur varg=gen2vecteur(x._SYMBptr->feuille);
10093     vecteur vres;
10094     const_iterateur it=varg.begin(),itend=varg.end();
10095     for (;it!=itend;++it){
10096       if (it->type<_POLY || it->type==_FRAC)
10097 	number=number+(*it);
10098       else
10099 	vres.push_back(terme2unitaire(*it,sorted,contextptr));
10100     }
10101     if (!is_exactly_zero(number))
10102       vres.push_back(makenewvecteur(1,number));
10103     if (x._SYMBptr->feuille.subtype==_SORTED__VECT)
10104       return vres;
10105     sort(vres.begin(),vres.end(),tri_context(contextptr));
10106     return fusionliste(vres);
10107   }
10108 
10109   /*
10110   // assumes v1, v2 are sorted and shrinked, merge them -> sorted and shrinked
10111   static vecteur fusion2liste(const vecteur & v1,const vecteur & v2){
10112     const_iterateur it=v1.begin(),itend=v1.end(),jt=v2.begin(),jtend=v2.end();
10113     vecteur res;
10114     gen tmp;
10115     for (;it!=itend;){
10116       if (jt==jtend){
10117 	for (;it!=itend;++it)
10118 	  res.push_back(*it);
10119 	return res;
10120       }
10121       // both iterator are valid
10122       vecteur & vi=*it->_VECTptr;
10123       vecteur & vj=*jt->_VECTptr;
10124       if (vi[1]==vj[1]){
10125 	tmp=vi[0]+vj[0];
10126 	if (!is_exactly_zero(tmp))
10127 	  res.push_back(makenewvecteur(tmp,vi[1]));
10128 	++it;
10129 	++jt;
10130       }
10131       else {
10132 	if (vi[1].islesscomplexthan(vj[1])){
10133 	  res.push_back(*it);
10134 	  ++it;
10135 	}
10136 	else {
10137 	  res.push_back(*jt);
10138 	  ++jt;
10139 	}
10140       } // end tests
10141     } // end for loop
10142     // finish jt
10143     for (;jt!=jtend;++jt)
10144       res.push_back(*jt);
10145     return res;
10146   }
10147   */
10148 
10149   // v should be sorted and shrinked
liste2symbolique(const vecteur & v)10150   gen liste2symbolique(const vecteur & v){
10151     vecteur res;
10152     const_iterateur it=v.begin(),itend=v.end();
10153     res.reserve(itend-it);
10154     for (;it!=itend;++it){
10155       vecteur & vtmp(*it->_VECTptr);
10156       gen & tmp = vtmp.back();
10157       gen coeff=eval(vtmp.front(),1,context0);
10158       if (is_exactly_zero(coeff))
10159 	continue;
10160       if (tmp.is_symb_of_sommet(at_prod) && tmp._SYMBptr->feuille.type==_VECT && tmp._SYMBptr->feuille._VECTptr->size()==1){
10161 	res.push_back(coeff*tmp._SYMBptr->feuille._VECTptr->front());
10162 	continue;
10163       }
10164       if (coeff.is_symb_of_sommet(at_neg)){
10165 	res.push_back(-(coeff._SYMBptr->feuille*tmp));
10166 	continue;
10167       }
10168       if ( (coeff.type==_FRAC || is_integer(coeff)) && is_positive(-coeff,context0))
10169 	res.push_back(-((-coeff)*tmp));
10170       else
10171 	res.push_back(coeff*tmp);
10172     }
10173     int s=int(res.size());
10174     if (!s)
10175       return zero;
10176     if (s==1)
10177       return res.front();
10178     return new_ref_symbolic(symbolic(at_plus,gen(res,_SORTED__VECT)));
10179   }
10180 
10181   /* Euclidean-like Arithmetic */
swap(int & a,int & b)10182   static void swap(int & a,int & b){
10183     int t=a;
10184     a=b;
10185     b=t;
10186   }
10187 
absint(int a)10188   int absint(int a){
10189     if (a<0)
10190       return -a;
10191     else
10192       return a;
10193   }
10194 
absdouble(double a)10195   double absdouble(double a){
10196     if (a<0)
10197       return -a;
10198     else
10199       return a;
10200   }
10201 
giacmin(int a,int b)10202   int giacmin(int a, int b){
10203     if (a<b)
10204       return a;
10205     else
10206       return b;
10207   }
10208 
giacmax(int a,int b)10209   int giacmax(int a, int b){
10210     if (a<b)
10211       return b;
10212     else
10213       return a;
10214   }
10215 
invmod(int a,int b)10216   int invmod(int a,int b){
10217     if (a==1 || a==-1 || a==1-b)
10218       return a;
10219     int aa(1),ab(0),ar(0);
10220     div_t qr;
10221     while (b){
10222       qr=div(a,b);
10223       ar=aa-qr.quot*ab;
10224       a=b;
10225       b=qr.rem;
10226       aa=ab;
10227       ab=ar;
10228     }
10229     if (a==1)
10230       return aa;
10231     if (a!=-1){
10232 #ifndef NO_STDEXCEPT
10233       setsizeerr(gettext("Not invertible"));
10234 #endif
10235       return 0;
10236     }
10237     return -aa;
10238   }
10239 
invmod(unsigned a,int b)10240   unsigned invmod(unsigned a,int b){
10241     int i=invmod(int(a),int(b));
10242     if (i<0)
10243       i+=b;
10244     return unsigned(i);
10245   }
10246 
invmod(longlong a,int b)10247   int invmod(longlong a,int b){
10248     return invmod(int(a%b),b);
10249   }
10250 
10251 #ifdef INT128
invmod(int128_t a,int b)10252   int invmod(int128_t a,int b){
10253     return invmod(int(a%b),b);
10254   }
10255 #endif
10256 
invmodll(longlong a,longlong b)10257   longlong invmodll(longlong a,longlong b){
10258     if (a==1 || a==-1 || a==1-b)
10259       return a;
10260     longlong aa(1),ab(0),ar(0);
10261 #ifdef VISUALC
10262     longlong q,r;
10263     while (b){
10264       q=a/b;
10265       r=a-q*b;
10266       ar=aa-q*ab;
10267       a=b;
10268       b=r;
10269       aa=ab;
10270       ab=ar;
10271     }
10272 #else
10273     lldiv_t qr;
10274     while (b){
10275       qr=lldiv(a,b);
10276       ar=aa-qr.quot*ab;
10277       a=b;
10278       b=qr.rem;
10279       aa=ab;
10280       ab=ar;
10281     }
10282 #endif
10283     if (a==1)
10284       return aa;
10285     if (a!=-1){
10286 #ifndef NO_STDEXCEPT
10287       setsizeerr(gettext("Not invertible"));
10288 #endif
10289       return 0;
10290     }
10291     return -aa;
10292   }
10293 
10294   /*
10295   int powmod(int a,unsigned long n,int m){
10296     if (!n)
10297       return 1;
10298     int b=powmod(a,n/2,m);
10299     longlong tmp=b;
10300     b=(tmp*b) % m;
10301     tmp=b;
10302     if (n % 2)
10303       return (tmp*a) % m;
10304     else
10305       return b;
10306   }
10307   */
10308 
powmod(int a,unsigned long n,int m)10309   int powmod(int a,unsigned long n,int m){
10310     if (!n)
10311       return 1;
10312     if (n==1)
10313       return a;
10314     if (n==2)
10315       return (a*longlong(a))%m;
10316     int b=a%m,c=1;
10317     if (m<46340){
10318       while (n>0){
10319 	if (n%2)
10320 	  c=(c*b)%m;
10321 	n /= 2;
10322 	b=(b*b)%m;
10323       }
10324     }
10325     else {
10326       while (n>0){
10327 	if (n%2)
10328 	  c=(c*longlong(b))%m;
10329 	n /= 2;
10330 	b=(b*longlong(b))%m;
10331       }
10332     }
10333     return c;
10334   }
10335 
smod(int r,int m)10336   int smod(int r,int m){
10337     if (m<=0){
10338       if (!m)
10339 	return r;
10340       m=-m;
10341     }
10342     r = r % m;
10343 #if 1
10344     r += (unsigned(r)>>31)*m; // make positive
10345     return r-(unsigned((m>>1)-r)>>31)*m;
10346 #else
10347     longlong tmp= longlong(r)+r;
10348     if (tmp>m)
10349       return r-m;
10350     if (tmp<=-m)
10351       return r+m;
10352     return r;
10353 #endif
10354   }
10355 
smod(longlong r,int m)10356   int smod(longlong r,int m){
10357     int R=r%m;
10358     R += (unsigned(R)>>31)*m; // make positive
10359     int res2=R-(unsigned((m>>1)-R)>>31)*m;
10360     return res2;
10361     int res1=(R>m/2)?R-m:R;
10362     if (res1!=res2)
10363       CERR << "smod longlong " << r << " " << m << '\n';
10364     return res1;
10365     //return smod(R,m);
10366   }
10367 
smodll(longlong a,longlong b)10368   longlong smodll(longlong a,longlong b){
10369     longlong r=a%b;
10370     if (r>b/2)
10371       r -= b;
10372     else {
10373       if (r<=-b/2)
10374 	r += b;
10375     }
10376     return r;
10377   }
10378 
gcd(int a,int b)10379   int gcd(int a,int b){
10380     if (a!=b){
10381       int r;
10382       while (b){
10383 	r=a%b;
10384 	a=b;
10385 	b=r;
10386       }
10387     }
10388     return absint(a);
10389   }
10390 
10391 #ifdef EMCC
my_mpz_gcd(mpz_t & z,const mpz_t & A,const mpz_t & B)10392   void my_mpz_gcd(mpz_t &z,const mpz_t & A,const mpz_t & B){
10393     mpz_t a,b;
10394     mpz_init_set(a,A);
10395     mpz_init_set(b,B);
10396     while (mpz_cmp_si(b,0)){
10397       mpz_cdiv_r(z,a,b);
10398       mpz_swap(a,b);
10399       mpz_swap(b,z);
10400     }
10401     mpz_set(z,a);
10402     mpz_abs(z,z);
10403     mpz_clear(a);
10404     mpz_clear(b);
10405   }
my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t & v,const mpz_t & a,const mpz_t & b)10406   void my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t &v,const mpz_t & a,const mpz_t & b){
10407     mpz_t q,r1,r2,u1,u2,v1,v2;
10408     // mpz_t r3,u3,v3;
10409     mpz_init_set(r1,a); mpz_init_set(r2,b);
10410     mpz_init_set_ui(u1,1); mpz_init_set_ui(u2,0);
10411     mpz_init_set_ui(v1,0); mpz_init_set_ui(v2,1);
10412     mpz_init(q);
10413     // mpz_init(r3); mpz_init(u3); mpz_init(v3);
10414     while (mpz_cmp_si(r2,0)){
10415       // CERR << "iegcd " << gen(r1) << " " << gen(r2) << '\n';
10416       mpz_cdiv_qr(q,r1,r1,r2);
10417       mpz_swap(r1,r2);
10418       mpz_submul(u1,q,u2);
10419       mpz_swap(u1,u2);
10420       mpz_submul(v1,q,v2);
10421       mpz_swap(v1,v2);
10422     }
10423     if (mpz_cmp_si(r1,0)<0){
10424       mpz_neg(r1,r1); mpz_neg(u1,u1); mpz_neg(v1,v1);
10425     }
10426     mpz_swap(d,r1); mpz_swap(u,u1); mpz_swap(v,v1);
10427 #if 0 // debugging
10428     CERR << gen(d) << " " << gen(u) << " " << gen(v) << '\n';
10429     mpz_gcdext(d,u,v,a,b);
10430     CERR << gen(d) << " " << gen(u) << " " << gen(v) << '\n';
10431 #endif
10432     mpz_clear(q); mpz_clear(r1); mpz_clear(r2);
10433     mpz_clear(u1); mpz_clear(u2);
10434     mpz_clear(v1); mpz_clear(v2);
10435     // mpz_clear(u3); mpz_clear(v3); mpz_clear(r3);
10436   }
my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m)10437   bool my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m){
10438     mpz_t d,v;
10439     mpz_init(d); mpz_init(v);
10440     my_mpz_gcdext(d,ainv,v,a,m);
10441     mpz_clear(v);
10442     bool ok=mpz_cmp_si(d,1)==0;
10443     mpz_clear(d);
10444     return ok;
10445   }
10446 #else
my_mpz_gcd(mpz_t & z,const mpz_t & a,const mpz_t & b)10447   void my_mpz_gcd(mpz_t &z,const mpz_t & a,const mpz_t & b){
10448     mpz_gcd(z,a,b);
10449   }
my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t & v,const mpz_t & a,const mpz_t & b)10450   void my_mpz_gcdext(mpz_t & d,mpz_t & u,mpz_t &v,const mpz_t & a,const mpz_t & b){
10451     mpz_gcdext(d,u,v,a,b);
10452   }
my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m)10453   bool my_mpz_invert(mpz_t & ainv,const mpz_t & a,const mpz_t & m){
10454     return mpz_invert(ainv,a,m)!=0;
10455   }
10456 #endif
10457 
simplify(int & a,int & b)10458   int simplify(int & a,int & b){
10459     int d=gcd(a,b);
10460     a=a/d;
10461     b=b/d;
10462     return d;
10463   }
10464 
_CPLXgcd(const gen & a,const gen & b)10465   static gen _CPLXgcd(const gen & a,const gen & b){ // a & b must be gen
10466     if (!is_cinteger(a) || !is_cinteger(b) )
10467       return plus_one;
10468     gen acopy(a),bcopy(b),r;
10469     for (;;){
10470       if (is_exactly_zero(bcopy)){
10471 	complex<double> c=gen2complex_d(acopy);
10472 	double d=arg(c);
10473 	int quadrant=int(std::floor((2*d)/M_PI));
10474 	switch (quadrant){
10475 	case 0:
10476 	  return acopy;
10477 	case 1:
10478 	  return acopy*(-cst_i);
10479 	case -1:
10480 	  return acopy*cst_i;
10481 	case 2: case -2:
10482 	  return -acopy;
10483 	default:
10484 	  return acopy;
10485 	}
10486       }
10487       r=acopy%bcopy;
10488       acopy=bcopy;
10489       bcopy=r;
10490     }
10491   }
10492 
polygcd(const polynome & a,const polynome & b)10493   static gen polygcd(const polynome & a,const polynome & b){
10494     ref_polynome * resptr=new ref_polynome(a.dim);
10495     gcd(a,b,resptr->t);
10496     return resptr;
10497   }
10498 
10499   // gcd(undef,x)=x to be used inside series
symgcd(const gen & a,const gen & b,GIAC_CONTEXT)10500   static gen symgcd(const gen & a,const gen& b,GIAC_CONTEXT){
10501     if (is_exactly_zero(a) || is_undef(a) || (is_one(b)))
10502       return b;
10503     if (is_one(a) || is_undef(b) || (is_exactly_zero(b)))
10504       return a;
10505     if (a==b)
10506       return a;
10507     if ( (a.type==_MOD) && (b.type==_MOD) && (a._MODptr->type<=_CPLX) && (b._MODptr->type<= _CPLX) )
10508       return chkmod(plus_one,a);
10509     if (a.type==_MOD || b.type==_MOD || a.type==_DOUBLE_ || a.type==_FLOAT_ || a.type==_REAL || b.type==_DOUBLE_ || b.type==_FLOAT_ || b.type==_REAL )
10510       return plus_one;
10511     if ( (a.type==_POLY) && (b.type==_POLY) )
10512       return polygcd(*a._POLYptr,*b._POLYptr);
10513     if ( (a.type==_EXT) && (b.type ==_EXT) ){
10514       if ( (*(a._EXTptr+1)!=*(b._EXTptr+1)) || (a._EXTptr->type!=_VECT) || (b._EXTptr->type!=_VECT) )
10515 	return plus_one;
10516       environment *env=new environment;
10517       vecteur g=gcd(*a._EXTptr->_VECTptr,*b._EXTptr->_VECTptr,env);
10518       delete env;
10519       return ext_reduce(g,*(a._EXTptr+1));
10520     }
10521     if ( (a.type==_FRAC) || (b.type==_FRAC))
10522         return plus_one;
10523     if (a.type==_EXT){
10524       if (a._EXTptr->type!=_VECT)
10525 	return gentypeerr(gettext("symgcd"));
10526       if ( (a._EXTptr+1)->type!=_VECT)
10527 	return symgcd(ext_reduce(a),b,contextptr);
10528       gen aa(lgcd(*a._EXTptr->_VECTptr));
10529       gen res=gcd(aa,b,contextptr),b2(rdiv(b,res,contextptr));
10530       if (is_one(b2) || is_minus_one(b2))// || b2.type==_POLY)
10531 	return res;
10532       vecteur ua,u,v,dd;
10533       divvecteur(*(a._EXTptr->_VECTptr),aa,ua);
10534       const vecteur & uv=*((a._EXTptr+1)->_VECTptr);
10535       egcd(ua,uv,0,u,v,dd);
10536       // u and v are not used but we can't use gcd here because we want to
10537       // "factor" dd=extension(ua,uv)*extension(u,uv)
10538       gen dd0(dd.front());
10539       simplify(b2,dd0);
10540       if (is_one(dd0))
10541 	return res*algebraic_EXTension(ua,*(a._EXTptr+1));
10542       return res;
10543     }
10544     if (b.type==_EXT)
10545       return symgcd(b,a,contextptr);
10546     if (a.type==_POLY)
10547       return gcd(*a._POLYptr,polynome(b,a._POLYptr->dim));
10548     if (b.type==_POLY)
10549       return gcd(*b._POLYptr,polynome(a,b._POLYptr->dim));
10550     if ( a.type!=_DOUBLE_ && a.type!=_FLOAT_ && a.type!=_VECT && b.type!=_DOUBLE_ && b.type!=_FLOAT_ && b.type!=_VECT )
10551       return rationalgcd(a,b,contextptr);
10552     return plus_one; // return gentypeerr(gettext("symgcd"));
10553   }
10554 
simplify(gen & n,gen & d)10555   gen simplify(gen & n, gen & d){
10556     if ( (d.type==_DOUBLE_ || d.type==_FLOAT_) ||
10557 	 ( (d.type==_CPLX) &&
10558 	   ((d._CPLXptr->type==_DOUBLE_ || d._CPLXptr->type==_FLOAT_) ||
10559 	    ((d._CPLXptr+1)->type==_DOUBLE_ || (d._CPLXptr+1)->type==_FLOAT_)) )
10560 	 ){
10561       gen dd=no_context_evalf(d);
10562       gen nn=no_context_evalf(n);
10563       // if (d==dd && n==nn) return 1; // avoid infinite recursion?
10564       n=rdiv(nn,dd,context0);
10565       d=plus_one;
10566       return dd;
10567     }
10568     if ( (n.type==_DOUBLE_ || n.type==_FLOAT_) ||
10569 	 ( (n.type==_CPLX) &&
10570 	   ((n._CPLXptr->type==_DOUBLE_ || n._CPLXptr->type==_FLOAT_) ||
10571 	    ((n._CPLXptr+1)->type==_DOUBLE_ || (n._CPLXptr+1)->type==_FLOAT_)) )
10572 	 ){
10573       gen nn=no_context_evalf(n);
10574       n=plus_one;
10575       d=rdiv(no_context_evalf(d),nn,context0);
10576       return nn*simplify(n,d);
10577     }
10578     if (n.type==_FRAC || d.type==_FRAC)
10579       return plus_one;
10580     if (is_one(d))
10581       return d;
10582     if (is_zero(d)){
10583       n=undef;
10584       d=1;
10585       return n;
10586     }
10587     if (is_zero(n)){
10588       gen tmp=d;
10589       d=1;
10590       return tmp;
10591     }
10592     if ( (n.type==_MOD) && (d.type!=_MOD) )
10593       d=makemod(d,*(n._MODptr+1));
10594     if (d.type==_MOD){
10595       if (d._MODptr->is_cinteger()){
10596 	gen dd(d);
10597 	n=n*inv(dd,context0);
10598 	d=makemodquoted(plus_one,*(d._MODptr+1));
10599 	return dd;
10600       }
10601     }
10602     if (is_one(n))
10603       return n;
10604     if ((n.type==_POLY) && (d.type==_POLY)){
10605       polynome np(*n._POLYptr),dp(*d._POLYptr);
10606       if (np.dim && dp.dim && np.dim!=dp.dim)
10607 	return gensizeerr(gettext("simplify: Polynomials do not have the same dimension"));
10608       polynome g(np.dim);
10609       g=simplify(np,dp);
10610       n=np;
10611       d=dp;
10612       return g;
10613     }
10614     if (n.type==_VECT){
10615       if (d.type==_VECT){
10616 	environment * env=new environment;
10617 	vecteur g=gcd(*n._VECTptr,*d._VECTptr,env);
10618 	delete env;
10619 	n=gen(*n._VECTptr/g,_POLY1__VECT);
10620 	d=gen(*d._VECTptr/g,_POLY1__VECT);
10621 	return gen(g,_POLY1__VECT);
10622       }
10623       gen gg=lgcd(*n._VECTptr,d);
10624       if (!is_one(gg)){
10625 	n=divvecteur(*n._VECTptr,gg);
10626 	d=d/gg;
10627       }
10628       return gg;
10629       // old code
10630       gen nd=_gcd(n,context0);
10631       gen g=simplify(nd,d);
10632       if (!is_one(g)) n=divvecteur(*n._VECTptr,g);
10633       return g;
10634     }
10635     if (d.type==_VECT){
10636       gen dd=_gcd(d,context0);
10637       gen g=simplify(n,dd);
10638       d=divvecteur(*d._VECTptr,g);
10639       return g;
10640     }
10641     if (d.type==_EXT){
10642       if ( (d._EXTptr->type==_INT_) || (d._EXTptr->type==_ZINT) ){
10643 	n=n*inv(d,context0);
10644 	gen d_copy=d;
10645 	d=1;
10646 	return d_copy;
10647       }
10648       if ( (d._EXTptr+1)->type==_EXT || (d._EXTptr+1)->type==_FRAC){
10649 	d=ext_reduce(d);
10650 	return simplify(n,d);
10651       }
10652       if (d._EXTptr->type==_VECT){
10653 	vecteur u,v,dd;
10654 	if ( (d._EXTptr+1)->type!=_VECT)
10655 	  return gensizeerr(gettext("gen.cc:simplify"));
10656 	egcd(*(d._EXTptr->_VECTptr),*((d._EXTptr+1)->_VECTptr),0,u,v,dd);
10657         gen tmp=algebraic_EXTension(u,*((d._EXTptr+1)->_VECTptr));
10658 	if (tmp.type!=_EXT){
10659 	  return gensizeerr(gettext("gen.cc:simplify/tmp.type!=_EXT"));
10660 	  // return 1;
10661 	}
10662 	n=n*tmp;
10663 	d=d*tmp;
10664 	return simplify(n,d)*inv_EXT(tmp);
10665       }
10666       return gentypeerr(gettext("simplify"));
10667     }
10668     if (n.type==_EXT){
10669       gen n_EXT=*n._EXTptr;
10670       gen g=simplify(n_EXT,d);
10671       n=algebraic_EXTension(n_EXT,*(n._EXTptr+1));
10672       return g;
10673     }
10674     if (n.type==_POLY) {
10675       return simplify3(n,d); // changed made 18 dec 2016 for speed
10676       polynome np(*n._POLYptr),dp(d,n._POLYptr->dim);
10677       polynome g(np.dim);
10678       g=simplify(np,dp);
10679       n=np;
10680       d=dp;
10681       return g;
10682     }
10683     if (d.type==_POLY){
10684       polynome np(n,d._POLYptr->dim),dp(*d._POLYptr);
10685       polynome g(np.dim);
10686       g=simplify(np,dp);
10687       n=np;
10688       d=dp;
10689       return g;
10690     }
10691     vecteur l(lvar(n));
10692     lvar(d,l);
10693     gen num=e2r(n,l,context0),den=e2r(d,l,context0),g=gcd(num,den,context0); // ok
10694     den=rdiv(den,g,context0);
10695     if (is_exactly_zero(re(den,context0))){ //ok
10696       den=cst_i*den;
10697       g=-cst_i*g;
10698     }
10699     if (is_positive(-den,context0)){  // ok
10700       den=-den;
10701       g=-g;
10702     }
10703     n=r2sym(rdiv(num,g,context0),l,context0); // ok
10704     d=r2sym(den,l,context0); // ok
10705     return r2sym(g,l,context0); // ok
10706   }
10707 
gcd(const gen & a,const gen & b)10708   gen gcd(const gen & a,const gen & b){
10709     return gcd(a,b,context0);
10710   }
gcd(const gen & a,const gen & b,GIAC_CONTEXT)10711   gen gcd(const gen & a,const gen & b,GIAC_CONTEXT){
10712     ref_mpz_t * res;
10713     switch ( (a.type<< _DECALAGE) | b.type ) {
10714     case _INT___INT_:
10715       return(gcd(a.val,b.val));
10716     case _INT___ZINT:
10717       if (a.val)
10718 	return(int(mpz_gcd_ui(NULL,*b._ZINTptr,absint(a.val))));
10719       else
10720 	return is_positive(b,contextptr)?b:-b;
10721     case _ZINT__INT_:
10722       if (b.val)
10723 	return(int(mpz_gcd_ui(NULL,*a._ZINTptr,absint(b.val))));
10724       else
10725 	return is_positive(a,contextptr)?a:-a;
10726     case _ZINT__ZINT:
10727 #ifndef USE_GMP_REPLACEMENTS
10728       {
10729 	int test=mpz_cmp(*a._ZINTptr,*b._ZINTptr);
10730 	if (test==0 || (test>0 && mpz_divisible_p(*a._ZINTptr,*b._ZINTptr)))
10731 	  return abs(b,contextptr);
10732 	if (test<0 && mpz_divisible_p(*b._ZINTptr,*a._ZINTptr))
10733 	  return abs(a,contextptr);
10734       }
10735 #endif
10736       res = new ref_mpz_t;
10737       my_mpz_gcd(res->z,*a._ZINTptr,*b._ZINTptr);
10738       return(res);
10739     case _INT___CPLX: case _ZINT__CPLX:
10740     case _CPLX__INT_: case _CPLX__ZINT:
10741     case _CPLX__CPLX:
10742       return _CPLXgcd(a,b);
10743     case _POLY__POLY:
10744       return polygcd(*a._POLYptr,*b._POLYptr);
10745     case _VECT__VECT:
10746       return gen(gcd(*a._VECTptr,*b._VECTptr,0,ntl_on(contextptr) && a._VECTptr->size()>=NTL_MODGCD && b._VECTptr->size()>=NTL_MODGCD),_POLY1__VECT);
10747     case _FRAC__FRAC:
10748       return fraction(gcd(a._FRACptr->num,b._FRACptr->num,contextptr),lcm(a._FRACptr->den,b._FRACptr->den));
10749     default:
10750       if (a.type==_FRAC)
10751 	return fraction(gcd(a._FRACptr->num,b,contextptr),a._FRACptr->den);
10752       if (b.type==_FRAC)
10753 	return fraction(gcd(b._FRACptr->num,a,contextptr),b._FRACptr->den);
10754       if (a.type==_USER)
10755 	return a._USERptr->gcd(b);
10756       if (b.type==_USER)
10757 	return b._USERptr->gcd(a);
10758       {
10759 	gen aa(a),bb(b);
10760 	if (is_integral(aa) && is_integral(bb))
10761 	  return gcd(aa,bb,contextptr);
10762       }
10763       return symgcd(a,b,contextptr);
10764     }
10765   }
10766 
lcm(const gen & a,const gen & b)10767   gen lcm(const gen & a,const gen & b){
10768     return normal(rdiv(a,gcd(a,b,context0),context0),context0)*b; // ok
10769   }
10770 
ciegcd(const gen & a_orig,const gen & b_orig,gen & u,gen & v,gen & d)10771   static void ciegcd(const gen &a_orig,const gen &b_orig, gen & u,gen &v,gen &d ){
10772     gen a(a_orig),b(b_orig),au(plus_one),bu(zero),q,r,ru;
10773     while (!is_exactly_zero(b)){
10774       q=iquo(a,b);
10775       r=a-b*q;
10776       a=b;
10777       b=r;
10778       ru=au-bu*q;
10779       au=bu;
10780       bu=ru;
10781     }
10782     u=au;
10783     d=a;
10784     v=iquo(d-a_orig*u,b_orig);
10785   }
10786 
iegcd(int a_,int b_,int & u,int & v)10787   int iegcd(int a_,int b_,int &u,int & v){
10788     int a(a_),b(b_),au(1),bu(0),r,ru;
10789     longlong q;
10790     while (b){
10791       q=a/b;
10792       r=a-b*q;
10793       a=b;
10794       b=r;
10795       ru=au-bu*q;
10796       au=bu;
10797       bu=ru;
10798     }
10799     u=au;
10800     v=(a-longlong(a_)*u)/b_;
10801     return a;
10802   }
10803 
egcd(const gen & ac,const gen & bc,gen & u,gen & v,gen & d)10804   void egcd(const gen &ac,const gen &bc, gen & u,gen &v,gen &d ){
10805     gen a(ac),b(bc);
10806     switch ( (a.type<< _DECALAGE) | b.type ) {
10807     case _INT___INT_: case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
10808       if (a.type==_INT_)
10809 	a.uncoerce();
10810       if (b.type==_INT_)
10811 	b.uncoerce();
10812       if (!u.type)
10813 	u.uncoerce();
10814       if (!v.type)
10815 	v.uncoerce();
10816       if (!d.type)
10817 	d.uncoerce();
10818       my_mpz_gcdext(*d._ZINTptr,*u._ZINTptr,*v._ZINTptr,*a._ZINTptr,*b._ZINTptr);
10819       if (mpz_sizeinbase(*u._ZINTptr,2)<32)
10820 	u=mpz_get_si(*u._ZINTptr);
10821       if (mpz_sizeinbase(*v._ZINTptr,2)<32)
10822 	v=mpz_get_si(*v._ZINTptr);
10823       if (mpz_sizeinbase(*d._ZINTptr,2)<32)
10824 	d=mpz_get_si(*d._ZINTptr);
10825       break;
10826     default:
10827       ciegcd(a,b,u,v,d);
10828       break;
10829     }
10830   }
10831 
_ZINTmod(const gen & a,const gen & b,ref_mpz_t * & rem)10832   static void _ZINTmod (const gen & a,const gen & b,ref_mpz_t * & rem){
10833     if (is_strictly_positive(-b,context0))
10834       return _ZINTmod(a,-b,rem);
10835     // at least one is not an int, uncoerce remaining int
10836     ref_mpz_t *aptr,*bptr;
10837     if (a.type!=_INT_)
10838 #ifdef SMARTPTR64
10839       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10840 #else
10841       aptr=a.__ZINTptr;
10842 #endif
10843     else {
10844       aptr=new ref_mpz_t;
10845       mpz_set_si(aptr->z,a.val);
10846     }
10847     if (b.type!=_INT_)
10848 #ifdef SMARTPTR64
10849       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10850 #else
10851       bptr=b.__ZINTptr;
10852 #endif
10853     else {
10854       bptr=new ref_mpz_t;
10855       mpz_set_si(bptr->z,b.val);
10856     }
10857     rem=new ref_mpz_t;
10858     mpz_tdiv_r(rem->z,aptr->z,bptr->z);
10859     if (a.type==_INT_)
10860       delete aptr;
10861     if (b.type==_INT_)
10862       delete bptr;
10863   }
10864 
operator %(const gen & a,const gen & b)10865   gen operator %(const gen & a,const gen & b){
10866     ref_mpz_t * rem;
10867     switch ( (a.type<< _DECALAGE) | b.type ) {
10868     case _INT___INT_:
10869       if (b.val)
10870 	return(a.val % b.val);
10871       else
10872 	return a.val;
10873     case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
10874       _ZINTmod(a,b,rem);
10875       return(rem);
10876     case _CPLX__INT_: case _CPLX__ZINT:
10877       return gen(smod((*a._CPLXptr), b), smod(*(a._CPLXptr+1), b) );
10878     case _INT___CPLX: case _ZINT__CPLX: case _CPLX__CPLX:
10879       return(a-b*iquo(a,b));
10880     case _VECT__VECT:
10881       return (*a._VECTptr)%(*b._VECTptr);
10882     default:
10883       return gentypeerr(gettext("%"));
10884     }
10885     return 0;
10886   }
10887 
is_multiple(const gen & a,const gen & b)10888   bool is_multiple(const gen & a,const gen &b){
10889     if (a.type==_INT_){
10890       if (b.type!=_INT_)
10891 	return false;
10892       return a.val%b.val==0;
10893     }
10894     if (a.type!=_ZINT)
10895       return false;
10896     if (b.type==_INT_)
10897       return modulo(*a._ZINTptr,b.val)==0;
10898     return a%b==0;
10899   }
10900 
_ZINTrem(const gen & a,const gen & b,gen & q,ref_mpz_t * & rem)10901   static void _ZINTrem(const gen & a,const gen &b,gen & q,ref_mpz_t * & rem){
10902     // COUT << a << " irem " << b << '\n';
10903     ref_mpz_t *aptr,*bptr;
10904     if (a.type!=_INT_)
10905 #ifdef SMARTPTR64
10906       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10907 #else
10908       aptr=a.__ZINTptr;
10909 #endif
10910     else {
10911       aptr = new ref_mpz_t;
10912       mpz_set_si(aptr->z,a.val);
10913     }
10914     if (b.type!=_INT_)
10915 #ifdef SMARTPTR64
10916       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10917 #else
10918       bptr=b.__ZINTptr;
10919 #endif
10920     else {
10921       bptr = new ref_mpz_t;
10922       mpz_set_si(bptr->z,b.val);
10923     }
10924     rem=new ref_mpz_t;
10925     q.uncoerce();
10926     mpz_tdiv_qr(*q._ZINTptr,rem->z,aptr->z,bptr->z);
10927     if (a.type==_INT_)
10928       delete aptr;
10929     if (b.type==_INT_)
10930       delete bptr;
10931   }
10932 
irem(const gen & a,const gen & b,gen & q)10933   gen irem(const gen & a,const gen & b,gen & q){
10934     ref_mpz_t * rem;
10935     register int r;
10936     switch ( (a.type<< _DECALAGE) | b.type ) {
10937     case _INT___INT_:
10938       if (!b.val)
10939 	return a;
10940       r=a.val % b.val;
10941       /*
10942       if (r<0){
10943 	if (b.val>0){
10944 	  q=gen(a.val/b.val-1);
10945 	  r += b.val;
10946 	}
10947 	else {
10948 	  q=gen(a.val/b.val+1);
10949 	  r -= b.val;
10950 	}
10951       }
10952       else
10953       */
10954       q=gen(a.val/b.val);
10955       return r;
10956     case _ZINT__ZINT: case _INT___ZINT: case _ZINT__INT_:
10957       _ZINTrem(a,b,q,rem);
10958       return(rem);
10959     case _INT___CPLX: case _ZINT__CPLX: case _CPLX__CPLX: case _CPLX__INT_: case _CPLX__ZINT:
10960       q=iquo(a,b);
10961       return(a-b*q);
10962     default:
10963       return gentypeerr(gettext("irem"));
10964     }
10965     return 0;
10966   }
10967 
_ZINTsmod(const gen & a,const gen & b,ref_mpz_t * & rem)10968   static void _ZINTsmod(const gen & a, const gen & b, ref_mpz_t * & rem){
10969     // at least one is not an int, uncoerce remaining int
10970     ref_mpz_t *aptr,*bptr;
10971     if (a.type!=_INT_)
10972 #ifdef SMARTPTR64
10973       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
10974 #else
10975       aptr=a.__ZINTptr;
10976 #endif
10977     else {
10978       aptr = new ref_mpz_t;
10979       mpz_set_si(aptr->z,a.val);
10980     }
10981     if (b.type!=_INT_)
10982 #ifdef SMARTPTR64
10983       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
10984 #else
10985       bptr=b.__ZINTptr;
10986 #endif
10987     else {
10988       bptr = new ref_mpz_t;
10989       mpz_set_si(bptr->z,b.val);
10990     }
10991     rem = new ref_mpz_t;
10992     mpz_t rem1,rem2,rem3;
10993     mpz_init(rem1); mpz_init(rem2); mpz_init(rem3);
10994     mpz_mod(rem1,aptr->z,bptr->z); // rem1 positive remainder
10995     if (mpz_sgn(bptr->z)>0)
10996       mpz_sub(rem2,rem1,bptr->z); // negative remainder
10997     else
10998       mpz_add(rem2,rem1,bptr->z);
10999     // choose smallest one in abs value
11000     mpz_neg(rem3,rem2);
11001     if (mpz_cmp(rem1,rem3)>0)
11002       mpz_set(rem->z,rem2);
11003     else
11004       mpz_set(rem->z,rem1);
11005     if (a.type==_INT_)
11006       delete aptr;
11007     if (b.type==_INT_)
11008       delete bptr;
11009     mpz_clear(rem1); mpz_clear(rem2); mpz_clear(rem3);
11010   }
11011 
smod(const vecteur & v,const gen & g,vecteur & w)11012   void smod(const vecteur & v,const gen & g,vecteur & w){
11013     const_iterateur it=v.begin(),itend=v.end();
11014     w.resize(itend-it);
11015     iterateur jt=w.begin();
11016     for (;it!=itend;++jt,++it)
11017       *jt=smod(*it,g);
11018   }
11019 
smod(const vecteur & v,const gen & g)11020   vecteur smod(const vecteur & v,const gen & g){
11021     vecteur w(v);
11022     smod(w,g,w);
11023     return w;
11024   }
11025 
smodSYMB(const gen & a,const gen & b)11026   static gen smodSYMB(const gen & a,const gen & b){
11027     vecteur lv(lvar(a));
11028     gen n,d,f;
11029     f=e2r(a,lv,context0); // ok
11030     fxnd(f,n,d);
11031     n=smod(n,b);
11032     d=smod(d,b);
11033     f=n/d;
11034     return r2e(f,lv,context0); // ok
11035   }
11036 
fixfracmod(const gen & res,int modulo)11037   static gen fixfracmod(const gen & res, int modulo){
11038     gen n=res._FRACptr->num,d=res._FRACptr->den;
11039     if (n.type!=_POLY)
11040       return res;
11041     if (d.type==_INT_)
11042       return invmod(d.val,modulo)*n;
11043     if (d.type!=_POLY)
11044       return res;
11045     polynome np=*n._POLYptr,dp=*d._POLYptr,tmp,quo,rem;
11046     np=smod(np,modulo);
11047     tmp=gcdmod(np,dp,modulo);
11048     divremmod(np,tmp,modulo,quo,rem);
11049     np=quo;
11050     divremmod(dp,tmp,modulo,quo,rem);
11051     dp=quo;
11052     if (is_one(dp))
11053       return np;
11054     return fraction(np,dp);
11055   }
11056 
smod(const gen & a,const gen & b)11057   gen smod(const gen & a,const gen & b){
11058     if (b.type==_INT_ && b.val==0)
11059       return a;
11060     ref_mpz_t * rem;
11061     switch ( (a.type<< _DECALAGE) | b.type ) {
11062     case _INT___INT_:
11063       return smod(a.val,b.val);
11064     case _ZINT__INT_:
11065       return smod(modulo(*a._ZINTptr,absint(b.val)),b.val);
11066     case _INT___ZINT: case _ZINT__ZINT:
11067       _ZINTsmod(a,b,rem);
11068       return(rem);
11069     case _CPLX__INT_: case _CPLX__ZINT:
11070       return gen(smod(*a._CPLXptr,b),smod(*(a._CPLXptr+1),b));
11071     case _POLY__INT_: case _POLY__ZINT:
11072       return smod(*a._POLYptr,b);
11073     case _VECT__INT_: case _VECT__ZINT:
11074       if (a.ref_count()==1){
11075 	smod(*a._VECTptr,b,*a._VECTptr);
11076 	if (a.subtype==_POLY1__VECT)
11077 	  *a._VECTptr=trim(*a._VECTptr,0);
11078 	return a;
11079       }
11080       {
11081 	gen res(new_ref_vecteur(*a._VECTptr),a.subtype);
11082 	smod(*res._VECTptr,b,*res._VECTptr);
11083 	if (a.subtype==_POLY1__VECT)
11084 	  *res._VECTptr=trim(*res._VECTptr,0);
11085 	return res;
11086       }
11087     default:
11088       if (a.type==_SYMB)
11089 	return smodSYMB(a,b);
11090       if (a.type==_FRAC && is_integer(b) && is_integer(a._FRACptr->den))
11091 	return smod(a._FRACptr->num*invmod(a._FRACptr->den,b),b);
11092       if (a.type==_FRAC && b.type==_INT_)
11093 	return fixfracmod(a,b.val);
11094       if ( (b.type==_INT_) || (b.type==_ZINT) )
11095 	return a;
11096       // error, b must be _DOUBLE_
11097 #ifndef NO_STDEXCEPT
11098       throw(std::runtime_error("smod 2nd argument must be _DOUBLE_"));
11099 #endif
11100       return undef;
11101     }
11102   }
11103 
_ZINTinvmod(const gen & a,const gen & modulo,ref_mpz_t * & res)11104   static bool _ZINTinvmod(const gen & a,const gen & modulo, ref_mpz_t * & res){
11105     ref_mpz_t *aptr,*bptr;
11106     if (a.type!=_INT_)
11107 #ifdef SMARTPTR64
11108       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11109 #else
11110       aptr = a.__ZINTptr;
11111 #endif
11112     else {
11113       aptr = new ref_mpz_t;
11114       mpz_set_si(aptr->z,a.val);
11115     }
11116     if (modulo.type)
11117 #ifdef SMARTPTR64
11118       bptr= (ref_mpz_t *) (* ((ulonglong * ) &modulo) >> 16);
11119 #else
11120       bptr = modulo.__ZINTptr;
11121 #endif
11122     else {
11123       bptr = new ref_mpz_t;
11124       mpz_set_si(bptr->z,modulo.val);
11125     }
11126     res = new ref_mpz_t;
11127     bool ok=my_mpz_invert(res->z,aptr->z,bptr->z)!=0;
11128     if (a.type==_INT_)
11129       delete aptr;
11130     if (!modulo.type)
11131       delete bptr;
11132     if (!ok){
11133 #ifndef NO_STDEXCEPT
11134       setsizeerr(gettext("Not invertible ")+a.print(context0)+" mod "+modulo.print(context0));
11135 #endif
11136       delete res;
11137       res=0;
11138       return false;
11139     }
11140     return true;
11141   }
11142 
invmod(const gen & a,const gen & modulo)11143   gen invmod(const gen & a,const gen & modulo){
11144     if (a.type==_USER)
11145       return a._USERptr->inv();
11146     if (a.type==_MOD){
11147       if (*(a._MODptr+1)!=modulo)
11148 	return gensizeerr("Incompatible modulo "+a.print(context0)+","+modulo.print(context0));
11149       return inv(a,context0);
11150     }
11151     if (a.type==_CPLX){
11152       gen r=re(a,context0),i=im(a,context0); // ok
11153       gen n=invmod(r*r+i*i,modulo);
11154       return smod(r*n,modulo)-cst_i*smod(i*n,modulo);
11155     }
11156     if (a.type==_POLY)
11157       return fraction(1,a);
11158     ref_mpz_t * res;
11159     switch ( (a.type<< _DECALAGE) | modulo.type) {
11160     case _INT___INT_:
11161       return(invmod(a.val,modulo.val));
11162     case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
11163       if (!_ZINTinvmod(a,modulo,res))
11164 	return gentypeerr(gettext("invmod"));
11165       return gen(res);
11166     default:
11167       return gentypeerr(gettext("invmod"));
11168     }
11169     return 0;
11170   }
11171 
in_fracmod(const gen & m,const gen & a,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t & u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t & sqrtm,mpz_t & tmp,gen & num,gen & den)11172   bool in_fracmod(const gen &m,const gen & a,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp,gen & num,gen & den){
11173     mpz_set(d,*m._ZINTptr);
11174     mpz_set(d1,*a._ZINTptr);
11175     mpz_set_si(u,0);
11176     mpz_set_si(u1,1);
11177     mpz_tdiv_q_2exp(q,*m._ZINTptr,1);
11178     mpz_sqrt(sqrtm,q);
11179     // int signe;
11180     for (;;){
11181       mpz_abs(absd1,d1);
11182       if (mpz_cmp(absd1,sqrtm)<=0)
11183 	break;
11184       mpz_fdiv_qr(q,r,d,d1);
11185       // u-q*u1->ur, v-q*v1->vr
11186       mpz_mul(tmp,q,u1);
11187       mpz_sub(ur,u,tmp);
11188       // u1 -> u, ur -> u1 ; v1 -> v, vr -> v1, d1 -> d, r -> d1
11189 #ifdef USE_GMP_REPLACEMENTS
11190       mpz_set(u,u1);
11191       mpz_set(u1,ur);
11192       mpz_set(d,d1);
11193       mpz_set(d1,r);
11194 #else
11195       mpz_swap(u,u1);
11196       mpz_swap(u1,ur);
11197       mpz_swap(d,d1);
11198       mpz_swap(d1,r);
11199 #endif
11200     }
11201     // u1*a+v1*m=d1 -> a=d1/u1 modulo m
11202     if (mpz_sizeinbase(d1,2)<=30)
11203       num=int(mpz_get_si(d1));
11204     else
11205       num=d1;
11206     if (mpz_sizeinbase(u1,2)<=30)
11207       den=int(mpz_get_si(u1));
11208     else
11209       den=u1;
11210     mpz_set(q,*m._ZINTptr);
11211     my_mpz_gcd(r,q,u1);
11212     bool ok=mpz_cmp_ui(r,1)==0;
11213     if (!ok){
11214       CERR << "Bad reconstruction " << a << " " << m << " " << gen(r) << '\n';
11215       simplify3(num,den);
11216       return false;
11217     }
11218     return true;
11219   }
11220 
alloc_fracmod(const gen & a_orig,const gen & modulo,gen & res,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t & u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t & sqrtm,mpz_t & tmp)11221   bool alloc_fracmod(const gen & a_orig,const gen & modulo,gen & res,mpz_t & d,mpz_t & d1,mpz_t & absd1,mpz_t &u,mpz_t & u1,mpz_t & ur,mpz_t & q,mpz_t & r,mpz_t &sqrtm,mpz_t & tmp){
11222     // write a as p/q with |p| and |q|<sqrt(modulo/2)
11223     if (a_orig.type==_VECT){
11224       const_iterateur it=a_orig._VECTptr->begin(),itend=a_orig._VECTptr->end();
11225       vecteur v;
11226       v.reserve(itend-it);
11227       for (;it!=itend;++it){
11228 	if (!alloc_fracmod(*it,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp))
11229 	  return false;
11230 	v.push_back(res);
11231       }
11232       res=gen(v,a_orig.subtype);
11233       return true;
11234     }
11235     if (a_orig.type==_POLY){
11236       vector< monomial<gen> >::const_iterator it=a_orig._POLYptr->coord.begin(),itend=a_orig._POLYptr->coord.end();
11237       polynome v(a_orig._POLYptr->dim);
11238       v.coord.reserve(itend-it);
11239       for (;it!=itend;++it){
11240 	if (!alloc_fracmod(it->value,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp))
11241 	  return false;
11242 	v.coord.push_back(monomial<gen>(res,it->index));
11243       }
11244       res=gen(v);
11245       return true;
11246     }
11247     if (a_orig.type==_CPLX){
11248       gen reres,imres;
11249       if ( !alloc_fracmod(*a_orig._CPLXptr,modulo,reres,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp) || !alloc_fracmod(*(a_orig._CPLXptr+1),modulo,imres,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp) )
11250 	return false;
11251       res=reres+cst_i*imres;
11252       return true;
11253     }
11254     gen a(a_orig),m(modulo),num,den;
11255     if (a.type==_INT_)
11256       a.uncoerce();
11257     if (m.type==_INT_)
11258       m.uncoerce();
11259     if ( (a.type!=_ZINT) || (m.type!=_ZINT) )
11260       return false;
11261     bool ok=in_fracmod(m,a,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp,num,den);
11262     if (num.type==_ZINT && mpz_sizeinbase(*num._ZINTptr,2)<=30)
11263       num=int(mpz_get_si(*num._ZINTptr));
11264     if (den.type==_ZINT && mpz_sizeinbase(*den._ZINTptr,2)<=30)
11265       den=int(mpz_get_si(*den._ZINTptr));
11266     if (is_positive(den,context0)) // ok
11267       res=fraction(num,den);
11268     else
11269       res=fraction(-num,-den);
11270     return ok;
11271   }
11272 
fracmod(const gen & a_orig,const gen & modulo,gen & res)11273   bool fracmod(const gen & a_orig,const gen & modulo,gen & res){
11274     unsigned prealloc=a_orig.type==_ZINT?mpz_sizeinbase(*a_orig._ZINTptr,2):0;
11275     mpz_t u,d,u1,d1,absd1,sqrtm,q,ur,r,tmp;
11276     mpz_init2(u,prealloc);
11277     mpz_init2(d,prealloc);
11278     mpz_init2(u1,prealloc);
11279     mpz_init(d1);
11280     mpz_init(absd1);
11281     mpz_init(sqrtm);
11282     mpz_init(q);
11283     mpz_init2(ur,prealloc);
11284     mpz_init2(r,prealloc);
11285     mpz_init2(tmp,prealloc);
11286     bool b=alloc_fracmod(a_orig,modulo,res,d,d1,absd1,u,u1,ur,q,r,sqrtm,tmp);
11287     mpz_clear(d);
11288     mpz_clear(u);
11289     mpz_clear(u1);
11290     mpz_clear(d1);
11291     mpz_clear(absd1);
11292     mpz_clear(sqrtm);
11293     mpz_clear(q);
11294     mpz_clear(ur);
11295     mpz_clear(r);
11296     mpz_clear(tmp);
11297     return b;
11298   }
11299 
fracmod(const gen & a_orig,const gen & modulo)11300   gen fracmod(const gen & a_orig,const gen & modulo){
11301     if (a_orig==0)
11302       return a_orig;
11303     gen res;
11304     if (!fracmod(a_orig,modulo,res))
11305       return gensizeerr(gettext("Reconstructed denominator is not prime with modulo"));
11306     return res;
11307   }
11308 
_ZINTpowmod(const gen & base,const gen & expo,const gen & modulo,ref_mpz_t * & res)11309   static void _ZINTpowmod(const gen & base,const gen & expo,const gen & modulo, ref_mpz_t * & res){
11310     ref_mpz_t *aptr,*bptr;
11311     if (base.type)
11312 #ifdef SMARTPTR64
11313       aptr= (ref_mpz_t *) (* ((ulonglong * ) &base) >> 16);
11314 #else
11315       aptr=base.__ZINTptr;
11316 #endif
11317     else {
11318       aptr = new ref_mpz_t;
11319       mpz_set_si(aptr->z,base.val);
11320     }
11321     if (modulo.type)
11322 #ifdef SMARTPTR64
11323       bptr= (ref_mpz_t *) (* ((ulonglong * ) &modulo) >> 16);
11324 #else
11325       bptr=modulo.__ZINTptr;
11326 #endif
11327     else {
11328       bptr = new ref_mpz_t;
11329       mpz_set_si(bptr->z,modulo.val);
11330     }
11331     res = new ref_mpz_t;
11332     if (!expo.type)
11333       mpz_powm_ui(res->z,aptr->z,expo.val,*modulo._ZINTptr);
11334     else
11335       mpz_powm (res->z,aptr->z,*expo._ZINTptr,bptr->z);
11336     if (!base.type)
11337       delete aptr;
11338     if (!modulo.type)
11339       delete bptr;
11340   }
11341 
powmod(const gen & base,const gen & expo,const gen & modulo)11342   gen powmod(const gen &base,const gen & expo,const gen & modulo){
11343     if (is_exactly_zero(modulo))
11344       return pow(base,expo,context0);
11345     if (base.type==_VECT){
11346       const_iterateur it=base._VECTptr->begin(),itend=base._VECTptr->end();
11347       vecteur res;
11348       for (;it!=itend;++it)
11349 	res.push_back(powmod(*it,expo,modulo));
11350       return gen(res,base.subtype);
11351     }
11352     if ((expo.type!=_INT_) && (expo.type!=_ZINT))
11353       return gensizeerr(gettext("powmod")); // exponent must be a _DOUBLE_ integer
11354     if (!is_positive(expo,context0)) // ok
11355       return(powmod(invmod(base,modulo),-expo,modulo));
11356     if (modulo.type==_INT_){
11357       // try converting base to int and expo to a long
11358       gen mybase(base % modulo);
11359       if ( (expo.type==_INT_) && (mybase.type==_INT_) ){
11360 	unsigned long tmp=expo.val;
11361 	return powmod(mybase.val,tmp,modulo.val);
11362       }
11363     }
11364     ref_mpz_t * res;
11365     switch ( (base.type<< _DECALAGE) | modulo.type) {
11366     case _INT___INT_: case _INT___ZINT: case _ZINT__INT_: case _ZINT__ZINT:
11367       _ZINTpowmod(base,expo,modulo,res);
11368       return(res);
11369     default:
11370       return gentypeerr(gettext("powmod"));
11371     }
11372     return 0;
11373   }
11374 
11375   // assuming amod and bmod are prime together, find c such that
11376   // c = a mod amod  and c = b mod bmod
11377   // hence a + A*amod = b + B*bmod
11378   // or A*amod -B*bmod = b - a
ichinrem(const gen & a,const gen & b,const gen & amod,const gen & bmod)11379   gen ichinrem(const gen & a,const gen &b,const gen & amod, const gen & bmod){
11380     if (a.type==_INT_ && b.type==_INT_ && amod.type==_INT_ && bmod.type==_INT_ && gcd(amod.val,bmod.val)==1){
11381       int amodinv=invmod(amod.val,bmod.val);
11382       longlong res=a.val+((longlong(amodinv)*(b.val-longlong(a.val)))%bmod.val)*amod.val;
11383       return res;
11384     }
11385     gen A,B,d,q;
11386     egcd(amod,bmod,A,B,d);
11387     if (is_one(d))
11388       q=b-a;
11389     else
11390       if (!is_exactly_zero(irem(b-a,d,q)))
11391 	return gensizeerr(gettext("No Integer Solution"));
11392     A=A*q;
11393     return smod(A*amod+a,amod*bmod);
11394   }
11395 
isqrt(const gen & a)11396   gen isqrt(const gen & a){
11397     if ( (a.type!=_INT_) && (a.type!=_ZINT))
11398       return gentypeerr(gettext("isqrt"));
11399     ref_mpz_t *aptr;
11400     if (a.type!=_INT_)
11401 #ifdef SMARTPTR64
11402       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11403 #else
11404       aptr=a.__ZINTptr;
11405 #endif
11406     else {
11407       aptr = new ref_mpz_t;
11408       mpz_set_si(aptr->z,a.val);
11409     }
11410     ref_mpz_t *res = new ref_mpz_t;
11411     mpz_sqrt(res->z,aptr->z);
11412     if (a.type==_INT_)
11413       delete aptr;
11414     return res;
11415   }
11416 
is_perfect_square(const gen & a)11417   int is_perfect_square(const gen & a){
11418     if ( (a.type!=_INT_) && (a.type!=_ZINT))
11419       return false;
11420     ref_mpz_t *aptr;
11421     if (a.type!=_INT_)
11422 #ifdef SMARTPTR64
11423       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11424 #else
11425       aptr=a.__ZINTptr;
11426 #endif
11427     else {
11428       aptr = new ref_mpz_t;
11429       mpz_set_si(aptr->z,a.val);
11430     }
11431     int res= mpz_perfect_square_p(aptr->z);
11432     if (a.type==_INT_)
11433       delete aptr;
11434     return res;
11435   }
11436 
is_probab_prime_p(const gen & a)11437   int is_probab_prime_p(const gen & a){
11438     if ( (a.type!=_INT_) && (a.type!=_ZINT)){
11439 #ifndef NO_STDEXCEPT
11440       settypeerr(gettext("is_probab_prime_p"));
11441 #endif
11442       return false;
11443     }
11444     if (a.type==_INT_ && a.val<2)
11445       return false;
11446     if (a.type==_INT_ && a.val<(1<<20)){
11447       for (int i=0;;++i){
11448 	int p=giac_primes[i];
11449 	if (p*p>a.val)
11450 	  return true;
11451 	if (a.val%p==0)
11452 	  return false;
11453       }
11454     }
11455     ref_mpz_t *aptr;
11456     if (a.type!=_INT_)
11457 #ifdef SMARTPTR64
11458       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11459 #else
11460       aptr=a.__ZINTptr;
11461 #endif
11462     else {
11463       aptr = new ref_mpz_t;
11464       mpz_set_si(aptr->z,a.val);
11465     }
11466     int res= mpz_probab_prime_p(aptr->z,TEST_PROBAB_PRIME);
11467     if (a.type==_INT_)
11468       delete aptr;
11469     return res;
11470   }
11471 
nextprime(const gen & a)11472   gen nextprime(const gen & a){
11473     if ( (a.type!=_INT_) && (a.type!=_ZINT))
11474       return gentypeerr(gettext("nextprime"));
11475     gen res(a);
11476     if (is_exactly_zero(smod(res,plus_two)))
11477       res=res+1;
11478     for ( ; ; res=res+2){
11479 #ifdef TIMEOUT
11480       control_c();
11481 #endif
11482       if (ctrl_c || interrupted)
11483 	return gensizeerr(gettext("Interrupted"));
11484       if (is_probab_prime_p(res))
11485 	return(res);
11486     }
11487   }
11488 
prevprime(const gen & a)11489   gen prevprime(const gen & a){
11490     if ( (a.type!=_INT_) && (a.type!=_ZINT))
11491       return gentypeerr(gettext("prevprime"));
11492     if (a==2)
11493       return a;
11494     if (is_greater(2,a,context0))
11495       return gensizeerr(context0);
11496     gen res(a);
11497     if (is_exactly_zero(smod(res,plus_two)))
11498       res=res-1;
11499     for ( ; res.type==_ZINT || (res.type==_INT_ && res.val>1); res=res-2){
11500 #ifdef TIMEOUT
11501       control_c();
11502 #endif
11503       if (ctrl_c || interrupted)
11504 	return gensizeerr(gettext("Interrupted"));
11505       if (is_probab_prime_p(res))
11506 	return(res);
11507     }
11508     return zero;
11509   }
11510 
jacobi(const gen & a,const gen & b)11511   int jacobi(const gen & a, const gen &b){
11512     if ( (a.type!=_INT_ && a.type!=_ZINT) || (b.type!=_INT_ && b.type!=_ZINT)){
11513 #ifndef NO_STDEXCEPT
11514       settypeerr(gettext("jacobi"));
11515 #endif
11516       return -RAND_MAX;
11517     }
11518     ref_mpz_t *aptr,*bptr;
11519     if (a.type!=_INT_)
11520 #ifdef SMARTPTR64
11521       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11522 #else
11523       aptr = a.__ZINTptr;
11524 #endif
11525     else {
11526       aptr = new ref_mpz_t;
11527       mpz_set_si(aptr->z,a.val);
11528     }
11529     if (b.type!=_INT_)
11530 #ifdef SMARTPTR64
11531       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
11532 #else
11533       bptr=b.__ZINTptr;
11534 #endif
11535     else {
11536       bptr = new ref_mpz_t;
11537       mpz_set_si(bptr->z,b.val);
11538     }
11539     int res= mpz_jacobi(aptr->z,bptr->z);
11540     if (a.type==_INT_)
11541       delete aptr;
11542     if (b.type==_INT_)
11543       delete bptr;
11544     return res;
11545   }
11546 
legendre(const gen & a,const gen & b)11547   int legendre(const gen & a, const gen & b){
11548     if ( (a.type!=_INT_ && a.type!=_ZINT) || (b.type!=_INT_ && b.type!=_ZINT)){
11549 #ifndef NO_STDEXCEPT
11550       settypeerr(gettext("legendre"));
11551 #endif
11552       return -RAND_MAX;
11553     }
11554     ref_mpz_t *aptr,*bptr;
11555     if (a.type!=_INT_)
11556 #ifdef SMARTPTR64
11557       aptr= (ref_mpz_t *) (* ((ulonglong * ) &a) >> 16);
11558 #else
11559       aptr=a.__ZINTptr;
11560 #endif
11561     else {
11562       aptr= new ref_mpz_t;
11563       mpz_set_si(aptr->z,a.val);
11564     }
11565     if (b.type!=_INT_)
11566 #ifdef SMARTPTR64
11567       bptr= (ref_mpz_t *) (* ((ulonglong * ) &b) >> 16);
11568 #else
11569       bptr=b.__ZINTptr;
11570 #endif
11571     else {
11572       bptr= new ref_mpz_t;
11573       mpz_set_si(bptr->z,b.val);
11574     }
11575     int res=mpz_legendre(aptr->z,bptr->z);
11576     if (a.type==_INT_)
11577       delete aptr;
11578     if (b.type==_INT_)
11579       delete bptr;
11580     return res;
11581   }
11582 
has_denominator(const gen & n)11583   bool has_denominator(const gen & n){
11584     switch (n.type ) {
11585     case _INT_: case _ZINT: case _CPLX: case _DOUBLE_: case _FLOAT_: case _IDNT: case _EXT: case _POLY: case _MOD: case _USER: case _REAL: case _VECT:
11586       return false;
11587     case _SYMB: case _FRAC:
11588       return true;
11589     default:
11590 #ifndef NO_STDEXCEPT
11591       settypeerr(gettext("has_denominator"));
11592 #endif
11593       return false;
11594     }
11595     return 0;
11596   }
11597 
11598 
factorial(unsigned long int i)11599   gen factorial(unsigned long int i){
11600     if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11601 #ifndef NO_STDEXCEPT
11602       setstabilityerr();
11603 #endif
11604       return plus_inf;
11605     }
11606     ref_mpz_t * e = new ref_mpz_t;
11607     mpz_fac_ui(e->z,i);
11608     return e;
11609   }
11610 
comb(unsigned long int i,unsigned long j)11611   gen comb(unsigned long int i,unsigned long j){
11612     if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11613       double d=std::min(j,i-j)*std::log10(double(i));
11614       if (d>2*FACTORIAL_SIZE_LIMIT){
11615 #ifndef NO_STDEXCEPT
11616 	setstabilityerr();
11617 #endif
11618 	return undef;
11619       }
11620     }
11621     ref_mpz_t * e = new ref_mpz_t;
11622     if (i<j)
11623       return e;
11624 #ifdef mpz_bin_uiui
11625     mpz_bin_uiui(e->z,i,j);
11626 #else
11627     mpz_set_ui(e->z,1);
11628     for (unsigned long int k=i;k>i-j;--k)
11629       mpz_mul_ui(e->z,e->z,k);
11630     mpz_t tmp;
11631     mpz_init(tmp);
11632     mpz_fac_ui(tmp,j);
11633     mpz_fdiv_q(e->z,e->z,tmp);
11634     mpz_clear(tmp);
11635 #endif
11636     return e;
11637   }
11638 
perm(unsigned long int i,unsigned long j)11639   gen perm(unsigned long int i,unsigned long j){
11640     if (i>(unsigned long int)FACTORIAL_SIZE_LIMIT){
11641       double d=j*std::log10(double(i));
11642       if (d>2*FACTORIAL_SIZE_LIMIT){
11643 #ifndef NO_STDEXCEPT
11644 	setstabilityerr();
11645 #endif
11646 	return undef;
11647       }
11648     }
11649     ref_mpz_t * e = new ref_mpz_t;
11650     if (i<j)
11651       return e;
11652     mpz_set_ui(e->z,1);
11653     for (unsigned long int k=i;k>i-j;--k)
11654       mpz_mul_ui(e->z,e->z,k);
11655     return e;
11656   }
11657 
11658   /* I/O: Input routines */
11659 
chartab2gen(char * s,GIAC_CONTEXT)11660   gen chartab2gen(char * s,GIAC_CONTEXT){
11661     gen res;
11662     // subtype=0;
11663     // initialize as a null _INT_
11664     // type = _INT_;
11665     // val = 0;
11666     if (!*s)
11667       return res;
11668 #ifdef EMCC
11669     int base=10;
11670 #else
11671     int base=(abs_calc_mode(contextptr)==38 || calc_mode(contextptr)==1)?10:0;
11672 #endif
11673     if (s[0]=='#' || s[0]=='0') {
11674       if (s[1]=='x' || s[1]=='X'){
11675 	s[0]='0';
11676 	s[1]='0';
11677 	base=16;
11678       }
11679       if (s[1]=='o' || s[1]=='O'){
11680 	s[0]='0';
11681 	s[1]='0';
11682 	base=8;
11683       }
11684     }
11685     if (s[1]=='b' || s[1]=='B'){
11686       s[0]='0';
11687       s[1]='0';
11688       base=2;
11689     }
11690 #ifdef _LIB_CE_ERRNO_H
11691 #ifndef BESTA_OS
11692     __set_errno(0);
11693 #endif
11694 #else
11695      errno = 0;
11696 #endif
11697     char * endchar;
11698 #ifdef VISUALC
11699     longlong ll=strtol(s,&endchar,base);
11700 #else
11701     longlong ll=strtoll(s,&endchar,base);
11702 #endif
11703     int l =int(strlen(s));
11704     if (l>0 && s[l-1]=='.'){
11705       // make a copy of s, call chartab2gen recursivly,
11706       // because some implementations of strtod do not like a . at the end
11707 #if 1 // def FREERTOS
11708       ALLOCA(char, scopy, l+2);
11709 #else
11710       char * scopy=(char *)alloca(l+2);
11711 #endif
11712       strcpy(scopy,s);
11713       scopy[l]='0';
11714       scopy[l+1]=0;
11715       return chartab2gen(scopy,contextptr);
11716     }
11717     if (*endchar) {// non integer
11718       int digits=decimal_digits(contextptr);
11719       // count numeric char
11720       int delta=0;
11721       if (l && s[0]=='0')
11722 	++delta;
11723       for (int k=0;k<l;++k){
11724 	if (s[k]=='e' || s[k]=='E'){
11725 	  delta += l-k;
11726 	  break;
11727 	}
11728 	if (s[k]<'0' || s[k]>'9')
11729 	  ++delta;
11730       }
11731       if (l>digits+delta)
11732 	digits=l-delta;
11733 #ifdef HAVE_LIBMPFR // #ifndef GIAC_HAS_STO_38
11734       if (digits>14){
11735 #if 1 // def HAVE_LIBMPFR
11736 	int nbits=digits2bits(digits);
11737 #ifdef HAVE_LIBPTHREAD
11738 	int locked=pthread_mutex_trylock(&mpfr_mutex);
11739 	if (!locked)
11740 	  mpfr_set_default_prec(nbits);
11741 	// mpf_set_default_prec (decimal_digits);
11742 	real_object r;
11743 	int res=mpfr_set_str(r.inf,s,10,MPFR_RNDN);
11744 	if (!locked)
11745 	  pthread_mutex_unlock(&mpfr_mutex);
11746 #else
11747 	real_object r;
11748 	mpfr_set_default_prec(nbits);
11749 	int res=mpfr_set_str(r.inf,s,10,MPFR_RNDN);
11750 #endif // HAVE_LIBPTHREAD
11751 #else // LIBMPFR
11752 	real_object r;
11753 	int res=mpf_set_str(r.inf,s,10);
11754 #endif // LIBMPFR
11755 	gen rg(r);
11756 	// rg.dbgprint();
11757 	if (!res)
11758 	  return rg;
11759       } // end if (digits>14)
11760 #endif // LIBMPFR was GIAC_HAS_STO_38
11761       double d;
11762 #if defined NSPIRE || defined FXCG
11763 #ifdef NSPIRE
11764       d=Strtod(s,&endchar);
11765 #else
11766       d=strtod(s,&endchar);
11767 #endif // NSPIRE
11768 #else // NSPIRE || FXCG
11769 #ifdef HAVE_LIBPTHREAD
11770       int locked=pthread_mutex_trylock(&locale_mutex);
11771       if (!locked){
11772 	char * lc=setlocale(LC_NUMERIC,(char *)NULL);
11773 	setlocale(LC_NUMERIC,"POSIX");
11774 	d=strtod(s,&endchar);
11775 	setlocale(LC_NUMERIC,lc);
11776 	pthread_mutex_unlock(&locale_mutex);
11777       }
11778       else
11779 	d=strtod(s,&endchar);
11780 #else
11781       char * lc=setlocale(LC_NUMERIC,(char const *)NULL);
11782       setlocale(LC_NUMERIC,"POSIX");
11783       d=strtod(s,&endchar);
11784       setlocale(LC_NUMERIC,lc);
11785 #endif // PTHREAD
11786 #endif // NSPIRE
11787       if (*endchar){
11788 #ifdef BCD
11789 	giac_float gf;
11790 	gf=strtobcd(s,(const char **)&endchar);
11791 	if (!*endchar)
11792 	  return gf;
11793 	for (int i=0;i<l;++i){
11794 	  unsigned si=(unsigned char)s[i];
11795 	  if (si==226 || si==194)
11796 	    return gf;
11797 	}
11798 	// if (abs_calc_mode(contextptr)==38) return gensizeerr(gettext("Invalid float"));
11799 #endif
11800 	for (int i=0;i<l;++i){
11801 	  unsigned si=(unsigned char)s[i];
11802 	  if (si==226 || si==194)
11803 	    return undef;
11804 	}
11805 	return gen(string(s),contextptr);
11806       }
11807       return gen(d);
11808     } // end non integer if (*endchar)
11809     if (!errno ){
11810       // this converts 0xFFFFFFFF to -1, because we want two's complement, if possible
11811       // it makes positive numbers 0x80000000 to 0xFFFFFFFF unavailable (only in base-2 notation),
11812       // but I am aware of that
11813       if (ll==int(ll) ||
11814 	  ( (base == 2 ||base == 8 || base == 16) &&
11815 	    ll == (unsigned int)(ll) )
11816 	  )
11817 	return gen ( int(ll));
11818       else
11819 	return gen(longlong(ll));
11820     }
11821     // check if a non 0-9 char is there
11822     if (!base){
11823       base=10;
11824       for (int i=0;i<l;++i){
11825 	if ((s[i]<'0') || (s[i]>'9'))
11826 	  base=16;
11827       }
11828     }
11829     int maxsize = 5 + (s[0]=='-');
11830     if (base==10 && l<maxsize){
11831       res.type=_INT_;
11832       res.val = atoi(s);
11833       return res;
11834     }
11835     else {
11836       ref_mpz_t * ptr= new ref_mpz_t;
11837       mpz_set_str(ptr->z,s,base);
11838       res= gen(ptr);
11839       return res;
11840     }
11841   }
11842 
string2gen(const string & ss,bool remove_ss_quotes)11843   gen string2gen(const string & ss,bool remove_ss_quotes){
11844     gen res;
11845 #ifdef SMARTPTR64
11846     * ((ulonglong * ) &res) = ulonglong(new ref_string(remove_ss_quotes?ss.substr(1,ss.size()-2):ss)) << 16;
11847 #else
11848     res.__STRNGptr = new ref_string(remove_ss_quotes?ss.substr(1,ss.size()-2):ss);
11849 #endif
11850     res.type=_STRNG;
11851     return res;
11852   }
11853 
11854   int giac_yyparse(void * scanner);
11855 
try_parse(const string & s_orig,GIAC_CONTEXT)11856   static int try_parse(const string & s_orig,GIAC_CONTEXT){
11857     string s=s_orig;
11858     if (1 || abs_calc_mode(contextptr)!=38){
11859       // remove leading spaces
11860       for (int i=0;i<s.size();++i){
11861 	if (s[i]!=' '){
11862 	  if (i)
11863 	    s=s.substr(i,s.size()-i);
11864 	  break;
11865 	}
11866       }
11867       if (s.size()>10 && (s.substr(0,5)=="\"def " || s.substr(0,10)=="\"function ")){
11868 	string news="";
11869 	int ss=s.size()-1;
11870 	for (;ss>5;--ss){
11871 	  if (s[ss]=='"')
11872 	    break;
11873 	}
11874 	for (int i=1;i<ss;++i){
11875 	  char ch=s[i];
11876 	  if (ch==char(0xa)){
11877 	    news+='\n';
11878 	    continue;
11879 	  }
11880 	  if (ch=='"' && s[i+1]=='"')
11881 	    ++i;
11882 	  if (ch=='`')
11883 	    news+='"';
11884 	  else
11885 	    news+=ch;
11886 	}
11887 	s=news;
11888       }
11889       s=python2xcas(s,contextptr);
11890       if (s.empty()){
11891 	parsed_gen(undef,contextptr);
11892 	return 1;
11893       }
11894     }
11895 #if !defined(WIN32) && defined(HAVE_PTHREAD_H)
11896     if (contextptr && thread_param_ptr(contextptr)->stackaddr && thread_param_ptr(contextptr)->stacksize/2){
11897       gen er;
11898       short int err=s.size();
11899       if (debug_infolevel>10000)
11900 	CERR << (size_t) &err << " " << ((size_t) thread_param_ptr(contextptr)->stackaddr)+4*65536 << '\n';
11901       if ( ((size_t) &err) < ((size_t) thread_param_ptr(contextptr)->stackaddr)+4*65536){
11902 	gensizeerr(gettext("Too many recursion levels"),er);
11903 	parsed_gen(er,contextptr);
11904 	return 1;
11905       }
11906     }
11907 #endif // pthread
11908     int res;
11909     int isqrt=i_sqrt_minus1(contextptr);
11910 #ifndef NO_STDEXCEPT
11911     try {
11912 #endif
11913       void * scanner;
11914       YY_BUFFER_STATE state=set_lexer_string(s,scanner,contextptr);
11915       if (xcas_mode(contextptr)==0 && try_parse_i(contextptr))
11916 	i_sqrt_minus1(0,contextptr);
11917       res=giac_yyparse(scanner);
11918       delete_lexer_string(state,scanner);
11919       // if xcas_mode(contextptr)<=0 scan for i:=something, if not present replace i by sqrt(-1)
11920       if (xcas_mode(contextptr)==0 && try_parse_i(contextptr)){
11921 	const gen& p = parsed_gen(contextptr);
11922 	if (1) { // p.type==_SYMB || p.type==_VECT){
11923 	  vecteur v(rlvarx(p,i__IDNT_e));
11924 	  if (!v.empty()){
11925 	    vecteur w=lop(v,at_program);
11926 	    int i,vs=int(w.size());
11927 	    for (i=0;i<vs;i++){
11928 	      gen & args = w[i]._SYMBptr->feuille;
11929 	      if (args.type!=_VECT || args._VECTptr->empty())
11930 		continue;
11931 	      if (contains(args._VECTptr->front(),i__IDNT_e)){
11932 		*logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11933 		return res;
11934 	      }
11935 	    }
11936 	    w=lop(v,at_local);
11937 	    vs=int(w.size());
11938 	    for (i=0;i<vs;i++){
11939 	      gen & args = w[i]._SYMBptr->feuille;
11940 	      if (args.type!=_VECT || args._VECTptr->empty())
11941 		continue;
11942 	      if (contains(args._VECTptr->front(),i__IDNT_e)){
11943 		*logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11944 		return res;
11945 	      }
11946 	    }
11947 	    v=lop(v,at_sto);
11948 	    vs=int(v.size());
11949 	    for (i=0;i<vs;i++){
11950 	      if (v[i]._SYMBptr->feuille[1]==i__IDNT_e){
11951 		*logptr(contextptr) << gettext("Warning, i is usually sqrt(-1), I'm using a symbolic variable instead but you should check your input") << '\n';
11952 		break;
11953 	      }
11954 	    }
11955 	    if (i==vs){
11956 #ifndef NSPIRE
11957 	      my_ostream * log = logptr(contextptr);
11958 	      logptr(0,contextptr);
11959 #endif
11960 	      i_sqrt_minus1(1,contextptr);
11961 	      void * scanner2;
11962 	      YY_BUFFER_STATE state2=set_lexer_string(s,scanner2,contextptr);
11963 	      res=giac_yyparse(scanner2);
11964 #ifndef NSPIRE
11965 	      logptr(log,contextptr);
11966 #endif
11967 	      delete_lexer_string(state2,scanner2);
11968 	    }
11969 	  }
11970 	}
11971       } // end if (xcas_mode(contextptr)==0 ...
11972 #ifndef NO_STDEXCEPT
11973     }
11974     catch (std::runtime_error & error){
11975       i_sqrt_minus1(isqrt,contextptr);
11976      if (!first_error_line(contextptr))
11977 	first_error_line(lexer_line_number(contextptr),contextptr);
11978       parser_error(error.what(),contextptr);
11979 #ifdef HAVE_SIGNAL_H_OLD
11980       messages_to_print += string(error.what()) + '\n';
11981 #endif
11982       return 1;
11983     }
11984 #endif
11985     i_sqrt_minus1(isqrt,contextptr);
11986     return res;
11987   }
11988 
aplatir_plus(const gen & g)11989   static gen aplatir_plus(const gen & g){
11990     // Quick check for embedded + at the left coming from parser
11991     if (g.is_symb_of_sommet(at_plus) && g._SYMBptr->feuille.type==_VECT){
11992       iterateur it=g._SYMBptr->feuille._VECTptr->begin(),itend=g._SYMBptr->feuille._VECTptr->end();
11993       if (it==itend)
11994 	return 0;
11995       vecteur v;
11996       v.reserve(itend-it+1);
11997       gen f;
11998       for (;it!=itend;){
11999 	for (--itend;itend!=it;--itend)
12000 	  v.push_back(aplatir_fois_plus(*itend));
12001 	if (!it->is_symb_of_sommet(at_plus)){
12002 	  v.push_back(aplatir_fois_plus(*it));
12003 	  break;
12004 	}
12005 	f=it->_SYMBptr->feuille;
12006 	if (f.type!=_VECT){
12007 	  v.push_back(*it);
12008 	  break;
12009 	}
12010 	it=f._VECTptr->begin();
12011 	itend=f._VECTptr->end();
12012       }
12013       reverse(v.begin(),v.end());
12014       return new_ref_symbolic(symbolic(at_plus,gen(v,_SEQ__VECT)));
12015     }
12016     return g;
12017   }
12018 
aplatir_fois_plus(const gen & g)12019   gen aplatir_fois_plus(const gen & g){
12020     if (g.type==_VECT){
12021       vecteur v(*g._VECTptr);
12022       iterateur it=v.begin(),itend=v.end();
12023       for (;it!=itend;++it)
12024 	*it=aplatir_fois_plus(*it);
12025       return gen(v,g.subtype);
12026     }
12027     if (g.type!=_SYMB)
12028       return g;
12029     if (g._SYMBptr->sommet==at_pow && g._SYMBptr->feuille.type==_VECT && g._SYMBptr->feuille.subtype!=_SEQ__VECT)
12030       return symbolic(at_pow,change_subtype(g._SYMBptr->feuille,_SEQ__VECT));
12031     if (g._SYMBptr->sommet==at_plus)
12032       return aplatir_plus(g);
12033     gen & f=g._SYMBptr->feuille;
12034     if (g._SYMBptr->sommet==at_prod && f.type==_VECT && f._VECTptr->size()==2)
12035       return sym_mult(aplatir_fois_plus(f._VECTptr->front()),aplatir_fois_plus(f._VECTptr->back()),context0);
12036     return new_ref_symbolic(symbolic(g._SYMBptr->sommet,aplatir_fois_plus(f)));
12037   }
12038 
aplatir_plus_only(const gen & g)12039   static gen aplatir_plus_only(const gen & g){
12040     if (g.type==_VECT){
12041       const vecteur & v=*g._VECTptr;
12042       vecteur w(v);
12043       const_iterateur it=v.begin(),itend=v.end();
12044       iterateur jt=w.begin();
12045       for (;it!=itend;++jt,++it)
12046 	*jt=aplatir_plus_only(*it);
12047       return gen(w,g.subtype);
12048     }
12049     if (g.type!=_SYMB)
12050       return g;
12051     // Quick check for embedded + at the left coming from parser
12052     if (g.is_symb_of_sommet(at_plus) && g._SYMBptr->feuille.type==_VECT){
12053       const_iterateur it=g._SYMBptr->feuille._VECTptr->begin(),itend=g._SYMBptr->feuille._VECTptr->end();
12054       if (it==itend)
12055 	return 0;
12056       vecteur v;
12057       v.reserve(itend-it+1);
12058       register const gen * f;
12059       for (;it!=itend;){
12060 	for (--itend;itend!=it;--itend)
12061 	  v.push_back(*itend);
12062 	// Check first element of the vector g, if it's not a + add it to v and end
12063 	if (it->type!=_SYMB || it->_SYMBptr->sommet!=at_plus || (f=&it->_SYMBptr->feuille,f->type!=_VECT) ){
12064 	  v.push_back(*it);
12065 	  break;
12066 	}
12067 	// first element was a plus, restart with all it's arguments
12068 	itend=f->_VECTptr->end();
12069 	it=f->_VECTptr->begin();
12070       }
12071       reverse(v.begin(),v.end());
12072       return gen(new_ref_symbolic(symbolic(at_plus,gen(v,_SEQ__VECT)))).change_subtype(g.subtype);
12073     }
12074     return gen(new_ref_symbolic(symbolic(g._SYMBptr->sommet,aplatir_plus_only(g._SYMBptr->feuille)))).change_subtype(g.subtype);
12075   }
12076 
protected_giac_yyparse(const string & chaine,gen & parse_result,GIAC_CONTEXT)12077   static int protected_giac_yyparse(const string & chaine,gen & parse_result,GIAC_CONTEXT){
12078     int s;
12079     s=int(chaine.size());
12080     if (!s)
12081       return 1;
12082 #ifdef HAVE_LIBPTHREAD
12083     static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER;
12084     int locked = pthread_mutex_lock(&parse_mutex);
12085 #else // HAVE_LIBPTHREAD
12086     int locked = 0;
12087 #endif
12088     int res = 1;
12089 #ifndef NO_STDEXCEPT
12090     try {
12091 #endif
12092       res=try_parse(chaine,contextptr);
12093       gen g=parsed_gen(contextptr);
12094       if (g.type<=_FLOAT_){
12095 	parse_result=aplatir_plus_only(g);
12096 	// parse_result=aplatir_fois_plus(g);
12097 	if (g.type==_SYMB && parse_result.type==_SYMB)
12098 	  parse_result.subtype=g.subtype;
12099 #ifdef HAVE_LIBPTHREAD
12100         if (!locked)
12101           pthread_mutex_unlock(&parse_mutex);
12102 #endif
12103 	return res;
12104       }
12105       parsed_gen(0,contextptr);
12106       parse_result.type=0;
12107       parse_result=0;
12108       CERR << "Incomplete parse" << '\n';
12109 #ifdef HAVE_LIBPTHREAD
12110       if (!locked)
12111         pthread_mutex_unlock(&parse_mutex);
12112 #endif
12113 #ifndef NO_STDEXCEPT
12114     } catch (std::runtime_error &e) {
12115 #ifdef HAVE_LIBPTHREAD
12116       if (!locked)
12117         pthread_mutex_unlock(&parse_mutex);
12118 #endif
12119     }
12120 #endif // exception
12121      return res;
12122   }
12123 
gen(const string & s,GIAC_CONTEXT)12124   gen::gen(const string & s,GIAC_CONTEXT){
12125     subtype=0;
12126     string ss(s);
12127     /*
12128       string::iterator it=ss.begin(),itend=ss.end();
12129       for (;it!=itend;++it)
12130       if (*it=='\\')
12131       *it=' ';
12132       */
12133     type=_INT_;
12134     if (s==string(s.size(),' ')){
12135       *this=undef;
12136       return;
12137     }
12138     if (protected_giac_yyparse(s,*this,contextptr)){
12139       if (ss.empty())
12140 	ss="""""";
12141       if (ss[0]!='"')
12142 	ss = '"'+ss;
12143       if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12144 	ss += '"';
12145 #ifdef SMARTPTR64
12146       * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12147       subtype=0;
12148 #else
12149       __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12150 #endif
12151       type=_STRNG;
12152     }
12153   }
12154 
genfromstring(const string & s)12155   gen genfromstring(const string & s){
12156     return gen(s,context0);
12157   }
12158 
12159   /*
12160   gen::gen(const string & s,const vecteur & l,GIAC_CONTEXT){
12161     type=_INT_;
12162     if (protected_giac_yyparse(s,*this,contextptr)){
12163       string ss(s);
12164       if (ss.empty())
12165 	ss="""""";
12166       if (ss[0]!='"')
12167 	ss = '"'+ss;
12168       if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12169 	ss += '"';
12170 #ifdef SMARTPTR64
12171       * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12172 #else
12173       __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12174 #endif
12175       type=_STRNG;
12176     }
12177     subtype=0;
12178   }
12179   */
12180 
gen(const wchar_t * ws,GIAC_CONTEXT)12181   gen::gen(const wchar_t * ws,GIAC_CONTEXT){
12182     size_t l=0;
12183     const wchar_t * ptr=ws;
12184     for (;*ptr;++ptr){ ++l; }
12185     char * line=new char[4*l+1];
12186     unicode2utf8(ws,line,int(l));
12187     string ss(line);
12188     delete [] line;
12189     subtype=0;
12190     type=_INT_;
12191     if (ss==string(ss.size(),' ')){
12192       *this=undef;
12193       return;
12194     }
12195 #ifdef HAVE_SSTREAM
12196     ostringstream warnstream;
12197 #endif // HAVE_SSTREAM
12198 #ifndef NSPIRE
12199     my_ostream * oldptr = logptr(contextptr);
12200 #ifdef WITH_MYOSTREAM
12201     my_ostream newptr(&warnstream);
12202     logptr(&newptr,contextptr);
12203 #else
12204 #if !defined HAVE_SSTREAM || defined NSPIRE
12205     logptr(&COUT,contextptr);
12206 #else
12207 #ifndef KHICAS
12208     logptr(&warnstream,contextptr);
12209 #endif
12210 #endif // HAVE_SSTREAM
12211 #endif // WITH_MYIOSTREAM
12212 #endif // NSPIRE
12213     if (protected_giac_yyparse(ss,*this,contextptr)){
12214       if (ss.empty())
12215 	ss="""""";
12216       if (ss[0]!='"')
12217 	ss = '"'+ss;
12218       if ((ss.size()==1) || (ss[ss.size()-1]!='"'))
12219 	ss += '"';
12220 #ifdef SMARTPTR64
12221       * ((ulonglong * ) this) = ulonglong(new ref_string(ss.substr(1,ss.size()-2))) << 16;
12222       subtype=0;
12223 #else
12224       __STRNGptr = new ref_string(ss.substr(1,ss.size()-2));
12225 #endif
12226       type=_STRNG;
12227     }
12228 #ifndef NSPIRE
12229     logptr(oldptr,contextptr);
12230 #endif
12231 #if !defined HAVE_SSTREAM || defined NSPIRE
12232 #else
12233     if (!warnstream.str().empty())
12234       parser_error(warnstream.str(),contextptr);
12235 #endif
12236   }
12237 
12238   /* I/O: Print routines */
sprint_int(char * s,int r)12239 int sprint_int(char * s,int r){
12240   char * ptr=s;
12241   if (r<0){
12242     *ptr='-';
12243     ++ptr;
12244     r=-r;
12245   }
12246   int i;
12247   if (r==0){
12248     *ptr='0';
12249     *(ptr+1)=0;
12250     return 1;
12251   }
12252   *(ptr+10)=0;
12253   for (i=9;r;--i){
12254     *(ptr+i)='0'+r%10;
12255     r/=10;
12256   }
12257   ++i;
12258   if (i>0){ // shift left i char
12259     char * buf;
12260     for (buf=ptr+i;buf<=ptr+9;++buf){
12261       *(buf-i)=*buf;
12262     }
12263     *(buf-i)=0;
12264     ptr=buf-i;
12265   }
12266   else
12267     ptr += 10;
12268   return ptr-s;
12269 }
12270 
sprint_double(char * s,double d)12271 void sprint_double(char * s,double d){
12272   char * buf=s;
12273   if (d==0){
12274     strcpy(buf,"0.0");
12275     return;
12276   }
12277   if (d<0){
12278     *buf='-';
12279     ++buf;
12280     d=-d;
12281   }
12282   int i=d;
12283   if (i==d && d<1e9){
12284     sprint_int(buf,i);
12285     return;
12286   }
12287   for (i=0;i<280 && d>=1.0;i+=14){
12288     d=d*1e-14;
12289   }
12290   for (;i>-280 && d<1.0;i-=14){
12291     d=d*1e14;
12292   }
12293   for (;i<310 && d>=1.0;++i){
12294     d=d*.1;
12295   }
12296   if (i==310){
12297     strcpy(buf,"inf");
12298     return;
12299   }
12300   for (;i>-310 && d<1.0;--i){
12301     d=d*10;
12302   }
12303   if (i==-310){
12304     strcpy(buf,"0.0");
12305     return;
12306   }
12307   // 1.0<=d<10, d*10^i
12308   d=d/10; ++i; // 0.1<=d<1, d*10^i
12309   *buf='.';
12310   char * ptr=buf;
12311   ++buf;
12312   int r=(int)(d*1e9+.5);
12313   if (r>=1e9){
12314     r=r/10;
12315     ++i;
12316   }
12317   buf += sprint_int(buf,r);
12318   if (i>0 && i<7){
12319     // move . i positions to the right
12320     for (int j=0;j<i;++j){
12321       *ptr=*(ptr+1);
12322       ++ptr;
12323     }
12324     *ptr='.';
12325     i=0;
12326   }
12327   for (;;--buf){
12328     char ch=*(buf-1);
12329     if (ch!='0'){
12330       *buf=0;
12331       break;
12332     }
12333   }
12334   if (i!=0){
12335     if (!os_shell){
12336       *buf='*';
12337       ++buf;
12338       *buf='1';
12339       ++buf;
12340       *buf='0';
12341       ++buf;
12342       *buf='^';
12343       ++buf;
12344     } else {
12345       *buf='e';
12346       ++buf;
12347     }
12348     sprint_int(buf,i);
12349   }
12350 }
12351 
print_DOUBLE_(double d,GIAC_CONTEXT)12352   string print_DOUBLE_(double d,GIAC_CONTEXT){
12353 #if defined KHICAS && !defined NSPIRE_NEWLIB
12354     {
12355       char s[256];
12356       sprint_double(s,d);
12357       return s;
12358     }
12359 #endif
12360     if (my_isnan(d))
12361       return calc_mode(contextptr)==1?"?":"undef";
12362     if (my_isinf(d))
12363       return "infinity";
12364 #ifdef BCD
12365     if (bcd_printdouble(contextptr))
12366       return print_FLOAT_(giac_float(d),contextptr);
12367 #endif
12368 #ifndef DOUBLEVAL
12369     // roundoff
12370     unsigned char * u = (unsigned char *)(&d);
12371     *u &= 0xe0;
12372 #endif
12373     if (d<0 && calc_mode(contextptr)==38)
12374       return "−"+print_DOUBLE_(-d,contextptr);
12375     string & forme=format_double(contextptr);
12376     if (!forme.empty()){
12377       char ch=forme[0];
12378       if (tolower(ch)!='g' && tolower(ch)!='a' && tolower(ch)!='f' && tolower(ch)!='e' )
12379 	ch='g';
12380       if (calc_mode(contextptr)==1)
12381 	ch=toupper(ch);
12382       if (forme.size()<2 || forme.size()>3 || forme[1]<'0' || forme[1]>'9' || (forme.size()==3 && forme[2]<'0' && forme[2]>'9'))
12383 	return "invalid format";
12384       if (my_isnan(d))
12385 	return "undef";
12386       if (my_isinf(d))
12387 	return "infinity";
12388       char s[256];
12389       string f2=string("%.")+forme.substr(1,forme.size()-1)+ch;
12390       sprintfdouble(s,f2.c_str(),d);
12391       return s;
12392     }
12393     if (xcas_mode(contextptr)==3 && double(int(d))==d)
12394       return print_INT_(int(d));
12395     char s[256];
12396 #ifdef SOFTMATH
12397     sprintfdouble(s,"%.14g",d);
12398     return s;
12399 #else
12400     string form("%."+print_INT_(giacmin(decimal_digits(contextptr),14)));
12401     int sf=scientific_format(contextptr);
12402     switch (sf){
12403     case 0: case 2:
12404       if (abs_calc_mode(contextptr)==38)
12405 	form += 'G';
12406       else
12407 	form += "g";
12408       break;
12409     case 1:
12410       form += "e"; // or "f" ??
12411       break;
12412     case 3:
12413       form += "a";
12414     }
12415     if (calc_mode(contextptr)==1)
12416       form[form.size()-1]=toupper(form[form.size()-1]);
12417     if (sf==2){
12418       // engineering format
12419       int ndigits=int(giac_floor(std::log10(d)+0.5));
12420       ndigits = 3*(ndigits /3);
12421       sprintfdouble(s,form.c_str(),d/std::pow(10.0,ndigits));
12422       return s+("e"+print_INT_(ndigits));
12423     }
12424     sprintfdouble(s,form.c_str(),d);
12425     // 1073741824=2^30, fixme always try with a .0 for large numbers if longfloat not available?
12426     if (sf
12427 #if 1 // def HAVE_LIBMPFR
12428 	|| d>=1073741824 || d<=-1073741824
12429 #endif
12430 	)
12431       return s;
12432     for (int i=0;s[i];++i){
12433       if (s[i]=='.' || s[i]==',' || s[i]=='e' || s[i]=='E')
12434 	return s;
12435     }
12436     return string(s)+".0";
12437 #endif
12438   }
12439 
maptoarray(const gen_map & m,GIAC_CONTEXT)12440   gen maptoarray(const gen_map & m,GIAC_CONTEXT){
12441     vecteur res;
12442     gen_map::const_iterator it=m.begin(),itend=m.end();
12443     if (it==itend)
12444       return gendimerr(gettext("Empty array"));
12445     gen_map::const_reverse_iterator lastit=m.rbegin();
12446     // find index ranges
12447     gen premidx=it->first,lastidx=lastit->first;
12448     if (premidx.type!=_VECT || lastidx.type!=_VECT)
12449       return gentypeerr(gettext("Bad array indexes"));
12450     vecteur & pv=*premidx._VECTptr;
12451     vecteur & lv=*lastidx._VECTptr;
12452     unsigned ps=unsigned(pv.size());
12453     vector<int> indexes(ps);
12454     if (ps==0)
12455       return res;
12456     if (lv.size()!=ps )
12457       return gendimerr(contextptr);
12458     for (unsigned i=0;i<ps;++i){
12459       res.push_back(symb_interval(pv[i]+array_start(contextptr),lv[i]+array_start(contextptr))); // res.push_back(symb_interval(pv[i]+(xcas_mode(contextptr)!=0),lv[i]+(xcas_mode(contextptr)!=0)));
12460       if (lv[i].type!=_INT_ || pv[i].type!=_INT_ || lv[i].val<pv[i].val)
12461 	return gendimerr(contextptr);
12462       indexes[i]=(lv[i]-pv[i]).val+1;
12463     }
12464     if (ps==1){
12465       vecteur tmp;
12466       for (;it!=itend;++it){
12467 	tmp.push_back(it->second);
12468       }
12469       res.push_back(tmp);
12470     }
12471     else {
12472       vecteur tmp(indexes[ps-1]);
12473       for (int i=ps-2;i>=0;--i){
12474 	vecteur newtmp;
12475 	for (int j=0;j<indexes[i];++j)
12476 	  newtmp.push_back(tmp);
12477 	tmp=newtmp;
12478       }
12479       gen tab=tmp;
12480       for (;it!=itend;++it){
12481 	gen * tmpptr=&tab;
12482 	if (tmpptr->type!=_VECT)
12483 	  return gendimerr(contextptr);
12484 	for (unsigned i=0;i<ps;++i){
12485 	  int pos=(it->first[i]-pv[i]).val;
12486 	  if (pos<0 || unsigned(pos)>=tmpptr->_VECTptr->size())
12487 	    return gendimerr(contextptr);
12488 	  tmpptr=&((*tmpptr->_VECTptr)[pos]);
12489 	}
12490 	*tmpptr = it->second;
12491       }
12492       res.push_back(tmp);
12493     }
12494     return new_ref_symbolic(symbolic(at_array,res));
12495   }
12496 
printmap(const gen_map & m,GIAC_CONTEXT)12497   static string printmap(const gen_map & m,GIAC_CONTEXT){
12498     string s("table(\n");
12499     gen_map::const_iterator it=m.begin(),itend=m.end();
12500     for (;it!=itend;){
12501       gen bb=it->first;
12502       if (bb.type!=_STRNG && array_start(contextptr)){
12503 	if (bb.type==_VECT)
12504 	  bb=bb+vecteur(bb._VECTptr->size(),plus_one);
12505 	else
12506 	  bb=bb+plus_one;
12507       }
12508       if (bb.type==_VECT && bb.subtype==_SEQ__VECT)
12509 	s+='(';
12510       s += bb.print(contextptr);
12511       if (bb.type==_VECT && bb.subtype==_SEQ__VECT)
12512 	s+=')';
12513       s += " = " + it->second.print(contextptr);
12514       ++it;
12515       if (it!=itend)
12516 	s += ',';
12517       s += '\n';
12518     }
12519     return s+")";
12520   }
12521 
printmpf_t(const mpf_t & inf,GIAC_CONTEXT)12522   std::string printmpf_t(const mpf_t & inf,GIAC_CONTEXT){
12523 #ifndef USE_GMP_REPLACEMENTS
12524 #ifdef VISUALC
12525     char * ptr=new char[decimal_digits(contextptr)+30];
12526 #else
12527     char ptr[decimal_digits(contextptr)+30];
12528 #endif
12529     bool negatif=mpf_sgn(inf)<0;
12530     mp_exp_t expo;
12531     if (negatif){
12532       mpf_t inf2;
12533       mpf_init(inf2);
12534       mpf_neg(inf2,inf);
12535       mpf_get_str(ptr,&expo,10,decimal_digits(contextptr),inf2);
12536       mpf_clear(inf2);
12537     }
12538     else
12539       mpf_get_str(ptr,&expo,10,decimal_digits(contextptr),inf);
12540     std::string res(ptr),reste(res.substr(1,res.size()-1));
12541 #ifdef VISUALC
12542     delete [] ptr;
12543 #endif
12544     res=res[0]+("."+reste);
12545     if (expo!=1)
12546       res += "e"+print_INT_(expo-1);
12547     if (negatif)
12548       return "-"+res;
12549     else
12550       return res;
12551 #else // USE_GMP_REPLACEMENTS
12552 #if defined NSPIRE || defined FXCG || defined KHICAS
12553     return "mpf_t not implemented";
12554 #else
12555     std::ostringstream out;
12556 #ifdef LONGFLOAT_DOUBLE
12557     out << std::setprecision(decimal_digits(contextptr)) << inf;
12558 #else
12559     out << std::setprecision(decimal_digits(contextptr)) << *inf;
12560 #endif
12561     return out.str();
12562 #endif // NSPIRE
12563 #endif // USE_GMP_REPLACEMENTS
12564   }
12565 
12566 
print_ZINT(const mpz_t & a)12567   string print_ZINT(const mpz_t & a){
12568     /*
12569     char * s =mpz_get_str (NULL, 10,a) ;
12570     string res(s);
12571     free(s);
12572     return res;
12573     */
12574     size_t l=mpz_sizeinbase (a, 10) + 2;
12575     if (l>unsigned(MAX_PRINTABLE_ZINT))
12576       return "Integer_too_large_for_display";
12577 #if defined( VISUALC ) || defined( BESTA_OS )
12578     ALLOCA(char, s, l); //s = ( char * )alloca( l );
12579 #else
12580     char s[l];
12581 #endif
12582     mpz_get_str (s, 10,a) ;
12583     string tmp(s);
12584 
12585     return tmp;
12586   }
12587 
hexa_print_ZINT(const mpz_t & a)12588   string hexa_print_ZINT(const mpz_t & a){
12589     size_t l=mpz_sizeinbase (a, 16) + 2;
12590     if (l>unsigned(MAX_PRINTABLE_ZINT))
12591       return "Integer_too_large";
12592 #if defined( VISUALC ) || defined( BESTA_OS )
12593     ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12594 #else
12595     char s[l];
12596 #endif
12597     string res("0x");
12598 #ifdef USE_GMP_REPLACEMENTS
12599     if (mpz_sgn(a) == -1){
12600       mpz_t tmpint;
12601       mpz_init(tmpint);
12602       mpz_neg(tmpint, a);
12603       mpz_get_str(s,16,tmpint);
12604       mpz_clear(tmpint);
12605 
12606       res = "-" + res + s;
12607     }
12608     else {
12609       mpz_get_str(s,16,a);
12610       res += s;
12611     }
12612 #else
12613     mpz_get_str (s,16,a) ;
12614     res += s;
12615 #endif // USE_GMP_REPLACEMENTS
12616 
12617     return res;
12618   }
12619 
octal_print_ZINT(const mpz_t & a)12620   string octal_print_ZINT(const mpz_t & a){
12621     size_t l=mpz_sizeinbase (a, 8) + 2;
12622     if (l>unsigned(MAX_PRINTABLE_ZINT))
12623       return "Integer_too_large";
12624 #if defined( VISUALC ) || defined( BESTA_OS )
12625     ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12626 #else
12627     char s[l];
12628 #endif
12629     string res("0");
12630 #ifdef USE_GMP_REPLACEMENTS
12631     if (mpz_sgn(a) == -1){
12632       mpz_t tmpint;
12633       mpz_init(tmpint);
12634       mpz_neg(tmpint, a);
12635       mpz_get_str(s,8,tmpint);
12636       mpz_clear(tmpint);
12637       res = "-" + res + s;
12638     }
12639     else {
12640       mpz_get_str(s,8,a);
12641       res += s;
12642     }
12643 #else
12644     mpz_get_str (s,8,a) ;
12645     res += s;
12646 #endif // USE_GMP_REPLACEMENTS
12647 
12648     return res;
12649   }
12650 
binary_print_ZINT(const mpz_t & a)12651   string binary_print_ZINT(const mpz_t & a){
12652     size_t l=mpz_sizeinbase (a, 2) + 2;
12653     if (l>unsigned(MAX_PRINTABLE_ZINT))
12654       return "Integer_too_large";
12655 #if defined( VISUALC ) || defined( BESTA_OS )
12656     ALLOCA(char, s, l);//char * s = ( char * )alloca( l );
12657 #else
12658     char s[l];
12659 #endif
12660     string res("0b");
12661 #ifdef USE_GMP_REPLACEMENTS
12662     if (mpz_sgn(a) == -1){
12663       mpz_t tmpint;
12664       mpz_init(tmpint);
12665       mpz_neg(tmpint, a);
12666       mpz_get_str(s,2,tmpint);
12667       mpz_clear(tmpint);
12668       res = "-" + res + s;
12669     }
12670     else {
12671       mpz_get_str(s,2,a);
12672       res += s;
12673     }
12674 #else
12675     mpz_get_str (s,2,a) ;
12676     res += s;
12677 #endif // USE_GMP_REPLACEMENTS
12678 
12679     return res;
12680   }
12681 
printinner_VECT(const vecteur & v,int subtype,GIAC_CONTEXT)12682   string printinner_VECT(const vecteur & v, int subtype,GIAC_CONTEXT){
12683     string s;
12684     return add_printinner_VECT(s,v,subtype,contextptr);
12685   }
12686 
add_printinner_VECT(string & s,const vecteur & v,int subtype,GIAC_CONTEXT)12687   string & add_printinner_VECT(string & s,const vecteur &v,int subtype,GIAC_CONTEXT){
12688     vecteur::const_iterator it=v.begin(), itend=v.end();
12689     if (it==itend)
12690       return s;
12691     for(;;){
12692       if ( (subtype==_RPN_FUNC__VECT) && (it->type==_SYMB) && (it->_SYMBptr->sommet==at_quote))
12693 	s += "'"+it->_SYMBptr->feuille.print(contextptr)+"'";
12694       else {
12695 	if ( (it->type==_SYMB && it->_SYMBptr->sommet==at_sto)
12696 	     // || (it->type==_VECT && it->subtype==_SEQ__VECT && it->_VECTptr->size()>=2)
12697 	     )
12698 	  s += "("+it->print(contextptr)+")";
12699 	else
12700 	  add_print(s,*it,contextptr); // s += it->print(contextptr);
12701       }
12702       ++it;
12703       if (it==itend){
12704 	return s;
12705       }
12706       if ( (subtype!=_RPN_FUNC__VECT) &&
12707 	   //	   (subtype || (!rpn_mode(contextptr)) ) &&
12708 	   ( ((it-1)->type!=_SYMB) || ((it-1)->_SYMBptr->sommet!=at_comment) )
12709 	   )
12710 	s += ',';
12711       else
12712 	s += ' ';
12713     }
12714   }
12715 
begin_VECT_string(int subtype,bool tex,GIAC_CONTEXT)12716   string begin_VECT_string(int subtype,bool tex,GIAC_CONTEXT){
12717     string s;
12718     switch (subtype){
12719     case _SEQ__VECT:
12720       break;
12721     case _SET__VECT:
12722       if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1){
12723 	if (tex)
12724 	  s+="\\{";
12725 	else
12726 	  s="{";
12727       }
12728       else
12729 	s="set[";
12730       break;
12731     case _RPN_STACK__VECT:
12732       s="stack(";
12733       break;
12734     case _RPN_FUNC__VECT:
12735       s="<< ";
12736       break;
12737     case _GROUP__VECT:
12738       s="group[";
12739       break;
12740 #ifdef HAVE_LIBMPFI
12741     case _INTERVAL__VECT:
12742       s="i[";
12743       break;
12744 #endif
12745     case _LINE__VECT:
12746       s="line[";
12747       break;
12748     case _VECTOR__VECT:
12749       s="vector[";
12750       break;
12751     case _GGBVECT:
12752       s=(calc_mode(contextptr)==1?"ggbvect(":"ggbvect[");
12753       break;
12754 #ifndef EMCC
12755     case _LOGO__VECT:
12756       s="logo[";
12757       break;
12758 #endif
12759     case _PNT__VECT:
12760       s="pnt[";
12761       break;
12762     case _POINT__VECT:
12763       s="point[";
12764       break;
12765     case _TUPLE__VECT:
12766       s="tuple[";
12767       break;
12768     case _MATRIX__VECT:
12769       if (calc_mode(contextptr)==1)
12770 	s="{";
12771       else {
12772 	// s="matrix[";
12773 	if (!os_shell)
12774 	  s="[";
12775 	else
12776 	  s=abs_calc_mode(contextptr)==38?"[":"matrix[";
12777       }
12778       break;
12779     case _POLY1__VECT:
12780       if (!os_shell)
12781 	s="[";
12782       else
12783 	s="poly1[";
12784       break;
12785     case _ASSUME__VECT:
12786       s = "assume[";
12787       break;
12788     case _FOLDER__VECT:
12789       s = "folder[";
12790       break;
12791     case _POLYEDRE__VECT:
12792       s= "polyedre[";
12793       break;
12794     case _RGBA__VECT:
12795       s= "rgba[";
12796       break;
12797     case _LIST__VECT:
12798       if (!os_shell)
12799 	s="[";
12800       else {
12801 	if (tex)
12802 	  s="\\{";
12803 	else
12804 	  s=abs_calc_mode(contextptr)==38?"{":"list[";
12805       }
12806       break;
12807     case _GGB__VECT:
12808       if (calc_mode(contextptr)==1)
12809 	s="("; // warning: can not be reparsed from giac
12810       else
12811 	s="ggbpnt[";
12812       break;
12813     case _TABLE__VECT:
12814       s="{/";
12815       break;
12816     default:
12817       s=calc_mode(contextptr)==1?"{":"[";
12818     }
12819     return s;
12820   }
12821 
end_VECT_string(int subtype,bool tex,GIAC_CONTEXT)12822   string end_VECT_string(int subtype,bool tex,GIAC_CONTEXT){
12823     string s;
12824     switch (subtype){
12825     case _SEQ__VECT:
12826       return s;
12827     case _SET__VECT:
12828       if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1){
12829 	if (tex)
12830 	  return "\\}";
12831 	else
12832 	  return "}";
12833       }
12834       else
12835 	return "]";
12836     case _RPN_STACK__VECT:
12837       return ")";
12838     case _RPN_FUNC__VECT:
12839       return " >>";
12840     case _LIST__VECT:
12841       if (tex)
12842 	return "\\}";
12843       else
12844 	return abs_calc_mode(contextptr)==38?"}":"]";
12845     case _GGB__VECT:
12846       if (calc_mode(contextptr)==1)
12847 	return ")";
12848       else
12849 	return "]";
12850     case _POINT__VECT: case _VECTOR__VECT: case _POLY1__VECT: case _PNT__VECT:
12851       return "]";
12852     case _GGBVECT:
12853       return calc_mode(contextptr)==1?")":"]";
12854     case 0: case _MATRIX__VECT:
12855       return calc_mode(contextptr)==1?"}":"]";
12856     case _TABLE__VECT:
12857       return "/}";
12858     default:
12859       return calc_mode(contextptr)==1?"}":"]";
12860     }
12861   }
12862 
svg2doutput(const gen & g,string & S,GIAC_CONTEXT)12863   const char * svg2doutput(const gen & g,string & S,GIAC_CONTEXT){
12864 #ifdef EMCC
12865     bool fullview=true;
12866     vector<double> vx,vy,vz;
12867     double window_xmin,window_xmax,window_ymin,window_ymax,window_zmin,window_zmax;
12868     bool ortho=autoscaleg(g,vx,vy,vz,contextptr);
12869     autoscaleminmax(vx,window_xmin,window_xmax,fullview);
12870     autoscaleminmax(vy,window_ymin,window_ymax,fullview);
12871     double xscale=window_xmax-window_xmin,yscale=window_ymax-window_ymin;
12872     double ratio=yscale/xscale;
12873     double gratio=0.6,gwidth=9;
12874 #ifndef GIAC_GGB
12875     gwidth=EM_ASM_DOUBLE_V({
12876 	var hw=window.innerWidth;
12877 	if (hw>=1000)
12878 	  return 9.0*hw/1000.0;
12879 	else
12880 	  return hw/60.0;
12881       });
12882 #endif // GIAC_GGB
12883     //CERR << gwidth << '\n';
12884     int maxgratio=ortho?10:3;
12885     if (ratio<gratio/maxgratio || ratio>maxgratio*gratio) ortho=false; else ortho=true;
12886     if (ortho){
12887       if (ratio>gratio){ // yscale>gratio*xscale, use yscale for x
12888 	double xc=(window_xmax+window_xmin)/2;
12889 	window_xmin=xc-yscale/(2*gratio);
12890 	window_xmax=xc+yscale/(2*gratio);
12891       }
12892       else { // xscale>yscale/gratio
12893 	double yc=(window_ymax+window_ymin)/2;
12894 	window_ymin=yc-gratio*xscale/2;
12895 	window_ymax=yc+gratio*xscale/2;
12896       }
12897       ratio=gratio;
12898       ortho=false;
12899     }
12900     bool axes=overwrite_viewbox(g,window_xmin,window_xmax,window_ymin,window_ymax,window_zmin,window_zmax);
12901     xscale=window_xmax-window_xmin;yscale=window_ymax-window_ymin;
12902     ratio=yscale/xscale;
12903     //COUT << window_xmin << " " << window_xmax << " " << window_ymin << " " << window_ymax << '\n';
12904     //g=_symetrie(makesequence(_droite(makesequence(0,1),contextptr),g),contextptr);
12905     //S='"'+svg_preamble(7,7,gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax,ortho,false)+gen2svg(g,contextptr)+svg_grid(gnuplot_xmin,gnuplot_xmax,gnuplot_ymin,gnuplot_ymax)+"</svg>\"";
12906     S='"'+svg_preamble_pixel(g,gwidth,gwidth*gratio,window_xmin,window_xmax,window_ymin,window_ymax,ortho,false);
12907     plot_attr P;
12908     title_legende(g,P);
12909     S= S+(gen2svg(g,window_xmin,window_xmax,window_ymin,window_ymax,ratio/gratio,contextptr,false)+(axes?svg_grid(window_xmin,window_xmax,window_ymin,window_ymax,P)+"</svg>\"":""));
12910 #endif
12911     return S.c_str();
12912   }
12913 
print_VECT(const vecteur & v,int subtype,GIAC_CONTEXT)12914   string print_VECT(const vecteur & v,int subtype,GIAC_CONTEXT){
12915     if (v.empty()){
12916       switch (subtype){
12917       case _SEQ__VECT:
12918 	return xcas_mode(contextptr)==1?"NULL":"seq[]";
12919       case _SET__VECT:
12920 	if (xcas_mode(contextptr)>0 || calc_mode(contextptr)==1)
12921 	  return "{ }";
12922 	else
12923 	  return "set[ ]";
12924       case _RPN_FUNC__VECT:
12925         return "<< >>";
12926       case _RPN_STACK__VECT:
12927         return "stack()";
12928       }
12929     }
12930 #if 1 // for debugging/profiling pixon_print
12931     if (!v.empty() && is_pnt_or_pixon(v.back())){
12932       gen f=v.back();
12933       if (f.is_symb_of_sommet(at_pnt)){
12934 	f=f._SYMBptr->feuille;
12935 	if (f.type==_VECT)
12936 	  f=f._VECTptr->front();
12937       }
12938       if (f.is_symb_of_sommet(at_pixon)){
12939 	string S;
12940 	pixon_print(v,S,contextptr);
12941 	return S;
12942       }
12943     }
12944 #endif
12945     string s;
12946     if (subtype==_SPREAD__VECT && !v.empty() && v.front().type==_VECT){
12947 #ifdef EMCC
12948       bool add_quotes=true;
12949       s = "[";
12950 #else
12951       bool add_quotes=false;
12952       s = "spreadsheet[";
12953 #endif
12954       int nr=int(v.size());
12955       int nc=int(v.front()._VECTptr->size());
12956       for (int i=0;;){
12957 	int save_r,save_c;
12958 	vecteur & w=*v[i]._VECTptr;
12959 	s +='[';
12960 	for (int j=0;;){
12961 	  save_r=printcell_current_row(contextptr);
12962 	  save_c=printcell_current_col(contextptr);
12963 	  printcell_current_row(contextptr)=i;
12964 	  printcell_current_col(contextptr)=j;
12965 	  if (add_quotes){
12966 	    gen tmp=w[j];
12967 	    if (tmp.type==_VECT && tmp._VECTptr->size()>=2){
12968 	      vecteur & w=*tmp._VECTptr;
12969 	      s += "['"+w[0].print(contextptr)+"',";
12970 	      s += "'"+w[1].print(contextptr)+"',";
12971 	      // COUT << i << " " << j << " " << w[1] << '\n';
12972 	      if (w[1].type==_STRNG && *w[1]._STRNGptr=="")
12973 		s += "'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;']";
12974 	      else {
12975 		string ms;
12976 		if (w[1].is_symb_of_sommet(at_pnt)){
12977 		  svg2doutput(w[1],ms,contextptr); // remove quotes
12978 		  if (ms[0]=='"' && ms[ms.size()-1]=='"')
12979 		    ms=ms.substr(1,ms.size()-2);
12980 		}
12981 #ifndef GIAC_HAS_STO_38
12982 		else
12983 		  ms=*_mathml(makesequence(w[1],1),contextptr)._STRNGptr;
12984 #endif
12985 		string res;
12986 		int l=ms.size();
12987 		res.reserve(l);
12988 		const char * ch=ms.c_str();
12989 		for (int i=0;i<l;++i,++ch){
12990 		  res+= (*ch=='\n'? ' ': *ch);
12991 		}
12992 		s += "'&nbsp;"+res+"&nbsp;']";
12993 	      }
12994 	    }
12995 	    else
12996 	      s += w[j].print(contextptr);
12997 	  }
12998 	  else
12999 	    s += w[j].print(contextptr);
13000 	  printcell_current_row(contextptr)=save_r;
13001 	  printcell_current_col(contextptr)=save_c;
13002 	  ++j;
13003 	  if (j==nc)
13004 	    break;
13005 	  else
13006 	    s+=',';
13007 	}
13008 	s+=']';
13009 	++i;
13010 	if (i==nr)
13011 	  break;
13012 	else
13013 	  s+=',';
13014       }
13015       return s+']';
13016     }
13017     if ( ( subtype==_SEQ__VECT) && (v.size()==1) && !xcas_mode(contextptr))
13018       return "seq["+v.front().print(contextptr)+"]";
13019     else
13020       s=begin_VECT_string(subtype,false,contextptr);
13021     s += printinner_VECT(v,subtype,contextptr);
13022     return s+end_VECT_string(subtype,false,contextptr);
13023   }
13024 
print_SPOL1(const sparse_poly1 & p,GIAC_CONTEXT)13025   string print_SPOL1(const sparse_poly1 & p,GIAC_CONTEXT){
13026     if (p.empty())
13027       return "0";
13028     int sf=series_flags(contextptr);
13029     if (sf & (1<<5) && !(sf & (1<<4))){
13030       identificateur tt(string(1,series_variable_name(contextptr)));
13031       gen remains,g=sparse_poly12gen(p,tt,remains,!(sf & (1<<6)));
13032       if ( (sf & (1<<6)) && !is_zero(remains))
13033 	g += symb_of(gen(abs_calc_mode(contextptr)==38?"b":"O",contextptr),remains);
13034       return g.print(contextptr);
13035     }
13036     string s;
13037     sparse_poly1::const_iterator it=p.begin(), itend=p.end();
13038     bool paren=itend-it>1;
13039     if (paren) s+='(';
13040     for(;;){
13041       s += it->print(contextptr);
13042       ++it;
13043       if (it==itend){
13044 	if (paren)
13045 	  return s+')';
13046 	return s;
13047       }
13048       s += '+';
13049     }
13050   }
13051 
print_the_type(int val,GIAC_CONTEXT)13052   string print_the_type(int val,GIAC_CONTEXT){
13053     if (xcas_mode(contextptr)==1){
13054       switch(val){
13055       case _INT_:
13056 	return "integer";
13057       case _DOUBLE_:
13058 	return "double";
13059       case _FLOAT_:
13060 	return "float";
13061       case _ZINT:
13062 	return "integer";
13063       case _CPLX:
13064 	return "complex";
13065       case _VECT:
13066 	return "vector";
13067       case _IDNT:
13068 	return "symbol";
13069       case _SYMB:
13070 	return "algebraic";
13071       case _FRAC:
13072 	return "rational";
13073       case _MAPLE_LIST:
13074 	return "list";
13075       }
13076     }
13077     if (abs_calc_mode(contextptr)!=38){
13078       switch(val){
13079       case _DOUBLE_:
13080 	return "real";
13081       case _ZINT:
13082 	return "integer";
13083       case _CPLX:
13084 	return "complex";
13085       case _VECT:
13086 	return "vector";
13087       case _IDNT:
13088 	return "identifier";
13089       case _SYMB:
13090 	return "expression";
13091       case _FRAC:
13092 	return "rational";
13093       case _STRNG:
13094 	return "string";
13095       case _FUNC:
13096 	return "func";
13097       }
13098     }
13099     switch(val){
13100     case _INT_:
13101       return "DOM_int";
13102     case _DOUBLE_:
13103       return "DOM_FLOAT";
13104     case _FLOAT_:
13105       return "DOM_SPECIALFLOAT";
13106     case _ZINT:
13107       return "DOM_INT";
13108     case _CPLX:
13109       return "DOM_COMPLEX";
13110     case _VECT:
13111       return "DOM_LIST";
13112     case _IDNT:
13113       return "DOM_IDENT";
13114     case _SYMB:
13115       return "DOM_SYMBOLIC";
13116     case _FRAC:
13117       return "DOM_RAT";
13118     case _STRNG:
13119       return "DOM_STRING";
13120     case _FUNC:
13121       return "DOM_FUNC";
13122     case _REAL:
13123       return "DOM_LONGFLOAT";
13124     case _MAP:
13125       return "DOM_MAP";
13126     case _SPOL1:
13127       return "DOM_SERIES";
13128     }
13129     return print_INT_(val);
13130   }
13131 
print_STRNG(const string & s)13132   string print_STRNG(const string & s){
13133     string res("\"");
13134     int l=int(s.size());
13135     for (int i=0;i<l;++i){
13136       res += s[i];
13137       if (s[i]=='"')
13138 	res += '"';
13139     }
13140     return res+'"';
13141   }
13142 
printi(GIAC_CONTEXT)13143   const char * printi(GIAC_CONTEXT){
13144 #ifdef KHICAS
13145     return os_shell?"i":"��";
13146 #endif
13147     if (calc_mode(contextptr)==1)
13148       return "ί";
13149     if (abs_calc_mode(contextptr)==38)
13150       return ""; // "\xe2\x81\xb1";
13151     if (xcas_mode(contextptr)==3)
13152       return "\xa1";
13153     if (xcas_mode(contextptr)>0)
13154       return "I";
13155     else
13156       return "i";
13157   }
13158 
print_EQW(const eqwdata & e)13159   static string print_EQW(const eqwdata & e){
13160     string s;
13161     s += "eqwdata(position"+print_INT_(e.x)+","+print_INT_(e.y)+",dxdy,"+print_INT_(e.dx)+","+print_INT_(e.dy);
13162     s += ",font,"+print_INT_(e.eqw_attributs.fontsize);
13163     s += ",background," +print_INT_(e.eqw_attributs.background);
13164     s += ",text_color," +print_INT_(e.eqw_attributs.text_color)+",";
13165     if (e.selected)
13166       s +="selected,";
13167     if (e.active)
13168       s +="active,";
13169     s += e.g.print(context0)+")";
13170     return s;
13171   }
13172 
print() const13173   string gen::print() const{
13174     return print(context0);
13175   }
13176 
13177   // FIXME!!!
sprint(std::string * sptr,GIAC_CONTEXT) const13178   int gen::sprint(std::string * sptr,GIAC_CONTEXT) const{
13179     return 0;
13180   }
13181 
print_universal(GIAC_CONTEXT) const13182   string gen::print_universal(GIAC_CONTEXT) const{
13183     int lang=language(contextptr);
13184     language(-1,contextptr);
13185     string res;
13186 #ifdef NO_STDEXCEPT
13187     res=print(contextptr);
13188 #else
13189     try {
13190       res=print(contextptr);
13191     }
13192     catch (...){ }
13193 #endif
13194     language(lang,contextptr);
13195     return res;
13196   }
13197 
wprint(GIAC_CONTEXT) const13198   wchar_t * gen::wprint(GIAC_CONTEXT) const {
13199     string s=print(contextptr);
13200     unsigned int ss=unsigned(s.size());
13201     wchar_t * ptr = (wchar_t *) malloc(sizeof(wchar_t)*(ss+1));
13202     /*
13203     unsigned int l=utf82unicode(s.c_str(),ptr,ss);
13204     if (l<ss){ // realloc
13205       wchar_t * newptr=(wchar_t *)malloc(sizeof(wchar_t)*(l+1));
13206       wstrcpy(newptr,ptr);
13207       free(ptr);
13208       ptr=newptr;
13209     }
13210     */
13211     return ptr;
13212   }
13213 
printint32(int val,int subtype,GIAC_CONTEXT)13214   string printint32(int val,int subtype,GIAC_CONTEXT){
13215     if (subtype==_INT_TYPE)
13216       return print_the_type(val,contextptr);
13217 
13218     if (subtype==_INT_SOLVER){
13219       switch (val){
13220       case _UNFACTORED:
13221 	return "unfactored";
13222       case _BISECTION_SOLVER:
13223 	return "bisection_solver";
13224       case _FALSEPOS_SOLVER:
13225 	return "falsepos_solver";
13226       case _BRENT_SOLVER:
13227 	return "brent_solver";
13228       case _NEWTON_SOLVER:
13229 	return "newton_solver";
13230       case _DNEWTON_SOLVER:
13231 	return "dnewton_solver";
13232       case _NEWTONJ_SOLVER:
13233 	return "newtonj_solver";
13234       case _SECANT_SOLVER:
13235 	return "secant_solver";
13236       case _STEFFENSON_SOLVER:
13237 	return "steffenson_solver";
13238       case _HYBRIDSJ_SOLVER:
13239 	return "hybridsj_solver";
13240       case _HYBRIDJ_SOLVER:
13241 	return "hybridj_solver";
13242       case _HYBRIDS_SOLVER:
13243 	return "hybrids_solver";
13244       case _HYBRID_SOLVER:
13245 	return "hybrid_solver";
13246       case _GOLUB_REINSCH_DECOMP:
13247 	return "golub_reinsch_decomp";
13248       case _GOLUB_REINSCH_MOD_DECOMP:
13249 	return "golub_reinsch_mode_decomp";
13250       case _JACOBI_DECOMP:
13251 	return "jacobi_decomp";
13252       case _MINOR_DET:
13253 	return "minor_det";
13254       case _HESSENBERG_PCAR:
13255 	return "hessenberg_pcar";
13256       case _RATIONAL_DET:
13257 	return "rational_det";
13258       case _KEEP_PIVOT:
13259 	return "keep_pivot";
13260       case _FADEEV:
13261 	return "fadeev";
13262       case _BAREISS:
13263 	return "bareiss";
13264       case _RECTANGLE_GAUCHE:
13265 	return "left_rectangle";
13266       case _RECTANGLE_DROIT:
13267 	return "right_rectangle";
13268       case _POINT_MILIEU:
13269 	return "middle_point";
13270       case _TRAPEZE:
13271 	return "trapezoid";
13272       case _SIMPSON:
13273 	return "simpson";
13274       case _ROMBERGT:
13275 	return "rombergt";
13276       case _ROMBERGM:
13277 	return "rombergm";
13278       case _GAUSS15:
13279 	return "gauss15";
13280       default:
13281 	return print_INT_(val);
13282       }
13283     }
13284     if (subtype==_INT_BOOLEAN){
13285       if (python_compat(contextptr)){
13286 	if (val)
13287 	  return "True";
13288 	else
13289 	  return "False";
13290       }
13291       if (xcas_mode(contextptr)==2){
13292 	if (val)
13293 	  return "TRUE";
13294 	else
13295 	  return "FALSE";
13296       }
13297       else {
13298 	if (val)
13299 	  return "true";
13300 	else
13301 	  return "false";
13302       }
13303     }
13304     if (subtype==_INT_COLOR){
13305       switch (language(contextptr)){
13306       case 1:
13307 	switch (val){
13308 	case _BLACK:
13309 	  return "noir";
13310 	case _RED:
13311 	  return "rouge";
13312 	case _GREEN:
13313 	  return "vert";
13314 	case _YELLOW:
13315 	  return "jaune";
13316 	case _BLUE:
13317 	  return "bleu";
13318 	case _MAGENTA:
13319 	  return "magenta";
13320 	case _CYAN:
13321 	  return "cyan";
13322 	case _WHITE:
13323 	  return "blanc";
13324 	case _FILL_POLYGON:
13325 	  return "rempli";
13326 	case _QUADRANT2:
13327 	  return "quadrant2";
13328 	case _QUADRANT3:
13329 	  return "quadrant3";
13330 	case _QUADRANT4:
13331 	  return "quadrant4";
13332 	case _POINT_LOSANGE:
13333 	  return "point_losange";
13334 	case _POINT_CARRE:
13335 	  return "point_carre";
13336 	case _POINT_PLUS:
13337 	  return "point_plus";
13338 	case _POINT_TRIANGLE:
13339 	  return "point_triangle";
13340 	case _POINT_ETOILE:
13341 	  return "point_etoile";
13342 	case _POINT_POINT:
13343 	  return "point_point";
13344 	case _POINT_INVISIBLE:
13345 	  return "point_invisible";
13346 	case 49:
13347 	  return "gomme";
13348 	case _LINE_WIDTH_2:
13349 	  return "epaisseur_ligne_2";
13350 	case _LINE_WIDTH_3:
13351 	  return "epaisseur_ligne_3";
13352 	case _LINE_WIDTH_4:
13353 	  return "epaisseur_ligne_4";
13354 	case _LINE_WIDTH_5:
13355 	  return "epaisseur_ligne_5";
13356 	case _LINE_WIDTH_6:
13357 	  return "epaisseur_ligne_6";
13358 	case _LINE_WIDTH_7:
13359 	  return "epaisseur_ligne_7";
13360 	case _LINE_WIDTH_8:
13361 	  return "epaisseur_ligne_8";
13362 	case _POINT_WIDTH_2:
13363 	  return "epaisseur_point_2";
13364 	case _POINT_WIDTH_3:
13365 	  return "epaisseur_point_3";
13366 	case _POINT_WIDTH_4:
13367 	  return "epaisseur_point_4";
13368 	case _POINT_WIDTH_5:
13369 	  return "epaisseur_point_5";
13370 	case _POINT_WIDTH_6:
13371 	  return "epaisseur_point_6";
13372 	case _POINT_WIDTH_7:
13373 	  return "epaisseur_point_7";
13374 	case _POINT_WIDTH_8:
13375 	  return "epaisseur_point_8";
13376 	case _HIDDEN_NAME:
13377 	  return "nom_cache";
13378 	case _DASH_LINE:
13379 	  return "ligne_tiret";
13380 	case _DOT_LINE:
13381 	  return "ligne_point";
13382 	case _DASHDOT_LINE:
13383 	  return "ligne_tiret_point";
13384 	case _DASHDOTDOT_LINE:
13385 	  return "ligne_tiret_pointpoint";
13386 	case _CAP_FLAT_LINE:
13387 	  return "ligne_chapeau_plat";
13388 	case _CAP_ROUND_LINE:
13389 	  return "ligne_chapeau_rond";
13390 	case _CAP_SQUARE_LINE:
13391 	  return "ligne_chapeau_carre";
13392 	}
13393 	break;
13394       case 4:
13395 	switch (val){
13396 	case _BLACK:
13397 	  return "black";
13398 	case _RED:
13399 	  return "red";
13400 	case _GREEN:
13401 	  return "green";
13402 	case _YELLOW:
13403 	  return "yellow";
13404 	case _BLUE:
13405 	  return "blue";
13406 	case _MAGENTA:
13407 	  return "magenta";
13408 	case _CYAN:
13409 	  return "cyan";
13410 	case _WHITE:
13411 	  return "white";
13412 	case _FILL_POLYGON:
13413 	  return "filled";
13414 	case _QUADRANT2:
13415 	  return "quadrant2";
13416 	case _QUADRANT3:
13417 	  return "quadrant3";
13418 	case _QUADRANT4:
13419 	  return "quadrant4";
13420 	case _POINT_LOSANGE:
13421 	  return "ρομβοειδές_σημείο";
13422 	case _POINT_CARRE:
13423 	  return "τετραγωνικό_σημείο";
13424 	case _POINT_PLUS:
13425 	  return "σταυροειδές_σημείο";
13426 	case _POINT_TRIANGLE:
13427 	  return "τριγωνικό_σημείο";
13428 	case _POINT_ETOILE:
13429 	  return "αστροειδές_σημείο";
13430 	case _POINT_POINT:
13431 	  return "point_point";
13432 	case _POINT_INVISIBLE:
13433 	  return "αόρατο_σημείο";
13434 	case 49:
13435 	  return "gomme";
13436 	case _LINE_WIDTH_2:
13437 	  return "εύρος_γραμμής_2";
13438 	case _LINE_WIDTH_3:
13439 	  return "εύρος_γραμμής_3";
13440 	case _LINE_WIDTH_4:
13441 	  return "εύρος_γραμμής_4";
13442 	case _LINE_WIDTH_5:
13443 	  return "εύρος_γραμμής_5";
13444 	case _LINE_WIDTH_6:
13445 	  return "εύρος_γραμμής_6";
13446 	case _LINE_WIDTH_7:
13447 	  return "εύρος_γραμμής_7";
13448 	case _LINE_WIDTH_8:
13449 	  return "εύρος_γραμμής_8";
13450 	case _POINT_WIDTH_2:
13451 	  return "εύρος_σημείου_2";
13452 	case _POINT_WIDTH_3:
13453 	  return "εύρος_σημείου_3";
13454 	case _POINT_WIDTH_4:
13455 	  return "εύρος_σημείου_4";
13456 	case _POINT_WIDTH_5:
13457 	  return "εύρος_σημείου_5";
13458 	case _POINT_WIDTH_6:
13459 	  return "εύρος_σημείου_6";
13460 	case _POINT_WIDTH_7:
13461 	  return "εύρος_σημείου_7";
13462 	case _POINT_WIDTH_8:
13463 	  return "εύρος_σημείου_8";
13464 	case _HIDDEN_NAME:
13465 	  return "hidden_name";
13466 	case _DASH_LINE:
13467 	  return "γραμμή_διακεκομμένη";
13468 	case _DOT_LINE:
13469 	  return "παύλα_τελεία";
13470 	case _DASHDOT_LINE:
13471 	  return "γραμμή_παύλα_τελεία";
13472 	case _DASHDOTDOT_LINE:
13473 	  return "γραμμή_παύλα_τελείατελεία";
13474 	case _CAP_FLAT_LINE:
13475 	  return "γραμμή_επίπεδο_καβούκι";
13476 	case _CAP_ROUND_LINE:
13477 	  return "γραμμή_στρογγυλό_καβούκι";
13478 	case _CAP_SQUARE_LINE:
13479 	  return "γραμμή_τετράγωνο_καβούκι";
13480 	}
13481       default:
13482 	switch (val){
13483 	case _BLACK:
13484 	  return "black";
13485 	case _RED:
13486 	  return "red";
13487 	case _GREEN:
13488 	  return "green";
13489 	case _YELLOW:
13490 	  return "yellow";
13491 	case _BLUE:
13492 	  return "blue";
13493 	case _MAGENTA:
13494 	  return "magenta";
13495 	case _CYAN:
13496 	  return "cyan";
13497 	case _WHITE:
13498 	  return "white";
13499 	case _FILL_POLYGON:
13500 	  return "filled";
13501 	case _QUADRANT2:
13502 	  return "quadrant2";
13503 	case _QUADRANT3:
13504 	  return "quadrant3";
13505 	case _QUADRANT4:
13506 	  return "quadrant4";
13507 	case _POINT_LOSANGE:
13508 	  return "rhombus_point";
13509 	case _POINT_CARRE:
13510 	  return "square_point";
13511 	case _POINT_PLUS:
13512 	  return "plus_point";
13513 	case _POINT_TRIANGLE:
13514 	  return "triangle_point";
13515 	case _POINT_ETOILE:
13516 	  return "star_point";
13517 	case _POINT_POINT:
13518 	  return "point_point";
13519 	case _POINT_INVISIBLE:
13520 	  return "invisible_point";
13521 	case 49:
13522 	  return "gomme";
13523 	case _LINE_WIDTH_2:
13524 	  return "line_width_2";
13525 	case _LINE_WIDTH_3:
13526 	  return "line_width_3";
13527 	case _LINE_WIDTH_4:
13528 	  return "line_width_4";
13529 	case _LINE_WIDTH_5:
13530 	  return "line_width_5";
13531 	case _LINE_WIDTH_6:
13532 	  return "line_width_6";
13533 	case _LINE_WIDTH_7:
13534 	  return "line_width_7";
13535 	case _LINE_WIDTH_8:
13536 	  return "line_width_8";
13537 	case _POINT_WIDTH_2:
13538 	  return "point_width_2";
13539 	case _POINT_WIDTH_3:
13540 	  return "point_width_3";
13541 	case _POINT_WIDTH_4:
13542 	  return "point_width_4";
13543 	case _POINT_WIDTH_5:
13544 	  return "point_width_5";
13545 	case _POINT_WIDTH_6:
13546 	  return "point_width_6";
13547 	case _POINT_WIDTH_7:
13548 	  return "point_width_7";
13549 	case _POINT_WIDTH_8:
13550 	  return "point_width_8";
13551 	case _HIDDEN_NAME:
13552 	  return "hidden_name";
13553 	case _DASH_LINE:
13554 	  return "dash_line";
13555 	case _DOT_LINE:
13556 	  return "dot_line";
13557 	case _DASHDOT_LINE:
13558 	  return "dashdot_line";
13559 	case _DASHDOTDOT_LINE:
13560 	  return "dashdotdot_line";
13561 	case _CAP_FLAT_LINE:
13562 	  return "cap_flat_line";
13563 	case _CAP_ROUND_LINE:
13564 	  return "cap_round_line";
13565 	case _CAP_SQUARE_LINE:
13566 	  return "cap_square_line";
13567 	}
13568       }
13569       // switch (val){ }
13570     }
13571     if (subtype==_INT_PLOT){
13572       switch(val){
13573       case _ADAPTIVE:
13574 	return "adaptive";
13575       case _AXES:
13576 	return "axes";
13577       case _COLOR:
13578 	return "color";
13579       case _FILLED:
13580 	return "filled";
13581       case _FONT:
13582 	return "font";
13583       case _LABELS:
13584 	return "labels";
13585       case _LEGEND:
13586 	return "legend";
13587       case _LINESTYLE:
13588 	return "linestyle";
13589       case _RESOLUTION:
13590 	return "resolution";
13591       case _SAMPLE:
13592 	return "sample";
13593       case _SCALING:
13594 	return "scaling";
13595       case _STYLE:
13596 	return "style";
13597       case _SYMBOL:
13598 	return "symbol";
13599       case _SYMBOLSIZE:
13600 	return "symbolsize";
13601       case _THICKNESS:
13602 	return "thickness";
13603       case _TITLE:
13604 	return "title";
13605       case _TITLEFONT:
13606 	return "titlefont";
13607       case _VIEW:
13608 	return "view";
13609       case _AXESFONT:
13610 	return "axesfont";
13611       case _COORDS:
13612 	return "coords";
13613       case _LABELFONT:
13614 	return "labelfont";
13615       case _LABELDIRECTIONS:
13616 	return "labeldirections";
13617       case _NUMPOINTS:
13618 	return "numpoints";
13619       case _TICKMARKS:
13620 	return "tickmarks";
13621       case _XTICKMARKS:
13622 	return "xtickmarks";
13623       case _NSTEP:
13624 	return "nstep";
13625       case _XSTEP:
13626 	return "xstep";
13627       case _YSTEP:
13628 	return "ystep";
13629       case _ZSTEP:
13630 	return "zstep";
13631       case _TSTEP:
13632 	return "tstep";
13633       case _USTEP:
13634 	return "ustep";
13635       case _VSTEP:
13636 	return "vstep";
13637       case _FRAMES:
13638 	return "frames";
13639       case _GL_TEXTURE:
13640 	return "gl_texture";
13641       case _GL_LIGHT0:
13642 	return "gl_light0";
13643       case _GL_LIGHT1:
13644 	return "gl_light1";
13645       case _GL_LIGHT2:
13646 	return "gl_light2";
13647       case _GL_LIGHT3:
13648 	return "gl_light3";
13649       case _GL_LIGHT4:
13650 	return "gl_light4";
13651       case _GL_LIGHT5:
13652 	return "gl_light5";
13653       case _GL_LIGHT6:
13654 	return "gl_light6";
13655       case _GL_LIGHT7:
13656 	return "gl_light7";
13657       case _GL_AMBIENT:
13658 	return "gl_ambient";
13659       case _GL_SPECULAR:
13660 	return "gl_specular";
13661       case _GL_DIFFUSE:
13662 	return "gl_diffuse";
13663       case _GL_POSITION:
13664 	return "gl_position";
13665       case _GL_SPOT_DIRECTION:
13666 	return "gl_spot_direction";
13667       case _GL_SPOT_EXPONENT:
13668 	return "gl_spot_exponent";
13669       case _GL_SPOT_CUTOFF:
13670 	return "gl_spot_cutoff";
13671       case _GL_CONSTANT_ATTENUATION:
13672 	return "gl_constant_attenuation";
13673       case _GL_LINEAR_ATTENUATION:
13674 	return "gl_linear_attenuation";
13675       case _GL_QUADRATIC_ATTENUATION:
13676 	return "gl_quadratic_attenuation";
13677       case _GL_OPTION:
13678 	return "gl_option";
13679       case _GL_SMOOTH:
13680 	return "gl_smooth";
13681       case _GL_FLAT:
13682 	return "gl_flat";
13683       case _GL_SHININESS:
13684 	return "gl_shininess";
13685       case _GL_FRONT:
13686 	return "gl_front";
13687       case _GL_BACK:
13688 	return "gl_back";
13689       case _GL_FRONT_AND_BACK:
13690 	return "gl_front_and_back";
13691       case _GL_AMBIENT_AND_DIFFUSE:
13692 	return "gl_ambient_and_diffuse";
13693       case _GL_EMISSION:
13694 	return "gl_emission";
13695       case _GL_LIGHT_MODEL_AMBIENT:
13696 	return "gl_light_model_ambient";
13697       case _GL_LIGHT_MODEL_LOCAL_VIEWER:
13698 	return "gl_light_model_local_viewer";
13699       case _GL_LIGHT_MODEL_TWO_SIDE:
13700 	return "gl_light_model_two_side";
13701       case _GL_LIGHT_MODEL_COLOR_CONTROL:
13702 	return "gl_light_model_color_control";
13703       case _GL_BLEND:
13704 	return "gl_blend";
13705       case _GL_SRC_ALPHA:
13706 	return "gl_src_alpha";
13707       case _GL_ONE_MINUS_SRC_ALPHA:
13708 	return "gl_one_minus_src_alpha";
13709       case _GL_SEPARATE_SPECULAR_COLOR:
13710 	return "gl_separate_specular_color";
13711       case _GL_SINGLE_COLOR:
13712 	return "gl_single_color";
13713       case _GL_MATERIAL:
13714 	return "gl_material";
13715       case _GL_COLOR_INDEXES:
13716 	return "gl_color_indexes";
13717       case _GL_LIGHT:
13718 	return "gl_light";
13719       case _GL_PERSPECTIVE:
13720 	return "gl_perspective";
13721       case _GL_ORTHO:
13722 	return "gl_ortho";
13723       case _GL_QUATERNION:
13724 	return "gl_quaternion";
13725       case _GL_ROTATION_AXIS:
13726 	return "gl_rotation_axis";
13727       case _GL_X:
13728 	return "gl_x";
13729       case _GL_Y:
13730 	return "gl_y";
13731       case _GL_Z:
13732 	return "gl_z";
13733       case _GL_XTICK:
13734 	return "gl_xtick";
13735       case _GL_YTICK:
13736 	return "gl_ytick";
13737       case _GL_ZTICK:
13738 	return "gl_ztick";
13739       case _GL_ANIMATE:
13740 	return "gl_animate";
13741       case _GL_SHOWAXES:
13742 	return "gl_showaxes";
13743       case _GL_SHOWNAMES:
13744 	return "gl_shownames";
13745       case _GL_X_AXIS_NAME:
13746 	return "gl_x_axis_name";
13747       case _GL_Y_AXIS_NAME:
13748 	return "gl_y_axis_name";
13749       case _GL_Z_AXIS_NAME:
13750 	return "gl_z_axis_name";
13751       case _GL_X_AXIS_UNIT:
13752 	return "gl_x_axis_unit";
13753       case _GL_Y_AXIS_UNIT:
13754 	return "gl_y_axis_unit";
13755       case _GL_Z_AXIS_UNIT:
13756 	return "gl_z_axis_unit";
13757       case _GL_LOGX:
13758 	return "gl_logx";
13759       case _GL_LOGY:
13760 	return "gl_logy";
13761       case _GL_LOGZ:
13762 	return "gl_logz";
13763       }
13764     }
13765     if (subtype==_INT_MAPLELIB){
13766       switch (val){
13767       case _LINALG:
13768 	return "linalg";
13769       case _NUMTHEORY:
13770 	return "numtheory";
13771       case _GROEBNER:
13772 	return "groebner";
13773       }
13774     }
13775     if (subtype==_INT_MAPLECONVERSION){
13776       switch (val){
13777       case _MAPLE_LIST:
13778 	return "list";
13779       case _SET__VECT:
13780 	return "set";
13781       case _MATRIX__VECT:
13782 	return "matrix";
13783       case _POLY1__VECT:
13784 	return "polynom";
13785       case _TRIG:
13786 	return "trig";
13787       case _EXPLN:
13788 	return "expln";
13789       case _PARFRAC:
13790 	return "parfrac";
13791       case _FULLPARFRAC:
13792 	return "fullparfrac";
13793       case _CONFRAC:
13794 	return "confrac";
13795       case _BASE:
13796 	return "base";
13797       case _POSINT:
13798 	return "posint";
13799       case _NEGINT:
13800 	return "negint";
13801       case _NONPOSINT:
13802 	return "nonposint";
13803       case _NONNEGINT:
13804 	return "nonnegint";
13805       case _LP_ASSUME:
13806 	return "lp_assume";
13807       case _LP_BINARY:
13808 	return "lp_binary";
13809       case _LP_BINARYVARIABLES:
13810 	return "lp_binaryvariables";
13811       case _LP_DEPTHLIMIT:
13812 	return "lp_depthlimit";
13813       case _LP_MAXIMIZE:
13814 	return "lp_maximize";
13815       case _LP_NONNEGATIVE:
13816 	return "lp_nonnegative";
13817       case _LP_NONNEGINT:
13818 	return "lp_nonnegint";
13819       case _LP_VARIABLES:
13820 	return "lp_variables";
13821       case _LP_INTEGER:
13822 	return "lp_integer";
13823       case _LP_INTEGERVARIABLES:
13824 	return "lp_integervariables";
13825       }
13826     }
13827     if (subtype==_INT_MUPADOPERATOR){
13828       switch (val){
13829       case _DELETE_OPERATOR:
13830 	return "Delete";
13831       case _PREFIX_OPERATOR:
13832 	return "Prefix";
13833       case _POSTFIX_OPERATOR:
13834 	return "Postfix";
13835       case _BINARY_OPERATOR:
13836 	return "Binary";
13837       case _NARY_OPERATOR:
13838 	return "Nary";
13839       }
13840     }
13841     if (subtype==_INT_GROEBNER){
13842       switch (val){
13843       case _REVLEX_ORDER:
13844 	return "revlex";
13845       case _PLEX_ORDER:
13846 	return "plex";
13847       case _TDEG_ORDER:
13848 	return "tdeg";
13849       case _WITH_COCOA:
13850 	return "with_cocoa";
13851       case _WITH_F5:
13852 	return "with_f5";
13853       case _MODULAR_CHECK:
13854 	return "modular_check";
13855       case _RUR_REVLEX:
13856 	return "rur";
13857       }
13858     }
13859     return print_INT_(val);
13860   }
13861 
print_float(const float & f,char * ch)13862   static void print_float(const float & f,char * ch){
13863     sprintfdouble(ch,"%.14g",f);
13864   }
13865 
print_FLOAT_(const giac_float & f,GIAC_CONTEXT)13866   string print_FLOAT_(const giac_float & f,GIAC_CONTEXT){
13867     char ch[64];
13868 #ifdef BCD
13869 #ifndef CAS38_DISABLED
13870     int i=get_int(f);
13871     if (is_zero(f-i))
13872       return print_INT_(i)+'.';
13873 #endif
13874     print_float(f,ch);
13875 #else
13876     print_float(f,ch);
13877 #endif
13878     return ch;
13879   }
13880 
print_FRAC(const gen & f,GIAC_CONTEXT)13881   static string print_FRAC(const gen & f,GIAC_CONTEXT){
13882     if (f._FRACptr->num.type==_INT_ && f._FRACptr->den.type==_INT_){
13883       string s(f._FRACptr->num.print(contextptr));
13884       s += "/";
13885       add_print(s,f._FRACptr->den,contextptr);
13886       return s;
13887     }
13888     if (calc_mode(contextptr)==1 && f._FRACptr->den.type==_CPLX){
13889       gen n=f._FRACptr->num,d=f._FRACptr->den,dr,di;
13890       reim(d,dr,di,contextptr);
13891       n=n*gen(dr,-di);
13892       d=dr*dr+di*di;
13893       gen nd=fraction(n,d);
13894       if (nd.type==_FRAC)
13895 	return print_FRAC(nd,contextptr);
13896       else
13897 	return nd.print(contextptr);
13898     }
13899     return _FRAC2_SYMB(f).print(contextptr);
13900   }
13901 
print(GIAC_CONTEXT) const13902   string gen::print(GIAC_CONTEXT) const{
13903     switch (type ) {
13904     case _INT_:
13905       if (val<0 && val != (1<<31) && calc_mode(contextptr)==38)
13906 	return "−"+(-*this).print(contextptr);
13907       if (subtype)
13908 	return localize(printint32(val,subtype,contextptr),language(contextptr));
13909       switch (integer_format(contextptr)){
13910       case 16:
13911 	return hexa_print_INT_(val);
13912       case 8:
13913 	return octal_print_INT_(val);
13914       case 2:
13915 	return binary_print_INT_(val);
13916       default:
13917 	return print_INT_(val);
13918       }
13919     case _DOUBLE_:
13920       return print_DOUBLE_(_DOUBLE_val,contextptr);
13921     case _FLOAT_:
13922       if (abs_calc_mode(contextptr)==38 && is_strictly_positive(-*this,contextptr)) return "−"+print_FLOAT_(-_FLOAT_val,contextptr);
13923       return print_FLOAT_(_FLOAT_val,contextptr);
13924     case _ZINT:
13925       if (abs_calc_mode(contextptr)==38 && is_strictly_positive(-*this,contextptr))
13926 	return "−"+(-*this).print(contextptr);
13927       switch (integer_format(contextptr)){
13928       case 16:
13929 	return hexa_print_ZINT(*_ZINTptr);
13930       case 8:
13931 	return octal_print_ZINT(*_ZINTptr);
13932       default:
13933 	return print_ZINT(*_ZINTptr);
13934       }
13935     case _REAL:
13936       return _REALptr->print(contextptr);
13937     case _CPLX:
13938       // if (abs_calc_mode(contextptr)==38) return "("+_CPLXptr->print(contextptr)+","+(_CPLXptr+1)->print(contextptr)+")";
13939       if (is_exactly_zero(*(_CPLXptr+1)))
13940 	return _CPLXptr->print(contextptr);
13941 #ifndef GIAC_GGB
13942       if (*complex_display_ptr(*this) &1){
13943 #ifdef BCD
13944 	if (_CPLXptr->type==_FLOAT_ && (_CPLXptr+1)->type==_FLOAT_)
13945 #ifdef GIAC_HAS_STO_38
13946     //grad
13947 	  return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+print_FLOAT_(atan2f(_CPLXptr->_FLOAT_val,(_CPLXptr+1)->_FLOAT_val,angle_radian(contextptr)?AMRad:(angle_degree(contextptr)?AMDeg:AMGrad)),contextptr);
13948 #else
13949 	return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+print_FLOAT_(atan2f(_CPLXptr->_FLOAT_val,(_CPLXptr+1)->_FLOAT_val,angle_radian(contextptr)),contextptr);
13950 #endif
13951 #endif
13952 	// return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+(angle_radian(contextptr)?arg(*this,contextptr):arg(*this,contextptr)*rad2deg_g).print(contextptr);
13953 	return abs(*this,contextptr).print(contextptr)+"\xe2\x88\xa1"+arg(*this,contextptr).print(contextptr);
13954       }
13955 #endif // GIAC_GGB
13956       if (is_exactly_zero(*_CPLXptr)){
13957 	if (is_one(*(_CPLXptr+1)))
13958 	  return printi(contextptr);
13959 	if (is_minus_one(*(_CPLXptr+1)))
13960 	  return (abs_calc_mode(contextptr)==38?string("−"):string("-"))+printi(contextptr);
13961 	return ((_CPLXptr+1)->print(contextptr) + string("*"))+printi(contextptr);
13962       }
13963       if (is_one(*(_CPLXptr+1)))
13964 	return (_CPLXptr->print(contextptr) + string("+"))+printi(contextptr);
13965       if (is_minus_one(*(_CPLXptr+1)))
13966 	return (_CPLXptr->print(contextptr) + string("-"))+printi(contextptr);
13967       if (is_positive(-(*(_CPLXptr+1)),contextptr))
13968 	return (_CPLXptr->print(contextptr) + string("-") + (-(*(_CPLXptr+1))).print(contextptr) + "*")+printi(contextptr);
13969       return (_CPLXptr->print(contextptr) + string("+") + (_CPLXptr+1)->print(contextptr) + "*")+printi(contextptr);
13970     case _IDNT:
13971       if (calc_mode(contextptr)==1 && (is_inf(*this) || is_undef(*this)))
13972 	return "?";
13973       return _IDNTptr->print(contextptr);
13974     case _SYMB:
13975       {
13976 	int d=depth(*this,0,print_max_depth);
13977 	if (d>=print_max_depth)
13978 	  return "Too many embeddings";
13979       }
13980       if (is_inf(_SYMBptr->feuille)){
13981 	if (_SYMBptr->sommet==at_plus){
13982 #ifdef KHICAS
13983 	  return "oo";
13984 #else
13985 	  if (
13986 	      // calc_mode(contextptr)!=1
13987 	      abs_calc_mode(contextptr)==38
13988 	      )
13989 	    return "∞";
13990 	  else
13991 	    return "+infinity";
13992 #endif
13993 	}
13994 	if (_SYMBptr->sommet==at_neg){
13995 #ifdef KHICAS
13996 	  return "-oo";
13997 #else
13998 	  if (
13999 	      // calc_mode(contextptr)!=1
14000 	      abs_calc_mode(contextptr)==38
14001 	      )
14002 	    return "-∞";
14003 	  else
14004 	    return "-infinity";
14005 #endif
14006 	}
14007       }
14008       if (subtype==_SPREAD__SYMB){
14009 	if (_SYMBptr->sommet==at_sto)
14010 	  return "=("+_SYMBptr->print(contextptr)+")";
14011 	return "="+_SYMBptr->print(contextptr);
14012       }
14013       else
14014 	return _SYMBptr->print(contextptr);
14015     case _VECT:
14016       if (subtype==_GRAPH__VECT){
14017 	string s;
14018 	if (is_graphe(*this,s,contextptr))
14019 	  return '"'+s+'"';
14020       }
14021       return print_VECT(*_VECTptr,subtype,contextptr);
14022     case _POLY:
14023       return _POLYptr->print() ;
14024     case _SPOL1:
14025       return print_SPOL1(*_SPOL1ptr,contextptr);
14026     case _EXT: {
14027       string s("%%{");
14028       s += _EXTptr->print(contextptr);
14029       s += ':';
14030       s += (*(_EXTptr+1)).print(contextptr);
14031       s += "%%}";
14032       return s;
14033     }
14034     case _USER:
14035       return _USERptr->print(contextptr);
14036     case _MOD:
14037 #ifdef GIAC_HAS_STO_38
14038       if ( (_MODptr->type==_SYMB && _MODptr->_SYMBptr->sommet!=at_pow) || (_MODptr->type==_VECT && _MODptr->subtype==_SEQ__VECT) )
14039 	return "("+_MODptr->print(contextptr)+") %% "+(*(_MODptr+1)).print(contextptr);
14040       return _MODptr->print(contextptr)+" %% "+(*(_MODptr+1)).print(contextptr);
14041 #else
14042       if ( (_MODptr->type==_SYMB && _MODptr->_SYMBptr->sommet!=at_pow) || (_MODptr->type==_VECT && _MODptr->subtype==_SEQ__VECT) )
14043 	return "("+_MODptr->print(contextptr)+")"+(python_compat(contextptr)?" mod ":" % ")+(*(_MODptr+1)).print(contextptr);
14044       return _MODptr->print(contextptr)+(python_compat(contextptr)?" mod ":" % ")+(*(_MODptr+1)).print(contextptr);
14045 #endif
14046     case _FRAC:
14047       return print_FRAC(*this,contextptr);
14048     case _STRNG:
14049 #ifdef GIAC_HAS_STO_38
14050       // if (subtype==-1)
14051       // return AspenPrintErrorString(*_STRNGptr);
14052 #endif
14053       return print_STRNG(*_STRNGptr);
14054     case _FUNC:
14055       if (*this==at_return){
14056 	if (xcas_mode(contextptr)==3)
14057 	  return "Return";
14058 	else
14059 	  return "return ;";
14060       }
14061       if (rpn_mode(contextptr) || _FUNCptr->ptr()->printsommet==&printastifunction || subtype==0)
14062 	return _FUNCptr->ptr()->print(contextptr);
14063       else
14064 	return string("'")+_FUNCptr->ptr()->print(contextptr)+"'";
14065     case _MAP:
14066       if (subtype==1)
14067 	return maptoarray(*_MAPptr,contextptr).print(contextptr);
14068       else
14069 	return printmap(*_MAPptr,contextptr);
14070     case _EQW:
14071       return print_EQW(*_EQWptr);
14072     case _POINTER_: {
14073       // handle 64 bits pointers
14074       unsigned long long u=(unsigned long long)_POINTER_val;
14075       if (u<(1U<<31))
14076 	return "pointer("+hexa_print_INT_(int((alias_type)_POINTER_val))+","+print_INT_(subtype)+")";
14077       gen z=longlong(u);
14078       return "pointer("+hexa_print_ZINT(*z._ZINTptr)+","+print_INT_(subtype)+")";
14079     }
14080     default:
14081 #ifndef NO_STDEXCEPT
14082       settypeerr(gettext("print"));
14083 #endif
14084       return "print error";
14085     }
14086     return "print error";
14087   }
14088 
14089 #ifdef ConnectivityKit
dbgprint() const14090   const char * gen::dbgprint() const { return "Done";}
14091 #else
14092 #if defined(VISUALC) && !defined(MS_SMART)
dbgprint() const14093   const char * gen::dbgprint() const { ATLTRACE2("%s\r\n", this->print(0).c_str()); return "Done";}
14094 #else
dbgprint() const14095   const char * gen::dbgprint() const{
14096     if (this->type==_POLY)
14097       return _POLYptr->dbgprint();
14098     static string *sptr=0;
14099     if (!sptr) sptr=new string;
14100     *sptr=this->print(context0);
14101 #if 0 // ndef NSPIRE
14102     COUT << *sptr;
14103 #endif
14104     return sptr->c_str();
14105   }
14106 #endif
14107 #endif
14108 
14109 #ifdef KHICAS
operator <<(stdostream & os,const gen & a)14110  stdostream & operator << (stdostream & os,const gen & a){
14111    return os << a.print(context0);
14112  }
14113 #endif
14114 #ifndef NSPIRE
operator <<(ostream & os,const gen & a)14115   ostream & operator << (ostream & os,const gen & a) { return os << a.print(context0); }
14116 #endif
14117 
print(GIAC_CONTEXT) const14118   string monome::print(GIAC_CONTEXT) const {
14119     // if (abs_calc_mode(contextptr)==38 )
14120       return "%%%{" + coeff.print(contextptr) + ',' + exponent.print(contextptr) + "%%%}" ;
14121       //return "<<" + coeff.print(contextptr) + ',' + exponent.print(contextptr) + ">>" ;
14122   }
14123 
dbgprint() const14124   const char * monome::dbgprint() const {
14125     static string *sptr=0;
14126     if (!sptr) sptr=new string;
14127     *sptr=this->print(context0);
14128 #if 0 // ndef NSPIRE
14129     COUT << *sptr;
14130 #endif
14131     return sptr->c_str();
14132   }
14133 
14134 #ifndef NSPIRE
operator <<(ostream & os,const monome & m)14135   ostream & operator << (ostream & os,const monome & m){
14136     return os << m.print(context0) ;
14137   }
14138 #endif
14139 
14140   /*
14141   gen string2_ZINT(string s,int l,int & pos){
14142     char ss[l+1];
14143     int neg=1;
14144     if (s[pos]=='-'){
14145       pos++;
14146       neg=-1;
14147     }
14148     int i=0;
14149     for (;(pos<l) && (s[pos]>='0') && (s[pos]<='9');pos++,i++)
14150       ss[i]=s[pos];
14151     if ((!i) && (s[pos]=='i') || (s[pos]=='I')){
14152       return(neg);
14153     }
14154     assert(i);
14155     ss[i]=char(0);
14156     mpz_t *mpzin = new mpz_t[1];
14157     mpz_init(*mpzin);
14158     mpz_set_str (*mpzin, ss, 10);
14159     if (neg>0)
14160       return(gen(mpzin));
14161     else
14162       return(-gen(mpzin));
14163   }
14164 
14165   istream & operator >> (istream & is,gen & a){
14166     string s;
14167     is >> s;
14168     int l=s.size();
14169     int pos=0;
14170     a=gen(0);
14171     while (pos<l){
14172       if ((s[pos]=='i') || (s[pos]=='I')){
14173 	a=a+gen(0,1);
14174 	pos++;
14175       }
14176       else {
14177 	if (s[pos]=='+')
14178 	  pos++;
14179 	else {
14180 	  gen tmp(string2_ZINT(s,l,pos));
14181 	  if (s[pos]=='*'){
14182 	    pos++;
14183 	    assert( (s[pos]=='i') || (s[pos]=='I') );
14184 	    pos++; // skip *I
14185 	    a=a+tmp*cst_i;
14186 	  }
14187 	  else {
14188 	    if ((s[pos]=='i') || (s[pos]=='I')){
14189 	      pos++; // skip I
14190 	      a=a+tmp*cst_i;
14191 	    }
14192 	    else
14193 	      a=a+tmp;
14194 	  }
14195 	}
14196       }
14197     }
14198     return is;
14199   }
14200   */
14201 #ifdef NSPIRE
operator >>(nio::ios_base<T> & is,gen & a)14202   template<class T> nio::ios_base<T> & operator>>(nio::ios_base<T> & is,gen & a){
14203     string s;
14204     is >> s;
14205     a = gen(s,context0);
14206     return is;
14207   }
14208 #else
operator >>(istream & is,gen & a)14209   istream & operator >> (istream & is,gen & a){
14210     string s;
14211     is >> s;
14212     a = gen(s,context0);
14213     return is;
14214   }
14215 #endif
14216 
14217   /* Some string utilities not use anymore */
14218   // Note that this function should be optimized for large input
cut_string(const string & chaine,int nchar,vector<int> & ligne_end)14219   string cut_string(const string & chaine,int nchar,vector<int> & ligne_end) {
14220     // CERR << CLOCK() << '\n';
14221     int pos;
14222     if (ligne_end.empty())
14223       pos=0;
14224     else
14225       pos=ligne_end.back()+1;
14226     int l=int(chaine.size());
14227     string res;
14228     for (int i=0;i<l;){
14229       // look for \n between i and l
14230       int k=int(chaine.find_first_of('\n',i));
14231       if ( (l-i<nchar) && ((k<i)||(k>=l-1)) ){
14232 	ligne_end.push_back(pos+l);
14233 	// CERR << CLOCK() << '\n';
14234 	return res+chaine.substr(i,l-i);
14235       }
14236       if ((k>=i) && (k<i+nchar+4*(i==0)) ){
14237 	ligne_end.push_back(pos+k);
14238 	res += chaine.substr(i,k+1-i);
14239 	i=k+1;
14240       }
14241       else {
14242 	int j;
14243 	int j1=int(chaine.find_last_of('+',i+nchar+4*(i==0)));
14244 	int j2=int(chaine.find_last_of('-',i+nchar+4*(i==0)));
14245 	int j3=int(chaine.find_last_of(',',i+nchar+4*(i==0)));
14246 	j=giacmax(j1,giacmax(j2,j3));
14247 	if ((j-i)<(nchar/2))
14248 	  j=i+nchar+4*(i==0);
14249 	ligne_end.push_back(pos+giacmin(j,l));
14250 	res += chaine.substr(i,j-i);
14251 	i=j;
14252 	if (i<l){
14253 	  res +="\\\n     ";
14254 	  pos +=7;
14255 	}
14256       }
14257     }
14258     // CERR << CLOCK() << '\n';
14259     return res;
14260   }
14261 
calc_endlines_positions(const vecteur & history_in,const vecteur & history_out,int nchar,vector<int> & endlines,vector<int> & positions)14262   string calc_endlines_positions(const vecteur & history_in,const vecteur & history_out,int nchar,vector<int> & endlines,vector<int> & positions){
14263     string res;
14264     endlines.clear();
14265     positions.clear();
14266     int s_in=int(history_in.size()),s_out=int(history_out.size());
14267     int s=giacmax(s_in,s_out);
14268     for (int i=0;i<s;++i){
14269       string chaine;
14270       if (rpn_mode(context0))
14271 	chaine=print_INT_(s-i)+": ";
14272       else
14273 	chaine=print_INT_(i)+": ";
14274       if (!rpn_mode(context0)){
14275 	if (i<s_in)
14276 	  chaine+=history_in[i].print(context0)+" = ";
14277       }
14278       else
14279 	chaine +="   ";
14280       if (i<s_out)
14281 	chaine += history_out[i].print(context0);
14282       if (i)
14283 	res +='\n';
14284       res += cut_string(chaine,nchar,endlines);
14285       positions.push_back(endlines.back());
14286     }
14287     return res;
14288   }
14289 
is_operator_char(char c)14290   bool is_operator_char(char c){
14291     switch(c){
14292     case '+': case '-': case '*': case '/': case '^': case '%':
14293       return true;
14294     }
14295     return false;
14296   }
14297 
is_operator_char(char c,char op)14298   static bool is_operator_char(char c,char op){
14299     switch(c){
14300     case '+': case '-':
14301       return true;
14302     case '*': case '/': case '^': case '%':
14303       return c==op;
14304     }
14305     return false;
14306   }
14307 
matchpos(const string & s,int & pos)14308   bool matchpos(const string & s,int & pos){
14309     char c=s[pos];
14310     char c_orig=c;
14311     int l=int(s.size());
14312     int counter1=0,counter2=0,counter3=0,incr;
14313     if ( (c==')') || (c==']') || (c=='}') )
14314       incr=-1;
14315     else
14316       incr=1;
14317     for (;(pos>=0) && (pos<l);pos+=incr){
14318       switch (c=s[pos]){
14319       case '(':
14320 	counter1++;
14321 	break;
14322       case ')':
14323 	counter1--;
14324 	break;
14325       case '[':
14326 	counter2++;
14327 	break;
14328       case ']':
14329 	counter2--;
14330 	break;
14331       case '{':
14332 	counter3++;
14333 	break;
14334       case '}':
14335 	counter3--;
14336 	break;
14337       }
14338       if ( (!counter1) && (!counter2) && (!counter3) ){
14339 	bool res=false;
14340 	switch (c_orig){
14341 	case '(':
14342 	  res=c==')';
14343 	  break;
14344 	case '[':
14345 	  res=c==']';
14346 	  break;
14347 	case '{':
14348 	  res=c=='}';
14349 	  break;
14350 	case ')':
14351 	  res=c=='(';
14352 	  break;
14353 	case ']':
14354 	  res=c=='[';
14355 	  break;
14356 	case '}':
14357 	  res=c=='{';
14358 	  break;
14359 	}
14360 	return res;
14361       }
14362     }
14363     return false;
14364   }
14365 
find_left(const string & s,int & pos1,int & pos2)14366   static void find_left(const string & s,int & pos1,int & pos2){
14367     int l=int(s.size());
14368     pos1=giacmin(giacmax(pos1,0),l);
14369     int pos1orig=pos1;
14370     if (!pos1)
14371       return;
14372     pos2=giacmax(giacmin(pos2,l),0);
14373     int counter1=0,counter2=0;
14374     if (pos2==l){
14375       int i=pos2;
14376       for (;i>pos1;){
14377 	--i;
14378 	char ch = s[i];
14379 	if (ch=='(')
14380 	  ++counter1;
14381 	if (ch==')')
14382 	  --counter1;
14383 	if (ch=='[')
14384 	  ++counter2;
14385 	if (ch==']')
14386 	  --counter2;
14387       }
14388     }
14389     for (;pos1>=0;--pos1){
14390       char ch=s[pos1];
14391       if ( (!counter1) && (!counter2) && ( (ch=='(') || (ch=='[') || (ch=='+') || (ch=='-') || (ch==',')  )){
14392 	if ( (pos1<pos1orig) && ( (ch!='(') || (s[pos2-1]!=')') ) )
14393 	  ++pos1;
14394 	break;
14395       }
14396       if (ch=='('){
14397 	++counter1;
14398 	if ( (!counter1) && (!counter2) ){
14399 	  if (s[pos2-1]==')')
14400 	    break;
14401 	  if ( pos1 && isalphan(s[pos1-1])){
14402 	    --pos1;
14403 	    for (;pos1>=0;--pos1)
14404 	      if (!isalphan(s[pos1]))
14405 		break;
14406 	    ++pos1;
14407 	  }
14408 	  break;
14409 	}
14410       }
14411       if (ch==')')
14412 	--counter1;
14413       if (ch=='['){
14414 	++counter2;
14415 	if ( (!counter1) && (!counter2) ){
14416 	  if (s[pos2-1]==']')
14417 	    break;
14418 	  if ( pos1 && isalphan(s[pos1-1])){
14419 	    --pos1;
14420 	    for (;pos1>=0;--pos1)
14421 	      if (!isalphan(s[pos1]))
14422 		break;
14423 	    ++pos1;
14424 	  }
14425 	  break;
14426 	}
14427       }
14428       if (ch==']')
14429 	--counter2;
14430     }
14431   }
14432 
find_right(const string & s,int & pos1,int & pos2)14433   static void find_right(const string & s,int & pos1,int & pos2){
14434     int l=int(s.size());
14435     pos1=giacmin(giacmax(pos1,0),l);
14436     pos2=giacmax(giacmin(pos2,l),0);
14437     int pos2orig=pos2;
14438     int counter1=0,counter2=0;
14439     for (int i=pos1;(i<pos2-1) && (i<l);++i){
14440       char ch=s[i];
14441       if (ch=='(')
14442 	++counter1;
14443       if (ch==')')
14444 	--counter1;
14445       if (ch=='[')
14446 	++counter2;
14447       if (ch==']')
14448 	--counter2;
14449       if ( (counter1<0) && (pos1) ){ // restart at an earlier position
14450 	pos1=int(s.find_last_of('(',pos1-1));
14451 	if (pos1<0)
14452 	  pos1=0;
14453 	i=pos1-1;
14454 	counter1=0;
14455 	counter2=0;
14456       }
14457     }
14458     for (;pos2<=l;++pos2){
14459       char ch=s[pos2-1];
14460       if ( (!counter1) && (!counter2) && ( (ch==')') ||  (ch==']') || (ch=='+') || (ch=='-') || (ch==',')  ) && (pos2>pos2orig)){
14461 	--pos2;
14462 	break;
14463       }
14464       if (ch=='(')
14465 	++counter1;
14466       if (ch==')'){
14467 	--counter1;
14468 	if ( (!counter1) && (!counter2) ){
14469 	  if ( (pos1>0) && (s[pos1]=='(') && isalphan(s[pos1-1])){
14470 	    --pos1;
14471 	    for (;pos1>=0;--pos1)
14472 	      if (!isalphan(s[pos1]))
14473 		break;
14474 	    ++pos1;
14475 	  }
14476 	  break;
14477 	}
14478       }
14479       if (ch=='[')
14480 	++counter2;
14481       if (ch==']'){
14482 	--counter2;
14483 	if ( (!counter1) && (!counter2) ){
14484 	  if ( (pos1>0) && (s[pos1]=='[') && isalphan(s[pos1-1])){
14485 	    --pos1;
14486 	    for (;pos1>=0;--pos1)
14487 	      if (!isalphan(s[pos1]))
14488 		break;
14489 	    ++pos1;
14490 	  }
14491 	  break;
14492 	}
14493       }
14494     }
14495     if (pos2==l+1)
14496       find_left(s,pos1,pos2);
14497   }
14498 
increase_selection(const string & s,int & pos1,int & pos2)14499   void increase_selection(const string & s,int & pos1,int& pos2){
14500     int l=int(s.size());
14501     int pos1_orig(pos1),pos2_orig(pos2);
14502     // adjust selection (does not change anything on a valid selection)
14503     find_left(s,pos1,pos2);
14504     find_right(s,pos1,pos2);
14505     if ( (pos1!=pos1_orig) || (pos2!=pos2_orig) )
14506       return;
14507     if (pos1 && (pos2<l) && ( (s[pos1-1]=='(') || (s[pos1-1]==',')) && (s[pos2]!=')') && (s[pos2]!=',')){
14508       ++pos2;
14509       find_right(s,pos1,pos2);
14510       return;
14511     }
14512     if (pos1>1){
14513       char op=s[pos1-1];
14514       --pos1;
14515       for (;pos1;--pos1){
14516 	if (s[pos1]==',')
14517 	  op=0;
14518 	if (!is_operator_char(s[pos1],op))
14519 	  break;
14520       }
14521       if (s[pos1]=='(' && pos1){
14522 	--pos1;
14523 	for (;pos1;--pos1){
14524 	  if (!isalphan(s[pos1]))
14525 	    break;
14526 	}
14527 	++pos1;
14528       }
14529       find_left(s,pos1,pos2);
14530       find_right(s,pos1,pos2);
14531       return;
14532     }
14533     pos1=0;
14534     ++pos2;
14535     find_right(s,pos1,pos2);
14536   }
14537 
decrease_selection(const string & s,int & pos1,int & pos2)14538   void decrease_selection(const string & s,int & pos1,int& pos2){
14539     int l=int(s.size());
14540     int pos2_orig(pos2);
14541     // adjust selection (does not change anything on a valid selection)
14542     find_left(s,pos1,pos2);
14543     if (pos2!=l)
14544       --pos2;
14545     if (!pos2)
14546       return;
14547     int counter1=0,counter2=0;
14548     char op=' ';
14549     if (pos2<l-1)
14550       op=s[pos2+1];
14551     for (;pos2>pos1;--pos2){
14552       char ch=s[pos2];
14553       if (ch=='('){
14554 	++counter1;
14555 	if ( (!counter1) && (!counter2) && pos2_orig && (s[pos2_orig-1]==')') ){
14556 	  pos1=pos2+1;
14557 	  pos2=pos2_orig-1;
14558 	  return;
14559 	}
14560       }
14561       if (ch==')')
14562 	--counter1;
14563       if (ch=='[')
14564 	++counter2;
14565       if (ch==']')
14566 	--counter2;
14567       if (ch==',')
14568 	op=0;
14569       if ( (!counter1) && (!counter2) && ( is_operator_char(ch,op) || (ch==',')) )
14570 	return;
14571     }
14572     for (;pos1<l;++pos1){
14573       char ch=s[pos1];
14574       if ( (ch=='(') ||  (ch=='[') || (ch=='+') || (ch==','))
14575 	break;
14576     }
14577     ++pos1;
14578     pos2=pos1+1;
14579     find_right(s,pos1,pos2);
14580   }
14581 
move_selection_right(const string & s,int & pos1,int & pos2)14582   void move_selection_right(const string & s,int & pos1, int & pos2){
14583     int l=int(s.size());
14584     // int pos1_orig(pos1),pos2_orig(pos2);
14585     // adjust selection (does not change anything on a valid selection)
14586     find_right(s,pos1,pos2);
14587     pos1=pos2;
14588     char op=s[pos1];
14589     for (;pos1<l;++pos1){
14590       if (s[pos1]==',')
14591 	op=0;
14592       if (!is_operator_char(s[pos1],op) && (s[pos1]!=')') && (s[pos1]!=']'))
14593 	break;
14594     }
14595     pos2=pos1+1;
14596     find_right(s,pos1,pos2);
14597   }
14598 
move_selection_left(const string & s,int & pos1,int & pos2)14599   void move_selection_left(const string & s,int & pos1, int & pos2){
14600     // int l=s.size();
14601     // int pos1_orig(pos1),pos2_orig(pos2);
14602     // adjust selection (does not change anything on a valid selection)
14603     find_left(s,pos1,pos2);
14604     pos2=pos1-1;
14605     char op=s[pos2];
14606     for (;pos2>0;--pos2){
14607       if (s[pos2-1]==',')
14608 	op=0;
14609       if (!is_operator_char(s[pos2-1],op) && (s[pos2-1]!='(') && (s[pos2-1]!='[') )
14610 	break;
14611     }
14612     if (pos2<=0){
14613       pos1=0;
14614       pos2=0;
14615       return;
14616     }
14617     pos1=pos2-1;
14618     find_left(s,pos1,pos2);
14619     find_right(s,pos1,pos2);
14620   }
14621 
remove_extension(const string & chaine)14622   string remove_extension(const string & chaine){
14623     int s=int(chaine.size());
14624     if (s>4 && chaine.substr(s-4,4)==".tns")
14625       return remove_extension(chaine.substr(0,s-4));
14626     int l=int(chaine.find_last_of('.',s));
14627     int ll=int(chaine.find_last_of('/',s));
14628     if (l>0 && l<s){
14629       if ( ll<=0 || ll>=s || l>ll)
14630 	return chaine.substr(0,l);
14631     }
14632     return chaine;
14633   }
14634 
14635   //environment * env=new environment;
14636 
14637   // Real object and real interval functions
14638 
operator =(const real_object & g)14639   real_object & real_object::operator = (const real_object & g) {
14640 #ifdef HAVE_LIBMPFR
14641     mpfr_clear(inf);
14642     mpfr_init2(inf,mpfr_get_prec(g.inf));
14643     mpfr_set(inf,g.inf,MPFR_RNDN);
14644 #else
14645     mpf_clear(inf);
14646     mpf_init_set(inf,g.inf);
14647 #endif
14648     return *this;
14649   }
14650 
14651 #ifdef HAVE_LIBMPFI
real_interval(const mpfi_t & interv)14652   real_interval::real_interval(const mpfi_t & interv) {
14653     int nbits=mpfi_get_prec(interv);
14654     mpfr_set_prec(inf,nbits);
14655     mpfi_get_fr(inf,interv);
14656     mpfi_init2(infsup,nbits);
14657     mpfi_set(infsup,interv);
14658   }
14659 #endif
14660 
operator =(const real_interval & g)14661   real_object & real_interval::operator = (const real_interval & g) {
14662 #ifdef HAVE_LIBMPFR
14663     mpfr_clear(inf);
14664 #else
14665     mpf_clear(inf);
14666 #endif
14667 #ifdef HAVE_LIBMPFI
14668     mpfi_clear(infsup);
14669 #else
14670 #ifdef HAVE_LIBMPFR
14671     mpfr_clear(sup);
14672 #else
14673     mpf_clear(sup);
14674 #endif
14675 #endif
14676 #ifdef HAVE_LIBMPFR
14677     mpfr_init2(inf,mpfr_get_prec(g.inf));
14678     mpfr_set(inf,g.inf,MPFR_RNDN);
14679 #else
14680     mpf_init_set(inf,g.inf);
14681 #endif
14682 #ifdef HAVE_LIBMPFI
14683     mpfi_init2(infsup,mpfi_get_prec(g.infsup));
14684     mpfi_set(infsup,g.infsup);
14685 #else
14686 #ifdef HAVE_LIBMPFR
14687     mpfr_init2(sup,mpfr_get_prec(g.sup));
14688     mpfr_set(sup,g.sup,MPFR_RNDN);
14689 #else
14690     mpf_init_set(sup,g.sup);
14691 #endif
14692 #endif
14693     return *this;
14694   }
14695 
operator =(const real_object & g)14696   real_object & real_interval::operator = (const real_object & g) {
14697 #ifdef NO_RTTI
14698     const real_interval * ptr=0;
14699 #else
14700     const real_interval * ptr=dynamic_cast<const real_interval *> (&g);
14701 #endif
14702     if (ptr)
14703       return *this=*ptr;
14704 #ifdef HAVE_LIBMPFR
14705     mpfr_clear(inf);
14706 #ifdef HAVE_LIBMPFI
14707     mpfi_clear(infsup);
14708 #else
14709     mpfr_clear(sup);
14710 #endif
14711     mpfr_init2(inf,mpfr_get_prec(g.inf));
14712     mpfr_set(inf,g.inf,MPFR_RNDN);
14713 #ifdef HAVE_LIBMPFI
14714     mpfi_init2(infsup,mpfr_get_prec(g.inf));
14715     mpfi_set_fr(infsup,g.inf);
14716 #else
14717     mpfr_init2(sup,mpfr_get_prec(g.inf));
14718     mpfr_set(sup,g.inf,MPFR_RNDN);
14719 #endif
14720 #else // HAVE_LIBMPFR
14721     mpf_clear(inf);
14722 #ifdef HAVE_LIBMPFI
14723     mpfi_clear(infsup);
14724 #else
14725     mpf_clear(sup);
14726 #endif
14727     mpf_init_set(inf,g.inf);
14728 #ifdef HAVE_LIBMPFI
14729     mpfi_init_set_fr(infsup,g.inf);
14730 #else
14731     mpf_init_set(sup,g.inf);
14732 #endif
14733 #endif // HAVE_LIBMPFR
14734     return *this;
14735   }
14736 
real_object()14737   real_object::real_object() {
14738 #ifdef HAVE_LIBMPFR
14739     mpfr_init(inf);
14740 #else
14741     mpf_init(inf);
14742 #endif
14743   }
14744 
real_object(const real_object & g)14745   real_object::real_object(const real_object & g){
14746 #ifdef HAVE_LIBMPFR
14747     mpfr_init2(inf,mpfr_get_prec(g.inf));
14748     mpfr_set(inf,g.inf,MPFR_RNDN);
14749 #else
14750     mpf_init_set(inf,g.inf);
14751 #endif
14752   }
14753 
real_object(double d)14754   real_object::real_object(double d) {
14755 #ifdef HAVE_LIBMPFR
14756     mpfr_init_set_d(inf,d,MPFR_RNDN);
14757 #else
14758     mpf_init_set_d(inf,d);
14759 #endif
14760   }
14761 
14762 #ifdef HAVE_LIBMPFR
real_object(const mpfr_t & d)14763   real_object::real_object(const mpfr_t & d) {
14764     mpfr_init2(inf,mpfr_get_prec(d));
14765     mpfr_set(inf,d,MPFR_RNDN);
14766   }
14767 #endif
14768 
real_object(const mpf_t & d)14769   real_object::real_object(const mpf_t & d) {
14770 #ifdef HAVE_LIBMPFR
14771     mpfr_init(inf);
14772     mpfr_set_f(inf,d,MPFR_RNDN);
14773 #else
14774     mpf_init_set(inf,d);
14775 #endif
14776   }
14777 
real_object(const gen & g)14778   real_object::real_object(const gen & g){
14779     switch (g.type){
14780     case _INT_:
14781 #ifdef HAVE_LIBMPFR
14782       mpfr_init_set_si(inf,g.val,MPFR_RNDN);
14783 #else
14784       mpf_init_set_si(inf,g.val);
14785 #endif
14786       return;
14787     case _DOUBLE_:
14788 #ifdef HAVE_LIBMPFR
14789       mpfr_init_set_d(inf,g._DOUBLE_val,MPFR_RNDN);
14790 #else
14791       mpf_init_set_d(inf,g._DOUBLE_val);
14792 #endif
14793       return;
14794     case _ZINT:
14795 #ifdef HAVE_LIBMPFR
14796       mpfr_init(inf);
14797       mpfr_set_z(inf,*g._ZINTptr,MPFR_RNDN);
14798 #else
14799       mpf_init(inf);
14800       mpf_set_z(inf,*g._ZINTptr);
14801 #endif
14802       return;
14803     case _REAL:
14804 #ifdef HAVE_LIBMPFR
14805       mpfr_init2(inf,mpfr_get_prec(g._REALptr->inf));
14806       mpfr_set(inf,g._REALptr->inf,MPFR_RNDN);
14807 #else
14808       mpf_init_set(inf,g._REALptr->inf);
14809 #endif
14810       return;
14811     }
14812     if (g.type==_FRAC){
14813       gen tmp=real_object(g._FRACptr->num)/real_object(g._FRACptr->den);
14814       if (tmp.type==_REAL){
14815 #ifdef HAVE_LIBMPFR
14816 	mpfr_init2(inf,mpfr_get_prec(tmp._REALptr->inf));
14817 	mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14818 #else
14819 	mpf_init_set(inf,tmp._REALptr->inf);
14820 #endif
14821 	return;
14822       }
14823     }
14824 #ifndef NO_STDEXCEPT
14825     setsizeerr(gettext("Unable to convert to real ")+g.print(context0));
14826 #endif
14827     return;
14828   }
14829 
real_object(const gen & g,unsigned int precision)14830   real_object::real_object(const gen & g,unsigned int precision){
14831     switch (g.type){
14832     case _INT_:
14833 #ifdef HAVE_LIBMPFR
14834       mpfr_init2(inf,precision);
14835       mpfr_set_si(inf,g.val,MPFR_RNDN);
14836 #else
14837       mpf_init_set_si(inf,g.val);
14838 #endif
14839       return;
14840     case _DOUBLE_:
14841 #ifdef HAVE_LIBMPFR
14842       mpfr_init2(inf,precision);
14843       mpfr_set_d(inf,g._DOUBLE_val,MPFR_RNDN);
14844 #else
14845       mpf_init_set_d(inf,g._DOUBLE_val);
14846 #endif
14847       return;
14848     case _ZINT:
14849 #ifdef HAVE_LIBMPFR
14850       mpfr_init2(inf,precision);
14851       mpfr_set_z(inf,*g._ZINTptr,MPFR_RNDN);
14852 #else
14853       mpf_init(inf);
14854       mpf_set_z(inf,*g._ZINTptr);
14855 #endif
14856       return;
14857     case _REAL:
14858 #ifdef HAVE_LIBMPFR
14859       mpfr_init2(inf,precision);
14860       mpfr_set(inf,g._REALptr->inf,MPFR_RNDN);
14861 #else
14862       mpf_init_set(inf,g._REALptr->inf);
14863 #endif
14864       return;
14865     }
14866     if (g.type==_FRAC){
14867       gen tmp=real_object(g._FRACptr->num,precision)/real_object(g._FRACptr->den,precision);
14868       if (tmp.type==_REAL){
14869 #ifdef HAVE_LIBMPFR
14870 	mpfr_init2(inf,mpfr_get_prec(tmp._REALptr->inf));
14871 	mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14872 #else
14873 	mpf_init_set(inf,tmp._REALptr->inf);
14874 #endif
14875 	return;
14876       }
14877     }
14878     int save_decimal_digits=decimal_digits(context0);
14879     set_decimal_digits(precision,context0);
14880     gen tmp=re(evalf(g,1,context0),context0);
14881     set_decimal_digits(save_decimal_digits,context0);
14882     if (tmp.type!=_REAL){
14883 #ifndef NO_STDEXCEPT
14884       setsizeerr(gettext("Unable to convert to real ")+g.print(context0));
14885 #endif
14886       return;
14887     }
14888 #ifdef HAVE_LIBMPFR
14889     mpfr_init2(inf,precision);
14890     mpfr_set(inf,tmp._REALptr->inf,MPFR_RNDN);
14891 #else
14892     mpf_init_set(inf,tmp._REALptr->inf);
14893 #endif
14894   }
14895 
gen(const real_object & g)14896   gen::gen(const real_object & g){
14897 #ifdef SMARTPTR64
14898       * ((ulonglong * ) this) = ulonglong(new ref_real_object) << 16;
14899 #else
14900     __REALptr = new ref_real_object;
14901 #endif
14902     type = _REAL;
14903     subtype=0;
14904 #ifdef HAVE_LIBMPFR
14905     mpfr_set_prec(_REALptr->inf,mpfr_get_prec(g.inf));
14906     mpfr_set(_REALptr->inf,g.inf,MPFR_RNDN);
14907 #else
14908     mpf_set(_REALptr->inf,g.inf);
14909 #endif
14910 #ifdef KHICAS
14911     if ((size_t) _REALptr > stackptr)
14912       ctrl_c=interrupted=true;
14913 #endif
14914   }
14915 
gen(const real_interval & g)14916   gen::gen(const real_interval & g){
14917 #ifdef SMARTPTR64
14918       * ((ulonglong * ) this) = ulonglong(new ref_real_interval) << 16;
14919 #else
14920       __REALptr = (ref_real_object *) new ref_real_interval;
14921 #endif
14922 #ifdef KHICAS
14923     if ((size_t) _REALptr > stackptr)
14924       ctrl_c=interrupted=true;
14925 #endif
14926     type = _REAL;
14927     subtype=0;
14928 #ifdef NO_RTTI
14929     real_interval * ptr=0;
14930 #else
14931     real_interval * ptr=dynamic_cast<real_interval *>(_REALptr);
14932 #endif
14933 #ifdef HAVE_LIBMPFR
14934     mpfr_set_prec(ptr->inf,mpfr_get_prec(g.inf));
14935     mpfr_set(ptr->inf,g.inf,MPFR_RNDN);
14936 #else
14937     mpf_set(ptr->inf,g.inf);
14938 #endif
14939 #ifdef HAVE_LIBMPFI
14940     int nbits=mpfi_get_prec(g.infsup);
14941     mpfi_set_prec(ptr->infsup,nbits);
14942     mpfi_set(ptr->infsup,g.infsup);
14943 #else
14944 #ifdef HAVE_LIBMPFR
14945     mpfr_set(ptr->sup,g.sup,MPFR_RNDN);
14946 #else
14947     mpf_set(ptr->sup,g.sup);
14948 #endif
14949 #endif
14950   }
14951 
evalf_double() const14952   double real_object::evalf_double() const{
14953 #ifdef HAVE_LIBMPFR
14954     return mpfr_get_d(inf,MPFR_RNDN);
14955 #else
14956     return mpf_get_d(inf);
14957 #endif
14958   }
14959 
addition(const gen & g,GIAC_CONTEXT) const14960   gen real_object::addition (const gen & g,GIAC_CONTEXT) const{
14961     switch (g.type){
14962     case _REAL:
14963       return *this+*g._REALptr;
14964     case _CPLX:
14965       return gen(this->addition(*g._CPLXptr,contextptr),*(g._CPLXptr+1));
14966     case _FRAC:
14967       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
14968 	return sym_add(*this,g,contextptr);
14969     case _INT_: case _DOUBLE_: case _ZINT:
14970 #ifdef HAVE_LIBMPFR
14971       return *this+real_object(g,mpfr_get_prec(inf));
14972 #else
14973       return *this+real_object(g);
14974 #endif
14975     default:
14976       return sym_add(*this,g,contextptr);
14977     }
14978     return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
14979   }
14980 
addition(const gen & g,GIAC_CONTEXT) const14981   gen real_interval::addition (const gen & g,GIAC_CONTEXT) const{
14982     switch (g.type){
14983     case _REAL:
14984       return *this+*g._REALptr;
14985     case _CPLX:
14986       return gen(this->addition(*g._CPLXptr,contextptr),*(g._CPLXptr+1));
14987     case _FRAC:
14988       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
14989 	return sym_add(*this,g,contextptr);
14990     case _INT_: case _DOUBLE_: case _ZINT:
14991 #ifdef HAVE_LIBMPFR
14992       return *this+real_object(g,mpfr_get_prec(inf));
14993 #else
14994       return *this+real_object(g);
14995 #endif
14996     default:
14997       return sym_add(*this,g,contextptr);
14998     }
14999     return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15000   }
15001 
operator +(const gen & g) const15002   gen real_object::operator + (const gen & g) const{
15003     return addition(g,context0);
15004   }
15005 
add(const real_interval & i,const real_interval & g)15006   static real_interval add(const real_interval & i,const real_interval & g){
15007     real_interval res(i);
15008 #ifdef HAVE_LIBMPFR
15009     mpfr_add(res.inf,i.inf,g.inf,MPFR_RNDD);
15010 #ifdef HAVE_LIBMPFI
15011     mpfi_add(res.infsup,i.infsup,g.infsup);
15012 #else
15013     mpfr_add(res.sup,i.sup,g.sup,MPFR_RNDU);
15014 #endif
15015 #else // HAVE_LIBMPFR
15016     mpf_add(res.inf,i.inf,g.inf);
15017 #ifdef HAVE_LIBMPFI
15018     mpfi_add(res.infsup,i.infsup,g.infsup);
15019 #else
15020     mpf_add(res.sup,i.sup,g.sup);
15021 #endif
15022 #endif // HAVE_LIBMPFR
15023     return res;
15024   }
15025 
operator +(const real_interval & g) const15026   real_interval real_interval::operator + (const real_interval & g) const{
15027     return add(*this,g);
15028   }
15029 
add(const real_interval & i,const real_object & g)15030   static real_interval add(const real_interval & i,const real_object & g){
15031 #ifdef NO_RTTI
15032     const real_interval * ptr=0;
15033 #else
15034     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15035 #endif
15036     if (ptr)
15037       return add(i,*ptr);
15038     real_interval res(i);
15039 #ifdef HAVE_LIBMPFR
15040     mpfr_add(res.inf,i.inf,g.inf,MPFR_RNDD);
15041 #ifdef HAVE_LIBMPFI
15042     mpfi_add_fr(res.infsup,i.infsup,g.inf);
15043 #else
15044     mpfr_add(res.sup,i.sup,g.inf,MPFR_RNDU);
15045 #endif
15046 #else // HAVE_LIBMPFR
15047     mpf_add(res.inf,i.inf,g.inf);
15048 #ifdef HAVE_LIBMPFI
15049     mpfi_add_fr(res.infsup,i.infsup,g.inf);
15050 #else
15051     mpf_add(res.sup,i.sup,g.inf);
15052 #endif
15053 #endif // HAVE_LIBMPFR
15054     return res;
15055   }
15056 
operator +(const real_object & g) const15057   gen real_interval::operator + (const real_object & g) const{
15058     return add(*this,g);
15059   }
15060 
operator +(const real_object & g) const15061   gen real_object::operator + (const real_object & g) const{
15062 #ifdef NO_RTTI
15063     const real_interval * ptr=0;
15064 #else
15065     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15066 #endif
15067     if (ptr)
15068       return add(*ptr,*this);
15069 #ifdef HAVE_LIBMPFR
15070     mpfr_t sum;
15071     mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15072     mpfr_add(sum,this->inf,g.inf,MPFR_RNDN);
15073     real_object res(sum);
15074     mpfr_clear(sum);
15075 #else
15076     mpf_t sum;
15077     mpf_init(sum);
15078     mpf_add(sum,this->inf,g.inf);
15079 #ifdef LONGFLOAT_DOUBLE
15080     real_object res; res.inf=sum;
15081 #else
15082     real_object res(sum);
15083 #endif
15084     mpf_clear(sum);
15085 #endif
15086     return res;
15087   }
15088 
substract(const gen & g,GIAC_CONTEXT) const15089   gen real_object::substract (const gen & g,GIAC_CONTEXT) const{
15090     switch (g.type){
15091     case _REAL:
15092       return *this-*g._REALptr;
15093     case _FRAC:
15094       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15095 	return sym_sub(*this,g,contextptr);
15096     case _INT_: case _DOUBLE_: case _ZINT:
15097 #ifdef HAVE_LIBMPFR
15098       return *this - real_object(g,mpfr_get_prec(inf));
15099 #else
15100       return *this - real_object(g);
15101 #endif
15102     default:
15103       return sym_sub(*this,g,contextptr);
15104     }
15105     return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15106   }
15107 
substract(const gen & g,GIAC_CONTEXT) const15108   gen real_interval::substract (const gen & g,GIAC_CONTEXT) const{
15109     switch (g.type){
15110     case _REAL:
15111       return *this-*g._REALptr;
15112     case _FRAC:
15113       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15114 	return sym_sub(*this,g,contextptr);
15115     case _INT_: case _DOUBLE_: case _ZINT:
15116 #ifdef HAVE_LIBMPFR
15117       return *this - real_object(g,mpfr_get_prec(inf));
15118 #else
15119       return *this - real_object(g);
15120 #endif
15121     default:
15122       return sym_sub(*this,g,contextptr);
15123     }
15124     return gensizeerr(gettext("real_object + gen")+this->print(contextptr)+","+g.print(contextptr));
15125   }
15126 
operator -(const gen & g) const15127   gen real_object::operator - (const gen & g) const{
15128     return substract(g,context0);
15129   }
15130 
sub(const real_interval & i,const real_interval & g)15131   static real_interval sub(const real_interval & i,const real_interval & g){
15132     real_interval res(i);
15133 #ifdef HAVE_LIBMPFI
15134     mpfi_sub(res.infsup,i.infsup,g.infsup);
15135     mpfr_sub(res.inf,i.inf,g.inf,MPFR_RNDD);
15136 #else
15137 #ifdef HAVE_LIBMPFR
15138     mpfr_sub(res.inf,i.sup,g.inf,MPFR_RNDD);
15139     mpfr_sub(res.sup,i.inf,g.sup,MPFR_RNDU);
15140 #else
15141     mpf_sub(res.inf,i.sup,g.inf);
15142     mpf_sub(res.sup,i.inf,g.sup);
15143 #endif
15144 #endif
15145     return res;
15146   }
15147 
operator -(const real_interval & g) const15148   real_interval real_interval::operator - (const real_interval & g) const{
15149     return sub(*this,g);
15150   }
15151 
sub(const real_interval & i,const real_object & g)15152   static real_interval sub(const real_interval & i,const real_object & g){
15153 #ifdef NO_RTTI
15154     const real_interval * ptr=0;
15155 #else
15156     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15157 #endif
15158     if (ptr)
15159       return sub(i,*ptr);
15160     real_interval res(i);
15161 #ifdef HAVE_LIBMPFI
15162     mpfi_sub_fr(res.infsup,i.infsup,g.inf);
15163     mpfr_sub(res.inf,i.inf,g.inf,MPFR_RNDD);
15164 #else
15165 #ifdef HAVE_LIBMPFR
15166     mpfr_sub(res.inf,i.sup,g.inf,MPFR_RNDD);
15167     mpfr_sub(res.sup,i.inf,g.inf,MPFR_RNDU);
15168 #else
15169     mpf_sub(res.inf,i.sup,g.inf);
15170     mpf_sub(res.sup,i.inf,g.inf);
15171 #endif
15172 #endif
15173     return res;
15174   }
15175 
operator -(const real_object & g) const15176   gen real_interval::operator - (const real_object & g) const{
15177     return sub(*this,g);
15178   }
15179 
operator -(const real_object & g) const15180   gen real_object::operator - (const real_object & g) const{
15181 #ifdef NO_RTTI
15182     const real_interval * ptr=0;
15183 #else
15184     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15185 #endif
15186     if (ptr)
15187       return -(*ptr)+(*this);
15188 #ifdef HAVE_LIBMPFR
15189     mpfr_t sum;
15190     mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15191     mpfr_sub(sum,this->inf,g.inf,MPFR_RNDN);
15192     real_object res(sum);
15193     mpfr_clear(sum);
15194 #else
15195     mpf_t sum;
15196     mpf_init(sum);
15197     mpf_sub(sum,this->inf,g.inf);
15198 #ifdef LONGFLOAT_DOUBLE
15199     real_object res; res.inf=sum;
15200 #else
15201     real_object res(sum);
15202 #endif
15203     mpf_clear(sum);
15204 #endif
15205     return res;
15206   }
15207 
operator -() const15208   gen real_object::operator -() const {
15209 #ifdef NO_RTTI
15210     const real_interval * ptr=0;
15211 #else
15212     const real_interval * ptr=dynamic_cast<const real_interval *>(this);
15213 #endif
15214     if (ptr)
15215       return -*ptr;
15216     real_object res(*this);
15217 #ifdef HAVE_LIBMPFR
15218     mpfr_neg(res.inf,res.inf,MPFR_RNDN);
15219 #else
15220     mpf_neg(res.inf,res.inf);
15221 #endif
15222     return res;
15223   }
15224 
inv() const15225   gen real_object::inv() const {
15226     real_object res(*this);
15227 #ifdef HAVE_LIBMPFR
15228     mpfr_ui_div(res.inf,1,res.inf,MPFR_RNDN);
15229 #else
15230     mpf_ui_div(res.inf,1,res.inf);
15231 #endif
15232     return res;
15233   }
15234 
sqrt() const15235   gen real_object::sqrt() const {
15236 #ifdef LONGFLOAT_DOUBLE
15237     real_object res; res.inf=std::sqrt(inf); return res;
15238 #else
15239     real_object res(*this);
15240 #ifdef HAVE_LIBMPFR
15241     mpfr_sqrt(res.inf,res.inf,MPFR_RNDN);
15242 #else
15243     mpf_sqrt(res.inf,res.inf);
15244 #endif
15245     return res;
15246 #endif
15247   }
15248 
abs() const15249   gen real_object::abs() const {
15250 #ifdef HAVE_LIBMPFR
15251     if (mpfr_sgn(inf)>=0)
15252 #else
15253     if (mpf_sgn(inf)>=0)
15254 #endif
15255       return *this;
15256     return -(*this);
15257   }
15258 
15259 #ifndef HAVE_LIBMPFR
compile_with_mpfr()15260   static void compile_with_mpfr(){
15261     setsizeerr(gettext("Compile with MPFR or USE_GMP_REPLACEMENTS if you want transcendental long float support"));
15262   }
15263 #endif
15264 
exp() const15265   gen real_object::exp() const {
15266     real_object res(*this);
15267 #ifdef USE_GMP_REPLACEMENTS
15268 #ifdef LONGFLOAT_DOUBLE
15269     res.inf=std::exp(res.inf);
15270 #else
15271     *res.inf = ::exp(*res.inf);
15272 #endif
15273 #else
15274 #ifdef HAVE_LIBMPFR
15275     mpfr_exp(res.inf,res.inf,MPFR_RNDN);
15276 #else
15277     compile_with_mpfr();
15278 #endif
15279 #endif // USE_GMP_REPLACEMENTS
15280     return res;
15281   }
15282 
log() const15283   gen real_object::log() const {
15284     real_object res(*this);
15285 #ifdef USE_GMP_REPLACEMENTS
15286 #ifdef LONGFLOAT_DOUBLE
15287     res.inf=std::log(res.inf);
15288 #else
15289     *res.inf = ::log(*res.inf);
15290 #endif
15291 #else
15292 #ifdef HAVE_LIBMPFR
15293     mpfr_log(res.inf,res.inf,MPFR_RNDN);
15294 #else
15295     compile_with_mpfr();
15296 #endif
15297 #endif
15298     return res;
15299   }
15300 
sin() const15301   gen real_object::sin() const {
15302     real_object res(*this);
15303 #ifdef USE_GMP_REPLACEMENTS
15304 #ifdef LONGFLOAT_DOUBLE
15305     res.inf=std::sin(res.inf);
15306 #else
15307     *res.inf = ::sin(*res.inf);
15308 #endif
15309 #else
15310 #ifdef HAVE_LIBMPFR
15311     mpfr_sin(res.inf,res.inf,MPFR_RNDN);
15312 #else
15313     compile_with_mpfr();
15314 #endif
15315 #endif
15316     return res;
15317   }
15318 
cos() const15319   gen real_object::cos() const {
15320     real_object res(*this);
15321 #ifdef USE_GMP_REPLACEMENTS
15322 #ifdef LONGFLOAT_DOUBLE
15323     res.inf=std::cos(res.inf);
15324 #else
15325     *res.inf = ::cos(*res.inf);
15326 #endif
15327 #else
15328 #ifdef HAVE_LIBMPFR
15329     mpfr_cos(res.inf,res.inf,MPFR_RNDN);
15330 #else
15331     compile_with_mpfr();
15332 #endif
15333 #endif
15334     return res;
15335   }
15336 
tan() const15337   gen real_object::tan() const {
15338     real_object res(*this);
15339 #ifdef USE_GMP_REPLACEMENTS
15340 #ifdef LONGFLOAT_DOUBLE
15341     res.inf=std::tan(res.inf);
15342 #else
15343     *res.inf = ::tan(*res.inf);
15344 #endif
15345 #else
15346 #ifdef HAVE_LIBMPFR
15347     mpfr_tan(res.inf,res.inf,MPFR_RNDN);
15348 #else
15349     compile_with_mpfr();
15350 #endif
15351 #endif
15352     return res;
15353   }
15354 
sinh() const15355   gen real_object::sinh() const {
15356     real_object res(*this);
15357 #ifdef USE_GMP_REPLACEMENTS
15358 #ifdef LONGFLOAT_DOUBLE
15359     res.inf=std::sinh(res.inf);
15360 #else
15361     *res.inf = ::sinh(*res.inf);
15362 #endif
15363 #else
15364 #ifdef HAVE_LIBMPFR
15365     mpfr_sinh(res.inf,res.inf,MPFR_RNDN);
15366 #else
15367     compile_with_mpfr();
15368 #endif
15369 #endif
15370     return res;
15371   }
15372 
cosh() const15373   gen real_object::cosh() const {
15374     real_object res(*this);
15375 #ifdef USE_GMP_REPLACEMENTS
15376 #ifdef LONGFLOAT_DOUBLE
15377     res.inf=std::cosh(res.inf);
15378 #else
15379     *res.inf = ::cosh(*res.inf);
15380 #endif
15381 #else
15382 #ifdef HAVE_LIBMPFR
15383     mpfr_cosh(res.inf,res.inf,MPFR_RNDN);
15384 #else
15385     compile_with_mpfr();
15386 #endif
15387 #endif
15388     return res;
15389   }
15390 
tanh() const15391   gen real_object::tanh() const {
15392     real_object res(*this);
15393 #ifdef USE_GMP_REPLACEMENTS
15394 #ifdef LONGFLOAT_DOUBLE
15395     res.inf=std::tanh(res.inf);
15396 #else
15397     *res.inf = ::tanh(*res.inf);
15398 #endif
15399 #else
15400 #ifdef HAVE_LIBMPFR
15401     mpfr_tanh(res.inf,res.inf,MPFR_RNDN);
15402 #else
15403     compile_with_mpfr();
15404 #endif
15405 #endif
15406     return res;
15407   }
15408 
asin() const15409   gen real_object::asin() const {
15410     real_object res(*this);
15411 #ifdef USE_GMP_REPLACEMENTS
15412 #ifdef LONGFLOAT_DOUBLE
15413     res.inf=std::asin(res.inf);
15414 #else
15415     *res.inf = ::asin(*res.inf);
15416 #endif
15417 #else
15418 #ifdef HAVE_LIBMPFR
15419     mpfr_asin(res.inf,res.inf,MPFR_RNDN);
15420 #else
15421     compile_with_mpfr();
15422 #endif
15423 #endif
15424     return res;
15425   }
15426 
acos() const15427   gen real_object::acos() const {
15428     real_object res(*this);
15429 #ifdef USE_GMP_REPLACEMENTS
15430 #ifdef LONGFLOAT_DOUBLE
15431     res.inf=std::acos(res.inf);
15432 #else
15433     *res.inf = ::acos(*res.inf);
15434 #endif
15435 #else
15436 #ifdef HAVE_LIBMPFR
15437     mpfr_acos(res.inf,res.inf,MPFR_RNDN);
15438 #else
15439     compile_with_mpfr();
15440 #endif
15441 #endif
15442     return res;
15443   }
15444 
atan() const15445   gen real_object::atan() const {
15446     real_object res(*this);
15447 #ifdef USE_GMP_REPLACEMENTS
15448 #ifdef LONGFLOAT_DOUBLE
15449     res.inf=std::atan(res.inf);
15450 #else
15451     *res.inf = ::atan(*res.inf);
15452 #endif
15453 #else
15454 #ifdef HAVE_LIBMPFR
15455     mpfr_atan(res.inf,res.inf,MPFR_RNDN);
15456 #else
15457     compile_with_mpfr();
15458 #endif
15459 #endif
15460     return res;
15461   }
15462 
asinh() const15463   gen real_object::asinh() const {
15464     real_object res(*this);
15465 #ifdef USE_GMP_REPLACEMENTS
15466 #ifdef LONGFLOAT_DOUBLE
15467     res.inf= std::log(res.inf+std::sqrt(res.inf*res.inf+1));
15468 #else
15469     *res.inf = ::asinh(*res.inf);
15470 #endif
15471 #else
15472 #ifdef HAVE_LIBMPFR
15473     mpfr_asinh(res.inf,res.inf,MPFR_RNDN);
15474 #else
15475     compile_with_mpfr();
15476 #endif
15477 #endif
15478     return res;
15479   }
15480 
acosh() const15481   gen real_object::acosh() const {
15482     real_object res(*this);
15483 #ifdef USE_GMP_REPLACEMENTS
15484 #ifdef LONGFLOAT_DOUBLE
15485     res.inf=std::log(res.inf+std::sqrt(res.inf+1)*std::sqrt(res.inf-1));
15486 #else
15487     *res.inf = ::acosh(*res.inf);
15488 #endif
15489 #else
15490 #ifdef HAVE_LIBMPFR
15491     mpfr_acosh(res.inf,res.inf,MPFR_RNDN);
15492 #else
15493     compile_with_mpfr();
15494 #endif
15495 #endif
15496     return res;
15497   }
15498 
atanh() const15499   gen real_object::atanh() const {
15500     real_object res(*this);
15501 #ifdef USE_GMP_REPLACEMENTS
15502 #ifdef LONGFLOAT_DOUBLE
15503     res.inf=std::log((1+res.inf)/(1-res.inf))/2;
15504 #else
15505     *res.inf = ::atanh(*res.inf);
15506 #endif
15507 #else
15508 #ifdef HAVE_LIBMPFR
15509     mpfr_atanh(res.inf,res.inf,MPFR_RNDN);
15510 #else
15511     compile_with_mpfr();
15512 #endif
15513 #endif
15514     return res;
15515   }
15516 
operator -() const15517   gen real_interval::operator -() const {
15518     real_interval res(*this);
15519 #ifdef HAVE_LIBMPFR
15520     mpfr_neg(res.inf,res.inf,MPFR_RNDU);
15521 #ifdef HAVE_LIBMPFI
15522     mpfi_neg(res.infsup,res.infsup);
15523 #else
15524     mpfr_neg(res.sup,res.sup,MPFR_RNDD);
15525     mpfr_swap(res.inf,res.sup);
15526 #endif
15527 #else // MPFR
15528     mpf_neg(res.inf,res.inf);
15529 #ifdef HAVE_LIBMPFI
15530     mpfi_neg(res.infsup,res.infsup);
15531 #else
15532     mpf_neg(res.sup,res.sup);
15533 #ifdef mpf_swap
15534     mpf_swap(res.inf,res.sup);
15535 #endif
15536 #endif
15537 #endif // MPFR
15538     return res;
15539   }
15540 
inv() const15541   gen real_interval::inv() const {
15542     real_interval res(*this);
15543 #ifdef HAVE_LIBMPFI
15544     mpfi_ui_div(res.infsup,1,res.infsup);
15545     mpfr_ui_div(res.inf,1,res.inf,MPFR_RNDD);
15546 #else
15547     // FIXME check sign
15548 #ifndef NO_STDEXCEPT
15549     setsizeerr(gettext("real_interval inv"));
15550 #endif
15551     /* mpf_neg(res.inf,res.inf);
15552        mpf_neg(res.sup,res.sup);
15553        mpf_swap(res.inf,res.sup); */
15554 #endif
15555     return res;
15556   }
15557 
sqrt() const15558   gen real_interval::sqrt() const {
15559     real_interval res(*this);
15560 #ifdef HAVE_LIBMPFI
15561     mpfi_sqrt(res.infsup,res.infsup);
15562     mpfr_sqrt(res.inf,res.inf,MPFR_RNDD);
15563     return res;
15564 #else
15565     return gensizeerr(gettext("real_interval sqrt"));
15566 #endif
15567   }
15568 
abs() const15569   gen real_interval::abs() const {
15570     real_interval res(*this);
15571 #ifdef HAVE_LIBMPFI
15572     mpfi_abs(res.infsup,res.infsup);
15573     mpfr_abs(res.inf,res.inf,MPFR_RNDD);
15574     return res;
15575 #else
15576     return gensizeerr(gettext("real_interval abs"));
15577 #endif
15578   }
15579 
exp() const15580   gen real_interval::exp() const {
15581     real_interval res(*this);
15582 #ifdef HAVE_LIBMPFI
15583     mpfi_exp(res.infsup,res.infsup);
15584     mpfr_exp(res.inf,res.inf,MPFR_RNDD);
15585     return res;
15586 #else
15587     return gensizeerr(gettext("real_interval sqrt"));
15588 #endif
15589   }
15590 
log() const15591   gen real_interval::log() const {
15592     real_interval res(*this);
15593 #ifdef HAVE_LIBMPFI
15594     mpfi_log(res.infsup,res.infsup);
15595     mpfr_log(res.inf,res.inf,MPFR_RNDD);
15596     return res;
15597 #else
15598     return gensizeerr(gettext("real_interval sqrt"));
15599 #endif
15600   }
15601 
sin() const15602   gen real_interval::sin() const {
15603     real_interval res(*this);
15604 #ifdef HAVE_LIBMPFI
15605     mpfi_sin(res.infsup,res.infsup);
15606     mpfr_sin(res.inf,res.inf,MPFR_RNDD);
15607     return res;
15608 #else
15609     return gensizeerr(gettext("real_interval sqrt"));
15610 #endif
15611   }
15612 
cos() const15613   gen real_interval::cos() const {
15614     real_interval res(*this);
15615 #ifdef HAVE_LIBMPFI
15616     mpfi_cos(res.infsup,res.infsup);
15617     mpfr_cos(res.inf,res.inf,MPFR_RNDD);
15618     return res;
15619 #else
15620     return gensizeerr(gettext("real_interval sqrt"));
15621 #endif
15622   }
15623 
tan() const15624   gen real_interval::tan() const {
15625     real_interval res(*this);
15626 #ifdef HAVE_LIBMPFI
15627     mpfi_tan(res.infsup,res.infsup);
15628     mpfr_tan(res.inf,res.inf,MPFR_RNDD);
15629     return res;
15630 #else
15631     return gensizeerr(gettext("real_interval sqrt"));
15632 #endif
15633   }
15634 
sinh() const15635   gen real_interval::sinh() const {
15636     real_interval res(*this);
15637 #ifdef HAVE_LIBMPFI
15638     mpfi_sinh(res.infsup,res.infsup);
15639     mpfr_sinh(res.inf,res.inf,MPFR_RNDD);
15640     return res;
15641 #else
15642     return gensizeerr(gettext("real_interval sqrt"));
15643 #endif
15644   }
15645 
cosh() const15646   gen real_interval::cosh() const {
15647     real_interval res(*this);
15648 #ifdef HAVE_LIBMPFI
15649     mpfi_cosh(res.infsup,res.infsup);
15650     mpfr_cosh(res.inf,res.inf,MPFR_RNDD);
15651     return res;
15652 #else
15653     return gensizeerr(gettext("real_interval sqrt"));
15654 #endif
15655   }
15656 
tanh() const15657   gen real_interval::tanh() const {
15658     real_interval res(*this);
15659 #ifdef HAVE_LIBMPFI
15660     mpfi_tanh(res.infsup,res.infsup);
15661     mpfr_tanh(res.inf,res.inf,MPFR_RNDD);
15662     return res;
15663 #else
15664     return gensizeerr(gettext("real_interval sqrt"));
15665 #endif
15666   }
15667 
asin() const15668   gen real_interval::asin() const {
15669     real_interval res(*this);
15670 #ifdef HAVE_LIBMPFI
15671     mpfi_asin(res.infsup,res.infsup);
15672     mpfr_asin(res.inf,res.inf,MPFR_RNDD);
15673     return res;
15674 #else
15675     return gensizeerr(gettext("real_interval sqrt"));
15676 #endif
15677   }
15678 
acos() const15679   gen real_interval::acos() const {
15680     real_interval res(*this);
15681 #ifdef HAVE_LIBMPFI
15682     mpfi_acos(res.infsup,res.infsup);
15683     mpfr_acos(res.inf,res.inf,MPFR_RNDD);
15684     return res;
15685 #else
15686     return gensizeerr(gettext("real_interval sqrt"));
15687 #endif
15688   }
15689 
atan() const15690   gen real_interval::atan() const {
15691     real_interval res(*this);
15692 #ifdef HAVE_LIBMPFI
15693     mpfi_atan(res.infsup,res.infsup);
15694     mpfr_atan(res.inf,res.inf,MPFR_RNDD);
15695     return res;
15696 #else
15697     return gensizeerr(gettext("real_interval sqrt"));
15698 #endif
15699   }
15700 
asinh() const15701   gen real_interval::asinh() const {
15702     real_interval res(*this);
15703 #ifdef HAVE_LIBMPFI
15704     mpfi_asinh(res.infsup,res.infsup);
15705     mpfr_asinh(res.inf,res.inf,MPFR_RNDD);
15706     return res;
15707 #else
15708     return gensizeerr(gettext("real_interval sqrt"));
15709 #endif
15710   }
15711 
acosh() const15712   gen real_interval::acosh() const {
15713     real_interval res(*this);
15714 #ifdef HAVE_LIBMPFI
15715     mpfi_acosh(res.infsup,res.infsup);
15716     mpfr_acosh(res.inf,res.inf,MPFR_RNDD);
15717     return res;
15718 #else
15719     return gensizeerr(gettext("real_interval sqrt"));
15720 #endif
15721   }
15722 
atanh() const15723   gen real_interval::atanh() const {
15724     real_interval res(*this);
15725 #ifdef HAVE_LIBMPFI
15726     mpfi_atanh(res.infsup,res.infsup);
15727     mpfr_atanh(res.inf,res.inf,MPFR_RNDD);
15728     return res;
15729 #else
15730     return gensizeerr(gettext("real_interval sqrt"));
15731 #endif
15732   }
15733 
multiply(const gen & g,GIAC_CONTEXT) const15734   gen real_object::multiply (const gen & g,GIAC_CONTEXT) const{
15735     switch (g.type){
15736     case _REAL:
15737       return *this * *g._REALptr;
15738     case _CPLX:
15739       return gen(this->multiply(*g._CPLXptr,contextptr),this->multiply(*(g._CPLXptr+1),contextptr));
15740     case _FRAC:
15741       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15742 	return sym_mult(*this,g,contextptr);
15743     case _INT_: case _DOUBLE_: case _ZINT:
15744 #ifdef HAVE_LIBMPFR
15745       return *this * real_object(g,mpfr_get_prec(inf));
15746 #else
15747       return *this * real_object(g);
15748 #endif
15749     default:
15750       return sym_mult(*this,g,contextptr);
15751     }
15752   }
15753 
multiply(const gen & g,GIAC_CONTEXT) const15754   gen real_interval::multiply (const gen & g,GIAC_CONTEXT) const{
15755     switch (g.type){
15756     case _REAL:
15757       return *this * *g._REALptr;
15758     case _CPLX:
15759       return gen(this->multiply(*g._CPLXptr,contextptr),this->multiply(*(g._CPLXptr+1),contextptr));
15760     case _FRAC:
15761       if (!is_integer(g._FRACptr->num) || !is_integer(g._FRACptr->den))
15762 	return sym_mult(*this,g,contextptr);
15763     case _INT_: case _DOUBLE_: case _ZINT:
15764 #ifdef HAVE_LIBMPFR
15765       return *this * real_object(g,mpfr_get_prec(inf));
15766 #else
15767       return *this * real_object(g);
15768 #endif
15769     default:
15770       return sym_mult(*this,g,contextptr);
15771     }
15772   }
15773 
operator *(const gen & g) const15774   gen real_object::operator * (const gen & g) const{
15775     return multiply(g,context0);
15776   }
15777 
operator /(const gen & g) const15778   gen real_object::operator / (const gen & g) const{
15779     return *this * g.inverse(context0);
15780   }
15781 
divide(const gen & g,GIAC_CONTEXT) const15782   gen real_object::divide (const gen & g,GIAC_CONTEXT) const{
15783     return multiply(g.inverse(contextptr),contextptr);
15784   }
15785 
divide(const gen & g,GIAC_CONTEXT) const15786   gen real_interval::divide (const gen & g,GIAC_CONTEXT) const{
15787     return multiply(g.inverse(contextptr),contextptr);
15788   }
15789 
operator /(const real_object & g) const15790   gen real_object::operator / (const real_object & g) const{
15791     return *this * g.inv();
15792   }
15793 
mul(const real_interval & i,const real_interval & g)15794   static real_interval mul(const real_interval & i,const real_interval & g){
15795     real_interval res(i);
15796 #ifdef HAVE_LIBMPFR
15797     mpfr_mul(res.inf,i.inf,g.inf,MPFR_RNDN);
15798 #else
15799     mpf_mul(res.inf,i.inf,g.inf);
15800 #endif
15801 #ifdef HAVE_LIBMPFI
15802     mpfi_mul(res.infsup,i.infsup,g.infsup);
15803 #else
15804     // FIXME: should check signs for interval arithmetic!!
15805 #ifndef NO_STDEXCEPT
15806     setsizeerr(gettext("real_interval mul"));
15807 #endif
15808     // mpf_mul(res.sup,i.sup,g.sup);
15809 #endif
15810     return res;
15811   }
15812 
operator *(const real_interval & g) const15813   real_interval real_interval::operator * (const real_interval & g) const{
15814     return mul(*this,g);
15815   }
15816 
mul(const real_interval & i,const real_object & g)15817   static real_interval mul(const real_interval & i,const real_object & g){
15818 #ifdef NO_RTTI
15819     const real_interval * ptr=0;
15820 #else
15821     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15822 #endif
15823     if (ptr)
15824       return mul(i,*ptr);
15825     real_interval res(i);
15826 #ifdef HAVE_LIBMPFR
15827     mpfr_mul(res.inf,i.inf,g.inf,MPFR_RNDN);
15828 #else
15829     mpf_mul(res.inf,i.inf,g.inf);
15830 #endif
15831 #ifdef HAVE_LIBMPFI
15832     mpfi_mul_fr(res.infsup,i.infsup,g.inf);
15833 #else
15834     // FIXME: should check signs for interval arithmetic!!
15835 #ifndef NO_STDEXCEPT
15836     setsizeerr(gettext("real_interval mul 2"));
15837 #endif
15838     // mpf_mul(res.sup,i.sup,g.inf);
15839 #endif
15840     return res;
15841   }
15842 
operator *(const real_object & g) const15843   gen real_interval::operator * (const real_object & g) const{
15844     return mul(*this,g);
15845   }
15846 
operator *(const real_object & g) const15847   gen real_object::operator * (const real_object & g) const{
15848 #ifdef NO_RTTI
15849     const real_interval * ptr=0;
15850 #else
15851     const real_interval * ptr=dynamic_cast<const real_interval *>(&g);
15852 #endif
15853     if (ptr)
15854       return mul(*ptr,*this);
15855 #ifdef HAVE_LIBMPFR
15856     mpfr_t sum;
15857     mpfr_init2(sum,giacmin(mpfr_get_prec(this->inf),mpfr_get_prec(g.inf)));
15858     mpfr_mul(sum,this->inf,g.inf,MPFR_RNDN);
15859     real_object res(sum);
15860     mpfr_clear(sum);
15861 #else
15862     mpf_t sum;
15863     mpf_init(sum);
15864     mpf_mul(sum,this->inf,g.inf);
15865 #ifdef LONGFLOAT_DOUBLE
15866     real_object res; res.inf=sum;
15867 #else
15868     real_object res(sum);
15869 #endif
15870     mpf_clear(sum);
15871 #endif
15872     return res;
15873   }
15874 
is_positive() const15875   int real_object::is_positive() const{
15876 #ifdef HAVE_LIBMPFR
15877     return mpfr_sgn(inf);
15878 #else
15879     return mpf_sgn(inf);
15880 #endif
15881   }
15882 
is_positive() const15883   int real_interval::is_positive() const{
15884 #ifdef HAVE_LIBMPFI
15885     if (mpfi_is_zero(infsup)>0)
15886       return 0;
15887     if (mpfi_is_pos(infsup))
15888       return 1;
15889     if (mpfi_is_nonpos(infsup))
15890       return -1;
15891     return 0;
15892 #else
15893 #ifdef HAVE_LIBMPFR
15894     return mpfr_sgn(inf);
15895 #else
15896     return mpf_sgn(inf);
15897 #endif
15898 #endif
15899   }
15900 
print_binary(const real_object & r)15901   string print_binary(const real_object & r){
15902 #ifdef HAVE_LIBMPFR
15903     mp_exp_t expo;
15904     int dd=mpfr_get_prec(r.inf);
15905 #ifdef VISUALC
15906     char * ptr=new char[dd+2];
15907 #else
15908     char ptr[dd+2];
15909 #endif
15910     if (!mpfr_get_str(ptr,&expo,2,dd,r.inf,MPFR_RNDN) || !(*ptr))
15911       return "MPFR print binary error "+r.print(context0);
15912     string res;
15913     if (ptr[0]=='-')
15914       res="-0000."+string(ptr+1);
15915     else
15916       res="0000."+string(ptr);
15917 #ifdef VISUALC
15918     delete [] ptr;
15919 #endif // VISUALC
15920     return res+"E"+print_INT_(expo);
15921 #else // MPFR
15922     return "Error no MPFR printing "+r.print(context0);
15923 #endif
15924   }
15925 
read_binary(const string & s,unsigned int precision)15926   gen read_binary(const string & s,unsigned int precision){
15927 #ifdef HAVE_LIBMPFR
15928     real_object r;
15929     mpfr_set_prec(r.inf,precision);
15930 #ifndef HAVE_MPFR_SET_STR_RAW
15931     // MPFR 2.2
15932     mpfr_strtofr (r.inf, (char *)s.c_str(), 0, 2, MPFR_RNDN);
15933 #else
15934     // FOR MPFR 2.0 use instead
15935     mpfr_set_str_raw(r.inf,(char *)s.c_str());
15936 #endif // GNUWINCE
15937     return r;
15938     return gensizeerr(gettext("MPFR error reading binary ")+s);
15939 #else // HAVE_LIBMPFR
15940     return gensizeerr(gettext("Error no MPFR reading ")+s);
15941 #endif // HAVE_LIBMPFR
15942     return undef;
15943   }
15944 
print(GIAC_CONTEXT) const15945   std::string real_object::print(GIAC_CONTEXT) const{
15946 #if defined HAVE_LIBMPFI && !defined NO_RTTI
15947     if (const real_interval * ptr=dynamic_cast<const real_interval *>(this)){
15948       mpfr_t l,u;
15949       int nbits=mpfi_get_prec(ptr->infsup);
15950       mpfr_init2(l,nbits); mpfr_init2(u,nbits);
15951       mpfi_get_left(l,ptr->infsup); mpfi_get_right(u,ptr->infsup);
15952       real_object L(l),U(u);
15953       mpfr_clear(l); mpfr_clear(u);
15954       string s("[");
15955       s += L.print(contextptr);
15956       s += "..";
15957       s += U.print(contextptr);
15958       s += "]";
15959       return s;
15960     }
15961 #endif
15962 #ifdef HAVE_LIBMPFR
15963     if (mpfr_nan_p(inf))
15964       return "undef";
15965     bool negatif=mpfr_sgn(inf)<0;
15966     if (mpfr_inf_p(inf))
15967       return negatif?"-infinity":"+infinity";
15968     mp_exp_t expo;
15969     int dd=mpfr_get_prec(inf);
15970 #ifdef EMCC // workaround: mpfr_set_prec or get_prec has problems with emcc
15971     if (dd==53)
15972       dd=100;
15973 #endif
15974     dd=bits2digits(dd);
15975     dd--;
15976 #ifdef VISUALC
15977     char * ptr=new char[dd+2];
15978 #else
15979     char ptr[dd+2];
15980 #endif
15981     if (negatif){
15982       mpfr_t inf2;
15983       mpfr_init2(inf2,mpfr_get_prec(inf));
15984       mpfr_neg(inf2,inf,MPFR_RNDN);
15985       mpfr_get_str(ptr,&expo,10,dd,inf2,MPFR_RNDN);
15986       mpfr_clear(inf2);
15987     }
15988     else
15989       mpfr_get_str(ptr,&expo,10,dd,inf,MPFR_RNDN);
15990     std::string res(ptr);
15991     if (expo){
15992       if (expo==1){
15993 	string reste(res.substr(1,res.size()-1));
15994 	res=res[0]+("."+reste);
15995       }
15996       else {
15997 	res = "0."+res;
15998 	res += calc_mode(contextptr)==1?'E':'e';
15999 	res += print_INT_(expo);
16000       }
16001     }
16002     else
16003       res="0."+res;
16004 #ifdef VISUALC
16005     delete [] ptr;
16006 #endif
16007     if (negatif)
16008       return "-"+res;
16009     else
16010       return res;
16011 #else
16012     return printmpf_t(inf,contextptr);
16013 #endif
16014   }
16015 
is_zero() const16016   bool real_object::is_zero() const{
16017 #ifdef HAVE_LIBMPFR
16018     return !mpfr_sgn(inf);
16019 #else
16020     return mpf_sgn(inf)==0;
16021 #endif
16022   }
16023 
maybe_zero() const16024   bool real_object::maybe_zero() const{
16025 #ifdef HAVE_LIBMPFR
16026     return !mpfr_sgn(inf);
16027 #else
16028     return mpf_sgn(inf)==0;
16029 #endif
16030   }
16031 
is_zero() const16032   bool real_interval::is_zero() const {
16033 #ifdef HAVE_LIBMPFI
16034     return mpfi_is_zero(infsup);
16035 #else
16036     return real_object::is_zero();
16037 #endif
16038   }
16039 
maybe_zero() const16040   bool real_interval::maybe_zero() const{
16041 #ifdef HAVE_LIBMPFI
16042     return mpfi_has_zero(infsup);
16043 #else
16044     return real_object::maybe_zero();
16045 #endif
16046   }
16047 
is_inf() const16048   bool real_object::is_inf() const{
16049 #ifdef HAVE_LIBMPFR
16050     return !mpfr_inf_p(inf);
16051 #else
16052 #ifndef NO_STDEXCEPT
16053     setsizeerr();
16054 #endif
16055     return false;
16056 #endif
16057   }
16058 
is_inf() const16059   bool real_interval::is_inf() const{
16060 #ifdef HAVE_LIBMPFI
16061     return !mpfi_inf_p(infsup);
16062 #else
16063     return real_object::is_inf();
16064 #endif
16065   }
16066 
is_nan() const16067   bool real_object::is_nan() const{
16068 #ifdef HAVE_LIBMPFR
16069     return !mpfr_nan_p(inf);
16070 #else
16071 #ifndef NO_STDEXCEPT
16072     setsizeerr();
16073 #endif
16074     return false;
16075 #endif
16076   }
16077 
is_nan() const16078   bool real_interval::is_nan() const{
16079 #ifdef HAVE_LIBMPFI
16080     return !mpfi_nan_p(infsup);
16081 #else
16082     return real_object::is_nan();
16083 #endif
16084   }
16085 
iprotecteval(const gen & g,int level,GIAC_CONTEXT)16086   gen iprotecteval(const gen & g,int level,GIAC_CONTEXT){
16087 #ifdef KHICAS
16088     enable_back_interrupt();
16089     gen res=protecteval(g,level,contextptr);
16090     disable_back_interrupt();
16091     return res;
16092 #else
16093     return protecteval(g,level,contextptr);
16094 #endif
16095   }
16096 
16097 #if 0 // def KHICAS
16098 #undef HAVE_LIBPTHREAD
16099 #endif
16100 
16101 #ifdef HAVE_LIBPTHREAD
16102   struct caseval_param{
16103     const char * s;
16104     gen ans;
16105     context * contextptr;
16106     pthread_mutex_t mutex;
16107   };
thread_caseval(void * ptr_)16108   void * thread_caseval(void * ptr_){
16109     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
16110     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
16111     caseval_param * ptr=(caseval_param *)ptr_;
16112     pthread_mutex_lock(&ptr->mutex);
16113     gen g(ptr->s,ptr->contextptr);
16114     g=equaltosto(g,ptr->contextptr);
16115     ptr->ans=iprotecteval(g,1,ptr->contextptr);
16116     pthread_mutex_unlock(&ptr->mutex);
16117     return ptr;
16118   }
16119 #endif
16120 
islogo(const gen & g)16121   bool islogo(const gen & g){
16122     if (g.type!=_VECT || g._VECTptr->empty()) return false;
16123     if (g.subtype==_LOGO__VECT) return true;
16124     const vecteur & v=*g._VECTptr;
16125     if (islogo(v.back()))
16126       return true;
16127     for (size_t i=0;i<v.size();++i){
16128       if (v[i].type==_VECT && v[i].subtype==_LOGO__VECT)
16129 	return true;
16130     }
16131     return false;
16132   }
16133 #ifdef KHICAS
16134   extern logo_turtle * turtleptr;
16135   gen _efface_logo(const gen & g,GIAC_CONTEXT);
16136 #endif
16137 
caseval(const char * s)16138   const char * caseval(const char *s){
16139     ctrl_c=interrupted=false;
16140     static string * sptr=0;
16141     if (!sptr) sptr=new string;
16142     string & S=*sptr;
16143     static context * contextptr=0;
16144     if (!contextptr) contextptr=new context;
16145     context & C=*contextptr;
16146     if (!strcmp(s,"shell off")){
16147       os_shell=false;
16148       return "shell off";
16149     }
16150     if (!strcmp(s,"warn off")){
16151       warn_symb_program_sto=false;
16152       return "warn off";
16153     }
16154     if (!strcmp(s,"shell on")){
16155       os_shell=true;
16156       return "shell on";
16157     }
16158     if (!strcmp(s,"warn on")){
16159       warn_symb_program_sto=true;
16160       return "warn on";
16161     }
16162 #ifdef KHICAS
16163     if (!turtleptr){
16164       turtle();
16165       _efface_logo(vecteur(0),contextptr);
16166     }
16167 #ifndef NSPIRE_NEWLIB
16168     if (!strcmp(s,"*")){
16169       int res=xcas::console_main(contextptr);
16170       S=printint(res);
16171       return S.c_str();
16172     }
16173 #endif
16174     if (!strcmp(s,"+")){
16175       char buf[4096]="def f(x):\n  return x*x\n";
16176       if (file_exists("temp.py")){
16177 	const char * ch=read_file("temp.py");
16178 	S=ch;
16179 	if (S.size()>sizeof(buf))
16180 	  S=S.substr(0,sizeof(buf)-1);
16181 	strcpy(buf,S.c_str());
16182       }
16183       xcas::textedit(buf,sizeof(buf),contextptr);
16184       S=buf;
16185       return S.c_str();
16186     }
16187     if (!strcmp(s,"toolbox menu")){
16188       char buf[1024]="";
16189       showCatalog(buf,0,0,&C);
16190       drawRectangle(0,0,320,222,_WHITE);
16191       S=buf;
16192       return S.c_str();
16193     }
16194     if (!strcmp(s,"var menu")){
16195       gen g=select_var(contextptr);
16196       drawRectangle(0,0,320,222,_WHITE);
16197       S=g.type==_STRNG?*g._STRNGptr:g.print(contextptr);
16198       if (!strcmp(S.c_str(),"undef"))
16199 	S="";
16200       return S.c_str();
16201     }
16202     if (!strcmp(s,".")){
16203       xcas::displaylogo();
16204       S=turtle_state(contextptr).print(&C);
16205       return S.c_str();
16206     }
16207     if (!strcmp(s,"..")){
16208       _efface_logo(vecteur(0),contextptr);
16209       return "turtle cleared";
16210     }
16211 #endif
16212     const char init[]="init geogebra";
16213     const char close[]="close geogebra";
16214     if (!strcmp(s,init)){
16215       init_geogebra(1,&C);
16216       return "geogebra mode on";
16217     }
16218     if (!strcmp(s,close)){
16219       init_geogebra(0,&C);
16220       return "geogebra mode off";
16221     }
16222 #ifdef TIMEOUT
16223     if (strlen(s)>8){
16224       string args(s);
16225       if (args.substr(0,8)=="timeout "){
16226 	string t=args.substr(8,args.size()-8);
16227 	double f=atof(t.c_str());
16228 	if (f>=0 && f<24*60){
16229 	  caseval_maxtime=f;
16230 	  S="Max eval time set to "+gen(f).print();
16231 	  return S.c_str();
16232 	}
16233       }
16234       if (args.substr(0,8)=="ckevery "){
16235 	string t=args.substr(8,args.size()-8);
16236 	int f=atoi(t.c_str());
16237 	if (f>0 && f<1e6){
16238 	  caseval_mod=f;
16239 	  S="Check every "+gen(f).print();
16240 	  return S.c_str();
16241 	}
16242       }
16243     }
16244     ctrl_c=false;
16245     interrupted=false;
16246     caseval_begin=time(0);
16247 #endif
16248 #ifdef HAVE_LIBPTHREAD
16249     gen g;
16250     caseval_param cp={s,0,&C,PTHREAD_MUTEX_INITIALIZER};
16251     pthread_t pth;
16252     pthread_attr_t attr;
16253     pthread_attr_init(&attr);
16254     int cres=pthread_create(&pth,&attr,thread_caseval,(void *)&cp);
16255     if (cres){
16256       g=gen(s,&C);
16257       g=equaltosto(g,&C);
16258       g=iprotecteval(g,1,&C);
16259     }
16260     else {
16261       // void * ptr;
16262 #ifdef TIMEOUT
16263       double d=caseval_maxtime;
16264 #else
16265       double d=3;
16266 #endif
16267       usleep(10000);
16268       for (;d>0;--d){
16269 	for (unsigned k=0;k<100;++k){
16270 	  if (ctrl_c || interrupted){
16271 	    d=0;
16272 	    break;
16273 	  }
16274 	  int locked=pthread_mutex_trylock(&cp.mutex);
16275 	  if (!locked){
16276 	    pthread_mutex_unlock(&cp.mutex);
16277 	    void * ptr;
16278 	    cres=pthread_join(pth,&ptr);
16279 	    d=-1;
16280 	    if (cres){
16281 	      g=string2gen("Thread join error",false);
16282 	      g.subtype=-1;
16283 	    }
16284 	    else
16285 	      g=cp.ans;
16286 	    break;
16287 	  }
16288 	  usleep(10000);
16289 	}
16290       }
16291       if (d==0){
16292 	ctrl_c=interrupted=true;
16293 	usleep(200000);
16294 	pthread_cancel(pth);
16295 	// cres=pthread_join(pth,NULL); // does not work
16296 	g=string2gen("Timeout",false);
16297 	g.subtype=-1;
16298       }
16299       pthread_attr_destroy(&attr);
16300     }
16301 #else
16302     gen g(s,&C);
16303     g=equaltosto(g,&C);
16304     if (g.type==_VECT && !g._VECTptr->empty() && g._VECTptr->front().is_symb_of_sommet(at_set_language)){
16305       vecteur v=*g._VECTptr;
16306       iprotecteval(v.front(),1,&C);
16307       v.erase(v.begin());
16308       if (g.subtype==_SEQ__VECT && v.size()==1)
16309 	g=v.front();
16310       else
16311 	g=gen(v,g.subtype);
16312     }
16313     gen gp=g;
16314     if (gp.is_symb_of_sommet(at_add_autosimplify))
16315       gp=gp._SYMBptr->feuille;
16316 #ifdef KHICAS
16317     bool push=false;
16318 #else
16319     bool push=!gp.is_symb_of_sommet(at_mathml) && !gp.is_symb_of_sommet(at_set_language);
16320 #endif
16321     //bool push=!g.is_symb_of_sommet(at_mathml);
16322     if (push){
16323       history_in(&C).push_back(g);
16324       // COUT << "hin " << g << '\n';
16325     }
16326     g=iprotecteval(g,1,&C);
16327     if (push){
16328       history_out(&C).push_back(g);
16329       // COUT << "hout " << g << '\n';
16330     }
16331 #endif
16332 #ifdef EMCC
16333     // compile with -s LEGACY_GL_EMULATION=1
16334     gen last=g;
16335     while (last.type==_VECT && last.subtype!=_LOGO__VECT && !last._VECTptr->empty()){
16336       gen tmp=last._VECTptr->back();
16337       if (tmp.is_symb_of_sommet(at_equal))
16338 	last=vecteur(last._VECTptr->begin(),last._VECTptr->end()-1);
16339       else
16340 	last=tmp;
16341     }
16342     if (last.type==_VECT && last.subtype==_LOGO__VECT){
16343       S="gr2d(logo("+last.print(&C)+"))";
16344       return S.c_str();
16345     }
16346     if (calc_mode(&C)!=1 && (last.is_symb_of_sommet(at_pnt) || last.is_symb_of_sommet(at_pixon))){
16347 #if !defined(GIAC_GGB) && defined(EMCC)
16348       if (is3d(last)){
16349 	bool worker=false;
16350 	worker=EM_ASM_INT_V({
16351 	    if (Module.worker) return 1; else return 0;
16352 	});
16353 	if (worker) return "3d not supported if workers are enabled";
16354 	//giac_renderer(last.print(&C).c_str());
16355 	int n=giac_gen_renderer(g,&C);
16356 	S="gl3d "+print_INT_(n);
16357 	return S.c_str();
16358       }
16359 #endif // GIAC_GGB
16360       last=remove_at_pnt(last);
16361       if (last.is_symb_of_sommet(at_pixon)){
16362 	S="gr2d(pixon(";
16363 	pixon_print(g,S,&C);
16364 	S+="))";
16365 	return S.c_str();
16366       }
16367       return svg2doutput(g,S,&C);
16368     }
16369 #endif // EMCC
16370     if (calc_mode(&C)==1 && !lop(g,at_rootof).empty())
16371       g=evalf(g,1,&C);
16372     if (has_undef_stringerr(g,S)){
16373       S="GIAC_ERROR: "+S;
16374     }
16375     else {
16376 #ifdef KHICAS // replace ],[ by ][
16377       gen last=g;
16378       while (last.type==_VECT && last.subtype!=_LOGO__VECT && !last._VECTptr->empty()){
16379 	gen tmp=last._VECTptr->back();
16380 	if (tmp.is_symb_of_sommet(at_equal))
16381 	  last=vecteur(last._VECTptr->begin(),last._VECTptr->end()-1);
16382 	else
16383 	  last=tmp;
16384       }
16385       if (last.is_symb_of_sommet(at_pnt)){
16386 	if (os_shell)
16387 	  xcas::displaygraph(g,&C);
16388 	S="Graphic_object";
16389       }
16390       else {
16391 	if (os_shell){
16392 	  if (islogo(g))
16393 	    xcas::displaylogo();
16394 	  else {
16395 	    if ( (g.type==_SYMB || (warn_symb_program_sto && g.type==_VECT)) && taille(g,256)<=256)
16396 	      g=xcas::eqw(g,true,&C);
16397 	  }
16398 	}
16399 	if (taille(g,100)>=100)
16400 	  S="Large_object";
16401 	else
16402 	  S=g.print(&C);
16403       }
16404       if (!os_shell){
16405 	string S_;
16406 	S_ += S[0];
16407 	for (size_t i=1;i+1<S.size();++i){
16408 	  if (S[i-1]==']' && S[i]==',' && S[i+1]=='[')
16409 	    ;
16410 	  else
16411 	    S_ += S[i];
16412 	}
16413 	if (S.size()>1)
16414 	  S_ +=S[S.size()-1];
16415 	S=S_;
16416 	if (S.size()>=3 && S[0]=='[' && S[1]!='[' && S[S.size()-1]==']')
16417 	  S='['+S+']'; // vector/list not allowed in Numworks calc app
16418       }
16419 #else
16420       S=g.print(&C);
16421 #if !defined GIAC_GGB
16422       if (g.type==_FRAC || g.type==_ZINT){
16423 	S += "=";
16424 	S += evalf_double(g,1,&C).print(&C);
16425       }
16426       if (g.type==_SYMB){
16427 	g=evalf_double(g,1,&C);
16428 	if (g.type<=_CPLX){
16429 	  S += "=";
16430 	  S += g.print(&C);
16431 	}
16432       }
16433 #endif // !defined GIAC_GGB
16434 #endif // NUWMORKS
16435     }
16436     return S.c_str();
16437   }
16438 
16439 #ifdef EMCC_BIND
EMSCRIPTEN_BINDINGS(cas)16440   EMSCRIPTEN_BINDINGS(cas){
16441     emscripten::function("caseval",&caseval,emscripten::allow_raw_pointers());
16442   }
16443 #endif
16444 
16445 #ifndef NO_NAMESPACE_GIAC
16446 } // namespace giac
16447 #endif // ndef NO_NAMESPACE_GIAC
16448 
16449