import std.c.stdio;import std.c.stdlib;import std.c.time;const int LONG_TIME=4000;byte[] p;byte[] t;int q;int main(char[][] args){ int startime, endtime; int i; if (args.length == 2) { sscanf(&args[1][0],"%d",&q); } else { printf("Usage: pi [precision]\n"); exit(55); } if (q < 0) { printf("Precision was too low, running with precision of 0.\n"); q = 0; } if (q > LONG_TIME) { printf("Be prepared to wait a while...\n"); } // Compute one more digit than we display to compensate for rounding q++; p.length = q + 1; t.length = q + 1; /* compute pi */ std.c.time.time(&startime); arctan(2); arctan(3); mul4(); std.c.time.time(&endtime); // Return to the number of digits we want to display q--; /* print pi */ printf("pi = %d.",cast(int)(p[0])); for (i = 1; i <= q; i++) printf("%d",cast(int)(p)); printf("\n"); printf("%ld seconds to compute pi with a precision of %d digits.\n",endtime-startime,q); return 0;}void arctan(int s){ int n; t[0] = 1; div(s); /* t[] = 1/s */ add(); n = 1; do { mul(n); div(s * s); div(n += 2); if (((n-1) / 2) % 2 == 0) add(); else sub(); } while (!tiszero());}void add(){ int j; for (j = q; j >= 0; j--) { if (t[j] + p[j] > 9) { p[j] += t[j] - 10; p[j-1] += 1; } else p[j] += t[j]; }}void sub(){ int j; for (j = q; j >= 0; j--) if (p[j] < t[j]) { p[j] -= t[j] - 10; p[j-1] -= 1; } else p[j] -= t[j];}void mul(int multiplier){ int b; int i; int carry = 0, digit = 0; for (i = q; i >= 0; i--) { b = (t * multiplier + carry); carry = b / 10; digit = b - carry * 10; t = digit; }}/* t[] /= l */void div(int divisor){ int i, b; int quotient, remainder = 0; for (i = 0; i <= q; i++) { b = (10 * remainder + t); quotient = b / divisor; remainder = b - divisor * quotient; t = quotient; }}void div4(){ int i, c, d = 0; for (i = 0; i <= q; i++) { c = (10 * d + p) / 4; d = (10 * d + p) % 4; p = c; }}void mul4(){ int i, c, d; d = c = 0; for (i = q; i >= 0; i--) { d = (p * 4 + c) % 10; c = (p * 4 + c) / 10; p = d; }}int tiszero(){ int k; for (k = 0; k <= q; k++) if (t[k] != 0) return false; return true;}
Then I tested the original and modified program on two systems, on linux machine from my univ and my laptop running windows. Here are my results:
Linux 2.6.17-1.2142_FC4smp
Digital Mars D Compiler v0.168
dmd, no modifications: 50 seconds
dmd, modifications: 33 seconds
dmd flags: -release -inline -O
g++ (GCC) 4.0.2 20051125 (Red Hat 4.0.2-8)
g++, no modifications: 29 seconds
g++, modifications: 32 seconds
g++ flags: -O3
Windows XP SP2 Pro
Digital Mars D Compiler v0.168
dmd, no modifications: 20 seconds
dmd, modifications: 15 seconds
dmd flags: -release -inline -O
g++ (GCC) 3.4.2 (mingw-special)
g++, no modifications: 12 seconds
g++, modifications: 14 seconds
g++ flags: -O3
gdc (GCC) 3.4.2 (mingw-special) (gdc 0.19, using dmd 0.162)
gdc, no modifications: 12 seconds
gdc, modifications: 14 seconds
gdc flags: -frelease -finline -O3
I ran each test twice and took the better result. I used a windows build of the GCC D Compiler available from the following page: http://gdcwin.sourceforge.net/