/* * C version of prime.f, a program to calculate 2^859433 - 1. * The algorithm is credited to Slowinski of CRI. * * compile with: * * cc prime.c -o prime -lm * * if FTIME is defined, ftime() is used to obtaining timing data. * otherwise, gettimeofday() is used. */ #include #include #include #include #ifdef FTIME #include #else #include #endif /* #define EXP 859433*/ /* will calculate 2^859433 - 1, the 33rd Mersenne prime */ /* #define EXP 216091 */ /* will calculate 2^216091 - 1, the 31st Mersenne prime */ #define EXP 132049 /* will calculate 2^132049 - 1, the 30th Mersenne prime */ main(argc, argv) int argc; char *argv[]; { #ifdef FTIME struct timeb tp0, tp1; #else struct timeval tp0, tp1; #endif double t, ftp0, ftp1; double c0 = 0, c1 = 0, c2 = 0; int n; int *a, *b, *c; int ddigit = 4; /* number decimal digits per part */ int vdig = (int)pow((double)10, (double)ddigit); /* decimal value of part */ int i, j, k, maxpart, mx; unsigned int size; char format[64]; n = EXP; if (argc == 2) /* command-line param for new n? */ n = (atoi(argv[1]) > 0) ? atoi(argv[1]) : EXP; printf("calculating 2^%d - 1\n", n); size = (n+1)*sizeof(int); printf ("allocating %d bytes for working arrays\n", 3*size); if ((a = (int *)malloc(size)) == NULL) { fprintf(stderr, "cannot allocate %d bytes for a\n", size); exit(1); } if ((b = (int *)malloc(size)) == NULL) { fprintf(stderr, "cannot allocate %d bytes for b\n", size); exit(1); } if ((c = (int *)malloc(size)) == NULL) { fprintf(stderr, "cannot allocate %d bytes for c\n", size); exit(1); } for (i = 1; i <= n; i++) { a[i] = 0; /* set results array to null */ b[i] = 2; /* load up multiplicand array with n 2s */ c[i] = 0; /* set carry array to null */ } a[1] = 1; /* set initial intermediate result to 1 */ mx = 1; #ifdef FTIME ftime(&tp0); #else gettimeofday (&tp0, (struct timezone *)NULL); #endif #pragma _CRI parallel shared(n, a, b, c, mx, vdig) private(i, j) for (j = 1; j <= n; j++) { #pragma _CRI taskloop vector for (i = 1; i <= mx; i++) { a[i] *= b[j]; } #pragma _CRI taskloop vector for (i = 2; i <= mx+1; i++) c[i] = a[i-1]/vdig; #pragma _CRI guard if (c[mx+1] > 0) mx++; #pragma _CRI endguard #pragma _CRI taskloop vector for (i = 1; i <= mx; i++) { a[i] = (a[i] % vdig) + c[i]; } } #pragma _CRI endparallel /* propogate carry through one last time */ j = 0; for (i = 1; i <= n; i++) { k = a[i] + j; a[i] = k % vdig; j = k/vdig; } #ifdef FTIME ftime(&tp1); ftp0 = (double)tp0.time+(double)tp0.millitm/(double)1000000; ftp1 = (double)tp1.time+(double)tp1.millitm/(double)1000000; #else gettimeofday (&tp1, (struct timezone *)NULL); ftp0 = (double)tp0.tv_sec+(double)tp0.tv_usec/(double)1000000; ftp1 = (double)tp1.tv_sec+(double)tp1.tv_usec/(double)1000000; #endif t = (ftp1-ftp0 == 0) ? 0.000001 : ftp1-ftp0; printf("wall time for main loop: %.5lf seconds\n", t); maxpart = 0; for (i = 0; i <= n; i++) if (a[i] != 0) maxpart = i; printf ("max parts used: %d (each part is %d decimal digits)\n", maxpart, ddigit); /* subtract one from answer and see if we match Slow's number */ a[1]--; if (a[1] < 0) { a[1] = vdig - 1; for (i = 2; i <= maxpart; i++) { a[i]--; if (a[i] < 0) a[i] = vdig - 1; else break; } } printf("result:\n"); sprintf(format, "%s%d%s", "%0", ddigit, "d"); j = 0; for (i = maxpart; i >= 1; i--) { printf (format, a[i]); j++; if (j % 15 == 0) printf ("\n"); } printf ("\n"); return (0); }