従来ATAN方式のπ計算Cプログラム

    2002/12/20 日立製作所 & 早稲田大学 後 保範 ( Ushiro Yasunori )
--------------------------------------------------------------
//  Atan公式によるπ計算プログラム(N**2版、Cプログラム)
//                      2002/9/26  後 保範
//=================================================================C
//  Pi Value Computation Program by Atan Normal Method             C
//    Pi = M1*Atan(1/X1) + M2*Atan(1/X2) + M3*Atan(1/X3)           C
//    Atan(1/X) = 1/X - 1/(3*X**3) + 1/(5*X**5) - 1/(7*X**7) +..   C
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,  2002/09/09                      C
//        (Hitachi Ltd. and Waseda University)                     C
//=================================================================C
#include <stdio.h> 
#include <math.h>
#include <time.h>
// Global Define
#define ND   1000010
#define L10V 5
double X, P10, D10;
int M, N2, L10;
int IV[ND+1], IXD[ND+1];
int INO[5] = {2,3,3,4,4};    // π計算公式のAtanの個数 
// π計算用各公式の定数 (M,X)の組、最大4個(Atanの個数)
int IDATA[5][4][2] = { 16, 5, -4,239, 0,0, 0,0,
   48,18,  32, 57, -20,239,  0,0,      32,10, -4,239, -16,515,  0,0,
  176,57, 28,239, -48,682, 96,12943,  48,49, 128,57, -20,239, 48,110443};
//=================================================================C
//   IV = M*Atan(1/X) Computation by Normal Method                 C
//      IXD = 1/X**K                                               C
//-----------------------------------------------------------------C
//    Written by Yasunori Ushiro,  2002/09/08                      C
//        (Hitachi Ltd. and Waseda University)                     C
//=================================================================C
  void ATANV()     // M*Atan(1/X)の多数桁の値の計算
  { int    i, k, KOSU, LST, ISG;
    double X2, DX2, W, W1, W2, VK, DK, WK, WK1, WK2;
//  Initial Constant
      X2   = X*X ;
      DX2  = 1.0/X2 ;
      KOSU = N2*L10/(log(X2)/log(10.0));   // 多数桁に必要なAtanの項数
//  Initial Value Set
      for(i=2; i<=N2; i++)
       { IXD[i] = 0 ; }	   
      IXD[1] = M ;
//  Initial Computation, IV=IXD=M/X
      W2 = 0.0;
      for(i=1; i<=N2; i++) 
       { W  = IXD[i] + W2*P10 ;
         W1 = floor(W/X) ;
         W2 = W - W1*X ;
         IXD[i] = W1 ;
         IV[i]  = IV[i] + IXD[i] ; }    // IV = M/X + 前のAtanの計算値
//  Main Computation
      LST =  1 ;
      ISG = -1 ;
      for (k=1; k<=KOSU; k++)           //  計算項数だけ反復計算
       { W2  = 0.0 ;
         WK2 = 0.0 ;
         VK  = 2*k + 1 ;
         DK  = 1.0/VK ;
         for(i=LST; i<=N2; i++)          // 多数桁は1要素(int)
          { W      = IXD[i] + W2*P10 ;   // に10進5桁ごとに分けて記憶
            W1     = floor(W*DX2) ;      // floor: 切り捨てて整数値にする
            W2     = W - W1*X2 ;
            IXD[i] = W1 ;                // W1 = 多数桁のM/X**(2k+1)の値 
            WK     = W1 + WK2*P10 ;      // W1 = 旧W1/X**2 = 旧W1*DX2
            WK1    = floor(WK*DK) ;
            WK2    = WK - WK1*VK ;       // WK2 = 多数桁のW1/(2k+1) 	 
            IV[i]  = IV[i] + ISG*WK1 ; }
         if(IXD[LST] == 0) 
	      { LST = LST + 1;               // 無駄な計算を省くための処理
            if(IXD[LST] == 0)  LST = LST + 1;  }
         ISG = -ISG ;   } 
    }
//=================================================================C
  void NORMAL()       // 多数桁の各要素を10進5桁に収める。
  { int    i;
    double W, W1; 
// First Loop
      for(i=N2; i>=2; i--)
       { W       = IV[i] ;           // 10進5桁を超えたものは、一つ前の
         W1      = floor(W*D10) ;    // 要素に桁上げ処理をする。 
         IV[i-1] = IV[i-1] + W1 ;
         IV[i]   = W - W1*P10 ; }
// Second  Loop
      for(i=N2; i>=2; i--)           // 再度正確な桁揃え 
       { if(IV[i] >= P10)               // 10**5以上の要素の処理
          { IV[i]   = IV[i] - P10 ;
            IV[i-1] = IV[i-1] + 1 ; }
         if(IV[i] < 0)                  // 負要素の処理
          { IV[i]   = IV[i] + P10 ;
            IV[i-1] = IV[i-1] - 1 ;}
        }
   }
//===================================================================C           
// Main Program                                                      C
//===================================================================C
 void main()
 { int    i, k, ID, NN, N, IX, KETA, T1, T2, T3, T4, KEND;
   double TT3, TT4;
   char   FNAME[] = "AtanOrg?.txt" ;
   char   FID[]   = "12345"	;
   FILE   *FT1;
//   Constant Set
      L10 = L10V ;                 // L10 = 5
      P10 = pow(10.0, L10) ;       // P10 = 10**5
      D10 = 1.0/P10 ;              // D10 = 1/10**5
//   Parameter Read
      printf(" Type In ID, (ID=1,2,3,4,5) \n") ;
      printf(" 1;Machin, 2;Gauss, 3;Klingen., 4;Stoemer, 5;Takano \n") ;
      scanf("%d",&ID) ;           // 計算公式選択
      if(ID <= 0 || ID >= 6) ID = 1 ;
      printf(" Type In N (N=Number of Pi Decimal-Digits) \n") ;
      scanf("%d",&NN) ;           // 計算桁数入力 
      N = NN/L10 ;
      if(N >= ND-3) N = ND - 3 ;
      NN = N*L10 ;
      N2 = N + 3 ;                //  計算要素数を求める(誤差を考慮して) 
      printf(" ** Pi Computation Start ** \n",
             "  Number of Pi Decimal-Digits= %d \n",NN) ;
      T1 = clock(); 
//  Open Output File
      ID = ID - 1;
      FNAME[7] = FID[ID] ;
      FT1 = fopen(FNAME,"w") ;
//  Clear Pi Area
      for(i=1; i <= N2; i++) IV[i] = 0 ;
//  Pi Computation Start
      for(k=0; k < INO[ID]; k++)     //  Atanの個数だけ反復計算
       { T2 = clock() ;
         M  = IDATA[ID][k][0] ;      //  Set M
         X  = IDATA[ID][k][1] ;      //  Set X
         ATANV() ;                   //  IV = IV + M*Atan(1/X) ---> π   
         T3  = clock() ;
         TT3 = (double)(T3 - T2)/CLOCKS_PER_SEC ; 
         IX = X ;
         printf(" Atan(1/ %d ) Computation,  Time(s)= %f \n",IX,TT3) ;
       }
//  Output 
      NORMAL() ;             //  各要素を10進5桁の値にそろえる
      T4  = clock() ;
      TT4 = (double)(T4-T1)/CLOCKS_PER_SEC ;     // πの計算時間
      printf(" Pi Computation,  Time(s)= %f \n",TT4) ;		
      fprintf(FT1," Pi = 3. \n") ;
      for (k=2; k<=N2-2; k=k+16)      //  Output Pi Value
       { KEND = k+15 ;                //  80 Decimal in a Line
         if(KEND > N2-2) KEND = N2-2 ;
         KETA = (k-2)*L10 + 1 ;
         fprintf(FT1,"\n %8d",KETA) ;
         for (i=k; i<=KEND; i=i+2)
          { fprintf(FT1," %5.5d%5.5d",IV[i],IV[i+1]) ;  } 
       }
  }