madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

be46167fc41559df710b29c86192cc991cca1945
[etc/texmf.git] / .texmf / tex / latex / 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