Sophie

Sophie

distrib > Arklinux > devel > x86_64 > media > main-src > by-pkgid > 5c195c726252edeca99ef2a503ef6940 > files > 1

tex-realcalc-1.0-1ark.src.rpm

%% realcalc.tex
%%
%% (C) Frank Buchholz, Jan. 1993
%% e-mail: buchholz@lusty.informatik.uni-dortmund.de
%  User documentation: All lines starting with two %
%  Try grep to extract these lines.
%%
%% Real arithmetic with big values and high precision.
%% Calculations are done with 9 decimal digits.
%% Usable with TeX and LaTeX.
%%
%% Parameter:
%%
%% 	<macro> Macro, witch catches the result.
%% 	<value> String or macro witch expands to a value in the range 
%% 		    from -2147483647.999999999 to 2147483647.999999999
%%	<precision> Number from 0 to 9
%%
%% Functions:
%%

% Don't read this file twice
\ifx\Radd\undefined \else \endinput \fi

% Make "@" be a letters
\chardef\catamp=\the\catcode`\@
\catcode`@=11
 
\def\@Rversion{Version 1.0, Jan. 1993}
\message{`Real arithmetic', \@Rversion (C) Frank Buchholz}

% Allocation of temporary registers
\newcount\@ta
\newcount\@tb
%
\newcount\@xs	% Sign of 1st value
\newcount\@xi	% Integer part of 1st value
\newcount\@xf	% Fractional part of 1st value
%
\newcount\@ys	% Sign of 2nd value
\newcount\@yi	% Integer part of 2nd value
\newcount\@yf	% Fractional part of 2nd value
%
\newcount\@mil	\@mil=1000000000	% 10^9
%
\countdef\@xa240
\countdef\@xb241
\countdef\@xc242
\countdef\@xd243
\countdef\@xe244
\countdef\@ya245
\countdef\@yb246
\countdef\@yc247
\countdef\@yd248
\countdef\@ye249
\let\@f=\@tb
\let\@product=\@ta

\chardef\@zero=0

%% 	\Radd<macro><value><value>	 	Addition
\def\Radd#1#2#3{\@callc\@Radd#1{#2}{#3}}

%% 	\Rsub<macro><value><value>	 	Subtraction
\def\Rsub#1#2#3{\@callc\@Radd#1{#2}{-#3}}

\def\@Radd#1#2.#3.#4\relax#5.#6.#7\relax{%
  % #1 Macro, witch gets the result
  % #2 integer part of 1st value 
  % #3 fractional part of 1st value
  % #4 dummy to swallow everthing after the 2nd '.'
  % #5 integer part of 2nd value 
  % #6 fractional part of 2nd value
  % #7 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#2}{#3}%
  \@readvalue\@ys\@yi\@yf{#5}{#6}%
  %
  % Add integer parts
  \@ta=\@xi \advance\@ta\@yi%
  %
  % Add fractional parts if they are not zero
  \ifnum\@xf=\@zero%
    \ifnum\@yf=\@zero%
      \@tb=\@zero%
    \else%
      \@longadd%
    \fi%
  \else%
    \@longadd%
  \fi%
  %
  % Store result
  \@store#1\@ta\@tb%
}

\def\@longadd{%
    % Propagate sign to fractional parts
    \multiply\@xf\@xs \multiply\@yf\@ys%
    %
    % Add fractional parts
    \@tb=\@xf \advance\@tb\@yf%
    %
    % Calculate carry
    \ifnum\@tb<\@zero% 
      \ifnum\@tb<-\@mil      \advance\@ta -\@ne \advance\@tb\@mil  \fi% 
    \else% 
      \ifnum\@tb<\@mil \else \advance\@ta \@ne	\advance\@tb-\@mil \fi% 
    \fi%
} 

%% 	\Rmul<macro><value><value>	 	Multiplication
\def\Rmul#1#2#3{\@callc\@Rmul#1{#2}{#3}}

\def\@Rmul#1#2.#3.#4\relax#5.#6.#7\relax{%
  % #1 Macro, witch gets the result
  % #2 integer part of 1st value 
  % #3 fractional part of 1st value
  % #4 dummy to swallow everthing after the 2nd '.'
  % #5 integer part of 2nd value 
  % #6 fractional part of 2nd value
  % #7 dummy to swallow everthing after the 2nd '.'
  %
  % How to do real multiplications:
  % Split values in various parts
  % x y = 1234 567890 . 123 456 789
  % ->	  xa   xb	xc  xd	xe
  % ->	  ya   yb	yc  yd	ye
  % Do 21 (!) integer multiplications if there are any fractional parts
  % r = x * Y
  % -> r =   xi*yi
  %	   + (xa*yc + xa*yc		     )*10^3 
  %	   + (xa*yd + xd*ya		     )*10^-0 
  %	   + (xa*ye + xe*ya  +	xb*yc + xc*yb)*10^-3 
  %	   + (xb*yd + xd*yb  +	xc*yc	     )*10^-6 
  %	   + (xb*ye + xe*yb  +	xc*yd + xd*yc)*10^-9 
  %	   + (xc*ye + xe*yc  +	xd*yd	     )*10^-12 
  %	   + (xd*ye + xe*yd		     )*10^-15 
  %	   + (xe*ye			     )*10^-18
  %
  % -> r = ((((( xe*ye				     / 1000 
  %		+ xd*ye + xe*yd 		  ) / 1000
  %	       + xc*ye + xe*yc	+  xd*yd	 ) / 1000
  %	      + xb*ye + xe*yb  +  xc*yd + xd*yc ) / 1000
  %	     + xb*yd + xd*yb  +  xc*yc	       ) / 1000
  %	    + xa*ye + ye*xa  +	xb*yc + xc*yb ) / 1000
  %	   + xa*yd + xd*ya + (xa*yc + ya*xc)*1000 + xi*yi
  % The last three digigs are saved just before the divisions.
  %
  % Init 
  %
  \@readvalue\@xs\@xi\@xf{#2}{#3}%
  \@readvalue\@ys\@yi\@yf{#5}{#6}%
  %
  % Sign
  \multiply\@xi\@xs%
  \multiply\@yi\@ys%
  \multiply\@xs\@ys%
  %
  \@product=\@zero%
  % 
  \ifnum\@xf=\@zero%
    \ifnum\@yf=\@zero%
      % No fractional parts
      \edef\@frac{000000000}	% digits of fractional part  
    \else%
      \@longmul			% Long multiplication		
    \fi%
  \else%
    \@longmul			% Long multiplication		
  \fi%
  %
  % Multiply integer parts
  \count@=\@xi \multiply\count@\@yi%
  \advance\@product\count@%
  %
  % Sign
  \multiply\@product\@xs%
  %
  % Store result
  \edef#1{\number\@product.\@frac}%
}

% Do long multiplication
\def\@longmul{%
    % Split values in pieces
    \@f=1000000%
    \count@=\@xi%		
    \divide\count@\@f					\@xa=\count@%
    \multiply\count@-\@f	\advance\count@\@xi	\@xb=\count@%
    \count@=\@xf%		
    \divide\count@\@f					\@xc=\count@%
    \multiply\count@-\@f	\advance\count@\@xf%	
    \@f=1000%
    \@xe=\count@%
    \divide\count@\@f					\@xd=\count@%
    \multiply\count@-\@f	\advance\count@\@xe	\@xe=\count@%
    % 
    \@f=1000000%
    \count@=\@yi%		
    \divide\count@\@f					\@ya=\count@%
    \multiply\count@-\@f	\advance\count@\@yi	\@yb=\count@%
    \count@=\@yf%		
    \divide\count@\@f					\@yc=\count@%
    \multiply\count@-\@f	\advance\count@\@yf%	
    \@f=1000%
    \@ye=\count@%
    \divide\count@\@f					\@yd=\count@%
    \multiply\count@-\@f	\advance\count@\@ye	\@ye=\count@%
    %
    \edef\@frac{} 				% digits of fractional part
    % 
    \@mul ee	      \relax\@shift		% 10^-18
    \@mul de ed       \relax\@shift		% 10^-15
    \@mul ce ec dd    \relax\@shift		% 10^-12
    \@mul be eb cd dc \relax\@saveshift		% 10^-9
    \@mul bd db cc    \relax\@saveshift		% 10^-6
    \@mul ae ea bc cb \relax\@saveshift		% 10^-3
    \multiply\@xa\@f  \multiply\@xc\@f		% 10^3
    \@mul ad da ac ca \relax%			
}

\def\@mul#1#2#3{%
  \count@=\csname @x#1\endcsname%
  \multiply\count@\csname @y#2\endcsname%
  \advance\@product\count@%
  %
  \ifx#3\relax%
    \let\next=\relax% 
  \else%
    \let\next=\@mul%
  \fi%
  \next#3%
}

\def\@shift{%
  \divide\@product\@f%
}

\def\@saveshift{%
  % Save rightmost digits 
  \count@=\@product%
  \divide\@product\@f%
  \multiply\@product\@f%
  \advance\count@-\@product%
  \advance\count@\@f%
  \edef\@frac{\expandafter\@ignorenext\number\count@\@frac}%
  %
  \divide\@product\@f%
}

%% 	\Rdiv<macro><value><value>	 	Division
\def\Rdiv#1#2#3{\@callc\@Radd#1{#2}{#3}}

\def\@Rdiv#1#2.#3.#4\relax#5.#6.#7\relax{%
  % #1 Macro, witch gets the result
  % #2 integer part of 1st value 
  % #3 fractional part of 1st value
  % #4 dummy to swallow everthing after the 2nd '.'
  % #5 integer part of 2nd value 
  % #6 fractional part of 2nd value
  % #7 dummy to swallow everthing after the 2nd '.'
  %
  \message{Error: Rdiv not ready}
  %
  \@readvalue\@xs\@xi\@xf{#2}{#3}%
  \@readvalue\@ys\@yi\@yf{#5}{#6}%
  %
  \ifnum\@yi=\@zero
    \@xi=\@zero
  \else
    \divide\@xi\@yi
  \fi
  %
  \@store#1\@xi\@xf%
}

%%	\Rneg<macro><value>		Negation
\def\Rneg#1#2{%
  % Expand the value and split it into the integer and the fractional part
  \edef\next{\noexpand\@Rneg\noexpand#1#2..\noexpand\relax}%
  \next%
}

\def\@Rneg#1#2.#3.#4\relax{
  % #1 Macro, witch gets the result
  % #2 Integer part of value
  % #3 Fractional part of value
  % #4 Remaining tokens
  %
  \@readvalue\@xs\@xi\@xf{#2}{#3}%
  %
  % Change sign
  \multiply\@xi-\@ne%
  \multiply\@xf-\@xs%
  % 
  % Store result
  \@store#1\@xi\@xf%
}

%%
%%	\Rtrunc<macro><precision><value> Truncate value to specified precision
\def\Rtrunc#1#2#3{%
  % Expand parameter and split the value into the integer and fractional part 
  \edef\next{\noexpand\@Rtrunc\noexpand#1#2#3..\noexpand\relax}%
  \next%
}

\def\@Rtrunc#1#2#3.#4.#5\relax{%
  % #1 Macro, witch gets the result
  % #2 Number of decimal places
  % #3 Integer part of value
  % #4 Fractional part of value
  % #5 dummy to swallow everthing after the 2nd '.'
  %
  \count@=#2%
  \edef\next{\empty}%
  \ifnum\count@>\@zero%
    \expandafter\@@Rtrunc#4000000000\relax%
  \fi%
  \edef#1{#3\next}%
}

\def\@@Rtrunc#1#2#3#4#5#6#7#8#9{%
  % #1...#9 fractional part, padded with trailing zeros
  \edef\next{.#1%
    \ifnum\count@>1 #2\fi%
    \ifnum\count@>2 #3\fi%
    \ifnum\count@>3 #4\fi%
    \ifnum\count@>4 #5\fi%
    \ifnum\count@>5 #6\fi%
    \ifnum\count@>6 #7\fi%
    \ifnum\count@>7 #8\fi%
    \ifnum\count@>8 #9\fi%
  }%
  \@swallow%
}

%%
%%	\Rifle<value><value>		Test v1 < v2
\def\Rifle#1#2{\@callb\@Rifle{#1}{#2}}

\def\@Rifle#1.#2.#3\relax#4.#5.#6\relax{%
  % #1 integer part of 1st value 
  % #2 fractional part of 1st value
  % #3 dummy to swallow everthing after the 2nd '.'
  % #4 integer part of 2nd value 
  % #5 fractional part of 2nd value
  % #6 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  \@readvalue\@ys\@yi\@yf{#4}{#5}%
  %
  \ifnum\@xs<\@ys% 
    \Rtesttrue% 
  \else%
    \ifnum\@xs>\@ys% 
      \Rtestfalse%
    \else%
      \Rtestfalse%
      \ifnum\@xi<\@yi \Rtesttrue \fi%
      \ifnum\@xi=\@yi%
	\multiply\@xf\@xs \multiply\@yf\@ys%
	\ifnum\@xf<\@yf \Rtesttrue \fi% 
      \fi%
    \fi%
  \fi%
  %
  \ifRtest%
}

%%	\Rifeq<value><value>		Test v1 = v2
\def\Rifeq#1#2{\@callb\@Rifeq{#1}{#2}}

\def\@Rifeq#1.#2.#3\relax#4.#5.#6\relax{%
  % #1 integer part of 1st value 
  % #2 fractional part of 1st value
  % #3 dummy to swallow everthing after the 2nd '.'
  % #4 integer part of 2nd value 
  % #5 fractional part of 2nd value
  % #6 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  \@readvalue\@ys\@yi\@yf{#4}{#5}%
  %
  \Rtestfalse%
  \ifnum\@xi=\@yi\ifnum\@xf=\@yf \Rtesttrue \fi\fi%
  \ifRtest%
}

%%	\Rifgt<value><value>		Test v1 > v2
\def\Rifgt#1#2{\@callb\@Rifgt{#1}{#2}}

\def\@Rifgt#1.#2.#3\relax#4.#5.#6\relax{%
  % #1 integer part of 1st value 
  % #2 fractional part of 1st value
  % #3 dummy to swallow everthing after the 2nd '.'
  % #4 integer part of 2nd value 
  % #5 fractional part of 2nd value
  % #6 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  \@readvalue\@ys\@yi\@yf{#4}{#5}%
  %
  \ifnum\@xs>\@ys% 
    \Rtesttrue% 
  \else%
    \ifnum\@xs<\@ys% 
      \Rtestfalse% 
    \else%
      \Rtestfalse%
      \ifnum\@xi>\@yi \Rtesttrue \fi%
      \ifnum\@xi=\@yi% 
	\multiply\@xf\@xs \multiply\@yf\@ys%
	\ifnum\@xf>\@yf \Rtesttrue \fi% 
      \fi%
    \fi%
  \fi%
  %
  \ifRtest%
}

%%	\Rifneg<value>			Test v < 0
\def\Rifneg#1{\@calla\@Rifneg{#1}}

\def\@Rifneg#1.#2.#3\relax{%
  % #1 Integer part of value
  % #2 Fractional part of value
  % #3 dummy to swallow everthing after the 2nd '.'
   %
   \@readvalue\@xs\@xi\@xf{#1}{#2}%
   %
   \ifnum\@xs<0 \Rtesttrue \else \Rtestfalse \fi%
   \ifRtest%
 }

%%	\Rifzero<value>			Test v = 0
\def\Rifzero#1{\@calla\@Rifzero{#1}}

\def\@Rifzero#1.#2.#3\relax{%
  % #1 Integer part of value
  % #2 Fractional part of value
  % #3 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  %
  \Rtestfalse%
  \ifnum\@xi=\@zero \ifnum\@xf=\@zero \Rtesttrue \fi \fi%
  \ifRtest%
}

%%	\Rifpos<value>			Test v >= 0
%%					Take care to have a corresponding \fi
\def\Rifpos#1{\@calla\@Rifpos{#1}}

\def\@Rifpos#1.#2.#3\relax{%
  % #1 Integer part of value
  % #2 Fractional part of value
  % #3 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  %
  \ifnum\@xs<0 \Rtestfalse \else \Rtesttrue \fi%
  \ifRtest%
}

%%	\Rifint<value>			Test v is an integer value
%%					Take care to have a corresponding \fi
\def\Rifint#1{\@calla\@Rifint{#1}}

\def\@Rifint#1.#2.#3\relax{%
  % #1 Integer part of value
  % #2 Fractional part of value
  % #3 dummy to swallow everthing after the 2nd '.'
  %
  \@readvalue\@xs\@xi\@xf{#1}{#2}%
  %
  \ifnum\@xf=0 \Rtesttrue \else \Rtestfalse \fi%
  \ifRtest%
}

% Utility macros

\def\@calla#1#2{%
  % #1 Macro to call
  % #2 Value
  % Expand the value and split them into the integer and the fractional part
  \edef\next{\noexpand#1#2..\noexpand\relax}%
  \next%
}

\def\@callb#1#2#3{%
  % #1 Macro to call
  % #2 1st value
  % #3 2nd value
  % Expand the values and split them into the integer and the fractional parts 
  \edef\next{\noexpand#1#2..\noexpand\relax#3..\noexpand\relax}%
  \next%
}

\def\@callc#1#2#3#4{%
  % #1 Macro to call
  % #2 Macro, witch gets the result
  % #3 1st value
  % #4 2nd value
  % Expand the values and split them into the integer and the fractional parts
  \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax#4..\noexpand\relax}%
  \next%
}

%% 	\ifRtest ... \else ... \fi	Re-execute the last test
\newif\ifRtest

%
% Read value
%
\def\@readvalue#1#2#3#4#5{%
  % #1	  macro to catch the sign ( -1 or 1 )
  % #2	  macro to catch the integer part (maybe negative)
  % #3	  macro to catch the fractional part (positive)
  % #4.#5 value
  %
  % Regular expression [-...d]d...["."[d...]]
  % Attention: There has to be at least one digit between "-" and "."!
  %
  % Integer part
  \if !#4! #2=\@zero \else #2=#4 \fi%
  %
  % Sign
  \ifnum#2<\@zero #1=-\@ne \else #1=\@ne \fi%
  \ifnum#2=\@zero \ifnum #4#5<\@zero #1=-\@ne \fi \fi%
  %
  % Fractional part
  \if !#5!% 
    #3=\@zero%
  \else%
    \@@setcount@#5000000000\relax%
    #3=\count@%
  \fi%
}

% Set count@ to fractional part with trailing zeros
\def\@@setcount@#1#2#3#4#5#6#7#8#9{%
  % #1...#9 fractional part, padded with '0'
  \count@=#1#2#3#4#5#6#7#8#9%
  \@swallow%
}

% Swallow everything up to next \relax
\def\@swallow#1\relax{}

%
% Store result 
%
\def\@store#1#2#3{%
  % #1 marcro to catch the result
  % #2 counter with integer part (maybe negative)
  % #3 counter with fractional part (maybe negative}
  % 
  % Sign
  \edef#1{}%
  \count@=#3%
  \ifnum\count@<\@zero% 
    \count@=-\count@%
    \ifnum#2=\@zero% 
      \edef#1{-}%
    \fi%
  \fi%
  %
  % Pad fractional part with leading zeros
  \advance\count@\@mil%
  %
  % Store result 
  \edef#1{#1\number#2.\expandafter\@ignorenext\number\count@}%
}

% Ignore next token
\def\@ignorenext#1{}

% Restore catcode of "@"
\catcode`\@=\catamp