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.
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.
8 %% Real arithmetic with big values and high precision.
9 %% Calculations are done with 9 decimal digits.
10 %% Usable with TeX and LaTeX.
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
22 % Don't read this file twice
23 \ifx\Radd\undefined \else \endinput \fi
25 % Make "@" be a letters
26 \chardef\catamp=\the\catcode`\@
29 \def\@Rversion{Version 1.0, Jan. 1993}
30 \message{`Real arithmetic', \@Rversion (C) Frank Buchholz}
32 % Allocation of temporary registers
36 \newcount\@xs % Sign of 1st value
37 \newcount\@xi % Integer part of 1st value
38 \newcount\@xf % Fractional part of 1st value
40 \newcount\@ys % Sign of 2nd value
41 \newcount\@yi % Integer part of 2nd value
42 \newcount\@yf % Fractional part of 2nd value
44 \newcount\@mil \@mil=1000000000 % 10^9
61 %% \Radd<macro><value><value> Addition
62 \def\Radd#1#2#3{\@callc\@Radd#1{#2}{#3}}
64 %% \Rsub<macro><value><value> Subtraction
65 \def\Rsub#1#2#3{\@callc\@Radd#1{#2}{-#3}}
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 '.'
76 \@readvalue\@xs\@xi\@xf{#2}{#3}%
77 \@readvalue\@ys\@yi\@yf{#5}{#6}%
80 \@ta=\@xi \advance\@ta\@yi%
82 % Add fractional parts if they are not zero
98 % Propagate sign to fractional parts
99 \multiply\@xf\@xs \multiply\@yf\@ys%
101 % Add fractional parts
102 \@tb=\@xf \advance\@tb\@yf%
106 \ifnum\@tb<-\@mil \advance\@ta -\@ne \advance\@tb\@mil \fi%
108 \ifnum\@tb<\@mil \else \advance\@ta \@ne \advance\@tb-\@mil \fi%
112 %% \Rmul<macro><value><value> Multiplication
113 \def\Rmul#1#2#3{\@callc\@Rmul#1{#2}{#3}}
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 '.'
124 % How to do real multiplications:
125 % Split values in various parts
126 % x y = 1234 567890 . 123 456 789
129 % Do 21 (!) integer multiplications if there are any fractional parts
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
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.
152 \@readvalue\@xs\@xi\@xf{#2}{#3}%
153 \@readvalue\@ys\@yi\@yf{#5}{#6}%
164 % No fractional parts
165 \edef\@frac{000000000} % digits of fractional part
167 \@longmul % Long multiplication
170 \@longmul % Long multiplication
173 % Multiply integer parts
174 \count@=\@xi \multiply\count@\@yi%
175 \advance\@product\count@%
178 \multiply\@product\@xs%
181 \edef#1{\number\@product.\@frac}%
184 % Do long multiplication
186 % Split values in pieces
189 \divide\count@\@f \@xa=\count@%
190 \multiply\count@-\@f \advance\count@\@xi \@xb=\count@%
192 \divide\count@\@f \@xc=\count@%
193 \multiply\count@-\@f \advance\count@\@xf%
196 \divide\count@\@f \@xd=\count@%
197 \multiply\count@-\@f \advance\count@\@xe \@xe=\count@%
201 \divide\count@\@f \@ya=\count@%
202 \multiply\count@-\@f \advance\count@\@yi \@yb=\count@%
204 \divide\count@\@f \@yc=\count@%
205 \multiply\count@-\@f \advance\count@\@yf%
208 \divide\count@\@f \@yd=\count@%
209 \multiply\count@-\@f \advance\count@\@ye \@ye=\count@%
211 \edef\@frac{} % digits of fractional part
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%
224 \count@=\csname @x#1\endcsname%
225 \multiply\count@\csname @y#2\endcsname%
226 \advance\@product\count@%
241 % Save rightmost digits
244 \multiply\@product\@f%
245 \advance\count@-\@product%
247 \edef\@frac{\expandafter\@ignorenext\number\count@\@frac}%
252 %% \Rdiv<macro><value><value> Division
253 \def\Rdiv#1#2#3{\@callc\@Radd#1{#2}{#3}}
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 '.'
264 \message{Error: Rdiv not ready}
266 \@readvalue\@xs\@xi\@xf{#2}{#3}%
267 \@readvalue\@ys\@yi\@yf{#5}{#6}%
278 %% \Rneg<macro><value> Negation
280 % Expand the value and split it into the integer and the fractional part
281 \edef\next{\noexpand\@Rneg\noexpand#1#2..\noexpand\relax}%
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
291 \@readvalue\@xs\@xi\@xf{#2}{#3}%
302 %% \Rtrunc<macro><precision><value> Truncate value to specified precision
304 % Expand parameter and split the value into the integer and fractional part
305 \edef\next{\noexpand\@Rtrunc\noexpand#1#2#3..\noexpand\relax}%
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 '.'
318 \ifnum\count@>\@zero%
319 \expandafter\@@Rtrunc#4000000000\relax%
324 \def\@@Rtrunc#1#2#3#4#5#6#7#8#9{%
325 % #1...#9 fractional part, padded with trailing zeros
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%
340 %% \Rifle<value><value> Test v1 < v2
341 \def\Rifle#1#2{\@callb\@Rifle{#1}{#2}}
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 '.'
351 \@readvalue\@xs\@xi\@xf{#1}{#2}%
352 \@readvalue\@ys\@yi\@yf{#4}{#5}%
361 \ifnum\@xi<\@yi \Rtesttrue \fi%
363 \multiply\@xf\@xs \multiply\@yf\@ys%
364 \ifnum\@xf<\@yf \Rtesttrue \fi%
372 %% \Rifeq<value><value> Test v1 = v2
373 \def\Rifeq#1#2{\@callb\@Rifeq{#1}{#2}}
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 '.'
383 \@readvalue\@xs\@xi\@xf{#1}{#2}%
384 \@readvalue\@ys\@yi\@yf{#4}{#5}%
387 \ifnum\@xi=\@yi\ifnum\@xf=\@yf \Rtesttrue \fi\fi%
391 %% \Rifgt<value><value> Test v1 > v2
392 \def\Rifgt#1#2{\@callb\@Rifgt{#1}{#2}}
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 '.'
402 \@readvalue\@xs\@xi\@xf{#1}{#2}%
403 \@readvalue\@ys\@yi\@yf{#4}{#5}%
412 \ifnum\@xi>\@yi \Rtesttrue \fi%
414 \multiply\@xf\@xs \multiply\@yf\@ys%
415 \ifnum\@xf>\@yf \Rtesttrue \fi%
423 %% \Rifneg<value> Test v < 0
424 \def\Rifneg#1{\@calla\@Rifneg{#1}}
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 '.'
431 \@readvalue\@xs\@xi\@xf{#1}{#2}%
433 \ifnum\@xs<0 \Rtesttrue \else \Rtestfalse \fi%
437 %% \Rifzero<value> Test v = 0
438 \def\Rifzero#1{\@calla\@Rifzero{#1}}
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 '.'
445 \@readvalue\@xs\@xi\@xf{#1}{#2}%
448 \ifnum\@xi=\@zero \ifnum\@xf=\@zero \Rtesttrue \fi \fi%
452 %% \Rifpos<value> Test v >= 0
453 %% Take care to have a corresponding \fi
454 \def\Rifpos#1{\@calla\@Rifpos{#1}}
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 '.'
461 \@readvalue\@xs\@xi\@xf{#1}{#2}%
463 \ifnum\@xs<0 \Rtestfalse \else \Rtesttrue \fi%
467 %% \Rifint<value> Test v is an integer value
468 %% Take care to have a corresponding \fi
469 \def\Rifint#1{\@calla\@Rifint{#1}}
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 '.'
476 \@readvalue\@xs\@xi\@xf{#1}{#2}%
478 \ifnum\@xf=0 \Rtesttrue \else \Rtestfalse \fi%
487 % Expand the value and split them into the integer and the fractional part
488 \edef\next{\noexpand#1#2..\noexpand\relax}%
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}%
501 \def\@callc#1#2#3#4{%
503 % #2 Macro, witch gets the result
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}%
511 %% \ifRtest ... \else ... \fi Re-execute the last test
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)
523 % Regular expression [-...d]d...["."[d...]]
524 % Attention: There has to be at least one digit between "-" and "."!
527 \if !#4! #2=\@zero \else #2=#4 \fi%
530 \ifnum#2<\@zero #1=-\@ne \else #1=\@ne \fi%
531 \ifnum#2=\@zero \ifnum #4#5<\@zero #1=-\@ne \fi \fi%
537 \@@setcount@#5000000000\relax%
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%
549 % Swallow everything up to next \relax
550 \def\@swallow#1\relax{}
556 % #1 marcro to catch the result
557 % #2 counter with integer part (maybe negative)
558 % #3 counter with fractional part (maybe negative}
563 \ifnum\count@<\@zero%
570 % Pad fractional part with leading zeros
571 \advance\count@\@mil%
574 \edef#1{#1\number#2.\expandafter\@ignorenext\number\count@}%
580 % Restore catcode of "@"