/* ***************************************************** ** 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); }
void MapLinearIntensities(FourVectors const &intens,uint32 *p1, uint32 *p2, uint32 *p3, uint32 *p4) { // convert four pixels worth of sse-style rgb into argb lwords // NOTE the _mm_empty macro is voodoo. do not mess with this routine casually - simply throwing // anything that ends up generating a fpu stack references in here would be bad news. static fltx4 pixscale={255.0,255.0,255.0,255.0}; fltx4 r,g,b; r=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.x,IGAMMA))); g=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.y,IGAMMA))); b=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.z,IGAMMA))); // now, convert to integer r=AndSIMD( AddSIMD( r, Four_MagicNumbers ), PIXMASK ); g=AndSIMD( AddSIMD( g, Four_MagicNumbers ), PIXMASK ); b=AndSIMD( AddSIMD( b, Four_MagicNumbers ), PIXMASK ); *(p1)=(SubInt(r, 0))|(SubInt(g, 0)<<8)|(SubInt(b, 0)<<16); *(p2)=(SubInt(r, 1))|(SubInt(g, 1)<<8)|(SubInt(b, 1)<<16); *(p3)=(SubInt(r, 2))|(SubInt(g, 2)<<8)|(SubInt(b, 2)<<16); *(p4)=(SubInt(r, 3))|(SubInt(g, 3)<<8)|(SubInt(b, 3)<<16); }
/* ** 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); }