7.147 bugs (2) in evalapply(), Maple 7 to Maple 9, and fix (11.12.02)

7.147.1 Helmut Kahovec

7.147.1 Helmut Kahovec

There are two bugs in the procedure evalapply(), which behave differently in Maple7 and Maple8. The first one was discovered by Carl Devore, the second by myself. Following are short Maple7 and Maple8 sessions that show the two bugs and their fixes.

Maple7:

Carl’s bug:

> f[1]:=x->sin(2*x); 
 
                        f[1] := x -> sin(2 x) 
 
> `@`(g,f[1])(1); %; 
 
                              g(f[1](1)) 
 
                              g(sin(2)) 
 
> map(evalf@f[1],[1,2,3]); %; 
 
                     [f[1](1), f[1](2), f[1](3)] 
 
                       [sin(2), sin(4), sin(6)] 
 
> `@`(f[1],g)(1); %; 
 
                              f[1](g(1)) 
 
                             sin(2 g(1)) 
 
> map(f[1]@evalf,[1,2,3]); %; 
 
                    [f[1](1.), f[1](2.), f[1](3.)] 
 
              [.9092974268, -.7568024953, -.2794154982]
 

My bug:

> `@`(g,''F'')(1); 
 
                       g('F'(eval(LOC[3], 1))) 
 
> map(g@'''F''',[1,2,3]); 
 
  [g('F'(eval(LOC[3], 1))), g('F'(eval(LOC[3], 1))), 
 
        g('F'(eval(LOC[3], 1)))] 
 
> `@`(''F'',g)(1); 
 
                         'F'(eval(LOC[3], 1)) 
 
> map('''F'''@g,[1,2,3]); 
 
  ['F'(eval(LOC[3], 1)), 'F'(eval(LOC[3], 1)), 'F'(eval(LOC[3], 1))]
 

My bug can be found very easily by executing the following procedure test(), which also shows the fix for Maple7.

> test:=proc(F) 
  local r,_r,_F; 
    r:=1; 
    F(r),F(%),subs(_r=r,F(_r)),subs(_r=%,F(_r)),subs(_F=eval(F),_F(r)); 
  end proc: 
 
> test(F); 
 
                     F(1), F(1), F(1), F(1), F(1) 
 
> test('F'); 
 
                     F(1), F(1), F(1), F(1), F(1) 
 
> test(''F''); 
 
         'F'(LOC[1]), 'F'(%), 'F'(LOC[2]), 'F'(LOC[2]), F(1) 
 
> test('''F'''); 
 
    ''F''(LOC[1]), ''F''(%), ''F''(LOC[2]), ''F''(LOC[2]), 'F'(1)
 

Thus – and in order to fix Carl’s bug, too – unprotect evalapply(), add the names _r,_f to the locals of evalapply(), replace line 10

  r := op(i,f)(eval(r,1))
 

(cf. the code that showstat(evalapply); returns) by the lines

  op(i,f); 
  if type('%',uneval) then 
    r:=subs(_r=r,_f='%',_f(_r)); 
  elif type(op(i,f),procedure) then 
    r:=eval(op(i,f))(eval(r,1)) 
  else 
    r:=op(i,f)(eval(r,1)) 
  end if
 

and protect the new evalapply() again. Now you get in turn:

> `@`(g,f[1])(1); 
 
                              g(sin(2)) 
 
> map(evalf@f[1],[1,2,3]); 
 
              [.9092974268, -.7568024953, -.2794154982] 
 
> `@`(f[1],g)(1); 
 
                             sin(2 g(1)) 
 
> map(f[1]@evalf,[1,2,3]); 
 
              [.9092974268, -.7568024953, -.2794154982] 
 
> `@`(g,''F'')(1); 
 
                              g('F'(1)) 
 
> map(g@'''F''',[1,2,3]); 
 
                  [g('F'(1)), g('F'(2)), g('F'(3))] 
 
> `@`(''F'',g)(1); 
 
                              'F'(g(1)) 
 
> map('''F'''@g,[1,2,3]); 
 
                  ['F'(g(1)), 'F'(g(2)), 'F'(g(3))]
 

Maple8:

Carl’s bug appears to be the same as in Maple7. My bug behaves differently in Maple8:

> `@`(g,''F'')(1); 
 
                          g('F'(eval(r, 1))) 
 
> op([1,1,1],'%'); 
 
                                  r 
 
> %; 
 
                       g(F(g('F'(eval(r, 1))))) 
 
> %; 
 
                    g(F(g(F(g('F'(eval(r, 1))))))) 
 
> r-'%%%'; 
 
                                r - r 
 
> map(g@'''F''',[1,2,3]); 
 
     [g('F'(eval(r, 1))), g('F'(eval(r, 1))), g('F'(eval(r, 1)))] 
 
> `@`(''F'',g)(1); 
 
                           'F'(eval(r, 1)) 
 
> map('''F'''@g,[1,2,3]); 
 
         ['F'(eval(r, 1)), 'F'(eval(r, 1)), 'F'(eval(r, 1))]
 

My bug can be found very easily by executing the following procedure test(), which also shows the possible fixes for Maple8.

> test:=proc(F) 
  local r,_r; 
    r:=1; 
    F(r),F(%),subs(_r=r,F(_r)),subs(_r=%,F(_r)) 
  end proc: 
 
> test(F); 
 
                        F(1), F(1), F(1), F(1) 
 
> test('F'); 
 
                        F(1), F(1), F(1), F(1) 
 
> test(''F''); 
 
                    'F'(r), 'F'(1), 'F'(1), 'F'(1)
 

Thus – and in order to fix Carl’s bug, too – unprotect evalapply(), add the name _r to the locals of evalapply(), replace line 10

  r := op(i,f)(eval(r,1))
 

(cf. the code that showstat(evalapply); returns) by the lines

  if type(op(i,f),uneval) then 
    r:=subs(_r=r,op(i,f)(_r)) 
  elif type(op(i,f),procedure) then 
    r:=eval(op(i,f))(eval(r,1)) 
  else 
    r:=op(i,f)(eval(r,1)) 
  end if
 

and protect the new evalapply() again. Now you get the same correct results that were shown in the Maple7 session above.