@@ -261,20 +261,24 @@ void unsetvars(const args_t& varlist)
261261value_t value (const expr& x)
262262{
263263 debug (" value '%s'" ,x.val .c_str ());
264+ if ( x.cache .val .which ()!=value_none ) {
265+ debug (" eval cached" );
266+ return x.cache ;
267+ }
264268
265- if ( x.op ==' S' ) return value_t (x.val );
269+ if ( x.op ==' S' ) return x. cache = value_t (x.val );
266270 if ( isalpha (x.val [0 ]) ) return getvar (x);
267271
268272 mpz_class intval;
269273 mpf_class fltval;
270- if ( intval.set_str (x.val ,0 )==0 ) return value_t (intval);
274+ if ( intval.set_str (x.val ,0 )==0 ) return x. cache = value_t (intval);
271275 else if ( fltval.set_str (x.val ,0 )==0 ) {
272276 // Set sufficient precision:
273277 if ( fltval.get_prec ()<4 *x.val .length () ) {
274278 fltval.set_prec (4 *x.val .length ());
275279 fltval.set_str (x.val ,0 );
276280 }
277- return value_t (fltval);
281+ return x. cache = value_t (fltval);
278282 }
279283 return value_t ();
280284}
@@ -418,27 +422,60 @@ value_t evalfun(args_t funargs)
418422 exit (exit_failure);
419423}
420424
425+ bool cachable (const expr& e)
426+ {
427+ switch ( e.op ) {
428+ case ' I' :
429+ case ' F' :
430+ case ' S' :
431+ return true ;
432+
433+ case ' +' :
434+ case ' -' :
435+ case ' *' :
436+ case ' %' :
437+ case ' /' :
438+ case ' ^' :
439+ case ' n' :
440+ case ' ?' :
441+ case ' |' :
442+ case ' &' :
443+ case ' !' :
444+ case ' f' :
445+ for (size_t i=0 ; i<e.nargs (); i++) if ( !cachable (e.args [i]) ) return false ;
446+ return true ;
447+ }
448+ return false ;
449+ }
450+
421451value_t eval (const expr& e)
422452{
423453 debug (" eval op='%c', val='%s', #args=%d" ,e.op ,e.val .c_str (),(int )e.args .size ());
454+ if ( e.cache .val .which ()!=value_none ) {
455+ debug (" eval cached" );
456+ return e.cache ;
457+ }
458+ value_t res;
424459 switch ( e.op ) {
425460 case ' I' :
426461 case ' F' :
427462 case ' S' :
428- case ' v' : return value (e);
429- case ' n' : return -eval (e.args [0 ]);
430- case ' +' : return eval (e.args [0 ]) + eval (e.args [1 ]);
431- case ' -' : return eval (e.args [0 ]) - eval (e.args [1 ]);
432- case ' *' : return eval (e.args [0 ]) * eval (e.args [1 ]);
433- case ' /' : return eval (e.args [0 ]) / eval (e.args [1 ]);
434- case ' %' : return eval (e.args [0 ]) % eval (e.args [1 ]);
435- case ' ^' : return pow (eval (e.args [0 ]),eval (e.args [1 ]));
436- case ' f' : return evalfun (e.args );
463+ case ' v' : res = value (e); break ;
464+ case ' n' : res = -eval (e.args [0 ]); break ;
465+ case ' +' : res = eval (e.args [0 ]) + eval (e.args [1 ]); break ;
466+ case ' -' : res = eval (e.args [0 ]) - eval (e.args [1 ]); break ;
467+ case ' *' : res = eval (e.args [0 ]) * eval (e.args [1 ]); break ;
468+ case ' /' : res = eval (e.args [0 ]) / eval (e.args [1 ]); break ;
469+ case ' %' : res = eval (e.args [0 ]) % eval (e.args [1 ]); break ;
470+ case ' ^' : res = pow (eval (e.args [0 ]),eval (e.args [1 ])); break ;
471+ case ' f' : res = evalfun (e.args ); break ;
437472 default :
438473 cerr << " unknown arithmetic operator '" << e.op << " ' in "
439474 << program[prognr] << endl;
440475 exit (exit_failure);
441476 }
477+ if ( cachable (e) ) e.cache = res;
478+ return res;
442479}
443480
444481bool compare (const expr& cmp)
@@ -1090,7 +1127,8 @@ void checktestdata(ostream &datastream)
10901127 datastream << setprecision (float_precision);
10911128
10921129 while ( true ) {
1093- command cmd = currcmd = program[prognr];
1130+ const command &cmd = program[prognr];
1131+ currcmd = cmd;
10941132
10951133 if ( cmd.name ()==" EOF" ) {
10961134 if ( gendata ) {
0 commit comments