## File: comp_pi.tex

package info (click to toggle)
tralics 2.14.4-2
 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 % Compute Pi in TeX! % D. Roegel (roegel@loria.fr), 21 July 1996 % % This programs uses the formula by John Machin: % % Pi=16*arctan(1/5)-4*arctan(1/239) % % The implementation of arrays uses a trick shown by Tom Rokicki % in his game of life program (life.tex). % % Warning: this program has limits, and I invite you to find them... % % Bugs: I believe there is one, since when you ask for 100 digits, % you get only 97 ... % % %% These lines no more needed [JG] %\ifx\begin\undef\else %\def\message#1{\edef\foo{{#1}}\expandafter\typeout\foo} %\fi \newlinechar=\^^J \message{^^J***** Computation of Pi with John Machin's formula *****} \message{^^J** i.e.: pi=16*arctan(1/5)-4*arctan(1/239)} \message{^^JHow many digits of pi do you want ? } \read16to\nbdigits \wlog{We want \nbdigits digits} \newcount\n \n\nbdigits \newcount\index \index\n \advance\index7 \divide\index4 \newcount\lastplusone \lastplusone\index \advance\lastplusone1 % \index is now the index for the last slot in the arrays % slot 1 -> integer digits % slot 2 -> digits 1 to 4 % slot 3 -> digits 5 to 8 % ... % slot \index -> digits (\index-2) * 4 +1 to (\index-1) * 4 % \font\xa=cmr10 at 11truept % array for current values of (1/5)^{2n+1} % and (1/239)^{2n+1} \fontdimen\lastplusone\xa=0pt % this creates room \font\xb=cmr10 at 13truept % array for current values of (1/5)^{2n+1}/(2n+1) % and (1/239)^{2n+1}/(2n+1) \fontdimen\lastplusone\xb=0pt % this creates room \font\xc=cmr10 at 15truept % array for current sums of arctan(1/5) % and arctan(1/239) \fontdimen\lastplusone\xc=0pt % this creates room \font\xr=cmr10 at 17truept % array for the result \fontdimen\lastplusone\xr=0pt % this creates room % \xa, \xb, \xc and \xr are now equal to 0 % Some variables: \newcount\dv % will hold dividers \newcount\firstpos % first non empty slot \newcount\I % scratch register for loops \newdimen\carry % for carry (in additions) and borrows (in subtractions) \newdimen\x % a scratch variable \newcount\N % counts the terms \newif\ifcont % flag used to find when an operation on bignums is not done % Initialization of working arrays \def\InitializeArrays{ { \I=1 \loop \fontdimen\I\xa=0sp \fontdimen\I\xb=0sp \fontdimen\I\xc=0sp \advance\I1 \ifnum\I<\lastplusone \repeat } } % Initialization of the result \newcount\I \I=1 \loop \fontdimen\I\xr=0sp \advance\I1 \ifnum\I<\lastplusone \repeat \InitializeArrays % divide #1 by #2 beginning at slot \firstpos and up to \index; % result is in #3 \def\Divide#1#2into#3{% \carry0sp \I\firstpos { \loop \x=\fontdimen\I#1 \multiply\carry10000 \advance\x\carry \carry\x \divide\x#2 \fontdimen\I#3=\x \multiply\x#2 \advance\carry-\x \advance\I1 \ifnum\I<\lastplusone \repeat } } % Addition: \def\Add#1to#2{% \carry0sp \I\index { \loop \x=\fontdimen\I#2 \advance\x by \fontdimen\I#1 \advance\x by \carry \fontdimen\I#2=\x \carry\x \divide\carry10000 \multiply\carry10000 \x=\fontdimen\I#2 \advance\x-\carry \fontdimen\I#2=\x \divide\carry10000 \advance\I-1 { \ifnum\I<\firstpos \ifnum\carry=0 \global\contfalse \else \global\conttrue \fi \else \global\conttrue \fi } \ifcont \repeat } } % Subtraction: \def\Sub#1from#2{% \carry0sp \I\index { \loop \x=\fontdimen\I#2 \advance\x by -\fontdimen\I#1 \advance\x by -\carry \fontdimen\I#2=\x \carry\x \divide\carry10000 \multiply\carry10000 \advance\x-\carry \fontdimen\I#2=\x \divide\carry10000 {\ifdim\fontdimen\I#2<0sp \advance\x10000sp \fontdimen\I#2=\x \global\advance\carry1sp \fi} \advance\I-1 { \ifnum\I<\firstpos \ifnum\carry=0 \global\contfalse \else \global\conttrue \fi \else \global\conttrue \fi } \ifcont \repeat } } % Multiplication: \def\Multiply#1#2{% \carry0sp \I\index \loop \x=\fontdimen\I#1 \multiply\x by #2 \advance\x by \carry \fontdimen\I#1=\x \carry\x \divide\carry10000 \multiply\carry10000 \x=\fontdimen\I#1 \advance\x-\carry \fontdimen\I#1=\x \divide\carry10000 \advance\I-1 { \ifnum\I<\firstpos \ifnum\carry=0 \global\contfalse \else \global\conttrue \fi \else \global\conttrue \fi } \ifcont \repeat } \def\updatefirstpos{ \ifdim\fontdimen\firstpos\xa=0pt \ifnum\firstpos<\lastplusone \global\advance\firstpos1 \fi \fi } \def\UpdateFirstPos{\updatefirstpos\updatefirstpos} \def\ComputeArcTan#1{% \firstpos=2 \dv=#1 \multiply\dv\dv \N1 \message{^^JI am now computing the following sum: arctan(1/#1)=1/#1} \Add\xb to\xc % first term \loop %--------------------------------------------------------- % negative terms: \Divide\xa\dv into\xa \UpdateFirstPos \advance\N2 \Divide\xa\N into\xb \message{-1/\the\N*1/#1^\the\N} \Sub\xb from\xc \fontdimen\firstpos\xb=0pt %--------------------------------------------------------- % positive terms: \Divide\xa\dv into\xa \UpdateFirstPos \advance\N2 \Divide\xa\N into\xb \message{+1/\the\N*1/#1^\the\N} \Add\xb to\xc \fontdimen\firstpos\xb=0pt \ifnum\firstpos<\lastplusone \repeat } \def\ShowResult#1#2{{ \count0=2 \def\res{} \loop \count1=\fontdimen\count0#2 % we add 0' in front, in order to have always 4 digits \ifnum\count1<10 \edef\res{\res000\number\count1 } \else \ifnum\count1<100 \edef\res{\res00\number\count1 } \else \ifnum\count1<1000 \edef\res{\res0\number\count1 } \else \edef\res{\res\number\count1 } \fi \fi \fi \advance\count0by 1 \ifnum\count0 <\lastplusone \repeat \message{^^J#1\res} %% added JG for Tralics \xbox{pi}{#1\res} } } % initialize \xa with 1/5: \fontdimen2\xa 2000sp % 1/5=0.2000 ... % initialize \xb with 1/5: \fontdimen2\xb 2000sp \ComputeArcTan{5} \message{^^JNow, I multiply it by 16...} \firstpos1 \Multiply\xc{16} \message{done} \firstpos1 \Add\xc to\xr \InitializeArrays % initialize \xa with 1: \fontdimen2\xa =10000sp \dv239 \Divide\xa\dv into\xa \Add\xa to\xb \ComputeArcTan{239} \message{^^JNow, I multiply it by 4...} \firstpos1 \Multiply\xc{4} \message{done} \message{^^JAnd finally, I subtract 4*arctan(1/239) to 16*arctan(1/5)} \message{which results in :} %\tracingall \firstpos1 \Sub\xc from\xr \ShowResult{pi=3.}\xr \bye