]> git.donarmstrong.com Git - lib.git/blob - texmf/realcalc.tex
load tramp
[lib.git] / texmf / realcalc.tex
1 %% realcalc.tex
2 %%
3 %% (C) Frank Buchholz, Jan. 1993
4 %% e-mail: buchholz@lusty.informatik.uni-dortmund.de
5 %  User documentation: All lines starting with two %
6 %  Try grep to extract these lines.
7 %%
8 %% Real arithmetic with big values and high precision.
9 %% Calculations are done with 9 decimal digits.
10 %% Usable with TeX and LaTeX.
11 %%
12 %% Parameter:
13 %%
14 %%      <macro> Macro, witch catches the result.
15 %%      <value> String or macro witch expands to a value in the range 
16 %%                  from -2147483647.999999999 to 2147483647.999999999
17 %%      <precision> Number from 0 to 9
18 %%
19 %% Functions:
20 %%
21
22 % Don't read this file twice
23 \ifx\Radd\undefined \else \endinput \fi
24
25 % Make "@" be a letters
26 \chardef\catamp=\the\catcode`\@
27 \catcode`@=11
28  
29 \def\@Rversion{Version 1.0, Jan. 1993}
30 \message{`Real arithmetic', \@Rversion (C) Frank Buchholz}
31
32 % Allocation of temporary registers
33 \newcount\@ta
34 \newcount\@tb
35 %
36 \newcount\@xs   % Sign of 1st value
37 \newcount\@xi   % Integer part of 1st value
38 \newcount\@xf   % Fractional part of 1st value
39 %
40 \newcount\@ys   % Sign of 2nd value
41 \newcount\@yi   % Integer part of 2nd value
42 \newcount\@yf   % Fractional part of 2nd value
43 %
44 \newcount\@mil  \@mil=1000000000        % 10^9
45 %
46 \countdef\@xa240
47 \countdef\@xb241
48 \countdef\@xc242
49 \countdef\@xd243
50 \countdef\@xe244
51 \countdef\@ya245
52 \countdef\@yb246
53 \countdef\@yc247
54 \countdef\@yd248
55 \countdef\@ye249
56 \let\@f=\@tb
57 \let\@product=\@ta
58
59 \chardef\@zero=0
60
61 %%      \Radd<macro><value><value>              Addition
62 \def\Radd#1#2#3{\@callc\@Radd#1{#2}{#3}}
63
64 %%      \Rsub<macro><value><value>              Subtraction
65 \def\Rsub#1#2#3{\@callc\@Radd#1{#2}{-#3}}
66
67 \def\@Radd#1#2.#3.#4\relax#5.#6.#7\relax{%
68   % #1 Macro, witch gets the result
69   % #2 integer part of 1st value 
70   % #3 fractional part of 1st value
71   % #4 dummy to swallow everthing after the 2nd '.'
72   % #5 integer part of 2nd value 
73   % #6 fractional part of 2nd value
74   % #7 dummy to swallow everthing after the 2nd '.'
75   %
76   \@readvalue\@xs\@xi\@xf{#2}{#3}%
77   \@readvalue\@ys\@yi\@yf{#5}{#6}%
78   %
79   % Add integer parts
80   \@ta=\@xi \advance\@ta\@yi%
81   %
82   % Add fractional parts if they are not zero
83   \ifnum\@xf=\@zero%
84     \ifnum\@yf=\@zero%
85       \@tb=\@zero%
86     \else%
87       \@longadd%
88     \fi%
89   \else%
90     \@longadd%
91   \fi%
92   %
93   % Store result
94   \@store#1\@ta\@tb%
95 }
96
97 \def\@longadd{%
98     % Propagate sign to fractional parts
99     \multiply\@xf\@xs \multiply\@yf\@ys%
100     %
101     % Add fractional parts
102     \@tb=\@xf \advance\@tb\@yf%
103     %
104     % Calculate carry
105     \ifnum\@tb<\@zero% 
106       \ifnum\@tb<-\@mil      \advance\@ta -\@ne \advance\@tb\@mil  \fi% 
107     \else% 
108       \ifnum\@tb<\@mil \else \advance\@ta \@ne  \advance\@tb-\@mil \fi% 
109     \fi%
110
111
112 %%      \Rmul<macro><value><value>              Multiplication
113 \def\Rmul#1#2#3{\@callc\@Rmul#1{#2}{#3}}
114
115 \def\@Rmul#1#2.#3.#4\relax#5.#6.#7\relax{%
116   % #1 Macro, witch gets the result
117   % #2 integer part of 1st value 
118   % #3 fractional part of 1st value
119   % #4 dummy to swallow everthing after the 2nd '.'
120   % #5 integer part of 2nd value 
121   % #6 fractional part of 2nd value
122   % #7 dummy to swallow everthing after the 2nd '.'
123   %
124   % How to do real multiplications:
125   % Split values in various parts
126   % x y = 1234 567890 . 123 456 789
127   % ->    xa   xb       xc  xd  xe
128   % ->    ya   yb       yc  yd  ye
129   % Do 21 (!) integer multiplications if there are any fractional parts
130   % r = x * Y
131   % -> r =   xi*yi
132   %        + (xa*yc + xa*yc                  )*10^3 
133   %        + (xa*yd + xd*ya                  )*10^-0 
134   %        + (xa*ye + xe*ya  +  xb*yc + xc*yb)*10^-3 
135   %        + (xb*yd + xd*yb  +  xc*yc        )*10^-6 
136   %        + (xb*ye + xe*yb  +  xc*yd + xd*yc)*10^-9 
137   %        + (xc*ye + xe*yc  +  xd*yd        )*10^-12 
138   %        + (xd*ye + xe*yd                  )*10^-15 
139   %        + (xe*ye                          )*10^-18
140   %
141   % -> r = ((((( xe*ye                               / 1000 
142   %             + xd*ye + xe*yd                   ) / 1000
143   %            + xc*ye + xe*yc  +  xd*yd         ) / 1000
144   %           + xb*ye + xe*yb  +  xc*yd + xd*yc ) / 1000
145   %          + xb*yd + xd*yb  +  xc*yc         ) / 1000
146   %         + xa*ye + ye*xa  +  xb*yc + xc*yb ) / 1000
147   %        + xa*yd + xd*ya + (xa*yc + ya*xc)*1000 + xi*yi
148   % The last three digigs are saved just before the divisions.
149   %
150   % Init 
151   %
152   \@readvalue\@xs\@xi\@xf{#2}{#3}%
153   \@readvalue\@ys\@yi\@yf{#5}{#6}%
154   %
155   % Sign
156   \multiply\@xi\@xs%
157   \multiply\@yi\@ys%
158   \multiply\@xs\@ys%
159   %
160   \@product=\@zero%
161   % 
162   \ifnum\@xf=\@zero%
163     \ifnum\@yf=\@zero%
164       % No fractional parts
165       \edef\@frac{000000000}    % digits of fractional part  
166     \else%
167       \@longmul                 % Long multiplication           
168     \fi%
169   \else%
170     \@longmul                   % Long multiplication           
171   \fi%
172   %
173   % Multiply integer parts
174   \count@=\@xi \multiply\count@\@yi%
175   \advance\@product\count@%
176   %
177   % Sign
178   \multiply\@product\@xs%
179   %
180   % Store result
181   \edef#1{\number\@product.\@frac}%
182 }
183
184 % Do long multiplication
185 \def\@longmul{%
186     % Split values in pieces
187     \@f=1000000%
188     \count@=\@xi%               
189     \divide\count@\@f                                   \@xa=\count@%
190     \multiply\count@-\@f        \advance\count@\@xi     \@xb=\count@%
191     \count@=\@xf%               
192     \divide\count@\@f                                   \@xc=\count@%
193     \multiply\count@-\@f        \advance\count@\@xf%    
194     \@f=1000%
195     \@xe=\count@%
196     \divide\count@\@f                                   \@xd=\count@%
197     \multiply\count@-\@f        \advance\count@\@xe     \@xe=\count@%
198     % 
199     \@f=1000000%
200     \count@=\@yi%               
201     \divide\count@\@f                                   \@ya=\count@%
202     \multiply\count@-\@f        \advance\count@\@yi     \@yb=\count@%
203     \count@=\@yf%               
204     \divide\count@\@f                                   \@yc=\count@%
205     \multiply\count@-\@f        \advance\count@\@yf%    
206     \@f=1000%
207     \@ye=\count@%
208     \divide\count@\@f                                   \@yd=\count@%
209     \multiply\count@-\@f        \advance\count@\@ye     \@ye=\count@%
210     %
211     \edef\@frac{}                               % digits of fractional part
212     % 
213     \@mul ee          \relax\@shift             % 10^-18
214     \@mul de ed       \relax\@shift             % 10^-15
215     \@mul ce ec dd    \relax\@shift             % 10^-12
216     \@mul be eb cd dc \relax\@saveshift         % 10^-9
217     \@mul bd db cc    \relax\@saveshift         % 10^-6
218     \@mul ae ea bc cb \relax\@saveshift         % 10^-3
219     \multiply\@xa\@f  \multiply\@xc\@f          % 10^3
220     \@mul ad da ac ca \relax%                   
221 }
222
223 \def\@mul#1#2#3{%
224   \count@=\csname @x#1\endcsname%
225   \multiply\count@\csname @y#2\endcsname%
226   \advance\@product\count@%
227   %
228   \ifx#3\relax%
229     \let\next=\relax% 
230   \else%
231     \let\next=\@mul%
232   \fi%
233   \next#3%
234 }
235
236 \def\@shift{%
237   \divide\@product\@f%
238 }
239
240 \def\@saveshift{%
241   % Save rightmost digits 
242   \count@=\@product%
243   \divide\@product\@f%
244   \multiply\@product\@f%
245   \advance\count@-\@product%
246   \advance\count@\@f%
247   \edef\@frac{\expandafter\@ignorenext\number\count@\@frac}%
248   %
249   \divide\@product\@f%
250 }
251
252 %%      \Rdiv<macro><value><value>              Division
253 \def\Rdiv#1#2#3{\@callc\@Radd#1{#2}{#3}}
254
255 \def\@Rdiv#1#2.#3.#4\relax#5.#6.#7\relax{%
256   % #1 Macro, witch gets the result
257   % #2 integer part of 1st value 
258   % #3 fractional part of 1st value
259   % #4 dummy to swallow everthing after the 2nd '.'
260   % #5 integer part of 2nd value 
261   % #6 fractional part of 2nd value
262   % #7 dummy to swallow everthing after the 2nd '.'
263   %
264   \message{Error: Rdiv not ready}
265   %
266   \@readvalue\@xs\@xi\@xf{#2}{#3}%
267   \@readvalue\@ys\@yi\@yf{#5}{#6}%
268   %
269   \ifnum\@yi=\@zero
270     \@xi=\@zero
271   \else
272     \divide\@xi\@yi
273   \fi
274   %
275   \@store#1\@xi\@xf%
276 }
277
278 %%      \Rneg<macro><value>             Negation
279 \def\Rneg#1#2{%
280   % Expand the value and split it into the integer and the fractional part
281   \edef\next{\noexpand\@Rneg\noexpand#1#2..\noexpand\relax}%
282   \next%
283 }
284
285 \def\@Rneg#1#2.#3.#4\relax{
286   % #1 Macro, witch gets the result
287   % #2 Integer part of value
288   % #3 Fractional part of value
289   % #4 Remaining tokens
290   %
291   \@readvalue\@xs\@xi\@xf{#2}{#3}%
292   %
293   % Change sign
294   \multiply\@xi-\@ne%
295   \multiply\@xf-\@xs%
296   % 
297   % Store result
298   \@store#1\@xi\@xf%
299 }
300
301 %%
302 %%      \Rtrunc<macro><precision><value> Truncate value to specified precision
303 \def\Rtrunc#1#2#3{%
304   % Expand parameter and split the value into the integer and fractional part 
305   \edef\next{\noexpand\@Rtrunc\noexpand#1#2#3..\noexpand\relax}%
306   \next%
307 }
308
309 \def\@Rtrunc#1#2#3.#4.#5\relax{%
310   % #1 Macro, witch gets the result
311   % #2 Number of decimal places
312   % #3 Integer part of value
313   % #4 Fractional part of value
314   % #5 dummy to swallow everthing after the 2nd '.'
315   %
316   \count@=#2%
317   \edef\next{\empty}%
318   \ifnum\count@>\@zero%
319     \expandafter\@@Rtrunc#4000000000\relax%
320   \fi%
321   \edef#1{#3\next}%
322 }
323
324 \def\@@Rtrunc#1#2#3#4#5#6#7#8#9{%
325   % #1...#9 fractional part, padded with trailing zeros
326   \edef\next{.#1%
327     \ifnum\count@>1 #2\fi%
328     \ifnum\count@>2 #3\fi%
329     \ifnum\count@>3 #4\fi%
330     \ifnum\count@>4 #5\fi%
331     \ifnum\count@>5 #6\fi%
332     \ifnum\count@>6 #7\fi%
333     \ifnum\count@>7 #8\fi%
334     \ifnum\count@>8 #9\fi%
335   }%
336   \@swallow%
337 }
338
339 %%
340 %%      \Rifle<value><value>            Test v1 < v2
341 \def\Rifle#1#2{\@callb\@Rifle{#1}{#2}}
342
343 \def\@Rifle#1.#2.#3\relax#4.#5.#6\relax{%
344   % #1 integer part of 1st value 
345   % #2 fractional part of 1st value
346   % #3 dummy to swallow everthing after the 2nd '.'
347   % #4 integer part of 2nd value 
348   % #5 fractional part of 2nd value
349   % #6 dummy to swallow everthing after the 2nd '.'
350   %
351   \@readvalue\@xs\@xi\@xf{#1}{#2}%
352   \@readvalue\@ys\@yi\@yf{#4}{#5}%
353   %
354   \ifnum\@xs<\@ys% 
355     \Rtesttrue% 
356   \else%
357     \ifnum\@xs>\@ys% 
358       \Rtestfalse%
359     \else%
360       \Rtestfalse%
361       \ifnum\@xi<\@yi \Rtesttrue \fi%
362       \ifnum\@xi=\@yi%
363         \multiply\@xf\@xs \multiply\@yf\@ys%
364         \ifnum\@xf<\@yf \Rtesttrue \fi% 
365       \fi%
366     \fi%
367   \fi%
368   %
369   \ifRtest%
370 }
371
372 %%      \Rifeq<value><value>            Test v1 = v2
373 \def\Rifeq#1#2{\@callb\@Rifeq{#1}{#2}}
374
375 \def\@Rifeq#1.#2.#3\relax#4.#5.#6\relax{%
376   % #1 integer part of 1st value 
377   % #2 fractional part of 1st value
378   % #3 dummy to swallow everthing after the 2nd '.'
379   % #4 integer part of 2nd value 
380   % #5 fractional part of 2nd value
381   % #6 dummy to swallow everthing after the 2nd '.'
382   %
383   \@readvalue\@xs\@xi\@xf{#1}{#2}%
384   \@readvalue\@ys\@yi\@yf{#4}{#5}%
385   %
386   \Rtestfalse%
387   \ifnum\@xi=\@yi\ifnum\@xf=\@yf \Rtesttrue \fi\fi%
388   \ifRtest%
389 }
390
391 %%      \Rifgt<value><value>            Test v1 > v2
392 \def\Rifgt#1#2{\@callb\@Rifgt{#1}{#2}}
393
394 \def\@Rifgt#1.#2.#3\relax#4.#5.#6\relax{%
395   % #1 integer part of 1st value 
396   % #2 fractional part of 1st value
397   % #3 dummy to swallow everthing after the 2nd '.'
398   % #4 integer part of 2nd value 
399   % #5 fractional part of 2nd value
400   % #6 dummy to swallow everthing after the 2nd '.'
401   %
402   \@readvalue\@xs\@xi\@xf{#1}{#2}%
403   \@readvalue\@ys\@yi\@yf{#4}{#5}%
404   %
405   \ifnum\@xs>\@ys% 
406     \Rtesttrue% 
407   \else%
408     \ifnum\@xs<\@ys% 
409       \Rtestfalse% 
410     \else%
411       \Rtestfalse%
412       \ifnum\@xi>\@yi \Rtesttrue \fi%
413       \ifnum\@xi=\@yi% 
414         \multiply\@xf\@xs \multiply\@yf\@ys%
415         \ifnum\@xf>\@yf \Rtesttrue \fi% 
416       \fi%
417     \fi%
418   \fi%
419   %
420   \ifRtest%
421 }
422
423 %%      \Rifneg<value>                  Test v < 0
424 \def\Rifneg#1{\@calla\@Rifneg{#1}}
425
426 \def\@Rifneg#1.#2.#3\relax{%
427   % #1 Integer part of value
428   % #2 Fractional part of value
429   % #3 dummy to swallow everthing after the 2nd '.'
430    %
431    \@readvalue\@xs\@xi\@xf{#1}{#2}%
432    %
433    \ifnum\@xs<0 \Rtesttrue \else \Rtestfalse \fi%
434    \ifRtest%
435  }
436
437 %%      \Rifzero<value>                 Test v = 0
438 \def\Rifzero#1{\@calla\@Rifzero{#1}}
439
440 \def\@Rifzero#1.#2.#3\relax{%
441   % #1 Integer part of value
442   % #2 Fractional part of value
443   % #3 dummy to swallow everthing after the 2nd '.'
444   %
445   \@readvalue\@xs\@xi\@xf{#1}{#2}%
446   %
447   \Rtestfalse%
448   \ifnum\@xi=\@zero \ifnum\@xf=\@zero \Rtesttrue \fi \fi%
449   \ifRtest%
450 }
451
452 %%      \Rifpos<value>                  Test v >= 0
453 %%                                      Take care to have a corresponding \fi
454 \def\Rifpos#1{\@calla\@Rifpos{#1}}
455
456 \def\@Rifpos#1.#2.#3\relax{%
457   % #1 Integer part of value
458   % #2 Fractional part of value
459   % #3 dummy to swallow everthing after the 2nd '.'
460   %
461   \@readvalue\@xs\@xi\@xf{#1}{#2}%
462   %
463   \ifnum\@xs<0 \Rtestfalse \else \Rtesttrue \fi%
464   \ifRtest%
465 }
466
467 %%      \Rifint<value>                  Test v is an integer value
468 %%                                      Take care to have a corresponding \fi
469 \def\Rifint#1{\@calla\@Rifint{#1}}
470
471 \def\@Rifint#1.#2.#3\relax{%
472   % #1 Integer part of value
473   % #2 Fractional part of value
474   % #3 dummy to swallow everthing after the 2nd '.'
475   %
476   \@readvalue\@xs\@xi\@xf{#1}{#2}%
477   %
478   \ifnum\@xf=0 \Rtesttrue \else \Rtestfalse \fi%
479   \ifRtest%
480 }
481
482 % Utility macros
483
484 \def\@calla#1#2{%
485   % #1 Macro to call
486   % #2 Value
487   % Expand the value and split them into the integer and the fractional part
488   \edef\next{\noexpand#1#2..\noexpand\relax}%
489   \next%
490 }
491
492 \def\@callb#1#2#3{%
493   % #1 Macro to call
494   % #2 1st value
495   % #3 2nd value
496   % Expand the values and split them into the integer and the fractional parts 
497   \edef\next{\noexpand#1#2..\noexpand\relax#3..\noexpand\relax}%
498   \next%
499 }
500
501 \def\@callc#1#2#3#4{%
502   % #1 Macro to call
503   % #2 Macro, witch gets the result
504   % #3 1st value
505   % #4 2nd value
506   % Expand the values and split them into the integer and the fractional parts
507   \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax#4..\noexpand\relax}%
508   \next%
509 }
510
511 %%      \ifRtest ... \else ... \fi      Re-execute the last test
512 \newif\ifRtest
513
514 %
515 % Read value
516 %
517 \def\@readvalue#1#2#3#4#5{%
518   % #1    macro to catch the sign ( -1 or 1 )
519   % #2    macro to catch the integer part (maybe negative)
520   % #3    macro to catch the fractional part (positive)
521   % #4.#5 value
522   %
523   % Regular expression [-...d]d...["."[d...]]
524   % Attention: There has to be at least one digit between "-" and "."!
525   %
526   % Integer part
527   \if !#4! #2=\@zero \else #2=#4 \fi%
528   %
529   % Sign
530   \ifnum#2<\@zero #1=-\@ne \else #1=\@ne \fi%
531   \ifnum#2=\@zero \ifnum #4#5<\@zero #1=-\@ne \fi \fi%
532   %
533   % Fractional part
534   \if !#5!% 
535     #3=\@zero%
536   \else%
537     \@@setcount@#5000000000\relax%
538     #3=\count@%
539   \fi%
540 }
541
542 % Set count@ to fractional part with trailing zeros
543 \def\@@setcount@#1#2#3#4#5#6#7#8#9{%
544   % #1...#9 fractional part, padded with '0'
545   \count@=#1#2#3#4#5#6#7#8#9%
546   \@swallow%
547 }
548
549 % Swallow everything up to next \relax
550 \def\@swallow#1\relax{}
551
552 %
553 % Store result 
554 %
555 \def\@store#1#2#3{%
556   % #1 marcro to catch the result
557   % #2 counter with integer part (maybe negative)
558   % #3 counter with fractional part (maybe negative}
559   % 
560   % Sign
561   \edef#1{}%
562   \count@=#3%
563   \ifnum\count@<\@zero% 
564     \count@=-\count@%
565     \ifnum#2=\@zero% 
566       \edef#1{-}%
567     \fi%
568   \fi%
569   %
570   % Pad fractional part with leading zeros
571   \advance\count@\@mil%
572   %
573   % Store result 
574   \edef#1{#1\number#2.\expandafter\@ignorenext\number\count@}%
575 }
576
577 % Ignore next token
578 \def\@ignorenext#1{}
579
580 % Restore catcode of "@"
581 \catcode`\@=\catamp