Example #1
0
static int
ComputeClassicAGM(size_t Len, size_t MaxPasses)
{
  int Sign;
  size_t Pass;
  double Pow2;
  clock_t LoopTime,EndTime,StartTime;
  BigInt AGM_A, AGM_B, AGM_C, AGMWork;
  int Done; /* boolean */

  AGM_A = CreateBigInt(Len);
  AGM_B = CreateBigInt(Len);
  AGM_C = CreateBigInt(Len);
  AGMWork = OldRoot;

  StartTime = clock();
  Pow2 = 4.0;
  Pass = 0;

  if (!LoadData(AGM_A,AGM_B,AGM_C,NO_NUM,NO_NUM,NO_NUM,
                &StartTime,&Pow2,&Pass,Len,Cfg.PiFormulaToUse))
    {
     fprintf(stderr, "Init     : ");
     LoopTime = clock();
     SetNum(AGM_A,Len,BI_One,0);
     SetNum(AGM_C,Len,BI_OneHalf,0);
     ClassicSqrt(AGM_B,AGM_C,Len);
     SetNum(AGM_C,Len,BI_One,0);
     EndTime = clock();
     fprintf(stderr,"Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_B,AGM_C,NO_NUM,NO_NUM,NO_NUM,
                 ((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);
    }

/*
  DumpBigInt("AGM_A",AGM_A,Len);
  DumpBigInt("AGM_B",AGM_B,Len);
  DumpBigInt("AGM_C",AGM_C,Len);
*/

  Done=0;
  MaxPasses+=Pass;
  while ((!Done) && (Pass < MaxPasses))
    {
      fprintf(stderr, "Pass %4s: ", Num2Str(1<<(++Pass)));
      LoopTime = clock();

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part1");
      /* w = (a-b)/2 */
      Sign = Sub(AGMWork, AGM_A, AGM_B, Len);
      if (Sign) Negate(AGMWork,Len);
      DivBy(AGMWork,AGMWork, 2, Len);
      if (!Cfg.Macintosh) BackSpace(9);

      /* m = w*w */
      if (!Cfg.Macintosh) fprintf(stderr,"Sqr1");
      if (IsZero(AGMWork,Len/2)) Done=1;
      if (Done) ClearBigInt(AGMWork,Len);
      else FullMul(AGMWork, AGMWork, AGMWork, Len);
      if (!Cfg.Macintosh) BackSpace(4);

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part2");

      /* m = m* w^(J+1) */
      MulByFloat(AGMWork,Pow2,Len);
      Pow2 *= 2.0;

      /* c = c - m */
      if (Sign) Add(AGM_C, AGM_C, AGMWork, Len);
      else      Sub(AGM_C, AGM_C, AGMWork, Len);

      /* See if it's done */
      if (IsZero(AGMWork,Len-(Len/16))) Done=1;
      if (!Cfg.Macintosh) BackSpace(9);

      /* m = a*b */
      if (!Cfg.Macintosh) fprintf(stderr,"Sqr2");
      if (Pass==1) Copy(AGMWork,AGM_B,Len); /* first pass, AGM_A = 1.0 */
      else if (!Done)   /* If last iter, we can skip it. */
         FullMul(AGMWork, AGM_A, AGM_B, Len);

      /* a = (a+b)/2 */
      Add(AGM_A, AGM_A, AGM_B, Len);
      DivBy(AGM_A,AGM_A, 2, Len);
      if (!Cfg.Macintosh) BackSpace(4);

      /* b = sqrt(a*b) */
      if (!Done) /* Optimization */
          ClassicSqrt(AGM_B, AGMWork, Len);

      EndTime=clock();

/*
      DumpBigInt("AGM_A",AGM_A,Len);
      DumpBigInt("AGM_B",AGM_B,Len);
      DumpBigInt("AGM_C",AGM_C,Len);
*/
      DumpDebug("Pass %u took:", Pass);
      fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
      DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);

      if (TestKeyboard()) break;
     if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_B,AGM_C,NO_NUM,NO_NUM,NO_NUM,
                 ((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);
    }

  LoopTime=clock();
  if (Done)
    {
     fprintf(stderr,"Final    : ");
     if (!Cfg.Macintosh) fprintf(stderr,"Sqr");
     FullMul(AGM_A, AGM_A, AGM_A, Len);
     MulBy(AGM_A,AGM_A,4,Len);
     if (!Cfg.Macintosh) BackSpace(3);

     ClassicDivide(AGM_B, AGM_A, AGM_C,Len);
     EndTime=clock();
     fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     PrintFormattedPi("Classic AGM",((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC, AGM_B, Len);
     DeleteSaveFile();
    }
  else if (Pass >= FatalPasses)
       FatalError("The AGM didn't converge.\n");
  else SaveData(AGM_A,AGM_B,AGM_C,NO_NUM,NO_NUM,NO_NUM,
                ((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);

  fprintf(stderr,"\nTotal Execution time: %0.2f seconds.\n\n",((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC);
  if (!Done) DumpTimings(((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC);

  return (Done);
}
Example #2
0
/*
**      The AGM itself
**
** A[0]=1 B[0]=1/sqrt(2) Sum=1
**
** n=1..inf
** A[n] = (A[n-1] + B[n-1])/2
** B[n] = Sqrt(A[n-1]*B[n-1])
** C[n] = (A[n-1]-B[n-1])/2    or:
** C[n]^2 = A[n]^2 - B[n]^2    or:
** C[n]^2 = 4A[n+1]*C[n+1]
** Sum  = Sum - C[n]^2*(2^(n+1))
** PI[n] = 4A[n+1]^2 / Sum
**
** However, it's not implemented that way.  We can save a full
** sized multiplication (with two numbers) by rearranging it,
** and keeping the squares of the A and B.  Also, we can do the
** first pass a little differently since A and A^2 will both be 1.
**
** A[0]=1           A[0]^2=1
** B[0]=1/sqrt(2)   B[0]^2=0.5
**
** First pass:
**
** A[1]     = (A[0] + B[0])/2
** B[1]^2   = A[0]*B[0]  ; Since A[0]==1, B[1]^2=B[0]
** C[1]^2   = ((A[0]^2+B[0]^2)/2-B[1]^2)/2
**
** Remainging passes:
**
** C[n]     = (A[n-1]-B[n-1])/2; C[n] is actually temp usage of C[n]^2
** A[n]     = A[n-1] - C[n]
** C[n]^2   = C[n]*C[n]
** B[n]^2   = (A[n-1]^2+B[n-1]^2-4C[n]^2)/2
**
** Then the rest of the formula is done the same:
**
** A[n]^2   = C[n]^2 + B[n]^2
** B[n]     = sqrt(B[n]^2)
** Sum      = Sum - C[n]^2*(2^(n+1))
**
** It is an unusual arrangment, but they are all derived directly
** from the standard AGM formulas as given by Salamin.
**
*/
static int
ComputeFastAGM(size_t Len, size_t MaxPasses)
{
  int Sign;
  size_t Pass;
  double Pow2;
  clock_t LoopTime,EndTime,StartTime;
  BigInt AGM_A, AGM_B, AGM_Sum, AGM_C2;
  BigInt AGM_A2, AGM_B2; /* Squares */
  int Done; /* boolean */

  if ((Cfg.PiFormulaToUse != 2) && (Cfg.PiFormulaToUse != 3))
    FatalError("FastAGM was somehow called with pi formula %d\n",
               Cfg.PiFormulaToUse);

  if (!Cfg.Macintosh) fprintf(stderr,"Creating vars");
  AGM_A   = CreateBigInt(Len);
  AGM_A2  = CreateBigInt(Len);
  AGM_B   = CreateBigInt(Len);
  AGM_B2  = CreateBigInt(Len);
  AGM_C2  = CreateBigInt(Len);
  AGM_Sum = CreateBigInt(Len);
  if (!Cfg.Macintosh) BackSpace(13);

  Num1IsCached = Num2IsCached = 0;
  StartTime = clock();
  Pow2 = 4.0;
  Pass = 0;
  if (!LoadData(AGM_A,AGM_A2,AGM_B,AGM_B2,AGM_Sum,OldRoot,
    &StartTime,&Pow2,&Pass,Len,Cfg.PiFormulaToUse))
    {
     fprintf(stderr, "Init     : ");
     LoopTime = clock();
     Pow2 = 4.0;
     Pass = 0;

     if (Cfg.PiFormulaToUse==2)
       {
        if (!Cfg.Macintosh) fprintf(stderr,"Setting vars");
        SetNum(AGM_A,Len,  BI_One,0);
        SetNum(AGM_A2,Len, BI_One,0);
        SetNum(AGM_B2,Len, BI_OneHalf,0);
        SetNum(AGM_Sum,Len,BI_One,0);
        ClearBigInt(OldRoot,Len);
        if (!Cfg.Macintosh) BackSpace(12);
        Sqrt05(AGM_B,Len);
        if ((Cfg.AGMSelfCheck == 3) || (Cfg.AGMSelfCheck == 4))
          {
         /* We can use OldRoot and DSWork as scratch. */
           if (!Cfg.Macintosh) fprintf(stderr,"Self Check");
           SpecialSquare(OldRoot,AGM_B,Len,DSWork);
           DoCheck(OldRoot,AGM_B2,0,Len);
           ClearBigInt(OldRoot,Len);
           if (!Cfg.Macintosh) BackSpace(10);
          }
       }
     else
       {
        Sqrt20(AGM_A,Len);
        Sqrt60(AGM_A2,Len);
        if (!Cfg.Macintosh) fprintf(stderr,"Square");
        Add(AGM_B,AGM_A,AGM_A2,Len);
        DivBy(AGM_B,AGM_B,4,Len);
        SpecialSquare(AGM_B2,AGM_B,Len,AGM_A);
        if (!Cfg.Macintosh) BackSpace(6);
        if (!Cfg.Macintosh) fprintf(stderr,"Setting vars");
        ClearBigInt(OldRoot,Len);
        SetNum(AGM_A,Len,  BI_One,0);
        SetNum(AGM_A2,Len, BI_One,0);
        SetNum(AGM_Sum,Len,BI_One,0);
        if (!Cfg.Macintosh) BackSpace(12);
        Pass=1;
       }

     EndTime = clock();
     fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_A2,AGM_B,AGM_B2,AGM_Sum,OldRoot,
                 ((double)EndTime-(double)StartTime)/CLOCKS_PER_SEC,
	  Pow2,Pass,Len,Cfg.PiFormulaToUse);
    }

/*
  DumpBigInt("AGM_A  ",AGM_A,Len);
  DumpBigInt("AGM_A2 ",AGM_A2,Len);
  DumpBigInt("AGM_B  ",AGM_B,Len);
  DumpBigInt("AGM_B2 ",AGM_B2,Len);
  DumpBigInt("AGM_C2 ",AGM_C2,Len);
  DumpBigInt("AGM_Sum",AGM_Sum,Len);
*/

  Done=0;
  MaxPasses+=Pass;
  while ((!Done) && (Pass < MaxPasses))
    {size_t FNZ;
     int Key=0;
/* DJGPP stuff to test the self checking.
** Comment out the keyboard break statement at the end of the loop.
     extern int getkey(void);
     if (TestKeyboard()) {Key=getkey();srand((unsigned int)time(NULL));}
*/

      fprintf(stderr, "Pass %4s: ", Num2Str(2<<(++Pass)));
      LoopTime = clock();

      if ((Pass==1) &&
          (strcmp(GetCheckStr(AGM_A),"1000000000000000")==0))
        {
/*
** Since AGM_A==1, we can do the first pass a little differently
** and avoide the multiplication completely.
*/
         if (!Cfg.Macintosh) fprintf(stderr,"AGM Part1");

         /* Compute a=(a+b)/2 */
         if (Key=='1') CorruptVar(AGM_A,Len);
         Add(AGM_A, AGM_A, AGM_B, Len);DivBy(AGM_A,AGM_A, 2, Len);
         if (Cfg.AGMSelfCheck >= 1)
           {
            DivBy(DSWork,AGM_B,2,Len);AddInt(DSWork,BI_OneHalf);
            DoCheck(DSWork,AGM_A,1,Len);
           }

         /* Compute C^2 and B^2 */
         Add(AGM_C2,AGM_A2,AGM_B2,Len);DivBy(AGM_C2,AGM_C2,2,Len);
         if (Cfg.AGMSelfCheck >= 1) Add(DSWork,AGM_A2,AGM_B2,Len);
         Copy(AGM_B2,AGM_B,Len); /* AGM_A == 1.0, so we can copy */
         Sign=Sub(AGM_C2,AGM_C2,AGM_B2,Len);DivBy(AGM_C2,AGM_C2,2,Len);
         if (Key=='4') CorruptVar(AGM_B2,Len);
         if (Key=='5') CorruptVar(AGM_C2,Len);
         if (Sign) FatalError("AGM_C2 should never be negative.\n");
         if (!Cfg.Macintosh) BackSpace(9);
        }
      else
        {
         if (!Cfg.Macintosh) fprintf(stderr,"AGM Part1");

         /* Compute C */
/*
         Sign=Sub(AGM_C2, AGM_A, AGM_B, Len);DivBy(AGM_C2,AGM_C2,2,Len);
*/
         Sign=HalfDiff(AGM_C2,AGM_A,AGM_B,Len);
         if (Sign) FatalError("AGM_C2 should never be negative.\n");

         /* Compute A.  AGM_C2 is still only C at the moment. */
         if (Cfg.AGMSelfCheck >= 1)
           {Add(DSWork,AGM_A,AGM_B,Len);DivBy(DSWork,DSWork,2,Len);}
         if (Sub(AGM_A,AGM_A,AGM_C2,Len))
            FatalError("AGM_A should never be negative.\n");
         if (Key=='1') CorruptVar(AGM_A,Len);
         if (Cfg.AGMSelfCheck >= 1) DoCheck(DSWork,AGM_A,2,Len);

         if (!Cfg.Macintosh) BackSpace(9);
         if (!Cfg.Macintosh) fprintf(stderr,"Sqr");
         /* Compute C^2 */
         SpecialSquare(AGM_C2,AGM_C2,Len,AGM_B);
         if (Key=='5') CorruptVar(AGM_C2,Len);
         if (!Cfg.Macintosh) BackSpace(3);

         if (!Cfg.Macintosh) fprintf(stderr,"AGM Part2");
         if (Cfg.AGMSelfCheck >= 1) Add(DSWork,AGM_A2,AGM_B2,Len);
         /* Compute B^2 */
         Sign=SpecialAGMFunc1(AGM_B2,AGM_A2,AGM_C2,Len);
         if (Key=='4') CorruptVar(AGM_B2,Len);
/*
         Add(AGM_B2,AGM_B2,AGM_A2,Len);
         MulBy(AGM_A2,AGM_C2,4,Len);
         Sign=Sub(AGM_B2,AGM_B2,AGM_A2,Len);
         DivBy(AGM_B2,AGM_B2,2,Len);
*/

         if (Sign) FatalError("AGM_B2 should never be negative.\n");
         if (!Cfg.Macintosh) BackSpace(9);
        }

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part3");
      /* Compute A^2 */
      if (Cfg.AGMSelfCheck >= 1)
        {
         Add(DSWork,DSWork,AGM_B2,Len);
         Add(DSWork,DSWork,AGM_B2,Len);
         DivBy(DSWork,DSWork,4,Len);
        }
      Add(AGM_A2,AGM_C2,AGM_B2,Len);
      if (Key=='2') CorruptVar(AGM_A2,Len);
      if (Cfg.AGMSelfCheck >= 1) DoCheck(DSWork,AGM_A2,3,Len);
      if (!Cfg.Macintosh) BackSpace(9);

/*
** Do some self checking.  The estimate formula predicts the number of
** leading zeros.  It's based on the regular AGM accuracy formula.  It
** predicts just a couple of digits less than what is actually there,
** so if anything happens, this should fail.  But, since it is so
** close, it just might fail for the wrong reason.
*/
      if (!Cfg.Macintosh) fprintf(stderr,"Self Check");
      FNZ=FindFirstNonZero(AGM_C2,Len);
      if ((Pass > 3) && (FNZ != Len))
        {size_t P=Pass-2;size_t Est;
         /* formula based on the AGM 'number of digits right' formula */
         if (Cfg.PiFormulaToUse==2)
            Est=(1.364376354*(1<<(P))-P*.301029995-2.342434419)/2;
         else /* other agm does 1 less pass, so pass is one higher, so div by 4 */
            Est=(sqrt(3.0)*1.364376354*(1<<(P))-P*.301029995-2.690531961)/4;

         if (Est >= FNZ)
           {
            fprintf(stderr,"\aAGM self check fails.  Predicted: %lu Actual: %lu\n",
                    (ULINT)Est,(ULINT)FNZ);
            fprintf(stderr,"Beyond what I've tested, this may not be an actual failure\n");
            fprintf(stderr,"but an inaccuracy in the self check formula itself.\n");
           }
        }

      /* See if it's done.  (ie: more than half zeros) */
      if (FNZ > Len/2+4) Done=1;

      if ((Cfg.AGMSelfCheck == 2) || (Cfg.AGMSelfCheck == 4))
        {
      /* We can use AGM_B and DSWork as scratch. */
         SpecialSquare(AGM_B,AGM_A,Len,DSWork);
         DoCheck(AGM_B,AGM_A2,4,Len);
        }
      if (!Cfg.Macintosh) BackSpace(10);

      /* Compute B=sqrt(B^2) */
      if (!Done)
        AGMSqrt(AGM_B, AGM_B2, Len,  (Pass>5) ? (2<<(Pass-5)) : 0);
      if (Key=='3') CorruptVar(AGM_B,Len);

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part4");
      /* Sum = Sum - C2 * 2^(J+1) */
      MulByFloat(AGM_C2,Pow2,Len);Pow2 *= 2.0;
      if (Sub(AGM_Sum,AGM_Sum,AGM_C2,Len))
        FatalError("AGM_Sum should never be negative.\n");

      EndTime=clock();
/*
      DumpBigInt("AGM_A  ",AGM_A,Len);
      DumpBigInt("AGM_A2 ",AGM_A2,Len);
      DumpBigInt("AGM_B  ",AGM_B,Len);
      DumpBigInt("AGM_B2 ",AGM_B2,Len);
      DumpBigInt("AGM_C2 ",AGM_C2,Len);
      DumpBigInt("AGM_Sum",AGM_Sum,Len);
*/

      if (!Cfg.Macintosh) BackSpace(9);
      if (!Done && ((Cfg.AGMSelfCheck == 3) || (Cfg.AGMSelfCheck == 4)))
        {
      /* We can use AGM_C2 and DSWork as scratch. */
         if (!Cfg.Macintosh) fprintf(stderr,"Self Check");
         SpecialSquare(AGM_C2,AGM_B,Len,DSWork);
         DoCheck(AGM_C2,AGM_B2,5,Len);
         if (!Cfg.Macintosh) BackSpace(10);
        }

      DumpDebug("Pass %u took:", Pass);
      fprintf(stderr,"Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
      DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);

      if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_A2,AGM_B,AGM_B2,AGM_Sum,OldRoot,
                 ((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);
      if (TestKeyboard()) break;
    }


/* We've done the AGM part, now do the final calculation. */
  LoopTime=clock();
  if (Done)
    {
     fprintf(stderr, "Final    : ");
/*
** Since AGM_A and AGM_B have converged, I can compute the AGM_A2
** by calculating AGM_B2.  That can be done like up above, except
** we don't need the 4*AGM_C2 because that will be zero.
*/
     if (!Cfg.Macintosh) fprintf(stderr,"Part 1");
     Add(AGM_B2,AGM_B2,AGM_A2,Len);
     MulBy(AGM_B2,AGM_B2,2,Len);
     if (!Cfg.Macintosh) BackSpace(6);

     if (Cfg.PiFormulaToUse==3)
       {
        if (!Cfg.Macintosh) fprintf(stderr,"Part 2");
        if (!Cfg.Macintosh) BackSpace(6);
        Sqrt30(AGM_A2,Len);
        if (!Cfg.Macintosh) fprintf(stderr,"Part 3");
        SpecialFullMul(AGM_A,AGM_Sum,AGM_A2,Len,AGM_B);
        SubInt(AGM_A, BI_OneHalf);
        Copy(AGM_Sum,AGM_A,Len);
        if (!Cfg.Macintosh) BackSpace(6);
       }

     AGMDivide(AGM_B, AGM_B2, AGM_Sum, Len, AGM_A2);

     EndTime=clock();
     fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);

     if (Cfg.PiFormulaToUse==2)
        PrintFormattedPi("Fast 1/sqrt(2) AGM",((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC, AGM_B, Len);
     else
        PrintFormattedPi("Fast sqrt(3) AGM",((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC, AGM_B, Len);

     DeleteSaveFile();
    }
  else if (Pass >= FatalPasses)
       FatalError("The AGM didn't converge.\n");
  else SaveData(AGM_A,AGM_A2,AGM_B,AGM_B2,AGM_Sum,OldRoot,
                ((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);

  fprintf(stderr,"\nTotal Execution time: %0.2f\n\n",((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC);
  if (!Done) DumpTimings(((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC);

  return (Done);
}
Example #3
0
/*
*****************************************************
**      The AGM itself                             **
**                                                 **
** A[n] = (A[n-1] + B[n-1])/2                      **
** B[n] = Sqrt(A[n-1]*B[n-1])                      **
** C[n] = (A[n-1]-B[n-1])/2                        **
**                                                 **
**                          n                      **
** PI[n] = 4A[n+1]^2 / (1-(Sum (2^(j+1))*C[j]^2))  **
**                        j = 1                    **
*****************************************************
*/
static int
ComputeSlowAGM(size_t Len, size_t MaxPasses)
{
  int Sign;
  size_t Pass;
  double Pow2;
  clock_t LoopTime,StartTime,EndTime;
  BigInt AGM_A, AGM_B, AGM_C, AGMWork;
  int Done; /* boolean */

  if ((Cfg.PiFormulaToUse != 2) && (Cfg.PiFormulaToUse != 3))
    FatalError("SlowAGM was somehow called with pi formula %d\n",
               Cfg.PiFormulaToUse);

  AGM_A = CreateBigInt(Len);
  AGM_B = CreateBigInt(Len);
  AGM_C = CreateBigInt(Len);
  AGMWork = CreateBigInt(Len);

  Num1IsCached = Num2IsCached = 0;
  StartTime = clock();
  Pow2 = 4.0;
  Pass = 0;

  if (!LoadData(AGM_A,AGM_B,AGM_C,OldRoot,NO_NUM,NO_NUM,
                &StartTime,&Pow2,&Pass,Len,Cfg.PiFormulaToUse))
    {
     LoopTime = clock();
     fprintf(stderr, "Init     : ");

     if (Cfg.PiFormulaToUse==2)
       {
        SetNum(AGM_A,Len,BI_One,0);
        SetNum(AGM_C,Len,BI_One,0);
        ClearBigInt(OldRoot,Len);
        Sqrt05(AGM_B,Len);
       }
     else
       {
        Sqrt20(AGM_A,Len);
        Sqrt60(AGM_C,Len);
        if (!Cfg.Macintosh) fprintf(stderr,"Square");
        Add(AGM_B,AGM_A,AGM_C,Len);
        DivBy(AGM_B,AGM_B,4,Len);
        if (!Cfg.Macintosh) BackSpace(6);
        if (!Cfg.Macintosh) fprintf(stderr,"Setting vars");
        ClearBigInt(OldRoot,Len);
        SetNum(AGM_A,Len,BI_One,0);
        SetNum(AGM_C,Len,BI_One,0);
        if (!Cfg.Macintosh) BackSpace(12);
        Pass=1;
       }

     EndTime = clock();
     fprintf(stderr,"Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_B,AGM_C,OldRoot,NO_NUM,NO_NUM,
                 ((double)EndTime-(double)StartTime)
     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);
    }

/*
  DumpBigInt("AGM_A",AGM_A,Len);
  DumpBigInt("AGM_B",AGM_B,Len);
  DumpBigInt("AGM_C",AGM_C,Len);
*/

  Done=0;
  MaxPasses+=Pass;
  while ((!Done) && (Pass < MaxPasses))
    {
      fprintf(stderr, "Pass %4s: ", Num2Str(1<<(++Pass)));
      LoopTime = clock();

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part1");
      /* w = (a-b)/2 */
      Sign = Sub(AGMWork, AGM_A, AGM_B, Len);
      if (Sign) Negate(AGMWork,Len);
      DivBy(AGMWork,AGMWork, 2, Len);

      {size_t Nz;
       Nz=FindFirstNonZero(AGMWork,Len);
       if ((Pass > 4) && (Nz != Len))
         if ((1<<(Pass-4)) > Nz)
           fprintf(stderr,"AGMCheck1 fails.  Predicted: %lu Actual: %lu\a\n",
                   (unsigned long)1<<(Pass-4),(ULINT)Nz);
      }
      if (!Cfg.Macintosh) BackSpace(9);

      /* m = w*w */
      if (!Cfg.Macintosh) fprintf(stderr,"Sqr1");
      if (IsZero(AGMWork,Len/2)) Done=1;
      if (Done) ClearBigInt(AGMWork,Len);
      else FullMul(AGMWork, AGMWork, AGMWork, Len);
      if (!Cfg.Macintosh) BackSpace(4);

      if (!Cfg.Macintosh) fprintf(stderr,"AGM Part2");
      {size_t Nz;
      Nz=FindFirstNonZero(AGMWork,Len);
      if ((Pass > 3) && (Nz != Len))
        if ((1<<(Pass-3)) > Nz)
          fprintf(stderr,"AGMCheck2 fails.  Predicted: %lu Actual: %lu\a\n",
                  (unsigned long)1<<(Pass-3),(ULINT)Nz);
      }

      /* m = m* w^(J+1) */
      MulByFloat(AGMWork,Pow2,Len);
      Pow2 *= 2.0;

      /* c = c - m */
      if (Sign) Add(AGM_C, AGM_C, AGMWork, Len);
      else      Sub(AGM_C, AGM_C, AGMWork, Len);

      /* See if it's done */
      if (IsZero(AGMWork,Len-(Len/16))) Done=1;
      if (!Cfg.Macintosh) BackSpace(9);

      /* m = a*b */
      if (!Cfg.Macintosh) fprintf(stderr,"Sqr2");
      if (Pass==1) Copy(AGMWork,AGM_B,Len); /* first pass, AGM_A = 1.0 */
      else if (!Done)   /* If last iter, we can skip it. */
         FullMul(AGMWork, AGM_A, AGM_B, Len);
      if (!Cfg.Macintosh) BackSpace(4);

      /* a = (a+b)/2 */
      Add(AGM_A, AGM_A, AGM_B, Len);
      DivBy(AGM_A,AGM_A, 2, Len);

      /* b = sqrt(a*b) */
      if (!Done) /* Optimization */
          AGMSqrt(AGM_B, AGMWork, Len, (Pass>5) ? (2<<(Pass-5)) : 0 );

      EndTime=clock();

/*
      DumpBigInt("AGM_A",AGM_A,Len);
      DumpBigInt("AGM_B",AGM_B,Len);
      DumpBigInt("AGM_C",AGM_C,Len);
*/
      DumpDebug("Pass %u took:", Pass);
      fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
     /CLOCKS_PER_SEC);
      DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);

      if (TestKeyboard()) break;
     if (Cfg.AlwaysSaveData)
        SaveData(AGM_A,AGM_B,AGM_C,OldRoot,NO_NUM,NO_NUM,
                 ((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);
    }

  LoopTime=clock();
  if (Done)
    {
     fprintf(stderr,"Final    : ");
     if (!Cfg.Macintosh) fprintf(stderr,"Sqr");
     SpecialSquare(AGM_A, AGM_A, Len, AGMWork);
     MulBy(AGM_A,AGM_A,4,Len);
     if (!Cfg.Macintosh) BackSpace(3);

     if (Cfg.PiFormulaToUse==3)
       {
        Sqrt30(AGM_B,Len);
        if (!Cfg.Macintosh) fprintf(stderr,"Part 2");
        FullMul(AGM_C,AGM_C,AGM_B,Len);
        SubInt(AGM_C, BI_OneHalf);
        if (!Cfg.Macintosh) BackSpace(6);
       }

     AGMDivide(AGM_B, AGM_A, AGM_C, Len, AGMWork);
     EndTime=clock();
     fprintf(stderr, "Time= %0.2f\n", ((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     DumpTimings(((double)EndTime-(double)LoopTime)
	     /CLOCKS_PER_SEC);
     if (Cfg.PiFormulaToUse==2)
        PrintFormattedPi("Slow 1/sqrt(2) AGM",((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC, AGM_B, Len);
     else
        PrintFormattedPi("Slow sqrt(3) AGM",((double)EndTime-(double)StartTime)
	     /CLOCKS_PER_SEC, AGM_B, Len);
     DeleteSaveFile();
    }
  else if (Pass >= FatalPasses)
       FatalError("The AGM didn't converge.\n");
  else SaveData(AGM_A,AGM_B,AGM_C,OldRoot,NO_NUM,NO_NUM,
                ((double)clock()-(double)StartTime)
	     /CLOCKS_PER_SEC,Pow2,Pass,Len,Cfg.PiFormulaToUse);

  fprintf(stderr,"\nTotal Execution time: %0.2f seconds.\n\n",((double)clock()-(double)LoopTime)
	     /CLOCKS_PER_SEC);
  if (!Done) DumpTimings(((double)clock()-(double)LoopTime)
	     /CLOCKS_PER_SEC);

  return (Done);
}
Example #4
0
void CRMmainLoop::RunMessageLoop()
{
	MSG msg;
	UINT fps = 0;
	HRESULT hr = S_FALSE;

	ZeroMemory( &msg, sizeof(msg) ); //msg 초기화 함수
	//===================================================================
	// 음악 데이터를 불러온다.
	// 음악 데이터를 vector 형식으로 리스팅
	FindMusicData();

	//===================================================================
	// fmod 사용하기 fmodex.dll파일이 필요하다.
	hr = CRMsound::GetInstance()->CreateSound();
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_INIT, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}

	//sound를 불러와서 묶어 놓고 있는 상태
	//동영상 플레이 이후 별로의 로딩화면이 없는 상태이기 때문에 미리 로딩하는 개념
	hr = CRMsound::GetInstance()->LoadSound( BGM_TITLE, SOUND_BG_TITLE );
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_LOADING, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}
	hr = CRMsound::GetInstance()->LoadSound( SE_PAUSE_CANCEL, SOUND_EFFECT_PAUSE_CANCEL );
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_LOADING, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}

	hr = CRMsound::GetInstance()->LoadSound( SE_PAUSE_FLIP, SOUND_EFFECT_PAUSE_FLIP );
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_LOADING, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}

	hr = CRMsound::GetInstance()->LoadSound( SE_PAUSE_OK, SOUND_EFFECT_PAUSE_OK );
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_LOADING, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}

	hr = CRMsound::GetInstance()->LoadSound( SE_PAUSE_OPEN, SOUND_EFFECT_PAUSE_OPEN );
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_SOUND_LOADING, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}
	//===================================================================
	// 동영상 출력 부분
	hr = CRMvideoPlayer::GetInstance()->CreateFactory();
	
	if ( hr == S_OK )
	{
		CRMvideoPlayer::GetInstance()->StartVideo();
	}
	else
	{
		hr = GoNextScene();
		// 동영상 재생을 위한 초기화에 실패 했을 경우 동영상 재생 패스
		if ( hr != S_OK )
		{
			MessageBox( NULL, ERROR_CHANGE_SCENE, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
			return;
		}
	}

	hr = CreateObject();
	if ( hr != S_OK )
	{
		MessageBox( NULL, ERROR_CREATE_RESOURCE, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
		return;
	}
	// 오브젝트 생성 부분을 리팩토링

	
	while ( true )
	{
		if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) // PeekMessage는 대기 없이 무한 루프 상태로 진행(non blocked function)
		{
			if ( msg.message == WM_QUIT )
			{
				CRMvideoPlayer::GetInstance()->DestoryFactory();
				return;
			}
			TranslateMessage(&msg);
			DispatchMessage(&msg);	// Wndproc과 연결되어 있음
		}
		else
		{
			if ( m_SceneType == SCENE_OPENING )
			{
				CRMvideoPlayer::GetInstance()->RenderVideo();

				CRMinput::GetInstance()->UpdateKeyState();
				if ( CRMinput::GetInstance()->GetKeyStatusByKey( KEY_TABLE_RETURN ) == KEY_STATUS_UP )
				{
					CRMvideoPlayer::GetInstance()->DestoryFactory();
					hr = GoNextScene();

					if ( hr != S_OK )
					{
						MessageBox( NULL, ERROR_CHANGE_SCENE, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
						return;
					}
				}
				continue;
			}
#ifdef _DEBUG
			m_NowTime = timeGetTime();

			if ( m_PrevTime == 0 )
			{
				m_PrevTime = m_NowTime;
			}

			// FPS 출력용 계산
			if( ( m_NowTime - m_FpsCheckTime ) > 1000 )
			{
			//	printConsole("FPS : %d \n", fps);

				CRMlabel*		testLabel = new CRMlabel();
				std::wstring	testString;
				testString.append(L"FPS : ");
				testString.append( std::to_wstring(fps) );

				testLabel->CreateLabel(LABEL_FPS, testString, LABEL_FONT_NORMAL, 15.0F );
				testLabel->SetRGBA( 1.0f, 1.0f, 1.0f, 1.f );
				testLabel->SetSceneType( SCENE_PLAY );
				testLabel->SetPosition( 20, 20 );

				m_FpsCheckTime = m_NowTime;
				fps = 0;
			}

			m_ElapsedTime = m_NowTime - m_PrevTime;

			if( m_ElapsedTime == m_Fps )
			{
#endif		
				// 처리 해야 할 내부 로직들을 처리함
				// Update

				if ( GetActiveWindow() == NULL && GetNowScene() == SCENE_PLAY)
				{
					CRMpauseManager::GetInstance()->ShowPause();
				}
				CRMobjectManager::GetInstance()->Update();
				
				// {} 로 스택을 활용하여 더미클래스의 생성자, 소멸자를 호출
				{
					CRMdummyRender dummyRender;
					// 생성자
					// CRMrender::GetInstance()->RenderInit();

					CRMobjectManager::GetInstance()->Render();
					// 화면에 대한 처리를 진행
					// Render
				}
				// 소멸자
				// CRMrender::GetInstance()->RenderEnd();

				m_PrevTime = m_NowTime;
#ifdef _DEBUG
				++fps;
			}
#endif // _DEBUG

			//////////////////////////////////////////////////////////////////////////
			// 소리 밀림 방지를 위해 FPS = 60에 맞추던 부분에서 빼옴
			//////////////////////////////////////////////////////////////////////////
			CRMinput::GetInstance()->UpdateKeyState();

			// test sound
			TestSound();
			
			// test Key
			hr = TestKeyboard();
			if ( hr != S_OK )
			{
				MessageBox( NULL, ERROR_CHANGE_SCENE, ERROR_TITLE_NORMAL, MB_OK | MB_ICONSTOP );
				return;
			}


			//////////////////////////////////////////////////////////////////////////
			// 씬 관리 부분 
			//////////////////////////////////////////////////////////////////////////
			
			if ( m_SceneType == SCENE_PLAY )
			{
				CRMitemManager::GetInstance()->Update();

				CRMnoteManager::GetInstance()->StartNote();
				CRMjudgeManager::GetInstance()->JudgeNote();

				// 이렇게 자주 해줄 필요는 없는데...
				if ( ( CRMplayer1P::GetInstance()->IsEnd() && CRMplayer2P::GetInstance()->IsEnd() ) || !CRMsound::GetInstance()->GetIsPlaying() )
				{
					GoNextScene();
				}
			}
			else if ( m_SceneType == SCENE_RESULT )
			{
				CRMresultManager::GetInstance()->ShowResult();
			}

			//////////////////////////////////////////////////////////////////////////
			// 여기까지
			//////////////////////////////////////////////////////////////////////////

			if ( m_ElapsedTime > m_Fps )
			{
				m_PrevTime = m_NowTime;
			}
		}
	}
}