% 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