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

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;
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).
;
switch_->setu_(EXPR0);
let.switch_=if;if.false:
>
<for(3)> switch_(EXPR0)>
u_:u_:=(EXPR0);fi ENDFOR
max->...for.u=(TEXT2):switch_.u>u_:u_:=u;fi.endfor
.u_.endgroup
<*> show max(3,4)
;
?

```