Пример #1
0
/*
 *      Calculate PI using the Borwein's Quartically Convergent Algorithm
 *
 *      Init :  U0 = sqrt(2)
 *              B0 = 0
 *              P0 = 2 + sqrt(2)
 *
 *      Iterate:
 *
 *
 *      U      =   0.5 * [ sqrt(U ) + 1 / sqrt(U ) ]
 *       k+1                     k              k
 *
 *
 *                  sqrt(U ) * [ 1 + B  ]
 *                        k           k
 *      B      =   -----------------------
 *       k+1             U   +   B
 *                        k       k
 *
 *
 *                  P  *  B    *  [ 1 + U    ]
 *                   k     k+1           k+1
 *      P      =   ----------------------------
 *       k+1               1   +   B
 *                                  k+1
 *
 *
 *      P      --->  PI
 *       k+1
 *
 */
MAPM	compute_PI(int places)
{
MAPM    t1, c0_5, u0, u1, b0, b1, p0, p1;
int     ct, nn, dplaces, dflag;


dplaces = places + 16;              // compute a few extra digits
				    // in the intermediate math

m_apm_cpp_precision(dplaces);       // tell C++ about our precision 

dflag = FALSE;
ct    = 0;

c0_5  = "0.5"; 

u0    = sqrt("2");                  // make sure we use the MAPM sqrt
b0    = 0;
p0    = 2 + u0;

while (TRUE)
  {
/*
 *      U      =   0.5 * [ sqrt(U ) + 1 / sqrt(U ) ]
 *       k+1                     k              k
 */
   
   t1 = sqrt(u0);
   u1 = c0_5 * (t1 + 1 / t1);


/*
 *                  sqrt(U ) * [ 1 + B  ]
 *                        k           k
 *      B      =   -----------------------
 *       k+1             U   +   B
 *                        k       k
 *
 */

   b1 = (t1 * (1 + b0)) / (u0 + b0);


/*
 *                  P  *  B    *  [ 1 + U    ]
 *                   k     k+1           k+1
 *      P      =   ----------------------------
 *       k+1               1   +   B
 *                                  k+1
 */

   p1 = (p0 * b1 * (1 + u1)) / (1 + b1);


   if (dflag)
     break;

   /*
    *   compute the difference from this 
    *   iteration to the last one.
    */

   t1 = p1 - p0;

   if (++ct >= 4)
     {
      /*
       *  if diff == 0, we're done.
       */

      if (t1 == 0)
        break;
     }

   /*
    *   if the exponent of the error term (small error like 2.47...E-65)
    *   is small enough, break out after the *next* p1 is calculated.
    *
    *   get the exponent of the error term, which will be negative.
    */

   nn = -(t1.exponent());

   /*
    *  normally, this wouldn't be here. it's nice in the demo though.
    */

   fprintf(stderr, "PI now known to %d digits of accuracy ... \n",(2 * nn));

   if ((4 * nn) >= dplaces)
     dflag = TRUE;


   /* set up for the next iteration        */
   /*                                      */
   /* also, keep the number of significant */
   /* digits from growing without bound    */

   b0 = b1.round(dplaces);
   u0 = u1.round(dplaces);
   p0 = p1.round(dplaces);
  }

/* round to the accuracy asked for */

return (p1.round(places));
}
Пример #2
0
void m_apm_cpp_precision_mt(int digits)
{
	m_apm_enter();
	m_apm_cpp_precision(digits);
	m_apm_leave();
}
Пример #3
0
MAPM	compute_PI_2(int places)
{
MAPM    t1, t2, c2, a0, a1, b0, b1;
int     kk, nn, dplaces, dflag;


dplaces = places + 16;               // compute a few extra digits 
				     // in the intermediate math 

m_apm_cpp_precision(dplaces);        // tell C++ our precision requirements

dflag = FALSE;
kk    = 0;

t1 = sqrt("2.0");                    // make sure we use the MAPM sqrt
a0 = 6 - 4 * t1;
b0 = t1 - 1;
c2 = 2;

while (TRUE)
  {
   t1 = b0.ipow(4);                  // t1 = b0 ^ 4
   t1 = sqrt(sqrt(1 - t1));          // t1 = root_4(1 - t1)
   t1 = t1.round(dplaces);

   b1 = (1 - t1) / (1 + t1);
   b1 = b1.round(dplaces);

   t2 = 1 + b1;
   t2 = t2.ipow(4);                  // t2 = (1 + b1) ^ 4
   t2 = t2.round(dplaces);

   t1 = c2.ipow(2 * kk + 3);         // t1 = 2 ^ (2*kk+3)

   a1 = a0 * t2 - t1 * b1 * (1 + b1 + b1 * b1);
   a1 = a1.round(dplaces);

   if (dflag)
     break;
   
   //  compute the difference from this 
   //  iteration to the last one.

   t1 = a1 - a0;

   if (kk >= 3)
     {
      //  if diff == 0, we're done.

      if (t1 == 0)
        break;
     }

   /*
    *   if the exponent of the error term (small error like 2.47...E-65)
    *   is small enough, break out after the *next* a1 is calculated.
    *
    *   get the exponent of the error term, which will be negative.
    */

   nn = -(t1.exponent());

   //  normally, this wouldn't be here. it's nice in the demo though.

   fprintf(stderr, "PI now known to %d digits of accuracy ... \n",(4 * nn));

   if ((15 * nn) >= dplaces)
     dflag = TRUE;

   //  set up for the next iteration

   b0 = b1;
   a0 = a1;
   kk++;
  }

//  round to the accuracy asked for after taking the reciprocal

t1 = 1 / a1;
return(t1.round(places));
}