1 // -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -I../include -g -c  symbolic.cc -Wall -DIN_GIAC -DHAVE_CONFIG_H" -*-
2 #include "giacPCH.h"
3 /*
4  *  Copyright (C) 2000, 2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 using namespace std;
20 #include "symbolic.h"
21 #include "identificateur.h"
22 #include "usual.h"
23 #include "prog.h"
24 #include "rpn.h"
25 #include "plot.h"
26 #include "giacintl.h"
27 #include "global.h"
28 
29 // NB: the operator in the symbolic (sommet) can not be replace by a pointer
30 // to a unary_function_ptr in the current code. Indeed, symbolic are created
31 // in the parser from temporary gen objects of type _FUNC which contains
32 // copies of unary_function_ptr, these copies are deleted once the parser
33 // gen object is deleted -> segfault.
34 
35 #ifndef NO_NAMESPACE_GIAC
36 namespace giac {
37 #endif // ndef NO_NAMESPACE_GIAC
38 
39   // unary_function_ptr quoted_op[]={at_of,at_for,at_bloc,at_local,at_program,at_rpn_prog,at_ifte,at_try_catch,at_print,at_signal,at_as_function_of,at_lieu,at_legende,at_debug,at_sst,at_sst_in,at_cont,at_kill,at_halt,at_watch,at_rmwatch,at_breakpoint,at_maple2mupad,at_mupad2maple,at_maple2xcas,at_mupad2xcas,at_purge,0};
40   // functions here must be declared with define_unary_function_eval?_index
41   // index is even for on quoted, odd for quoted (1+)
42 #if defined(GIAC_GENERIC_CONSTANTS) || defined(VISUALC) || defined(x86_64)
archive_function_tab()43   const unary_function_ptr * archive_function_tab(){
44     static const unary_function_ptr archive_function_tab_ptr[]={*at_plus,*at_neg,*at_binary_minus,*at_prod,*at_division,*at_inv,*at_pow,*at_exp,*at_ln,*at_abs,*at_arg,*at_pnt,*at_point,*at_segment,*at_sto,*at_sin,
45 								*at_cos,*at_tan,*at_asin,*at_acos,*at_atan,*at_sinh,*at_cosh,*at_tanh,*at_asinh,*at_acosh,*at_atanh,*at_interval,*at_union,*at_minus,*at_intersect,*at_not,
46 								*at_and,*at_ou,*at_inferieur_strict,*at_inferieur_egal,*at_superieur_strict,*at_superieur_egal,*at_different,*at_equal,*at_rpn_prog,*at_local,*at_return,*at_Dialog,*at_double_deux_points,*at_pointprod,*at_pointdivision,*at_pointpow,*at_hash,*at_pourcent,*at_tilocal,*at_break,*at_continue,*at_ampersand_times,*at_maple_lib,*at_unit,*at_plot_style,*at_xor,*at_check_type,*at_quote_pow,*at_case,*at_dollar,*at_IFTE,*at_RPN_CASE,*at_RPN_LOCAL,*at_RPN_FOR,*at_RPN_WHILE,*at_NOP,*at_unit,*at_ifte,*at_for,*at_bloc,*at_program,*at_same,*at_increment,*at_decrement,*at_multcrement,*at_divcrement,*at_sq,*at_display,*at_of,*at_at,*at_normalmod,*at_equal2,*at_pointplus,*at_pointminus,*at_struct_dot,*at_try_catch,0};
47     archive_function_tab_length=sizeof(archive_function_tab_ptr)/sizeof(const unary_function_ptr *);
48     return archive_function_tab_ptr;
49   }
50   int archive_function_tab_length=0;
51 
52 #else
53   static const size_t archive_function_tab_alias[]={
54     // index = 2
55     alias_at_plus,alias_at_neg,alias_at_binary_minus,alias_at_prod,alias_at_division,
56     // 12
57     alias_at_inv,alias_at_pow,alias_at_exp,alias_at_ln,alias_at_abs,
58     // 22
59     alias_at_arg,alias_at_pnt,alias_at_point,alias_at_segment,alias_at_sto,
60     // 32
61     alias_at_sin,alias_at_cos,alias_at_tan,alias_at_asin,alias_at_acos,
62     // 42
63     alias_at_atan,alias_at_sinh,alias_at_cosh,alias_at_tanh,alias_at_asinh,
64     // 52
65     alias_at_acosh,alias_at_atanh,alias_at_interval,alias_at_union,alias_at_minus,
66     // 62
67     alias_at_intersect,alias_at_not,alias_at_and,alias_at_ou,alias_at_inferieur_strict,
68     // 72
69     alias_at_inferieur_egal,alias_at_superieur_strict,alias_at_superieur_egal,alias_at_different,alias_at_equal,
70     // 82
71     alias_at_rpn_prog,alias_at_local,alias_at_return,alias_at_Dialog,alias_at_double_deux_points,
72     // 92
73     alias_at_pointprod,alias_at_pointdivision,alias_at_pointpow,alias_at_hash,alias_at_pourcent,
74     // 102
75     alias_at_tilocal,alias_at_break,alias_at_continue,alias_at_ampersand_times,alias_at_maple_lib,
76     // 112
77     alias_at_unit,alias_at_plot_style,alias_at_xor,alias_at_check_type,alias_at_quote_pow,
78     // 122
79     alias_at_case,alias_at_dollar,alias_at_IFTE,alias_at_RPN_CASE,alias_at_RPN_LOCAL,
80     // 132
81     alias_at_RPN_FOR,alias_at_RPN_WHILE,alias_at_NOP,alias_at_unit,alias_at_ifte,
82     // 142
83     alias_at_for,alias_at_bloc,alias_at_program,alias_at_same,alias_at_increment,
84     // 152
85     alias_at_decrement,alias_at_multcrement,alias_at_divcrement,alias_at_sq,alias_at_display,
86     // 162
87     alias_at_of,alias_at_at,alias_at_normalmod,alias_at_equal2,alias_at_pointplus,
88     // 172
89     alias_at_pointminus,alias_at_struct_dot,alias_at_try_catch,
90     0
91   };
92   const unary_function_ptr * _archive_function_tab = (const unary_function_ptr *) &archive_function_tab_alias;
93   const unary_function_ptr * archive_function_tab(){
94     return _archive_function_tab;
95   }
96   int archive_function_tab_length=sizeof(archive_function_tab_alias)/sizeof(size_t);
97 
98 #endif
99 
archive_function_index(const unary_function_ptr & f)100   int archive_function_index(const unary_function_ptr & f){
101     return f.ptr()?(f.ptr()->index_quoted_function >> 1):0;
102     // return equalposcomp(archive_function_tab(),f);
103   }
104 
equalposcomp(const unary_function_ptr tab[],const unary_function_ptr & f)105   int equalposcomp(const unary_function_ptr tab[],const unary_function_ptr & f){
106     for (int i=1;*((size_t *)tab)!=0;++tab,++i){
107       if (*tab==f)
108 	return i;
109     }
110     return 0;
111   }
112 
equalposcomp(const vector<const unary_function_ptr * > & tab,const unary_function_ptr * f)113   int equalposcomp(const vector<const unary_function_ptr * > & tab,const unary_function_ptr * f){
114     vector<const unary_function_ptr * >::const_iterator it=tab.begin(),itend=tab.end();
115     for (int i=1;it!=itend;++it,++i){
116       if (**it==*f)
117 	return i;
118     }
119     return 0;
120   }
121 
equalposcomp(const const_unary_function_ptr_ptr tab[],const unary_function_ptr & f)122   int equalposcomp(const const_unary_function_ptr_ptr tab[],const unary_function_ptr & f){
123     for (int i=1;*((size_t *)tab)!=0;++tab,++i){
124       if (**tab==f)
125 	return i;
126     }
127     return 0;
128   }
129 
symbolic(const symbolic & mys,const gen & e)130   symbolic::symbolic(const symbolic & mys,const gen & e): sommet(mys.sommet){
131     vecteur tmp;
132     if (mys.feuille.type==_VECT){
133       tmp = *mys.feuille._VECTptr;
134       tmp.push_back(e);
135     }
136     else {
137       tmp.push_back(mys.feuille);
138       tmp.push_back(e);
139     }
140     feuille = gen(tmp,_SEQ__VECT);
141   };
142 
symbolic(const gen & a,const unary_function_ptr & o,const gen & b)143   symbolic::symbolic(const gen & a,const unary_function_ptr & o,const gen & b):sommet(o) {
144     if (b.type==_VECT)
145       feuille=gen(mergevecteur(vecteur(1,a),*b._VECTptr),b.subtype);
146     else
147       feuille=gen(makevecteur(a,b),_SEQ__VECT);
148   };
149 
symbolic(const gen & a,const unary_function_ptr * o,const gen & b)150   symbolic::symbolic(const gen & a,const unary_function_ptr * o,const gen & b):sommet(*o) {
151     if (b.type==_VECT)
152       feuille=gen(mergevecteur(vecteur(1,a),*b._VECTptr),b.subtype);
153     else
154       feuille=gen(makevecteur(a,b),_SEQ__VECT);
155   };
156 
size() const157   int symbolic::size() const {
158     if (feuille.type==_SYMB)
159       return 1+feuille._SYMBptr->size();
160     if (feuille.type!=_VECT)
161       return 2;
162     int s=1;
163     iterateur it=feuille._VECTptr->begin(),itend=feuille._VECTptr->end();
164     for (;it!=itend;++it){
165       if (it->type==_SYMB)
166 	s += it->_SYMBptr->size();
167       else
168 	++s;
169     }
170     return s;
171   }
172 
173   bool print_rewrite_prod_inv=false;
174 
add_print_plus(string & s,const symbolic & g,GIAC_CONTEXT)175   static string & add_print_plus(string & s,const symbolic & g,GIAC_CONTEXT){
176     if (is_inf(g.feuille)
177 	// && calc_mode(contextptr)!=1
178 	&& abs_calc_mode(contextptr)==38
179 	){
180       s+="∞";
181       return s;
182     }
183     if (g.feuille.type!=_VECT){
184       s += '+';
185       return add_print(s,g.feuille,contextptr);
186     }
187     vecteur & v = *g.feuille._VECTptr;
188     if (v.empty())
189       return s;
190     int l=int(v.size());
191     if (l==1)
192       s += '+';
193     add_print(s, v.front(),contextptr);
194     for (int i=1;i<l;++i){
195       s += '+';
196       bool par=false;
197       if (v[i].type==_SYMB){
198 	const unary_function_ptr & u=v[i]._SYMBptr->sommet;
199 	if (u==at_superieur_egal || u==at_superieur_strict || u==at_inferieur_strict || u==at_inferieur_egal)
200 	  par=true;
201       }
202       if (par) s+='(';
203       add_print(s,v[i],contextptr);
204       if (par) s+=')';
205     }
206     return s;
207   }
208 
add_print_neg(string & s,const gen & feuille,GIAC_CONTEXT)209   static string & add_print_neg(string & s,const gen & feuille,GIAC_CONTEXT){
210     int l = int(s.size());
211     // +- and -- -> - and +
212     if (l && s[l-1]=='+')
213       s[l-1]='-';
214     else {
215       if (l && s[l-1]=='-')
216 	s[l-1]='+';
217       else
218 	s += calc_mode(contextptr)==38?"−":"-";
219     }
220     if (feuille.type!=_CPLX){
221       if(feuille.type!=_SYMB || (feuille._SYMBptr->sommet==at_inv || feuille._SYMBptr->sommet==at_prod) || !need_parenthesis(feuille)){
222 	return add_print(s,feuille,contextptr);
223       }
224     }
225     s += "(";
226     add_print(s,feuille,contextptr);
227     s += ")";
228     return s;
229   }
230 
add_print_inv(string & s,const gen & feuille,GIAC_CONTEXT)231   static string & add_print_inv(string & s,const gen & feuille,GIAC_CONTEXT){
232     gen f = feuille;
233     bool isneg=false;
234     bool calc38=calc_mode(contextptr)==38;
235     if (f.is_symb_of_sommet(at_neg) && f._SYMBptr->feuille.type!=_VECT){
236       f = f._SYMBptr->feuille;
237       isneg=true;
238     }
239     if (f.type<_CPLX && is_positive(-f,contextptr)){
240       f=-f;
241       isneg=!isneg;
242     }
243     int l=int(s.size());
244     if (isneg && l && s[l-1]=='-'){
245       if (l==1)
246 	s.clear();
247       else
248 	s[l-1]='+';
249       isneg=false;
250     }
251     if (isneg && l && s[l-1]=='+'){
252       s[l-1]='-';
253       isneg=false;
254     }
255     bool bt=f.type==_SYMB && (f._SYMBptr->sommet==at_plus || f._SYMBptr->sommet==at_inv || f._SYMBptr->sommet==at_prod || need_parenthesis(f._SYMBptr->sommet));
256     if ( !bt && (f.type!=_CPLX) && (f.type!=_MOD)){
257       s += (isneg?(calc38?"−1/":"-1/"):"1/");
258       return add_print(s,f,contextptr);
259     }
260     else {
261       s += (isneg?(calc38?"−1/(":"-1"):"1/(");
262       add_print(s,f,contextptr);
263       s += ")";
264       return s;
265     }
266   }
267 
add_print_prod(string & s,const symbolic & g,GIAC_CONTEXT)268   static string & add_print_prod(string & s,const symbolic & g,GIAC_CONTEXT){
269     gen n0,d0;
270     if (print_rewrite_prod_inv &&
271 	rewrite_prod_inv(g.feuille,n0,d0)
272 	){
273       if (n0.type<_CPLX || n0.type==_IDNT){
274 	add_print(s,n0,contextptr);
275 	s += "/";
276       }
277       else {
278 	s +="(";
279 	add_print(s,n0,contextptr);
280 	s += ")/";
281       }
282       if (d0.type<_CPLX || d0.type==_IDNT)
283 	add_print(s,d0,contextptr); // s += d0.print(contextptr);
284       else {
285 	s += "(";
286 	add_print(s,d0,contextptr); s += ")"; // s += "("+d0.print(contextptr)+")";
287       }
288       return s;
289     }
290     if (g.feuille.type!=_VECT)
291       return add_print(s,g.feuille,contextptr);
292     vecteur & v = *g.feuille._VECTptr;
293     int l=int(v.size());
294     for (int i=0;i<l;++i){
295       gen e(v[i]);
296       if (e.type!=_SYMB){
297 	if (i)
298 	  s += '*';
299 	if ( (e.type==_CPLX
300 	      && need_parenthesis(e)
301 	      ) || e.type==_MOD )
302 	  s += "("+e.print(contextptr)+")";
303 	else
304 	  add_print(s,e,contextptr); // s +=e.print(contextptr);
305       }
306       else {
307 	if (e._SYMBptr->sommet==at_inv){
308 	  gen f(e._SYMBptr->feuille);
309 	  if (i){
310 	    if ( (f.type==_CPLX) || (f.type==_MOD) ||
311 		 ((f.type==_SYMB) &&
312 		  ( (f._SYMBptr->sommet==at_plus) || (f._SYMBptr->sommet==at_prod) || need_parenthesis(f._SYMBptr->sommet) || f._SYMBptr->sommet==at_inv || (f._SYMBptr->sommet==at_pow && f._SYMBptr->feuille[0].is_symb_of_sommet(at_inv))))
313 		 ){
314 	      s += "/(";
315 	      add_print(s,f,contextptr);
316 	      s += ")"; // s += ("/("+f.print(contextptr) + ")");
317 	    }
318 	    else {
319 	      s += "/";
320 	      add_print(s,f,contextptr);
321 	      // s += ("/"+f.print(contextptr));
322 	    }
323 	  }
324 	  else
325 	    add_print(s,e,contextptr); // s += e.print(contextptr);
326 	} // end if e._SYMBptr->sommet==at_inv
327 	else {
328 	  if (i)
329 	    s += '*';
330 	  if ( e._SYMBptr->sommet==at_plus || e._SYMBptr->sommet==at_neg || is_inequation(e) ){
331 	    s += "(";
332 	    add_print(s,e,contextptr);
333 	    s += ")";
334 	    // s += ("("+e.print(contextptr)+")");
335 	  }
336 	  else
337 	    add_print(s,e,contextptr); // s += e.print(contextptr);
338 	}
339       }
340     } // end_for
341     return s;
342   }
343 
add_print_pow(string & s,const symbolic & g,GIAC_CONTEXT)344   static string & add_print_pow(string & s,const symbolic & g,GIAC_CONTEXT){
345     if (g.feuille.type!=_VECT || g.feuille._VECTptr->size()!=2){
346       s += "pow(";
347       add_print(s,g.feuille,contextptr);
348       s+=')';
349       return s;
350     }
351     gen pui=g.feuille._VECTptr->back();
352     gen arg=g.feuille._VECTptr->front();
353 #ifndef GIAC_HAS_STO_38
354     if (__pow.printsommet==&cprintaspow){
355       s+="pow(";
356       add_print(s,arg,contextptr);
357       s+=",";
358       add_print(s,pui,contextptr);
359       s+=')';
360       return s;
361     }
362 #endif
363     bool argpar = ( (arg.type>_CPLX && arg.type!=_FLOAT_) || !is_positive(arg,contextptr)) && arg.type!=_IDNT ;
364 #if defined EMCC || defined GIAC_GGB
365     bool need=need_parenthesis(arg) || arg.type==_SYMB;
366     if (pui==plus_one_half){
367 #ifdef KHICAS // inactive code
368       need=true;
369       s += char(226);
370       s += char(136);
371       s += char(154);
372       s+= '(';
373 #else
374       s += (need?"√(":"√");
375 #endif
376       add_print(s,arg,contextptr);
377       s += (need?")":"");
378       return s;
379     }
380 #endif
381     if (abs_calc_mode(contextptr)==38){
382       bool need=need_parenthesis(arg) || arg.type==_SYMB;
383       if (pui==plus_one_half){
384 	s += (need?"√(":"√");
385 	add_print(s,arg,contextptr);
386 	s += (need?")":"");
387 	return s;
388       }
389       if ( pui==minus_one_half  || pui==fraction(minus_one,plus_two) ){
390 	s += (need?"1/√(":"1/√");
391 	add_print(s,arg,contextptr);
392 	s += (need?")":"");
393 	return s;
394       }
395       if (pui==minus_one){
396 	s += (need?"(":"");
397 	add_print(s,arg,contextptr);
398 	s += (need?")":"");
399 	return s;
400 	// return s += (need?")\xe2\x81\xb2":"\xe2\x81\xb2");
401       }
402 #if 0
403       if (pui==plus_two){
404 	s += (argpar?"(":"");
405 	add_print(s,arg,contextptr);
406 	s += (argpar?")²":"²");
407 	return s;
408       }
409 #endif
410     }
411     if (pui.type>_REAL && pui==plus_one_half){
412       s += "sqrt(";
413       add_print(s,arg,contextptr);
414       s += ')';
415       return s;
416     }
417     if ( pui.type>_REAL && (pui==minus_one_half  || pui==fraction(minus_one,plus_two) )){
418       s += "1/sqrt(";
419       add_print(s,arg,contextptr);
420       s += ')';
421       return s;
422     }
423     if (arg.type==_IDNT || (arg.type==_SYMB && arg._SYMBptr->sommet!=at_neg && (arg._SYMBptr->sommet!=at_exp || calc_mode(contextptr)!=1) && !arg._SYMBptr->sommet.ptr()->printsommet)){
424       argpar=arg.is_symb_of_sommet(at_inv) || (arg.is_symb_of_sommet(at_exp) && abs_calc_mode(contextptr)==38);
425       if (argpar) s +='(';
426       if (pui.type==_SYMB || pui.type==_FRAC || pui.type==_CPLX){
427 	add_print(s,arg,contextptr);
428 	if (argpar) s +=')';
429 #ifdef GIAC_HAS_STO_38
430 	s += '^';
431 #else
432 	if (
433 	    python_compat(contextptr)
434 #ifdef KHICAS
435 	    && os_shell
436 #endif
437 	    )
438 	  s += "**";
439 	else
440 	  s += __pow.s;
441 #endif
442 	s += '(';
443 	add_print(s,pui,contextptr);
444 	s += ')';
445 	return s;
446       }
447       else {
448 	add_print(s,arg,contextptr);
449 	if (argpar) s +=')';
450 #ifdef GIAC_HAS_STO_38
451 	s += '^';
452 #else
453 	if (python_compat(contextptr)
454 #ifdef KHICAS
455 	    && os_shell
456 #endif
457 	    )
458 	  s += "**";
459 	else
460 	  s += __pow.s;
461 #endif
462 	return add_print(s,pui,contextptr);
463       }
464     }
465     if (argpar)
466       s += '(';
467     add_print(s,arg,contextptr);
468     if (argpar)
469       s += ')';
470 #ifdef GIAC_HAS_STO_38
471     s += '^';
472 #else
473     s +=
474       python_compat(contextptr)
475 #ifdef KHICAS
476       && os_shell
477 #endif
478       ?"**":__pow.s;
479 #endif
480     bool puipar = pui.type==_SYMB || pui.type==_FRAC || pui.type==_CPLX || (pui.type==_VECT && pui.subtype==_SEQ__VECT);
481     if (puipar)
482       s += '(';
483     add_print(s,pui,contextptr);
484     if (puipar)
485       s += ')';
486     return s ;
487   }
488 
add_print_int(string & s,int i,GIAC_CONTEXT)489   static string & add_print_int(string & s,int i,GIAC_CONTEXT){
490     char ch[32];
491     int l=int(s.size());
492     if (i<0){
493       if (l && s[l-1]=='+')
494 	s[l-1]='-';
495       else {
496 	if (l && s[l-1]=='-'){
497 	  if (l==1)
498 	    s.clear();
499 	  else
500 	    s[l-1]='+';
501 	}
502 	else
503 	  s +=  (calc_mode(contextptr)==38)?"−":"-"; // add a minus
504       }
505       i=-i;
506     }
507     switch (integer_format(contextptr)){
508     case 16:
509       my_sprintf(ch,"0x%X",i);
510     case 8:
511       my_sprintf(ch,"0o%o",i);
512     default:
513       my_sprintf(ch,"%d",i);
514     }
515     s += ch;
516     return s;
517   }
518 
add_print_symbolic(string & s,const symbolic & g,GIAC_CONTEXT)519   static string & add_print_symbolic(string & s,const symbolic & g,GIAC_CONTEXT){
520     if (!g.sommet.ptr()){
521       s+="NULL(";
522       s+=g.feuille.print();
523       s+=")";
524       return s;
525     }
526     if ( g.sommet.ptr()->printsommet && g.sommet!=at_plus && g.sommet!=at_prod && g.sommet!=at_pow){
527       s += g.sommet.ptr()->printsommet(g.feuille,g.sommet.ptr()->s,contextptr);
528       return s;
529     }
530     if ( g.feuille.type==_VECT && g.feuille._VECTptr->empty() ){
531       s += g.sommet.ptr()->print(contextptr);
532       s += "(NULL)";
533       return s;
534     }
535     if (g.sommet==at_prod)
536       return add_print_prod(s,g,contextptr);
537     if (g.sommet==at_plus)
538       return add_print_plus(s,g,contextptr);
539     if (g.sommet==at_pow)
540       return add_print_pow(s,g,contextptr);
541     if (g.sommet==at_neg)
542       return add_print_neg(s,g.feuille,contextptr);
543     if (g.sommet==at_inv)
544       return add_print_inv(s,g.feuille,contextptr);
545     if (g.sommet==at_exp
546 #ifndef EMCC
547 	&& (calc_mode(contextptr)==1 || abs_calc_mode(contextptr)==38)
548 #endif
549 	){
550       s += printasexp(g.feuille,0,contextptr);
551       return s;
552     }
553     if ( g.feuille.type!=_VECT || ( g.sommet!=at_prod && g.feuille._VECTptr->front().type==_VECT ) ){
554       s += g.sommet.ptr()->print(contextptr);
555       s += '(';
556       add_print(s,g.feuille,contextptr);
557       s += ')';
558       return s;
559     }
560     int l=int(g.feuille._VECTptr->size());
561     s += g.sommet.ptr()->print(contextptr);
562     s += '(';
563     if (g.feuille.subtype!=_SEQ__VECT)
564       s += begin_VECT_string(g.feuille.subtype,false,contextptr);
565     for (int i=0;;++i){
566       add_print(s,(*(g.feuille._VECTptr))[i],contextptr); // s += (*(feuille._VECTptr))[i].print(contextptr);
567       if (i==l-1){
568 	break;
569       }
570       s += ',';
571     }
572     if (g.feuille.subtype!=_SEQ__VECT)
573       s += end_VECT_string(g.feuille.subtype,false,contextptr);
574     s += ')';
575     return s;
576   }
577 
add_print(string & s,const gen & g,GIAC_CONTEXT)578   string & add_print(string & s,const gen & g,GIAC_CONTEXT){
579     if (g.type==_IDNT){
580       if (calc_mode(contextptr)==1 && (is_inf(g) || is_undef(g)))
581 	s += "?";
582       else
583 	(s += g._IDNTptr->print(contextptr));
584       return s;
585     }
586     int l=int(s.size());
587     if (g.type==_INT_ && g.subtype==0)
588       return add_print_int(s,g.val,contextptr);
589     if (g.type==_VECT && g.subtype==0){
590       s += calc_mode(contextptr)==1?'{':'[';
591       add_printinner_VECT(s,*g._VECTptr,0,contextptr);
592       s += calc_mode(contextptr)==1?'}':']';
593       return s;
594     }
595     if (g.type==_FRAC && g._FRACptr->num.type==_INT_ && g._FRACptr->den.type==_INT_){
596       add_print(s,g._FRACptr->num,contextptr);
597       s += "/";
598       add_print(s,g._FRACptr->den,contextptr);
599       return s;
600     }
601     if (g.type==_SYMB){
602       if (g.subtype==_SPREAD__SYMB)
603 	s += "=";
604       return add_print_symbolic(s,*g._SYMBptr,contextptr);
605     }
606 #ifdef EMCC
607     const string tmp=g.print(contextptr);
608 #else
609     const string & tmp=g.print(contextptr);
610 #endif
611     // check +- -> - and -- -> +
612     if (l && s[l-1]=='+' ){
613       if (!tmp.empty() && tmp[0]=='-'){
614 	s = s.substr(0,l-1);
615 	s += tmp;
616 	return s;
617       }
618       if (tmp.size()>3 && (unsigned char)tmp[0]==226 && (unsigned char)tmp[1]==136 && (unsigned char) tmp[2]==146 ) { // -30, -120, -110
619 	s[l-1]='-';
620 	s += tmp.substr(3,tmp.size()-3);
621 	return s;
622       }
623     }
624     if (l && s[l-1]=='-' ){
625       if (!tmp.empty() && tmp[0]=='-'){
626 	s[l-1]='+';
627 	s += tmp.substr(1,tmp.size()-1);
628 	return s;
629       }
630       if (tmp.size()>3 && (unsigned char)tmp[0]==226 && (unsigned char)tmp[1]==136 && (unsigned char) tmp[2]==146 ) { // -30, -120, -110
631 	s[l-1]='+';
632 	s += tmp.substr(3,tmp.size()-3);
633 	return s;
634       }
635     }
636     s += tmp;
637     return s;
638   }
639 
print(GIAC_CONTEXT) const640   string symbolic::print(GIAC_CONTEXT) const{
641     string s;
642     add_print_symbolic(s,*this,contextptr);
643     return s;
644   }
645 
646   /* EVAL without system stack */
647 
eval_sto_pnt_symb(const gen & feuille,gen & e,GIAC_CONTEXT)648   static void eval_sto_pnt_symb(const gen & feuille,gen & e,GIAC_CONTEXT){
649     // e is also in history_plot(), ref_count==2
650     if (e.type==_SYMB && e.ref_count()<=2 && e._SYMBptr->feuille.type==_VECT && e._SYMBptr->feuille.ref_count()==1){
651       vecteur & v=*e._SYMBptr->feuille._VECTptr;
652       // legende not converted to string to avoid malloc ->faster
653       v.push_back(feuille._VECTptr->back());
654       // v=makevecteur(v.front(),v.back(),string2gen(feuille._VECTptr->back().print(contextptr),false));
655       e._SYMBptr->feuille.subtype=_PNT__VECT;
656     }
657     else
658       e=new_ref_symbolic(symbolic(at_pnt,gen(makevecteur(e._SYMBptr->feuille._VECTptr->front(),e._SYMBptr->feuille._VECTptr->back(),string2gen(feuille._VECTptr->back().print(contextptr),false)),_PNT__VECT)));
659     e.subtype=gnuplot_show_pnt(*e._SYMBptr,contextptr);
660   }
661 
eval_sto_pnt_vect(const gen & feuilleback,gen & e,GIAC_CONTEXT)662   static void eval_sto_pnt_vect(const gen & feuilleback,gen & e,GIAC_CONTEXT){
663     vecteur v=*e._VECTptr;
664     iterateur it=v.begin(),itend=v.end();
665     gen legende;
666     for (int pos=0;it!=itend;++pos,++it){
667       if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_pnt) && (it->_SYMBptr->feuille._VECTptr->size()==2)){
668 	if (feuilleback.type==_VECT && pos<int(feuilleback._VECTptr->size()))
669 	  legende=(*feuilleback._VECTptr)[pos];
670 	else
671 	  legende=feuilleback;
672 	if (legende.type==_IDNT && abs_calc_mode(contextptr)==38){
673 	  // HP: if legende is an IDNT, keep it as legende
674 	  // this save alloc (2 alloc instead of 3 alloc + 1 print
675 	  *it=new_ref_symbolic(symbolic(at_pnt,gen(makevecteur(it->_SYMBptr->feuille._VECTptr->front(),it->_SYMBptr->feuille._VECTptr->back(),legende),_PNT__VECT)));
676 	}
677 	else {
678 	  *it=new_ref_symbolic(symbolic(at_pnt,gen(makevecteur(it->_SYMBptr->feuille._VECTptr->front(),it->_SYMBptr->feuille._VECTptr->back(),string2gen(legende.print(contextptr),false)),_PNT__VECT)));
679 	}
680 	it->subtype=gnuplot_show_pnt(*it->_SYMBptr,contextptr);
681       }
682     }
683     e=gen(v,e.subtype);
684   }
685 
eval_sto(const gen & feuille,int level,GIAC_CONTEXT)686   static gen eval_sto(const gen & feuille,int level,GIAC_CONTEXT){ // autoname function
687     // detect vector/matrix addressing with () parsed as function definition
688     // e.g. M(j,k):=j+k+1 parsed as M:=(j,k)->j+k+1
689     // these affectations are marked by a subtype==1 by the parser
690     // if destination is a matrix
691     vecteur & feuillev=*feuille._VECTptr;
692     gen & feuilleback=feuillev.back();
693     if (feuille.type==_VECT && feuille.subtype==_SORTED__VECT && feuillev.size()==2 && feuillev.front().is_symb_of_sommet(at_program)){
694       gen prog=feuillev.front()._SYMBptr->feuille;
695       if (prog.type==_VECT && prog._VECTptr->size()==3 && (prog._VECTptr->front()!=_VECT || prog._VECTptr->front()._VECTptr->size()==2)){
696 	gen val=prog._VECTptr->back();
697 	if (feuilleback.type==_IDNT && feuilleback._IDNTptr->eval(1,feuilleback,contextptr).type==_VECT){
698 	  prog=symbolic(at_of,makesequence(feuilleback,prog._VECTptr->front()));
699 	  return eval_sto(gen(makevecteur(val,prog),_SORTED__VECT),level,contextptr);
700 	}
701       }
702     }
703     if ( feuilleback.type==_SYMB && (feuilleback._SYMBptr->sommet==at_unquote || feuilleback._SYMBptr->sommet==at_hash ) ){
704       gen ans(_sto(feuille.eval(level,contextptr),contextptr));
705       return ans;
706     }
707     bool & showpoint=show_point(contextptr),b=showpoint,quotearg=false;
708     if (b)
709       showpoint=false;
710 #ifdef GIAC_HAS_STO_38 // quote STO> E, STO> F, STO>R, STO> X, STO>Y
711     if (feuilleback.type==_IDNT){
712       const char * ch = feuilleback._IDNTptr->id_name;
713       if (strlen(ch)==2 && ch[1]>='0' && ch[1]<='9' && (ch[0]=='E' || ch[0]=='F' || ch[0]=='X' || ch[0]=='Y'))
714 	quotearg=true;
715     }
716 #endif
717     gen e;
718     if (quotearg)
719       e=feuillev.front();
720     else {
721       gen * feuillevfront=&feuillev.front();
722       // avoid self-modifying code in multi-assign
723       if (feuilleback.type==_VECT && feuillevfront->type==_VECT &&feuilleback._VECTptr->size()==feuillevfront->_VECTptr->size()){
724 	gen tmp;
725 	e =gen(*feuillevfront->_VECTptr,feuillevfront->subtype);
726 	iterateur it=e._VECTptr->begin(),itend=e._VECTptr->end();
727 	for (;it!=itend;++it){
728 	  if (it->in_eval(level,tmp,contextptr))
729 	    *it=tmp;
730 	  else {
731 	    if (it->type==_VECT)
732 	      *it=gen(*it->_VECTptr,tmp.subtype);
733 	  }
734 	}
735       }
736       else {
737 	// e=feuillev.front().eval(level,contextptr);
738 	if (!feuillevfront->in_eval(level,e,contextptr)){
739 	  if (feuillevfront->type==_VECT) // avoid self-modifying code
740 	    e=gen(*feuillevfront->_VECTptr,feuillevfront->subtype);
741 	  else
742 	    e=*feuillevfront;
743 	}
744       }
745     }
746     if (b)
747       showpoint=true;
748     if (e.type==_SYMB && e._SYMBptr->sommet==at_pnt && e._SYMBptr->feuille.type==_VECT && e._SYMBptr->feuille._VECTptr->size()==2 && (contextptr?!contextptr->previous:!protection_level) )
749       eval_sto_pnt_symb(feuille,e,contextptr);
750     if ( e.type==_VECT && !e._VECTptr->empty() && e._VECTptr->back().type==_SYMB && e._VECTptr->back()._SYMBptr->sommet==at_pnt && (contextptr?!contextptr->previous:!protection_level))
751       eval_sto_pnt_vect(feuilleback,e,contextptr);
752     return sto(e,feuilleback,python_compat(contextptr),contextptr);
753   } // end sommet==at_sto
754 
755   // http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-34.html#%_sec_5.4
756   enum {
757     nr_eval_dispatch=1,
758     nr_eval_vect=2,
759     nr_eval_of=18,
760     nr_eval_op=19, // below this increment destination
761     nr_eval_prog=21, // above this do not increment destination
762     nr_eval_sto=22,
763     nr_eval_local=23,
764     nr_eval_bloc=24,
765     nr_eval_if_cond=25,
766     nr_eval_if_true=26,
767     nr_eval_if_false=27,
768     nr_eval_for_init=28,
769     nr_eval_for_cond=29,
770     nr_eval_for_loop=30,
771     nr_eval_for_incr=31,
772     nr_eval_for_in=32,
773     nr_eval_catch=34,
774   };
775 
776 #define NR_INIT_STACK_SIZE 200
777 
778   struct nr_pointers_t{
779     gen * itbeg;
780     unsigned curpos,endpos;
781     unsigned arglpos;
782     gen old;
783     vecteur argl;
784     signed char state;
nr_pointers_tgiac::nr_pointers_t785     nr_pointers_t(unsigned _arglpos,gen * _itbeg,gen * _it,gen * _itend,gen _old,int argls,signed char _state):itbeg(_itbeg),curpos(unsigned(_it-_itbeg)),endpos(unsigned(_itend-_itbeg)),arglpos(_arglpos),old(_old),argl(argls),state(_state) {};
nr_pointers_tgiac::nr_pointers_t786     nr_pointers_t():itbeg(0),curpos(0),endpos(0),arglpos(0),old(0),argl(0),state(0){}
787   };
788 
fromto_restore(unsigned & arglpos,gen * & itbeg,gen * & it,gen * & itend,gen & old,vecteur & argl,signed char & state,vector<nr_pointers_t> & fromto_stack)789   inline void fromto_restore(unsigned & arglpos,gen * & itbeg,gen * & it,gen * & itend,gen & old,vecteur & argl,signed char & state,vector<nr_pointers_t> & fromto_stack){
790     vector<nr_pointers_t>::iterator ptr=fromto_stack.end()-1;
791     arglpos=ptr->arglpos;
792     itbeg=ptr->itbeg;
793     it=ptr->itbeg+ptr->curpos;
794     itend=ptr->itbeg+ptr->endpos;
795     old=ptr->old;
796     argl.swap(ptr->argl);
797     state=ptr->state;
798     fromto_stack.pop_back();
799   }
800 
801   struct nr_prog {
802     context * contextptr;
803     gen save_debug_info,vars;
804     bool save_sst_mode;
805     int protect;
nr_proggiac::nr_prog806     nr_prog(context * _contextptr,const gen & _save_debug_info,const gen & _vars,bool _save_sst_mode,int _protect):contextptr(_contextptr),save_debug_info(_save_debug_info),vars(_vars),save_sst_mode(_save_sst_mode),protect(_protect) {};
nr_proggiac::nr_prog807     nr_prog() : contextptr(0),save_debug_info(0),vars(0),save_sst_mode(false),protect(0) {}
808   };
809 
810   // name changed: BESTA compiler see this as repeated code with same sig as passing the itor itself
811   // - compiler whinges like a wounded pig --
increment_instruction_ptr(const gen * it0,const gen * itend,GIAC_CONTEXT)812   static void increment_instruction_ptr(const gen * it0,const gen * itend,GIAC_CONTEXT){
813     debug_struct *dbgptr=debug_ptr(contextptr);
814     const gen * it=it0;
815     for (;it!=itend;++it)
816       increment_instruction(*it,dbgptr);
817   }
818 
819   // nr_eval is slower than usual eval because it saves what is usually saved
820   // on stack on the heap. It does not use stack for recursive calls
821   // Should be used if we are near the bottom of the stack
nr_eval(const gen & g,int level,const context * ct)822   gen nr_eval(const gen & g,int level,const context * ct){
823     context * contextptr=(context *) ct;
824     gen *itbeg, * it, *itend; // source, begin, current and end of evaluation
825     gen * destination; // destination of evaluation result
826     gen res; // the final answer
827     gen tmp;
828     unsigned arglpos;
829     vector<nr_pointers_t> fromto_stack; // save/restore destination, source, source end pointers here
830     fromto_stack.reserve(NR_INIT_STACK_SIZE);
831     signed char state=nr_eval_dispatch;
832     gen old=0; // destination
833     gen progname=undef,label=undef,forlast,lasterr;
834     vecteur argl(1); // current evaled vecteur
835     vector<nr_prog> nr_prog_stack;
836     vector<int> nr_eval_for_stack;
837     nr_prog_stack.reserve(NR_INIT_STACK_SIZE);
838     gen prog;
839     itbeg=it=(gen *) &g; itend=it+1; destination=(gen *)&argl.front();
840     while (1){
841 #ifndef NO_STDEXCEPT
842       try {
843 #endif
844 	if (lasterr.type==_STRNG || (destination->type==_STRNG && destination->subtype==-1)){
845 	  // error!
846 	  debug_ptr(contextptr)->current_instruction += int(itend-it);
847 	  it=itend;
848 	  if (lasterr.type!=_STRNG)
849 	    lasterr=*destination;
850 	}
851 	if (it!=itend){
852 	  if (state>=nr_eval_prog){
853 	    if (destination->type==_SYMB && (destination->_SYMBptr->sommet==at_return || destination->_SYMBptr->sommet==at_break || (state!=nr_eval_for_incr && destination->_SYMBptr->sommet==at_continue) ) ){
854 	      ++it; // do not eval anymore until end of function or loop
855 	      ++debug_ptr(contextptr)->current_instruction;
856 	      continue;
857 	    }
858 	    // goto
859 	    if (!is_undef(label)){
860 	      if (it->is_symb_of_sommet(at_label) && label==it->_SYMBptr->feuille){
861 		*destination=*it;
862 		label=undef;
863 	      }
864 	      ++it;
865 	      if (it==itend){
866 		debug_ptr(contextptr)->current_instruction -= int(itend-itbeg);
867 		for (it=itbeg;it!=itend;++it){
868 		  if (it->is_symb_of_sommet(at_label) && label==it->_SYMBptr->feuille){
869 		    *destination=*it;
870 		    label=undef;
871 		    break;
872 		  }
873 		  ++debug_ptr(contextptr)->current_instruction;
874 		}
875 	      }
876 	      else
877 		++debug_ptr(contextptr)->current_instruction;
878 	      continue;
879 	    }
880 	    if (state!=nr_eval_if_cond && state!=nr_eval_for_init && state!=nr_eval_for_cond && state!=nr_eval_for_incr && state!=nr_eval_sto){
881 	      if (state==nr_eval_for_loop && it==itbeg+3 && it->is_symb_of_sommet(at_bloc))
882 		;
883 	      else {
884 		++debug_ptr(contextptr)->current_instruction;
885 		if (debug_ptr(contextptr)->debug_mode){
886 		  debug_loop(res,contextptr);
887 		  if (is_undef(res)) return res;
888 		}
889 	      }
890 	    }
891 	  }
892 	  switch (it->type){
893 	  case _VECT:
894 	    if (it->subtype==_SPREAD__VECT){
895 	      makespreadsheetmatrice(*it->_VECTptr,contextptr);
896 	      spread_eval(*it->_VECTptr,contextptr);
897 	      *destination=*it;
898 	      ++it;
899 	      if (it!=itend && state<=nr_eval_op)
900 		++destination;
901 	      continue;
902 	    }
903 	    if (it->subtype==_FOLDER__VECT || it->subtype==_RGBA__VECT){
904 	      ++it;
905 	      if (it!=itend && state<=nr_eval_op)
906 		++destination;
907 	      continue;
908 	    }
909 	    fromto_stack.push_back(nr_pointers_t(unsigned(destination-(gen *) &argl.front()),itbeg,it,itend,old,1,state));
910 	    argl.swap(fromto_stack.back().argl);
911 	    // vecteur beginning by comment?
912 	    tmp=*it;
913 	    if (it->subtype==_SEQ__VECT && !it->_VECTptr->empty() && it->_VECTptr->front().type==_SYMB
914 		&& (it->_VECTptr->front()._SYMBptr->sommet==at_comment)
915 		&& (it->_VECTptr->back().is_symb_of_sommet(at_return))
916 		){
917 	      itend=(gen *) &it->_VECTptr->back()+1;
918 	      it=(gen *) &it->_VECTptr->front();
919 	      for (;it!=itend;++it){
920 		if ( (it->type!=_SYMB) || (it->_SYMBptr->sommet!=at_comment) )
921 		  break;
922 	      }
923 	      if (it+1==itend){
924 		*destination=*it;
925 		fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
926 		destination=(gen *) &argl.front()+arglpos;
927 		++it;
928 		if (it!=itend && state<=nr_eval_op)
929 		  ++destination;
930 		continue;
931 	      }
932 	      if (it==itend){
933 		*destination=zero;
934 		fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
935 		destination=(gen *) &argl.front()+arglpos;
936 		++it;
937 		if (it!=itend && state<=nr_eval_op)
938 		  ++destination;
939 		continue;
940 	      }
941 	    }
942 	    else {
943 	      itend=(gen *)&it->_VECTptr->back()+1;
944 	      it=(gen *)&it->_VECTptr->front();
945 	    }
946 	    itbeg=it;
947 	    old=tmp;
948 	    // normal vector evaluation
949 	    state=nr_eval_vect;
950 	    argl.resize(itend-it);
951 	    // vecteur_stack.push_back(argl);
952 	    // argl=vecteur(itend-it);
953 	    destination=(gen *)&argl.front();
954 	    continue;
955 	  case _SYMB: {
956 	    // special cases
957 	    unary_function_ptr & u =it->_SYMBptr->sommet;
958 	    gen f=it->_SYMBptr->feuille;
959 	    if (u==at_quote){
960 	      *destination=quote(f,contextptr);
961 	      ++it;
962 	      if (it!=itend && state<=nr_eval_op)
963 		++destination;
964 	      continue;
965 	    }
966 	    if (u==at_program) {
967 	      *destination=quote_program(it->_SYMBptr->feuille,contextptr);
968 	      ++it;
969 	      if (it!=itend && state<=nr_eval_op)
970 		++destination;
971 	      continue;
972 	    }
973 	    int specop=0;
974 	    if (u==at_goto)
975 	      label=f;
976 	    if (u==at_ifte || u==at_when)
977 	      specop=nr_eval_if_cond;
978 	    if (u==at_for){
979 	      if (state==nr_eval_for_cond){ // for in for_cond is for the syntax for x in l
980 		*destination=*it;
981 		++it;
982 		continue;
983 	      }
984 	      nr_eval_for_stack.push_back(0); // index for for var in list/string
985 	      nr_eval_for_stack.push_back(debug_ptr(contextptr)->current_instruction);
986 	      specop=nr_eval_for_init;
987 	    }
988 	    if (u==at_bloc)
989 	      specop=nr_eval_bloc;
990 	    if (u==at_local)
991 	      specop=nr_eval_local;
992 	    if (u==at_sto)
993 	      specop=nr_eval_sto;
994 	    if (u==at_of)
995 	      specop=nr_eval_of;
996 	    if (u==at_try_catch)
997 	      specop=nr_eval_catch;
998 	    if (!specop && u.quoted() && !f.is_symb_of_sommet(at_unquote)){
999 	      // check for hash
1000 	      if (f.is_symb_of_sommet(at_hash) && f._SYMBptr->feuille.type==_STRNG)
1001 		f=gen(*f._SYMBptr->feuille._STRNGptr,contextptr);
1002 	      *destination=u(f,contextptr);
1003 	      ++it;
1004 	      if (it!=itend && state<=nr_eval_op)
1005 		++destination;
1006 	      continue;
1007 	    }
1008 	    // save pointers and state, eval args
1009 	    fromto_stack.push_back(nr_pointers_t(unsigned(destination-(gen *)&argl.front()),itbeg,it,itend,old,1,state));
1010 	    argl.swap(fromto_stack.back().argl);
1011 	    state=specop?specop:nr_eval_op;
1012 	    old=*it;
1013 	    destination=(gen *)&argl.front();
1014 	    if ( f.type==_VECT &&
1015 		 (
1016 		  (specop==nr_eval_sto && f._VECTptr->size()==2) ||
1017 		  (specop==nr_eval_if_cond && f._VECTptr->size()>=3) ||
1018 		  (specop==nr_eval_for_init && f._VECTptr->size()>=3) ||
1019 		  (specop==nr_eval_catch && f._VECTptr->size()>=3)
1020 		  ) ){
1021 	      // sto: eval first arg, but not the second arg
1022 	      // if: eval first arg, but not the second third arg
1023 	      // for: eval first arg [init]
1024 	      // try ... catch: eval first arg
1025 	      itbeg=it=&f._VECTptr->front();
1026 	      itend=it+1;
1027 	      continue;
1028 	    }
1029 	    if (specop==nr_eval_local){
1030 	      int protect=0;
1031 	      gen vars,values;
1032 	      context * save_contextptr=contextptr;
1033 	      // Bind local var
1034 	      prog=f;
1035 	      vars=prog._VECTptr->front();
1036 	      if (vars.type==_VECT && vars._VECTptr->size()==2 && vars._VECTptr->front().type!=_IDNT)
1037 		vars = vars._VECTptr->front();
1038 	      if (vars.type!=_VECT)
1039 		vars=makevecteur(vars);
1040 	      values=gen(vecteur(vars._VECTptr->size()));
1041 	      for (unsigned i=0;i<vars._VECTptr->size();++i){
1042 		tmp=(*vars._VECTptr)[i];
1043 		if (tmp.is_symb_of_sommet(at_sto) || is_equal(tmp)){
1044 		  (*values._VECTptr)[i]=tmp._SYMBptr->feuille._VECTptr->back();
1045 		  (*vars._VECTptr)[i]=tmp._SYMBptr->feuille._VECTptr->front().eval(1,contextptr);
1046 		}
1047 	      }
1048 	      prog=prog._VECTptr->back();
1049 	      protect=giac_bind(*values._VECTptr,*vars._VECTptr,contextptr);
1050 	      if (protect==-RAND_MAX){
1051 		gensizeerr(res,contextptr);
1052 		return res;
1053 	      }
1054 	      // save previous state
1055 	      nr_prog_stack.push_back(nr_prog(save_contextptr,0,vars,false,protect));
1056 	      if (prog.type==_VECT && prog.subtype==0){
1057 		itbeg=it=(gen *)&prog._VECTptr->front();
1058 		itend=(gen *)&prog._VECTptr->back()+1;
1059 	      }
1060 	      else {
1061 		itbeg=it=&prog;
1062 		itend=it+1;
1063 	      }
1064 	      continue;
1065 	    }
1066 	    // if (specop==nr_eval_of || specof==nr_eval_bloc){
1067 	    //  state=specop; // program name is in old, eval args normally
1068 	    // }
1069 	    // normal symbolic
1070 	    if (f.type==_VECT && (f.subtype==_SEQ__VECT || (specop==nr_eval_of || specop==nr_eval_bloc))){
1071 	      itend=(gen *)&f._VECTptr->back()+1;
1072 	      itbeg=it=(gen *)&f._VECTptr->front();
1073 	      argl.resize(itend-it);
1074 	      destination=(gen *)&argl.front();
1075 	    }
1076 	    else {
1077 	      itbeg=it=&it->_SYMBptr->feuille; // do not use &f here!
1078 	      itend=it+1;
1079 	    }
1080 	    continue;
1081 	  }
1082 	  case _IDNT:
1083 	    tmp=eval(*it,level,contextptr);
1084 	    if (tmp.type!=_VECT || tmp.subtype!=_SEQ__VECT || (state!=nr_eval_vect && !(state==nr_eval_op && old.type==_SYMB && old._SYMBptr->feuille.type==_VECT)))
1085 	      *destination=tmp;
1086 	    else {
1087 	      // tmp is a sequence inside a vector,
1088 	      // enlarge argl and copy tmp._VECTptr in argl
1089 	      int pos=int(destination-(gen *)&argl.front());
1090 	      for (unsigned i=1;i<tmp._VECTptr->size();++i)
1091 		argl.push_back(0);
1092 	      destination=(gen *)&argl.front()+pos;
1093 	      for (unsigned i=0;;){
1094 		*destination=(*tmp._VECTptr)[i];
1095 		++i;
1096 		if (i==tmp._VECTptr->size())
1097 		  break;
1098 		++destination;
1099 	      }
1100 	    }
1101 	    ++it;
1102 	    if (it!=itend && state<=nr_eval_op)
1103 	      ++destination;
1104 	    continue;
1105 	  default:
1106 	    *destination=*it;
1107 	    ++it;
1108 	    if (it!=itend && state<=nr_eval_op)
1109 	      ++destination;
1110 	    continue;
1111 	  } // end switch on it->type
1112 	}
1113 	// it==itend
1114 	// end eval of current vector
1115 	signed char oldsubtype=old.type==_VECT?old.subtype:0;
1116 	if (fromto_stack.empty()){
1117 	  return argl.front(); // end evaluation
1118 	}
1119 	// dispatch depending on current mode
1120 	switch (state){
1121 	case nr_eval_dispatch:
1122 	  continue;
1123 	case nr_eval_vect:
1124 	  // end eval of vecteur, store value in res
1125 	  if (oldsubtype==_SET__VECT && !argl.empty()){
1126 	    // remove multiple occurences
1127 	    islesscomplexthanf_sort(argl.begin(),argl.end());
1128 	    vecteur tmp;
1129 	    tmp.reserve(argl.size());
1130 	    tmp.push_back(argl.front());
1131 	    for (iterateur jt=argl.begin()+1;jt!=argl.end();++jt){
1132 	      if (*jt!=tmp.back())
1133 		tmp.push_back(*jt);
1134 	    }
1135 	    tmp.swap(argl);
1136 	    res=gen(argl,oldsubtype);
1137 	  }
1138 	  else {
1139 	    // FIXME: make a faster == check (may returns false for large == vecteurs)
1140 	    if (old.type==_VECT && old._VECTptr->size()<17 && *old._VECTptr==argl)
1141 	      res=old;
1142 	    else
1143 	      res=gen(argl,oldsubtype);
1144 	  }
1145 	  // restore previous state, old, pointers and argl
1146 	  fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1147 	  destination=(gen *)&argl.front()+arglpos;
1148 	  *destination=res;
1149 	  ++it;
1150 	  if (it!=itend && state<=nr_eval_op)
1151 	    ++destination;
1152 	  continue; // end state==nr_eval_vect
1153 	case nr_eval_for_init:
1154 	  forlast=undef;
1155 	  ++itend;
1156 	  state=nr_eval_for_cond;
1157 	  continue;
1158 	case nr_eval_for_cond:
1159 	  res=*destination;
1160 	  if ( nr_eval_for_stack.size()>=2 && (res.is_symb_of_sommet(at_for) || res.is_symb_of_sommet(at_pour)) && res._SYMBptr->feuille.type==_VECT && res._SYMBptr->feuille._VECTptr->size()==2){
1161 	    // for var in list/string
1162 	    res=eval(res._SYMBptr->feuille._VECTptr->back(),1,contextptr);
1163 	    if (res.type==_VECT){
1164 	      if (int(res._VECTptr->size())>nr_eval_for_stack[nr_eval_for_stack.size()-2]){
1165 		res=res[nr_eval_for_stack[nr_eval_for_stack.size()-2]];
1166 		sto(res,destination->_SYMBptr->feuille._VECTptr->front(),contextptr);
1167 		res=1;
1168 	      }
1169 	      else
1170 		res=0;
1171 	    }
1172 	    else {
1173 	      if (res.type==_STRNG){
1174 		if (int(res._STRNGptr->size())>nr_eval_for_stack[nr_eval_for_stack.size()-2]){
1175 		  res=string2gen(string(1,(*res._STRNGptr)[nr_eval_for_stack[nr_eval_for_stack.size()-2]]),false);
1176 		  sto(res,destination->_SYMBptr->feuille._VECTptr->front(),contextptr);
1177 		  res=1;
1178 		}
1179 		else
1180 		  res=0;
1181 	      }
1182 	      else
1183 		res=0;
1184 	    }
1185 	    ++nr_eval_for_stack[nr_eval_for_stack.size()-2];
1186 	  }
1187 	  res=equaltosame(res).eval(eval_level(contextptr),contextptr);
1188 	  if (!is_integer(res)){
1189 	    res=res.evalf_double(eval_level(contextptr),contextptr);
1190 	    if ( res.type!=_DOUBLE_ && res.type!=_CPLX ){
1191 	      if (old._SYMBptr->sommet==at_for){
1192 		if (!nr_eval_for_stack.empty()) // pop back instruction and for in index
1193 		  nr_eval_for_stack.pop_back();
1194 		if (!nr_eval_for_stack.empty())
1195 		  nr_eval_for_stack.pop_back();
1196 		fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1197 		destination=(gen *)&argl.front()+arglpos;
1198 		gensizeerr(gettext("For: Unable to check test"),*destination);
1199 		res=*destination;
1200 		it=itend;
1201 		continue;
1202 	      }
1203 	      else
1204 		res=old;
1205 	    }
1206 	  }
1207 	  if (!is_zero(res)){ // TRUE
1208 	    it++; itend+=2;
1209 	    state=nr_eval_for_loop;
1210 	  }
1211 	  else {
1212 	    increment_instruction_ptr(it+1,it+3,contextptr);
1213 	    if (!nr_eval_for_stack.empty()) // pop back instruction and for in index
1214 	      nr_eval_for_stack.pop_back();
1215 	    if (!nr_eval_for_stack.empty())
1216 	      nr_eval_for_stack.pop_back();
1217 	    // restore state and pointers
1218 	    fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1219 	    destination=(gen *)&argl.front()+arglpos;
1220 	    *destination=forlast;
1221 	    ++it;
1222 	    if (it!=itend && state<=nr_eval_op)
1223 	      ++destination;
1224 	  }
1225 	  continue;
1226 	case nr_eval_for_loop:
1227 	  if (destination->type==_SYMB && (destination->_SYMBptr->sommet==at_break || destination->_SYMBptr->sommet==at_return)){
1228 	    if (destination->_SYMBptr->sommet==at_break)
1229 	      *destination=undef;
1230 	    if (!nr_eval_for_stack.empty()) // pop back instruction and for in index
1231 	      nr_eval_for_stack.pop_back();
1232 	    if (!nr_eval_for_stack.empty())
1233 	      nr_eval_for_stack.pop_back();
1234 	    state=nr_eval_bloc;
1235 	  }
1236 	  else {
1237 	    it -= 2; --itend;
1238 	    state=nr_eval_for_incr;
1239 	    forlast=*destination;
1240 	  }
1241 	  continue;
1242 	case nr_eval_for_incr:
1243 	  if (!nr_eval_for_stack.empty())
1244 	    debug_ptr(contextptr)->current_instruction=nr_eval_for_stack.back();
1245 	  if (debug_ptr(contextptr)->debug_mode){
1246 	    debug_loop(res,contextptr);
1247 	    if (is_undef(res)) return res;
1248 	  }
1249 	  state=nr_eval_for_cond;
1250 	  it -= 2;
1251 	  itend -= 1;
1252 	  continue;
1253 	case nr_eval_catch:
1254 	  // catch lasterr, FIXME for debug
1255 	  state=nr_eval_if_false;
1256 	  if (lasterr.type==_STRNG){
1257 	    lasterr.subtype=0;
1258 	    sto(lasterr,*it,contextptr);
1259 	    ++it;
1260 	    itend += 2;
1261 	    lasterr=*destination=res=0;
1262 	    continue;
1263 	  }
1264 	  increment_instruction(*(it+1),contextptr);
1265 	  if (old._SYMBptr->feuille._VECTptr->size()==4){
1266 	    it += 2;
1267 	    itend += 3;
1268 	  }
1269 	  continue;
1270 	case nr_eval_if_cond:
1271 	  res=*destination;
1272 	  res=equaltosame(res).eval(eval_level(contextptr),contextptr);
1273 	  if (!is_integer(res)){
1274 	    res=res.evalf_double(eval_level(contextptr),contextptr);
1275 	    if ( res.type!=_DOUBLE_ && res.type!=_CPLX ){
1276 	      if (old._SYMBptr->sommet==at_ifte){
1277 		fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1278 		destination=(gen *)&argl.front()+arglpos;
1279 		gensizeerr(gettext("Ifte: Unable to check test"),*destination);
1280 		res=*destination;
1281 		it=itend;
1282 		continue;
1283 	      }
1284 	      else
1285 		res=old;
1286 	    }
1287 	  }
1288 	  if (!is_zero(res)){ // TRUE
1289 	    state=nr_eval_if_true;
1290 	    ++itend;
1291 	  }
1292 	  else { //FALSE
1293 	    if (old._SYMBptr->sommet==at_ifte){
1294 	      increment_instruction(*it,contextptr);
1295 	    }
1296 	    state=nr_eval_if_false;
1297 	    ++it; itend+=2;
1298 	  }
1299 	  continue;
1300 	case nr_eval_of:
1301 	  if (argl.size()==2 && argl.front().is_symb_of_sommet(at_program)){
1302 	    debug_struct * dbgptr=debug_ptr(contextptr);
1303 	    int protect=0;
1304 	    bool save_sst_mode=dbgptr->sst_mode;
1305 	    gen vars,values;
1306 	    context * save_contextptr=contextptr;
1307 	    dbgptr->sst_at_stack.push_back(dbgptr->sst_at);
1308 	    dbgptr->sst_at.clear();
1309 	    progname=old._SYMBptr->feuille._VECTptr->front();
1310 	    if (progname.is_symb_of_sommet(at_program))
1311 	      progname=undef;
1312 	    if (progname.type==_IDNT)
1313 	      adjust_sst_at(progname,contextptr);
1314 	    dbgptr->current_instruction_stack.push_back(dbgptr->current_instruction);
1315 	    dbgptr->current_instruction=0;
1316 	    if (dbgptr->sst_in_mode){
1317 	      dbgptr->sst_in_mode=false;
1318 	      dbgptr->sst_mode=true;
1319 	    }
1320 	    else
1321 	      dbgptr->sst_mode=false;
1322 	    // Bind local var
1323 	    prog=argl.front()._SYMBptr->feuille;
1324 	    vars=prog._VECTptr->front();
1325 	    values=argl[1];
1326 	    prog=prog._VECTptr->back();
1327 	    if (vars.type!=_VECT)
1328 	      vars=gen(makevecteur(vars));
1329 	    if (values.type!=_VECT || values.subtype!=_SEQ__VECT || (vars._VECTptr->size()==1 && values._VECTptr->size()!=1))
1330 	      values=gen(makevecteur(values));
1331 	    // *logptr(contextptr) << vars << " " << values << endl;
1332 	    // removed sst test so that when a breakpoint is evaled
1333 	    // the correct info is displayed
1334 	    (*dbgptr->fast_debug_info_ptr)=prog;
1335 	    (*dbgptr->debug_info_ptr)=prog;
1336 	    if (!vars._VECTptr->empty())
1337 	      protect=giac_bind(*values._VECTptr,*vars._VECTptr,contextptr);
1338 	    if (protect==-RAND_MAX){
1339 	      program_leave(*dbgptr->debug_info_ptr,save_sst_mode,dbgptr);
1340 	      gensizeerr(res,contextptr);
1341 	      return res;
1342 	    }
1343 	    // save previous state
1344 	    nr_prog_stack.push_back(nr_prog(save_contextptr,*dbgptr->debug_info_ptr,vars,save_sst_mode,protect));
1345 	    dbgptr->args_stack.push_back(gen(mergevecteur(vecteur(1,progname),*values._VECTptr)));
1346 	    if (prog.type==_VECT && prog.subtype==0){
1347 	      itbeg=it=(gen *)&prog._VECTptr->front();
1348 	      itend=(gen *)&prog._VECTptr->back()+1;
1349 	    }
1350 	    else {
1351 	      itbeg=it=&prog;
1352 	      itend=it+1;
1353 	    }
1354 	    state=nr_eval_prog;
1355 	  }
1356 	  else
1357 	    state=nr_eval_op; // like a goto nr_eval_op: below
1358 	  continue;
1359 	case nr_eval_if_true:
1360 	  if (old._SYMBptr->sommet==at_ifte)
1361 	    increment_instruction(*it,contextptr);  // no break here
1362 	case nr_eval_if_false:
1363 	  res=*destination; // no break here
1364 	case nr_eval_op: case nr_eval_sto:
1365 	  // eval operator
1366 	  if (state==nr_eval_sto)
1367 	    res=sto(*destination,old._SYMBptr->feuille._VECTptr->back(),contextptr);
1368 	  else {
1369 	    if (state==nr_eval_op){
1370 	      if (old._SYMBptr->feuille.type==_VECT && old._SYMBptr->feuille.subtype==_SEQ__VECT)
1371 		res=gen(argl,_SEQ__VECT);
1372 	      else
1373 		res=*destination;
1374 	      res=(*old._SYMBptr->sommet.ptr())(res,contextptr);
1375 	    }
1376 	  }
1377 	  // no break here -> restore
1378 	case nr_eval_bloc:
1379 	  // restore state and pointers
1380 	  if (state==nr_eval_bloc)
1381 	    res=*destination;
1382 	  fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1383 	  destination=(gen *)&argl.front()+arglpos;
1384 	  *destination=res;
1385 	  ++it;
1386 	  if (it!=itend && state<=nr_eval_op)
1387 	    ++destination;
1388 	  continue;
1389 	case nr_eval_prog: case nr_eval_local:
1390 	  // end of program reached, restore context
1391 	  res=*destination;
1392 	  if (state==nr_eval_prog && res.is_symb_of_sommet(at_return))
1393 	    res=res._SYMBptr->feuille;
1394 	  if (!nr_prog_stack.back().vars._VECTptr->empty())
1395 	    leave(nr_prog_stack.back().protect,*nr_prog_stack.back().vars._VECTptr,contextptr);
1396 	  if (state==nr_eval_prog)
1397 	    program_leave(nr_prog_stack.back().save_debug_info,nr_prog_stack.back().save_sst_mode,debug_ptr(contextptr));
1398 	  contextptr=nr_prog_stack.back().contextptr;
1399 	  nr_prog_stack.pop_back();
1400 	  // restore state and pointers
1401 	  fromto_restore(arglpos,itbeg,it,itend,old,argl,state,fromto_stack);
1402 	  destination=(gen *)&argl.front()+arglpos;
1403 	  *destination=res;
1404 	  ++it;
1405 	  if (it!=itend && state<=nr_eval_op)
1406 	    ++destination;
1407 	  continue;
1408 	default:
1409 	  gensizeerr(gettext("Bad state"),res);
1410 	  return res;
1411 	} // end switch
1412 #ifndef NO_STDEXCEPT
1413       }
1414       catch (std::runtime_error & e) {
1415 	last_evaled_argptr(contextptr)=NULL;
1416 	res=string2gen(e.what(),false);
1417 	res.subtype=-1;
1418 	*destination=res;
1419       }
1420 #endif
1421     } // end while(1)
1422     return argl.front();
1423   }
1424 
eval(int level,const context * contextptr) const1425   gen symbolic::eval(int level,const context * contextptr) const {
1426     if (level==0 || !sommet.ptr())
1427       return *this;
1428     // FIXME test should be removed later, it's here for tests. See global.cc DEFAULT_EVAL_LEVEL
1429     int & elevel=eval_level(contextptr);
1430     if (elevel==26)
1431       return nr_eval(*this,level,contextptr);
1432     if (sommet==at_sto && feuille.type==_VECT)
1433       return eval_sto(feuille,level,contextptr);
1434     const char * & last =last_evaled_function_name(contextptr);
1435     const char * save_last=last;
1436     last=sommet.ptr()->s;
1437     const gen * & lastarg=last_evaled_argptr(contextptr);
1438     const gen * save_lastarg=lastarg;
1439     lastarg=&feuille;
1440     gen ans;
1441     if (sommet.quoted()){
1442 #ifndef RTOS_THREADX
1443       if (feuille.type==_SYMB){
1444 	unary_function_ptr & u=feuille._SYMBptr->sommet;
1445 	if (u==at_unquote){
1446 	  ans=sommet(feuille.eval(level,contextptr),contextptr);
1447 	  last=save_last;
1448 	  lastarg=save_lastarg;
1449 	  return ans;
1450 	}
1451 	if (u==at_hash){
1452 	  ans=sommet(gen(*feuille._SYMBptr->feuille._STRNGptr,contextptr),contextptr);
1453 	  last=save_last;
1454 	  lastarg=save_lastarg;
1455 	  return ans;
1456 	}
1457       }
1458 #endif
1459       int save_level=elevel;
1460       elevel=level;
1461 #ifdef NO_STDEXCEPT
1462       ans=sommet(feuille,contextptr);
1463 #else
1464       try {
1465 	ans=sommet(feuille,contextptr);
1466       }
1467       catch (std::runtime_error & err){
1468 	lastarg=&feuille;
1469 	elevel=save_level;
1470 	throw(err);
1471       }
1472 #endif
1473       elevel=save_level;
1474       last=save_last;
1475       lastarg=save_lastarg;
1476       return ans;
1477     } // if (sommet.quoted())
1478     else {
1479       // pnt check required because pnt name might be the identifier->recursion
1480       if (feuille.type==_VECT && sommet==at_pnt && feuille._VECTptr->size()==3){
1481 	ans=(*sommet.ptr())(gen(vecteur(feuille._VECTptr->begin(),feuille._VECTptr->begin()+2),feuille.subtype).in_eval(level,ans,contextptr)?ans:feuille,contextptr);
1482 	last=save_last;
1483 	lastarg=save_lastarg;
1484 	return ans;
1485       }
1486       if (feuille.type==_IDNT && sommet==at_neg && !strcmp(feuille._IDNTptr->id_name,string_infinity)){
1487 	last=save_last;
1488 	lastarg=save_lastarg;
1489 	return minus_inf;
1490       }
1491       if (sommet==at_quote){
1492 	last=save_last;
1493 	lastarg=save_lastarg;
1494 	return quote(feuille,contextptr);
1495       }
1496       ans=(*sommet.ptr())(feuille.in_eval(level,ans,contextptr)?ans:feuille,contextptr);
1497       /*
1498 	if (feuille.in_eval(level,ans,contextptr))
1499 	ans=(*sommet.ptr())(ans,contextptr);
1500 	else
1501 	ans=(*sommet.ptr())(feuille,contextptr);
1502       */
1503       last=save_last;
1504       lastarg=save_lastarg;
1505       return ans;
1506     }
1507   }
1508 
rewrite_prod_inv(const gen & arg,gen & n,gen & d)1509   bool rewrite_prod_inv(const gen & arg,gen & n,gen & d){
1510     n=1; d=1;
1511     if (arg.type==_VECT && !arg._VECTptr->empty() && arg._VECTptr->back().is_symb_of_sommet(at_inv)) {
1512       vecteur & uv=*arg._VECTptr;
1513       int tmps=int(uv.size()),invbegin;
1514       vecteur den(1,uv.back()._SYMBptr->feuille);
1515       // group all inv from the end to the beginning for the denominator
1516       for (invbegin=tmps-2;invbegin>=0;--invbegin){
1517 	if (!uv[invbegin].is_symb_of_sommet(at_inv))
1518 	  break;
1519 	den.push_back(uv[invbegin]._SYMBptr->feuille);
1520       }
1521       vecteur num;
1522       for (int i=0;i<=invbegin;++i){
1523 	if (uv[i].is_symb_of_sommet(at_inv) && uv[i]._SYMBptr->feuille.type<_POLY)
1524 	  d=d*uv[i]._SYMBptr->feuille;
1525 	else
1526 	  num.push_back(uv[i]);
1527       }
1528       if (!is_one(d))
1529 	den.insert(den.begin(),d);
1530       if (den.size()>1)
1531 	d=new_ref_symbolic(symbolic(at_prod,den));
1532       else
1533 	d=den.front();
1534       if (!num.empty()){
1535 	if (num.size()==1)
1536 	  n=num.front();
1537 	else
1538 	  n=new_ref_symbolic(symbolic(at_prod,num));
1539       }
1540       return true;
1541     }
1542     // Group scalar denominators (warning, do not use for matrices!)
1543     vecteur num,den;
1544     prod2frac(new_ref_symbolic(symbolic(at_prod,arg)),num,den);
1545     if (!den.empty()){
1546       if (num.empty())
1547 	n=plus_one;
1548       else {
1549 	if (num.size()==1)
1550 	  n=num.front();
1551 	else
1552 	  n=new_ref_symbolic(symbolic(at_prod,num));
1553       }
1554       /* code that does not work with matrices
1555 	 if (den.size()==1)
1556 	 d=den.front();
1557 	 else
1558 	 d=ref_symbolic(symbolic(at_prod,den);)
1559       */
1560       if (den.size()==1 && den.front().type<_IDNT){
1561 	d=den.front();
1562 	return true;
1563       }
1564     }
1565     return false;
1566   }
1567 
evalf(int level,const context * contextptr) const1568   gen symbolic::evalf(int level,const context * contextptr) const {
1569     if (level==0)
1570       return *this;
1571     const char * & last =last_evaled_function_name(contextptr);
1572     const char * save_last=last;
1573     last=sommet.ptr()->s;
1574     const gen * & lastarg=last_evaled_argptr(contextptr);
1575     const gen * save_lastarg=lastarg;
1576     lastarg=&feuille;
1577     if (sommet==at_sto){ // autoname function
1578       gen e=feuille._VECTptr->front().evalf(level,contextptr);
1579       if ((e.type==_SYMB) && (e._SYMBptr->sommet==at_pnt) && (e._SYMBptr->feuille.type==_VECT) && (e._SYMBptr->feuille._VECTptr->size()==2))
1580 	e=new_ref_symbolic(symbolic(at_pnt,gen(makevecteur(e._SYMBptr->feuille._VECTptr->front(),e._SYMBptr->feuille._VECTptr->back(),string2gen(feuille._VECTptr->back().print(contextptr),false)),_PNT__VECT)));
1581       if ( (e.type==_VECT) && (e._VECTptr->size()) && (e._VECTptr->back().type==_SYMB) && (e._VECTptr->back()._SYMBptr->sommet==at_pnt)){
1582 	vecteur v=*e._VECTptr;
1583 	iterateur it=v.begin(),itend=v.end();
1584 	for (;it!=itend;++it){
1585 	  if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_pnt) && (it->_SYMBptr->feuille._VECTptr->size()==2))
1586 	    *it=new_ref_symbolic(symbolic(at_pnt,gen(makevecteur(it->_SYMBptr->feuille._VECTptr->front(),it->_SYMBptr->feuille._VECTptr->back(),string2gen(feuille._VECTptr->back().print(contextptr),false)),_PNT__VECT)));
1587 	}
1588 	e=v;
1589       }
1590       last=save_last;
1591       lastarg=save_lastarg;
1592       return sto(e,feuille._VECTptr->back(),contextptr);
1593     }
1594     gen ans;
1595     if (sommet==at_plus){
1596       if (feuille.type!=_VECT){
1597 	if (feuille.type==_IDNT && !strcmp(feuille._IDNTptr->id_name,string_infinity))
1598 	  ans=plus_inf;
1599 	else
1600 	  ans=feuille.evalf(level,contextptr);
1601       }
1602       else {
1603 	const_iterateur it=feuille._VECTptr->begin(),itend=feuille._VECTptr->end();
1604 	for (;it!=itend;++it){
1605 	  ans=ans+it->evalf(level,contextptr);
1606 	}
1607       }
1608       last=save_last;
1609       lastarg=save_lastarg;
1610       return ans;
1611     }
1612     if (sommet==at_prod){
1613       if (feuille.type!=_VECT)
1614 	ans=feuille.evalf(level,contextptr);
1615       else {
1616 	ans=1;
1617 	const_iterateur it=feuille._VECTptr->begin(),itend=feuille._VECTptr->end();
1618 	for (;it!=itend;++it){
1619 	  ans=operator_times(ans,it->evalf(level,contextptr),contextptr);
1620 	}
1621       }
1622       last=save_last;
1623       lastarg=save_lastarg;
1624       return ans;
1625     }
1626     if (sommet.quoted() && sommet!=at_and && !equalposcomp(plot_sommets,sommet) ){
1627       ans=sommet(feuille,contextptr);
1628       last=save_last;
1629       lastarg=save_lastarg;
1630       return ans;
1631     }
1632     else {
1633       if ((sommet==at_neg) && (feuille.type==_IDNT) && !strcmp(feuille._IDNTptr->id_name,string_infinity)){
1634 	last=save_last;
1635 	lastarg=save_lastarg;
1636 	return minus_inf;
1637       }
1638       if (sommet==at_quote){
1639 	last=save_last;
1640 	lastarg=save_lastarg;
1641 	return quote(feuille,contextptr);
1642       }
1643       if (sommet==at_and || (sommet!=at_cercle && equalposcomp(plot_sommets,sommet))){
1644 	// bool save_is_inevalf=is_inevalf;
1645 	// is_inevalf=true;
1646 	ans=new_ref_symbolic(symbolic(sommet,feuille.evalf(1,contextptr)));
1647 	// is_inevalf=save_is_inevalf;
1648 	last=save_last;
1649 	lastarg=save_lastarg;
1650 	return ans;
1651       }
1652       ans=(*sommet.ptr())(feuille.evalf(level,contextptr),contextptr);
1653       last=save_last;
1654       lastarg=save_lastarg;
1655       return ans;
1656     }
1657   }
1658 
1659 
taille(const gen & g,unsigned max)1660   unsigned taille(const gen & g,unsigned max){
1661     if (g.type<=_IDNT)
1662       return 1;
1663     if (g.type==_FRAC)
1664       return 1+taille(g._FRACptr->num,max)+taille(g._FRACptr->den,max);
1665     if (g.type==_SYMB){
1666       if (max && g.is_symb_of_sommet(at_curve))
1667 	return 10;
1668       return 1+taille(g._SYMBptr->feuille,max);
1669     }
1670     if (g.type==_VECT){
1671       unsigned res=0;
1672       const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
1673       for (;it!=itend;++it){
1674 	res += taille(*it,max);
1675 	if (max && res>max)
1676 	  return res;
1677       }
1678       return res;
1679     }
1680     return 2;
1681   }
1682 
malloc_size(int s,int nalloc=2)1683   int malloc_size(int s,int nalloc=2){
1684     return nextpow2(s/4)*4+nalloc*16;
1685   }
1686 
tailles(const gen & g,vector<int> & v)1687   void tailles(const gen & g,vector<int> & v){
1688     switch (g.type){
1689     case _INT_: case _DOUBLE_: case _FLOAT_: case _FUNC:
1690       ++v[0];
1691       return;
1692     case _CPLX:
1693       tailles(*g._CPLXptr,v);
1694       tailles(*(g._CPLXptr+1),v);
1695       ++v[1];
1696       v[8] += malloc_size(sizeof(ref_complex));
1697       return;
1698     case _IDNT:
1699       ++v[2];
1700       // v[8] += malloc_size(sizeof(ref_identificateur)); // shared in syms()
1701       return;
1702     case _FRAC:
1703       tailles(g._FRACptr->num,v);
1704       tailles(g._FRACptr->den,v);
1705       ++v[3];
1706       v[8] += malloc_size(sizeof(ref_fraction));
1707       return;
1708     case _VECT: {
1709       const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end();
1710       ++v[4];
1711       // CERR << g._VECTptr->capacity() << " "  << itend-it  << " " << g << endl;
1712 #if defined IMMEDIATE_VECTOR
1713       if (g._VECTptr->capacity()<=(IMMEDIATE_VECTOR*sizeof(int))/sizeof(gen))
1714 	v[8] += malloc_size(sizeof(ref_vecteur),1);
1715       else
1716 #endif
1717 	v[8] += malloc_size(sizeof(ref_vecteur))+g._VECTptr->capacity()*sizeof(gen);
1718       for (;it!=itend;++it){
1719 	tailles(*it,v);
1720       }
1721       return;
1722     }
1723     case _SYMB:
1724       tailles(g._SYMBptr->feuille,v);
1725       ++v[5];
1726       v[8] += malloc_size(sizeof(ref_symbolic));
1727       return;
1728     case _STRNG:
1729       v[8] += g._STRNGptr->capacity() + malloc_size(sizeof(ref_string));
1730       ++v[6] ;
1731       return;
1732     default:
1733       ++v[7];
1734     }
1735   }
1736 
bytesize(const gen & g)1737   int bytesize(const gen & g){
1738     vector<int> v(9);
1739     tailles(g,v);
1740     return v[8];
1741   }
1742 
tailles(const gen & g)1743   vecteur tailles(const gen & g){
1744     vector<int> v(9); // atomic, idnt, frac, vector, symb, string, other, all
1745     tailles(g,v);
1746     vecteur w;
1747     vector_int2vecteur(v,w);
1748     return makevecteur(makevecteur(string2gen("atom",false),string2gen("cplx",false),
1749 				   string2gen("idnt",false),string2gen("frac",false),
1750 				   string2gen("vector",false),string2gen("symb",false),
1751 				   string2gen("strng",false),string2gen("other",false),
1752 				   string2gen("total",false))
1753 		       ,w);
1754   }
1755 
1756   int print_max_depth=100;
depth(const gen & g,unsigned add,unsigned max)1757   unsigned depth(const gen & g,unsigned add,unsigned max){
1758     gen g_(g);
1759     for (;g_.type==_SYMB;++add){
1760       g_=g_._SYMBptr->feuille;
1761     }
1762     if (add>=max)
1763       return add;
1764     if (g_.type==_VECT){
1765       unsigned res=add;
1766       const_iterateur it=g_._VECTptr->begin(),itend=g_._VECTptr->end();
1767       for (;it!=itend;++it){
1768 	unsigned cur=depth(*it,add,max);
1769 	if (max && cur>max)
1770 	  return res;
1771 	if (cur>res)
1772 	  res=cur;
1773       }
1774       return res;
1775     }
1776     return add;
1777   }
1778 
1779 #ifdef NSPIRE
operator <<(nio::ios_base<T> & os,const symbolic & s)1780   template<class T> nio::ios_base<T> & operator << (nio::ios_base<T> & os,const symbolic & s) { return os << s.print(context0); }
1781 #else
operator <<(ostream & os,const symbolic & s)1782   ostream & operator << (ostream & os,const symbolic & s) { return os << s.print(context0); }
1783 #endif
1784 
1785 #ifndef NO_NAMESPACE_GIAC
1786 } // namespace giac
1787 #endif // ndef NO_NAMESPACE_GIAC
1788