This is longpi.c in view mode; [Download] [Up]
/************************************************************************/ /* */ /* LONGPI: calculates the number PI (3.14...) to <n> digits */ /* */ /* */ /* Should compile without any problems on any good ANSI C compiler */ /* */ /* Last changes: 2.12.1991 @pf68030 */ /* */ /************************************************************************/ /* Execution times for LONGPI 1000 on several computers: ----------------------------------------------------- Note: calculating 1000 digits of PI requires 8 KBytes of memory. If the processor cache has at least 8 K things will considerably speed up because of a cache hit ratio approaching 100% ! Computer type OS CPU, Speed Time used ------------------------------------------------------------------ Atari ST 1040, TOS 1.x 8 MHz 68000 215 s IBM PS/2, MSDOS 10 MHz 286 207 s VAX 11/750, VMS 4.7 ? 100 s AT 386 MSDOS 25 MHz 386DX, 32K Cache 62 s Atari TT030 TOS 3.0x 32 MHz 68030 37 s (68000 code) AT 486 EISA MSDOS 5 33 MHz 486DX 32 s MAC IIsi MacOS 6.0.x 20 MHz 68030 26 s (68020 code) MAC IIci MacOS 6.0.x 25 MHz 68030 19.8 s (68020 code) AT 486 EISA MSDOS 33 MHz 486DX 17 s ('386 code) Atari TT030 TOS 3.0x 32 MHz 68030 13.5 s (68020 code) HP 9000 UNIX 50 MHz 68030 12.6 s (+0.1 s systime) HP 9000 UNIX 25 MHz 68040 9.8 s (+0.1 s systime) NeXTstation UNIX 25 MHz 68040 7.3 s (+0.1 s systime) (added by Xilef) AT 486 SCO-UNIX 33 MHz 486DX, 64K Cache 6.4 s SUN Sparcstation2 SunOS Sparc RISC processor 5.1 s Compilers: ---------- Pure C (Turbo C successor): Atari ST/TT Quick C IBM PS/2 Turbo C++ AT 486 (32 sec) Microsoft C AT 486 (17 sec) VAX 11 C VAX 11/750 (what else ?) Standard unix compilers ('cc') on *IX systems. Cache: ------ 68000...68010: 0 68020 256 bytes 68030 2*256 bytes (code+data separated) 68040 2*4 Kbytes physical 80286 0 80486 8 Kbytes physical cache (code+data unified) */ /************************************************************************/ /* THE PROGRAM... */ /************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <time.h> #ifdef __wrongclock #define CLK_TCK 60 #endif #ifdef __TOS__ #define MOTOROLA /* may be defined on _real_ 32 bit architectures */ #endif clock_t chronometer; /* only available in ANSI C */ long kf,ks,*mf,*ms; long cnt,n,temp,nd; long i; long col,col1; long loc,stor[100]; FILE *fp; /* some prototypes ! */ void shift(long *l1, long *l2, long lp, long lmod); /************************************************************************/ /* launch the 'chronometer' */ void chronostart(void) { chronometer=clock(); }; /************************************************************************/ /* get elapsed time */ void chronostop(void) { clock_t newtime; double seconds; newtime=clock(); seconds=(double)(newtime-chronometer)/(double)CLK_TCK; printf("time used: %.02lf sec\n", seconds); fprintf(fp, "\n\ntime used: %.02lf sec\n", seconds); }; /************************************************************************/ /* output routines: */ void yprint( long m ) { if (cnt < n) { if (++col==11) { col = 1; if (++col1==6) { col1=0; fprintf(fp,"\n"); printf("\n"); fprintf(fp,"%4ld",m%10); printf("%4ld",m%10); } else { fprintf(fp,"%3ld",m%10); printf("%3ld",m%10); } } else { fprintf(fp,"%ld",m); printf("%ld",m); } cnt++; } } /************************************************************************/ void xprint( long m ) { long ii,wk,wk1; if (m<8) { for (ii=1; ii<=loc;) yprint(stor[ii++]); loc=0; } else if (m>9) { wk = m/10; m %= 10; for (wk1=loc; wk1>=1;wk1--) { wk += stor[wk1]; stor[wk1] = wk % 10; wk /= 10; } } stor[++loc] = m; } /************************************************************************/ int main( int argc, char *argv[] ) { long i=0; /* temp. variable */ stor[i++] = 0; if (argc < 2) { fprintf(stderr,"Format is:\n\tlongpi <# of places>\n"); exit(-1); } n = atol(argv[1]); /* convert to long */ mf = (long *)calloc( (int)(n+8), sizeof(long) ); if (mf==NULL) { fprintf(stderr,"Memory allocation failure [mf]\n"); exit(-1); } ms = (long *)calloc( (int)(n+8), sizeof(long) ); if (ms==NULL) { fprintf(stderr,"Memory allocation failure [ms]\n"); exit(-1); } #ifdef MOTOROLA /* align to longword boundary ( = more speed in 32 bit systems) */ /* !! casting a pointer to a longword var. only works in _real_ */ /* 32 bit systems such as 680x0, VAX or SUN machines ! */ /* modification 11.11.1992: align to CACHELINE!!! (16 BYTE) */ (long)mf += 16; (long)mf &= 0xFFFFFFF0L; (long)ms += 16; (long)ms &= 0xFFFFFFF0L; printf("Memory allocated: &mf[]=$%lX, &ms[]=$%lX; each is %ld bytes.\n", mf, ms, (n+3)*sizeof(long) ); #else printf("Memory allocated."); #endif fp = fopen("pi.out","w"); fprintf(fp,"\nThe following is an approximation of PI to %ld digits\n", n); printf("\nThe following is an approximation of PI to %ld digits\n", n); chronostart(); cnt = 0; kf = 25; ks = 57121L; /* Magische Konstanten */ mf[1] = 1; for (i=2; i<=n; i+=2) { mf[i] = -16; mf[i+1] = 16; } for (i=1; i<=n; i+=2) { ms[i] = -4; ms[i+1] = 4; } fprintf(fp,"\n 3."); printf("\n 3."); while (cnt < n) { for (i=0; ++i<=n-cnt; ) { mf[i] *= 10; ms[i] *= 10; } for (i=n-cnt+1; --i>=2; ) { temp = 2*i-1; shift( &mf[i-1], &mf[i], temp-2, temp*kf); shift( &ms[i-1], &ms[i], temp-2, temp*ks); } nd = 0; shift( &nd, &mf[1], 1L, 5L); shift( &nd, &ms[1], 1L, 239L); xprint(nd); } printf("\n\nCalculations Completed!\n"); chronostop(); return(0); }; /************************************************************************/ /* called very, very often! */ void shift(long *l1, long *l2, long lp, long lmod) { register long k,k1; k=( (k1 = *l2)>0 ? k1/lmod : -(-k1/lmod)-1 ); *l2 -= k*lmod; *l1 += k*lp; }; /************************************************************************/