yarkin

BBP

Jan 29th, 2013
1,061
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.58 KB | None | 0 0
  1. /* This program employs the recently discovered digit extraction scheme
  2. to produce hex digits of pi. This code is valid up to ic = 2^24 on
  3. systems with IEEE arithmetic. */
  4.  
  5. /* David H. Bailey 960429 */
  6.  
  7. #include < stdio.h >
  8. #include < math.h >
  9.  
  10. main()
  11. {
  12.     double pid, s1, s2, s3, s4;
  13.     double series (int m, int n);
  14.     void ihex (double x, int m, char c[]);
  15.     int ic = 1000000;
  16.     #define NHX 16
  17.     char chx[NHX];
  18.  
  19.     /* ic is the hex digit position -- output begins at position ic + 1. */
  20.  
  21.     s1 = series (1, ic);
  22.     s2 = series (4, ic);
  23.     s3 = series (5, ic);
  24.     s4 = series (6, ic);
  25.     pid = 4. * s1 - 2. * s2 - s3 - s4;
  26.     pid = pid - (int) pid + 1.;
  27.     ihex (pid, NHX, chx);
  28.     printf ("Pi hex digit computation\n");
  29.     printf ("position = %i + 1\n %20.15f\n %12.12s\n", ic, pid, chx);
  30. }
  31.  
  32. void ihex (double x, int nhx, char chx[])
  33.  
  34. /* This returns, in chx, the first nhx hex digits of the fraction of x.
  35. */
  36.  
  37. {
  38.     int i;
  39.     double y;
  40.     char hx[] = "0123456789ABCDEF";
  41.  
  42.     y = fabs (x);
  43.  
  44.     for (i = 0; i < nhx; i++){
  45.         y = 16. * (y - floor (y));
  46.         chx[i] = hx[(int) y];
  47.     }
  48. }
  49.  
  50. double series (int m, int ic)
  51.  
  52. /* This routine evaluates the series sum_k 16^(ic-k)/(8*k+m)
  53. using the modular exponentiation technique. */
  54.  
  55. {
  56.     int k;
  57.     double ak, eps, p, s, t;
  58.     double expm (double x, double y);
  59.     #define eps 1e-17
  60.  
  61.     s = 0.;
  62.  
  63.     /* Sum the series up to ic. */
  64.  
  65.     for (k = 0; k < ic; k++){
  66.         ak = 8 * k + m;
  67.         p = ic - k;
  68.         t = expm (p, ak);
  69.         s = s + t / ak;
  70.         s = s - (int) s;
  71.     }
  72.  
  73.     /* Compute a few terms where k >= ic. */
  74.  
  75.     for (k = ic; k <= ic + 100; k++){
  76.         ak = 8 * k + m;
  77.         t = pow (16., (double) (ic - k)) / ak;
  78.         if (t < eps) break;
  79.         s = s + t;
  80.         s = s - (int) s;
  81.     }
  82.     return s;
  83. }
  84.  
  85. double expm (double p, double ak)
  86.  
  87. /* expm = 16^p mod ak. This routine uses the left-to-right binary
  88. exponentiation scheme. It is valid for ak <= 2^24. */
  89.  
  90. {
  91.     int i, j;
  92.     double p1, pt, r;
  93.     #define ntp 25
  94.     static double tp[ntp];
  95.     static int tp1 = 0;
  96.  
  97.     /* If this is the first call to expm, fill the power of two table tp. */
  98.  
  99.     if (tp1 == 0) {
  100.         tp1 = 1;
  101.         tp[0] = 1.;
  102.  
  103.         for (i = 1; i < ntp; i++) tp[i] = 2. * tp[i-1];
  104.     }
  105.  
  106.     if (ak == 1.) return 0.;
  107.  
  108.     /* Find the greatest power of two less than or equal to p. */
  109.  
  110.     for (i = 0; i < ntp; i++) if (tp[i] > p) break;
  111.  
  112.     pt = tp[i-1];
  113.     p1 = p;
  114.     r = 1.;
  115.  
  116.     /* Perform binary exponentiation algorithm modulo ak. */
  117.  
  118.     for (j = 1; j <= i; j++){
  119.         if (p1 >= pt){
  120.             r = 16. * r;
  121.             r = r - (int) (r / ak) * ak;
  122.             p1 = p1 - pt;
  123.         }
  124.         pt = 0.5 * pt;
  125.         if (pt >= 1.){
  126.             r = r * r;
  127.             r = r - (int) (r / ak) * ak;
  128.         }
  129.     }
  130.  
  131.     return r;
  132. }
Advertisement
Add Comment
Please, Sign In to add comment