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