% Macros for generating typeset pictures of computed numbers
% format(f,x) typeset generalized number x using format string f
% Mformat(f,x) like format, but x is in Mlog form (see marith.mp)
% init_numbers(s,m,x,sn,e) choose typeset style given sample sign, mantissa,...
% roundd(x,d) round numeric x to d places right of decimal point
% Fe_base what precedes the exponent for typeset powers of 10
% Fe_plus plus sign if any for typesetting positive exponents
% Ten_to[] powers of ten for indices 0,1,2,3,4
% Other than the above-documented user interface, all externally visible names
% start with F and end with _.
if unknown Fmfont_: % If this file has not been read yet
begingroup interim warningcheck:=0; % Allow big numbers in token lists
input string
%%%%%%%%%%%%%%%%%%%%%%% Choosing the Layout %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
picture Fmneg_, Femarker_, Feneg_, Fe_base, Fe_plus;
string Fmfont_, Fefont_;
numeric Fmscale_, Fescale_, Feraise_;
% Argument s is a leading minus sign; m is a 1-digit mantissa;
% x is whatever follows the mantissa; sn is a leading minus for the exponent;
% and e is a 1-digit exponent. Numbers in scientific notation are constructed
% by placing these peices side-by-side; decimal numbers use only m and/or s.
% To get exponenets with leading plus signs, assign to Fe_plus after calling
% init_numbers. To do something special with a unit mantissa followed by x,
% assign to Fe_base after calling init_numbers.
vardef init_numbers(expr s, m, x, sn, e) =
Fmneg_ := s;
for p within m:
Fmfont_ := fontpart p;
Fmscale_ := xxpart p;
exitif true;
endfor
Femarker_ := x;
Feneg_ := sn;
for p within e:
Fefont_ := fontpart p;
Fescale_ := xxpart p;
Feraise_ := ypart llcorner p;
exitif true;
endfor
Fe_base := Fline_up_("1" infont Fmfont_ scaled Fmscale_, Femarker_);
Fe_plus := nullpicture;
enddef;
%%%%%%%%%%%%%%%%%%%%%%% Low-Level Typesetting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
vardef Fmant_(expr x) =
(decimal abs x infont Fmfont_ scaled Fmscale_)
enddef;
vardef Fexp_(expr x) =
(decimal x infont Fefont_ scaled Fescale_ shifted (0,Feraise_))
enddef;
vardef Fline_up_(text t_) =
save p_, c_;
picture p_; p_=nullpicture;
pair c_; c_=(0,0);
for q_=t_:
addto p_ also q_ if string q_: infont defaultfont scaled defaultscale fi
shifted c_;
c_ := (xpart lrcorner p_, 0);
endfor
p_
enddef;
vardef Fdec_o_(expr x) =
if x<0: Fline_up_(Fmneg_, Fmant_(x))
else: Fmant_(x)
fi
enddef;
vardef Fsci_o_(expr x, e) =
Fline_up_(if x<0: Fmneg_,fi
if abs x =1: Fe_base else: Fmant_(x), Femarker_ fi,
if e<0: Feneg_ else: Fe_plus fi,
Fexp_(abs e))
enddef;
% Assume prologues=1 implies troff mode. TeX users who what prologues on
% should use some other positive value. The mpx file mechanism requires
% separate input files here.
if prologues=1: input troffnum
else: input texnum
fi
%%%%%%%%%%%%%%%%%%%%%%% Scaling and Rounding %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Find a pair p where x=xpart p*10**ypart p and either p=(0,0) or xpart p is
% between 1000 and 9999.99999. This is the `exponent form' of x.
vardef Feform_(expr x) =
interim warningcheck:=0;
if string x:
if unknown Mzero: scantokens "input marith"; fi
Meform(Mlog_str x)
else:
save b, e;
b=x; e=0;
if abs b>=10000: (b/10, 1)
elseif b=0: origin
else: forever:
exitif abs b>=1000;
b:=b*10; e:=e-1;
endfor
(b, e)
fi
fi
enddef;
% The marith.mp macros include a similar macro Meform that converts from
% `Mlog form' to exponent form.
% In case rounding has made the xpart of an exponent form number too large,
% fix it.
vardef Feadj_(expr x, y) =
if abs x>=10000: (x/10, y+1) else: (x,y) fi
enddef;
% Round x to d places right of the decimal point. When d<0, round to the
% nearest multiple of 10 to the -d.
vardef roundd(expr x, d) =
if abs d >4:
if d>0: x else: 0 fi
elseif d>0:
save i; i=floor x;
i + round(Ten_to[d]*(x-i))/Ten_to[d]
else:
round(x/Ten_to[-d])*Ten_to[-d]
fi
enddef;
Ten_to0=1; Ten_to1=10; Ten_to2=100; Ten_to3=1000; Ten_to4=10000;
% Round an exponent form number p to k significant figures.
primarydef p Fprec_ k =
Feadj_ (roundd(xpart p,k-4), ypart p) enddef;
% Round an exponent form number p to k digits right of the decimal point.
primarydef p Fdigs_ k =
Feadj_ (roundd(xpart p,k+ypart p), ypart p) enddef;
%%%%%%%%%%%%%%%%%%%%%%% High-Level Routines %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The following operators convert z from exponent form and produce typeset
% output: Formsci_ generates scientific notation; Formdec_ generates decimal
% notation; and Formgen_ generates whatever is likely to be most compact.
vardef Formsci_(expr z) = Fsci_o_(xpart z/1000, ypart z +3) enddef;
vardef Formdec_(expr z) =
if ypart z>0: Formsci_(z)
else:
Fdec_o_(xpart z
if ypart z>=-4: /Ten_to[-ypart z]
else: for i=ypart z upto -5: /(10) endfor/10000 fi)
fi
enddef;
vardef Formgen_(expr q) =
clearxy; (x,y)=q;
if x=0: Formdec_
elseif y>=-6: Formdec_
else: Formsci_
fi (q)
enddef;
def Fset_item_(expr s) =
if s<>"": s infont defaultfont scaled defaultscale, fi
enddef;
% For each format letter, the table below tells how to round and typeset
% a quantity z in exponent form.
string fmt_[];
fmt_[ASCII "e"] = "Formsci_(z Fprec_ p)"; % scientific, p significant figures
fmt_[ASCII "f"] = "Formdec_(z Fdigs_ p)"; % decimal, p digits right of the point
fmt_[ASCII "g"] = "Formgen_(z Fprec_ p)"; % decimal or scientific, p sig. figs.
fmt_[ASCII "G"] = "Formgen_(z Fdigs_ p)"; % decimal or scientific, p digits
% The format and Mformat macros take a format string f and generate typeset
% output for a numeric quantity x. String f should contain a `%' followed by
% an optional number and one of the format letters defined above. The number
% should be an integer giving the precision (default 3).
vardef dofmt_@#(expr f, x) =
if f="": nullpicture
else:
interim warningcheck:=0;
save k, l, s, p, z;
pair z; z=@#(x);
k = 1 + cspan(f, "%"<>);
l-k = cspan(substring(k,infinity)of f, isdigit);
p = if l>k: scantokens substring(k,l)of f else: 3 fi;
string s; s=fmt_[ASCII substring (l,l+1) of f];
if unknown s:
if k<=length f: errmessage("No valid format letter found in "&f); fi
s = "nullpicture";
fi
Fline_up_(
Fset_item_(substring (0,k-1) of f)
scantokens s,
Fset_item_(substring (l+1,infinity) of f)
nullpicture)
fi
enddef;
vardef format(expr f, x) = dofmt_.Feform_(f,x) enddef;
vardef Mformat(expr f, x) = dofmt_.Meform(f,x) enddef;
endgroup; % restore warningcheck to previous value
fi % end the if..fi that encloses this file
|