/*
* Computation of the n'th decimal digit of \pi with very little memory.
* Written by Fabrice Bellard on January 8, 1997.
*
* We use a slightly modified version of the method described by Simon
* Plouffe in "On the Computation of the n'th decimal digit of various
* transcendental numbers" (November 1996). We have modified the algorithm
* to get a running time of O(n^2) instead of O(n^3log(n)^3).
*
* This program uses mostly integer arithmetic. It may be slow on some
* hardwares where integer multiplications and divisons must be done
* by software. We have supposed that 'int' has a size of 32 bits. If
* your compiler supports 'long long' integers of 64 bits, you may use
* the integer version of 'mul_mod' (see HAS_LONG_LONG).
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
/* uncomment the following line to use 'long long' integers */
/* #define HAS_LONG_LONG */
#ifdef HAS_LONG_LONG
#define mul_mod(a,b,m) (( (long long) (a) * (long long) (b) ) % (m))
#else
#define mul_mod(a,b,m) fmod( (double) a * (double) b, m)
#endif
/* return the inverse of x mod y */
int inv_mod(int x, int y)
{
int q, u, v, a, c, t;
u = x;
v = y;
c = 1;
a = 0;
do {
q = v / u;
t = c;
c = a - q * c;
a = t;
t = u;
u = v - q * u;
v = t;
} while (u != 0);
a = a % y;
if (a < 0)
a = y + a;
return a;
}
/* return (a^b) mod m */
int pow_mod(int a, int b, int m)
{
int r, aa;
r = 1;
aa = a;
while (1) {
if (b & 1)
r = mul_mod(r, aa, m);
b = b >> 1;
if (b == 0)
break;
aa = mul_mod(aa, aa, m);
}
return r;
}
/* return true if n is prime */
int is_prime(int n)
{
int r, i;
if ((n % 2) == 0)
return 0;
r = (int) (sqrt(n));
for (i = 3; i <= r; i += 2)
if ((n % i) == 0)
return 0;
return 1;
}
/* return the prime number immediatly after n */
int next_prime(int n)
{
do {
n++;
} while (!is_prime(n));
return n;
}
int main(int argc, char *argv[])
{
int av, a, vmax, N, n, num, den, k, kq, kq2, t, v, s, i;
double sum;
if (argc < 2 || (n = atoi(argv[1])) <= 0) {
printf("This program computes the n'th decimal digit of \\pi\n"
"usage: pi n , where n is the digit you want\n");
exit(1);
}
N = (int) ((n + 20) * log(10) / log(2));
sum = 0;
for (a = 3; a <= (2 * N); a = next_prime(a)) {
vmax = (int) (log(2 * N) / log(a));
av = 1;
for (i = 0; i < vmax; i++)
av = av * a;
s = 0;
num = 1;
den = 1;
v = 0;
kq = 1;
kq2 = 1;
for (k = 1; k <= N; k++) {
t = k;
if (kq >= a) {
do {
t = t / a;
v--;
} while ((t % a) == 0);
kq = 0;
}
kq++;
num = mul_mod(num, t, av);
t = (2 * k - 1);
if (kq2 >= a) {
if (kq2 == a) {
do {
t = t / a;
v++;
} while ((t % a) == 0);
}
kq2 -= a;
}
den = mul_mod(den, t, av);
kq2 += 2;
if (v > 0) {
t = inv_mod(den, av);
t = mul_mod(t, num, av);
t = mul_mod(t, k, av);
for (i = v; i < vmax; i++)
t = mul_mod(t, a, av);
s += t;
if (s >= av)
s -= av;
}
}
t = pow_mod(10, n - 1, av);
s = mul_mod(s, t, av);
sum = fmod(sum + (double) s / (double) av, 1.0);
}
printf("Decimal digits of pi at position %d: %09d\n", n,
(int) (sum * 1e9));
return 0;
}
LyoKICogQ29tcHV0YXRpb24gb2YgdGhlIG4ndGggZGVjaW1hbCBkaWdpdCBvZiBccGkgd2l0aCB2ZXJ5IGxpdHRsZSBtZW1vcnkuCiAqIFdyaXR0ZW4gYnkgRmFicmljZSBCZWxsYXJkIG9uIEphbnVhcnkgOCwgMTk5Ny4KICogCiAqIFdlIHVzZSBhIHNsaWdodGx5IG1vZGlmaWVkIHZlcnNpb24gb2YgdGhlIG1ldGhvZCBkZXNjcmliZWQgYnkgU2ltb24KICogUGxvdWZmZSBpbiAiT24gdGhlIENvbXB1dGF0aW9uIG9mIHRoZSBuJ3RoIGRlY2ltYWwgZGlnaXQgb2YgdmFyaW91cwogKiB0cmFuc2NlbmRlbnRhbCBudW1iZXJzIiAoTm92ZW1iZXIgMTk5NikuIFdlIGhhdmUgbW9kaWZpZWQgdGhlIGFsZ29yaXRobQogKiB0byBnZXQgYSBydW5uaW5nIHRpbWUgb2YgTyhuXjIpIGluc3RlYWQgb2YgTyhuXjNsb2cobileMykuCiAqIAogKiBUaGlzIHByb2dyYW0gdXNlcyBtb3N0bHkgaW50ZWdlciBhcml0aG1ldGljLiBJdCBtYXkgYmUgc2xvdyBvbiBzb21lCiAqIGhhcmR3YXJlcyB3aGVyZSBpbnRlZ2VyIG11bHRpcGxpY2F0aW9ucyBhbmQgZGl2aXNvbnMgbXVzdCBiZSBkb25lCiAqIGJ5IHNvZnR3YXJlLiBXZSBoYXZlIHN1cHBvc2VkIHRoYXQgJ2ludCcgaGFzIGEgc2l6ZSBvZiAzMiBiaXRzLiBJZgogKiB5b3VyIGNvbXBpbGVyIHN1cHBvcnRzICdsb25nIGxvbmcnIGludGVnZXJzIG9mIDY0IGJpdHMsIHlvdSBtYXkgdXNlCiAqIHRoZSBpbnRlZ2VyIHZlcnNpb24gb2YgJ211bF9tb2QnIChzZWUgSEFTX0xPTkdfTE9ORykuICAKICovCgojaW5jbHVkZSA8c3RkbGliLmg+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8bWF0aC5oPgoKLyogdW5jb21tZW50IHRoZSBmb2xsb3dpbmcgbGluZSB0byB1c2UgJ2xvbmcgbG9uZycgaW50ZWdlcnMgKi8KLyogI2RlZmluZSBIQVNfTE9OR19MT05HICovCgojaWZkZWYgSEFTX0xPTkdfTE9ORwojZGVmaW5lIG11bF9tb2QoYSxiLG0pICgoIChsb25nIGxvbmcpIChhKSAqIChsb25nIGxvbmcpIChiKSApICUgKG0pKQojZWxzZQojZGVmaW5lIG11bF9tb2QoYSxiLG0pIGZtb2QoIChkb3VibGUpIGEgKiAoZG91YmxlKSBiLCBtKQojZW5kaWYKCi8qIHJldHVybiB0aGUgaW52ZXJzZSBvZiB4IG1vZCB5ICovCmludCBpbnZfbW9kKGludCB4LCBpbnQgeSkKewogICAgaW50IHEsIHUsIHYsIGEsIGMsIHQ7CgogICAgdSA9IHg7CiAgICB2ID0geTsKICAgIGMgPSAxOwogICAgYSA9IDA7CiAgICBkbyB7CiAgICBxID0gdiAvIHU7CgogICAgdCA9IGM7CiAgICBjID0gYSAtIHEgKiBjOwogICAgYSA9IHQ7CgogICAgdCA9IHU7CiAgICB1ID0gdiAtIHEgKiB1OwogICAgdiA9IHQ7CiAgICB9IHdoaWxlICh1ICE9IDApOwogICAgYSA9IGEgJSB5OwogICAgaWYgKGEgPCAwKQogICAgYSA9IHkgKyBhOwogICAgcmV0dXJuIGE7Cn0KCi8qIHJldHVybiAoYV5iKSBtb2QgbSAqLwppbnQgcG93X21vZChpbnQgYSwgaW50IGIsIGludCBtKQp7CiAgICBpbnQgciwgYWE7CgogICAgciA9IDE7CiAgICBhYSA9IGE7CiAgICB3aGlsZSAoMSkgewogICAgaWYgKGIgJiAxKQogICAgICAgIHIgPSBtdWxfbW9kKHIsIGFhLCBtKTsKICAgIGIgPSBiID4+IDE7CiAgICBpZiAoYiA9PSAwKQogICAgICAgIGJyZWFrOwogICAgYWEgPSBtdWxfbW9kKGFhLCBhYSwgbSk7CiAgICB9CiAgICByZXR1cm4gcjsKfQoKLyogcmV0dXJuIHRydWUgaWYgbiBpcyBwcmltZSAqLwppbnQgaXNfcHJpbWUoaW50IG4pCnsKICAgIGludCByLCBpOwogICAgaWYgKChuICUgMikgPT0gMCkKICAgIHJldHVybiAwOwoKICAgIHIgPSAoaW50KSAoc3FydChuKSk7CiAgICBmb3IgKGkgPSAzOyBpIDw9IHI7IGkgKz0gMikKICAgIGlmICgobiAlIGkpID09IDApCiAgICAgICAgcmV0dXJuIDA7CiAgICByZXR1cm4gMTsKfQoKLyogcmV0dXJuIHRoZSBwcmltZSBudW1iZXIgaW1tZWRpYXRseSBhZnRlciBuICovCmludCBuZXh0X3ByaW1lKGludCBuKQp7CiAgICBkbyB7CiAgICBuKys7CiAgICB9IHdoaWxlICghaXNfcHJpbWUobikpOwogICAgcmV0dXJuIG47Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCnsKICAgIGludCBhdiwgYSwgdm1heCwgTiwgbiwgbnVtLCBkZW4sIGssIGtxLCBrcTIsIHQsIHYsIHMsIGk7CiAgICBkb3VibGUgc3VtOwoKICAgIGlmIChhcmdjIDwgMiB8fCAobiA9IGF0b2koYXJndlsxXSkpIDw9IDApIHsKICAgIHByaW50ZigiVGhpcyBwcm9ncmFtIGNvbXB1dGVzIHRoZSBuJ3RoIGRlY2ltYWwgZGlnaXQgb2YgXFxwaVxuIgogICAgICAgICAgICJ1c2FnZTogcGkgbiAsIHdoZXJlIG4gaXMgdGhlIGRpZ2l0IHlvdSB3YW50XG4iKTsKICAgIGV4aXQoMSk7CiAgICB9CgogICAgTiA9IChpbnQpICgobiArIDIwKSAqIGxvZygxMCkgLyBsb2coMikpOwoKICAgIHN1bSA9IDA7CgogICAgZm9yIChhID0gMzsgYSA8PSAoMiAqIE4pOyBhID0gbmV4dF9wcmltZShhKSkgewoKICAgIHZtYXggPSAoaW50KSAobG9nKDIgKiBOKSAvIGxvZyhhKSk7CiAgICBhdiA9IDE7CiAgICBmb3IgKGkgPSAwOyBpIDwgdm1heDsgaSsrKQogICAgICAgIGF2ID0gYXYgKiBhOwoKICAgIHMgPSAwOwogICAgbnVtID0gMTsKICAgIGRlbiA9IDE7CiAgICB2ID0gMDsKICAgIGtxID0gMTsKICAgIGtxMiA9IDE7CgogICAgZm9yIChrID0gMTsgayA8PSBOOyBrKyspIHsKCiAgICAgICAgdCA9IGs7CiAgICAgICAgaWYgKGtxID49IGEpIHsKICAgICAgICBkbyB7CiAgICAgICAgICAgIHQgPSB0IC8gYTsKICAgICAgICAgICAgdi0tOwogICAgICAgIH0gd2hpbGUgKCh0ICUgYSkgPT0gMCk7CiAgICAgICAga3EgPSAwOwogICAgICAgIH0KICAgICAgICBrcSsrOwogICAgICAgIG51bSA9IG11bF9tb2QobnVtLCB0LCBhdik7CgogICAgICAgIHQgPSAoMiAqIGsgLSAxKTsKICAgICAgICBpZiAoa3EyID49IGEpIHsKICAgICAgICBpZiAoa3EyID09IGEpIHsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICB0ID0gdCAvIGE7CiAgICAgICAgICAgIHYrKzsKICAgICAgICAgICAgfSB3aGlsZSAoKHQgJSBhKSA9PSAwKTsKICAgICAgICB9CiAgICAgICAga3EyIC09IGE7CiAgICAgICAgfQogICAgICAgIGRlbiA9IG11bF9tb2QoZGVuLCB0LCBhdik7CiAgICAgICAga3EyICs9IDI7CgogICAgICAgIGlmICh2ID4gMCkgewogICAgICAgIHQgPSBpbnZfbW9kKGRlbiwgYXYpOwogICAgICAgIHQgPSBtdWxfbW9kKHQsIG51bSwgYXYpOwogICAgICAgIHQgPSBtdWxfbW9kKHQsIGssIGF2KTsKICAgICAgICBmb3IgKGkgPSB2OyBpIDwgdm1heDsgaSsrKQogICAgICAgICAgICB0ID0gbXVsX21vZCh0LCBhLCBhdik7CiAgICAgICAgcyArPSB0OwogICAgICAgIGlmIChzID49IGF2KQogICAgICAgICAgICBzIC09IGF2OwogICAgICAgIH0KCiAgICB9CgogICAgdCA9IHBvd19tb2QoMTAsIG4gLSAxLCBhdik7CiAgICBzID0gbXVsX21vZChzLCB0LCBhdik7CiAgICBzdW0gPSBmbW9kKHN1bSArIChkb3VibGUpIHMgLyAoZG91YmxlKSBhdiwgMS4wKTsKICAgIH0KICAgIHByaW50ZigiRGVjaW1hbCBkaWdpdHMgb2YgcGkgYXQgcG9zaXRpb24gJWQ6ICUwOWRcbiIsIG4sCiAgICAgICAoaW50KSAoc3VtICogMWU5KSk7CiAgICByZXR1cm4gMDsKfQ==