@@ -261,20 +261,24 @@ void unsetvars(const args_t& varlist)
261
261
value_t value (const expr& x)
262
262
{
263
263
debug (" value '%s'" ,x.val .c_str ());
264
+ if ( x.cache .val .which ()!=value_none ) {
265
+ debug (" eval cached" );
266
+ return x.cache ;
267
+ }
264
268
265
- if ( x.op ==' S' ) return value_t (x.val );
269
+ if ( x.op ==' S' ) return x. cache = value_t (x.val );
266
270
if ( isalpha (x.val [0 ]) ) return getvar (x);
267
271
268
272
mpz_class intval;
269
273
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);
271
275
else if ( fltval.set_str (x.val ,0 )==0 ) {
272
276
// Set sufficient precision:
273
277
if ( fltval.get_prec ()<4 *x.val .length () ) {
274
278
fltval.set_prec (4 *x.val .length ());
275
279
fltval.set_str (x.val ,0 );
276
280
}
277
- return value_t (fltval);
281
+ return x. cache = value_t (fltval);
278
282
}
279
283
return value_t ();
280
284
}
@@ -418,27 +422,60 @@ value_t evalfun(args_t funargs)
418
422
exit (exit_failure);
419
423
}
420
424
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
+
421
451
value_t eval (const expr& e)
422
452
{
423
453
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;
424
459
switch ( e.op ) {
425
460
case ' I' :
426
461
case ' F' :
427
462
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 ;
437
472
default :
438
473
cerr << " unknown arithmetic operator '" << e.op << " ' in "
439
474
<< program[prognr] << endl;
440
475
exit (exit_failure);
441
476
}
477
+ if ( cachable (e) ) e.cache = res;
478
+ return res;
442
479
}
443
480
444
481
bool compare (const expr& cmp)
@@ -1090,7 +1127,8 @@ void checktestdata(ostream &datastream)
1090
1127
datastream << setprecision (float_precision);
1091
1128
1092
1129
while ( true ) {
1093
- command cmd = currcmd = program[prognr];
1130
+ const command &cmd = program[prognr];
1131
+ currcmd = cmd;
1094
1132
1095
1133
if ( cmd.name ()==" EOF" ) {
1096
1134
if ( gendata ) {
0 commit comments