[tex-k] bug in Bernshtein trick in Appendix D of The METAFONTbook

胡亚捷 (Hu Yajie) 2500418497 at qq.com
Fri Jul 24 05:21:06 CEST 2020

Thanks for vetting my bug report. Actually, the second part of it
(make the macros work with `show') is a feature request, and
my proposed solution is not perfect: if you try
    *show .5[2a,2b,2c,2d];
    >> 0.125u_4+0.375u_3+0.375u_2+0.125u_1
the internal variables will still show up. (Knuth's solution would `show'
`0.75b+0.25a+0.75u_3-0.25u_4', which is slightly better but not satisfactory.)

If you don't find it important to make the Bernshtein macros work with `show',
you may drop the second part of my bug report. But if you do, you may want to
substitute the following solution:

def lbrack = hide(delimiters []) lookahead [ enddef;
let [[[ = [; let ]]] = ]; let [ = lbrack;
def lookahead(text t) =
 hide(let [ = lbrack;
  for u=t, hide(nn_ := 0; let uu_ = \): if incr nn_=1: def uu_ = u enddef
   else: expandafter def expandafter uu_ expandafter = uu_, u enddef
  fi; endfor)
 if nn_<3: [[[uu_]]] else: Bernshtein nn_ fi enddef;
primarydef t Bernshtein nn = begingroup c_[[[1]]] := 1;
 for n=1 upto nn-1: c_[[[n+1]]] := t*c_[[[n]]];
  for k=n downto 2: c_[[[k]]] := t[[[c_[[[k]]], c_[[[k-1]]] ]]];
  endfor c_[[[1]]] := (1-t)*c_[[[1]]]; endfor
 nn_:=0; for u=uu_: +c_[[[incr nn_]]]*(u) endfor endgroup enddef;

(nn_ and uu_ are the new names of n_ and u_ to avoid name conflict with flex.)
The new solution avoids assigning the evaluated expressions by storing them in
a macro instead of an array, so no private dependencies will show up:
    *show .5[2a,2b,2c,2d];
    >> 0.25d+0.75c+0.75b+0.25a
    *show 2[2a,2b,2c,2d];
    >> 16d-24c+12b-2a
and everyone will be happy.


By the way, in the following macros on page C291:

vardef max(text t) =
 let switch_ = firstset_;
 for u=t: switch_ u>u_: u_ := u ;fi endfor
 u_ enddef;
vardef min(text t) =
 let switch_ = firstset_;
 for u=t: switch_ u<u_: u_ := u ;fi endfor
 u_ enddef;
def firstset_ primary u =
 setu_ u; let switch_ = if; if false: enddef;

The `setu_ u' in the last line should be changed to `save u_; setu_ u',
otherwise you get the following error if you use them twice on numerics:

*show max(1,2);
>> 2
*show max(3,4);
! Inconsistent equation (off by 1).
<to be read again>
<to be read again>
<for(3)> switch_(EXPR0)>
                        u_:u_:=(EXPR0);fi ENDFOR
<*> show max(3,4)

More information about the tex-k mailing list.