summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/metapost/base/format.mp
blob: 84e4376a44e6f03c9ded35c6069dbe7d3cefd6bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
% $Id: format.mp,v 1.2 2004/09/19 21:47:10 karl Exp $
% Public domain.

% 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 troffmode=1 implies troff mode. This internal is present
% since version 0.99, and should be set in the change file.  
% As a default, fall back to the previous 'prologues=1' test.
% The mpx file mechanism requires separate input files here.
if troffmode=1:  input troffnum
else:  
  if prologues=1:  input troffnum
  else:            input texnum
  fi
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