home *** CD-ROM | disk | FTP | other *** search
- /* C version of a program to calculate PI. Version 4, 87-11-29
- B A Wichmann.
-
- Special notes for the C version:
-
- a) Converted by hand from Standard Pascal.
-
- b) This is the 32-bit version.
-
- c) It calculates to a fixed number (500) digits, to remove
- terminal i/o variability.
-
- This program is an integer benchmark, that is, a program which reflects
- the speed of a computer performing integer calculations. The computation
- used is an 'actual' one, rather than synthetic (as used by most PC
- benchmarks). The program can be used to compare the processing speeds
- of 16-bit and 32-bit implementations.
-
- (The following changes are needed to the program text for
- successful execution on a 16-bit system:
-
- Bits16 = true;
- Radix = 10;
- DRadix = 1;
- MaxT = 1000;
- last declaration, 251 changed to 1001
- Change the output statement to add ',1', see comment.)
-
- Since the main computation uses integer arithmetic, the results are
- repeatable (except for the last line which gives the rounding error
- estimate which could vary by one digit).
- The program can be timed by adding timing statements to the program
- or by timing the whole program (ensuring that the input of the data
- does not cause any delay).
- The time taken for the 32-bit version of the program is about:
- = K * Digits * ( Digits + 5.5 )
- where K depends upon the machine and is approximately 20 machine
- instruction times. The machine instruction time for an interpretive
- system is that of a single interpreted instruction. For example,
- on a BBC 'B' the interpreter time is about 200 microseconds per
- instruction. (Digits is the number of digits requested.)
- Note that the program can be converted to other languages quite
- easily. Such conversions should adhere to the form of the Pascal
- version if comparisons are to be meaningful. (If fact, the program
- was first written in BASIC.) The 16-bit version is much slower
- since the radix for the computation has to be reduced from 10000
- to 10. Version 4 of this program contains additional checks to
- ensure correct execution since experience has shown that this
- is necessary, especially if the program is translated into other
- languages.
-
- */
-
- #include <stdio.h>
- #include <time2.h>
-
-
- #define Bits16 0 /* false for 32-bit, true for 16-bit version */
- #define MaxD 1000 /* Maximum number of digits permitted */
- #define Radix 10000 /* Radix for calculation of 4 digits */
- /* NB. Radix of 5 digits overflows on 32-bit integers */
- #define DRadix 4 /* Number of zeros in Radix, Radix=10^DRadix */
- #define MaxT 250 /* MaxD / DRadix */
-
- typedef long int CompInt;
-
- static int Digits; /* Number of digits required */
- static CompInt Ar[MaxT+1];
- static CompInt Br[MaxT+1];
- static CompInt Sr[MaxT+1];
- static char St[MaxT+1][DRadix+1];
-
- void Check(position, digit)
- int position,digit;
-
- {
- if (position < Digits - 6)
- {
- if (St[(position-1) / DRadix + 2] [((position-1) % DRadix + 1)] !=
- (digit+ 48))
- printf("Incorrect value, position %d, digit%d\n",
- position, digit);
- }
- }
-
- main()
- /* This program calculates PI to arbitrary accuracy */
-
- /* PI= 8*arctan(1/3) + 4*arctan(1/7)
- =2.4(1+2*1/(3*10)+2*4*1/(3*5*10^2)+ ...)
- +.56(1+2*2/(3*100)+2*4/(3*5)*(2/100)^2+ ...) */
-
- {
-
- CompInt A, B, Sc;
- unsigned short int Terms;
- unsigned short int d,j;
- CompInt x, Fivex, y, i;
- unsigned short int k, kminus1; /* Limit is MaxT + 1 */
- clock_t start, end;
-
- printf("Working... \n");
-
- start=clock();
-
- /* printf("Number of digits required\n"); */
- /* scanf(" %2d",&Digits); */
- Digits = 500;
- if ((Digits > 1000) || (Bits16 && (Digits > 550)))
- printf("Too many digits\n");
- Terms = Digits / DRadix; /* = terms to be used of Acc */
- for (j = 1; j <= Terms; j++)
- {
- Ar[j] = 0; Br[j] = 0; Sr[j] = 0;
- }
- Sr[1] = 2;
- Ar[1] = 2;
- if (Bits16) {
- if ((Radix !=10) || (DRadix !=0) || (MaxT != 1000)) {
- printf("Wrong program specification\n");
- }
- Sr[2] = 9;
- Sr[3] = 6;
- Ar[2] = 4;
- Br[2] = 5;
- Br[3] = 6;
- }
- else {
- Sr[2] = 9600; /* = .96 * Radix */
- Ar[2] = 4000; /* = .4 * Radix */
- Br[2] = 5600; /* = .56 * Radix */
- i = 2; k = 1;
- };
- do {
- A = 0; B = 0;
- if (k==1)
- kminus1 = 1;
- else
- kminus1 = k-1;
-
- /* k records the number of initial zeros in Ar[] (&& hence Br[] ). */
-
- for (j = Terms; j >= kminus1; j--)
- {
- /* Multiply Ar[] && Br[] by i */
- Ar[j] = (Ar[j]*i)+A;
- Br[j] = (Br[j]*i)+B;
- A = Ar[j] / Radix;
- Ar[j] = Ar[j]-(A*Radix);
- B = Br[j] / Radix;
- Br[j] = Br[j]-(B*Radix);
- } /* j*/;
-
- if (DRadix == 1){
- x = x+1;
- for (j=Terms; j <= kminus1+1; j--){
- Br[j] = Br[j-1];
- Ar[j] = Ar[j-1];
- }
- Br[kminus1] = 0;
- Ar[kminus1] = 0;
- }
- x = 10*(i+1);
- Fivex = 5*x;
- A = 0; B = 0;
- for (j = kminus1; j <=Terms; j++)
- {
- /* Divide Ar[] by x && Br[] by Fivex */
- y = (Ar[j]+A) / x;
- A = Radix*((Ar[j]+A)-(y*x));
- Ar[j] = y;
- y = (Br[j]+B) / Fivex;
- B = Radix*((Br[j]+B)-(Fivex*y));
- Br[j] = y;
- Sr[j] = Sr[j]+Ar[j]+Br[j];
- }/*j*/;
- if (Ar[k]==0){
- k++;}
- i += 2;
- }
- while (k != Terms+1);
- /* Calculation complete, perform conversion for listing */
- Sc = 0;
- for (j = Terms; j>=1; j--)
- {
- /* Normalise Sr */
- Sr[j] = Sr[j]+Sc;
- Sc = Sr[j] / Radix;
- Sr[j] = Sr[j]-(Sc*Radix);
- for (d = DRadix; d >= 1; d--)
- {
- St[j][d] = 48+ (Sr[j] % 10);
- if ((St[j][d]<48) || (St[j][d] >57))
- printf("Wrong program specification");
- Sr[j] = Sr[j] / 10;
- /* printf("%c",St[j][d]);*/
- } /*d*/
- } /*j*/
- Check( 1, 1); Check( 41, 6); Check( 81, 8);
- Check(121, 0); Check(161, 8); Check(201, 4);
- Check(241, 2); Check(281, 1); Check(321, 4);
- Check(361, 0); Check(401, 3); Check(441, 3);
- Check(481, 8); Check(521, 8); Check(561, 0);
- Check(601, 0); Check(641, 7); Check(681, 1);
- Check(721, 8); Check(761, 4); Check(801, 5);
- Check(841, 2); Check(881, 8); Check(921, 1);
- Check(961, 1);
- printf(" 3.");
- for (j = 2; j <= Terms;j++)
- {
- if ((Bits16 && (j % 4 == 2)) || !(Bits16))
- printf(" ");
- printf("%c%c%c%c",St[j][1],St[j][2],St[j][3],St[j][4]); /* printf(St[j,1]); for 16-bit version */
- if (((DRadix == 1) && (j % 40 == 1)) ||
- ((DRadix == 4) && (j % 10 == 0)))
- printf("\n");
- }
- printf("\n");
- printf("Last digits inaccurate: add about %5.0f \n",
- (0.78*Digits+0.0001*(Digits*Digits)) );
- end=clock();
- printf("The timing for this PI test, which tests integer calculation, was: %f\n", (end-start) / CLK_TCK);
- }
-