% This is taken from Donald Arseneau % http://groups.google.com/group/comp.text.tex/browse_thread % /thread/95b55bc557d96b5/4daa67ff2a027d37 \def\pointless#1{\expandafter\remove@PT\the#1} {\catcode`p=12 \catcode`t=12 \gdef\remove@PT#1pt{#1}} \let\mul\pointless % Example: \area=\pointless\hsize\baselineskip \newcount\FPD@hi \FPD@hi=67108863 \def\AbsVal#1{\ifnum#1<\z@ -\fi#1} \def\AbsValD#1{\ifdim#1<\z@ -\fi#1} \def\MaxD#1#2{\ifdim#1>#2#1\else#2\fi} % Approximate Fixed Point Division of two dimensions % 3.14159/2.71828 = 1.15573 % Two parameters: Numerator and denominator. The answer is returned % in the numerator (which must be a register). The denominator is % unchanged (it may be a numeric string, "123"). % \@tempcntb is used and altered. % \newif\ifFPD@overflow \newdimen\FBD@denom \def\fpdivide#1#2{% \FPD@overflowfalse \ifdim\AbsValD#2<1\p@ \begingroup\FBD@denom\ifdim#2<\z@-\fi5000#2% \let\next\@empty \ifdim\AbsValD#1>\FBD@denom \def\next{% \FPD@overflowtrue \debug2{Overflow dividing \the#1 by \the#2 -> inf}% #1=5000\p@}% \fi \ifdim\AbsValD#2<.001\p@\ifdim\AbsValD#2<.001\p@ \def\next{% \FPD@overflowtrue \debug2{Overflow dividing \the#1 by \the#2 -> 0}% #1=0\p@}% \fi\fi \expandafter\endgroup\next \fi \ifFPD@overflow\else \let\FPD@nume#1\@tempcntb#2\relax \FPD@scale\FPD@scale\FPD@scale\FPD@scale \divide#1\@tempcntb \fi } % Rescale numbers to preserve accuracy. The number 16 is the level of % uncertainty. Use a lower power of 2 for more accuracy (2 is most precise). % But if you change it, you must change the repetions of \FPD@scale in % \fpdivide above: magic_number^repetitions = 65536 (16^4 = 65536). % \def\FPD@scale{\ifnum\AbsVal\FPD@nume<\FPD@hi \multiply\FPD@nume\sixt@@n \else \divide\@tempcntb\sixt@@n \fi } % The syntax is % \fpdivide\dimenA\dimenB % equivalent to % \divide\counterA \counterB \let\div\fpdivide %%%%%%%%%%%%%%% % Here is sqrt code I stole from Kevin Hamlen: \def\sqrt#1{% \begingroup \dimen@#1\relax \@tempdima#1\relax \loop % temp1 := sqrt(arg1) \@tempdimb=#1% \div\@tempdimb \@tempdima% \advance\@tempdimb by\@tempdima% \divide\@tempdimb by\tw@% \ifdim\@tempdimb<\@tempdima% \@tempdima=\@tempdimb\repeat% \xa\endgroup\xa#1\the\@tempdima\relax } \def\pythag#1#2#3{% WATCH OVERFLOW HERE!!! % #3 = sqrt(#1^2+#2^2) %#3=\mul#1#1 \advance#3\mul#2#2 \xa\xa\xa\ifdim\xa\AbsValD\xa#1\xa<\AbsValD#2% %this should be safer... \ifdim\AbsValD#1<.001\p@#3#2\else #3=#1\relax \div#3#2\relax #3=\mul#3#3\relax \advance#31\p@ \sqrt#3\relax #3\mul#2#3% \fi \else \ifdim\AbsValD#2<.001\p@#3#1\else #3=#2\relax \div#3#1\relax #3=\mul#3#3\relax \advance#31\p@ \sqrt#3\relax #3\mul#1#3% \fi \fi \ifdim#3<\z@#3-#3\fi % MUST BE POSITIVE! } \def\unitvector#1#2#3{% #3 is temp space \pythag#1#2#3% \div#1#3\div#2#3% } \def\sumsq#1#2#3{% this is probably not safe! % #3 = sqrt(#1^2+#2^2) #3=\mul#1#1\advance#3\mul#2#2% }