コード例 #1
0
ファイル: bigmul.c プロジェクト: ProjectZeroSlackr/PiCalc
/*
** Do a Fast Fourier Transform based multiplication.
*/
INT32
FFTMul(BigInt Prod, BigInt Num1, BigInt Num2, size_t NumLen,
       size_t ProdLen, INT32 Scale)
/*
** Scale=0 means don't multiply by Scale.
** Scale!=0 means do multiply by Scale.  (Usually 10.)
**
** If a scaling causes a carry, that carry will be returned, else
** zero will be returned.
*/
{
  size_t x;
  size_t NumLen2 = NumLen * 2;
  size_t FFTLen2=CalcFFTLen(NumLen);
  FFT_DATA_TYPE *FFTNum2=FFTNum;
  int All16=0;INT32 ScaleCarry=0;

  if (NumLen <= 64)
    {INT32 *Buf1=(INT32*)CoreMemPtr;
     INT32 *Buf2=Buf1+NumLen;
     INT32 *DBuf=Buf2+NumLen;
     ReadNumIntoBuf(Num1,Buf1,NumLen);
     ReadNumIntoBuf(Num2,Buf2,NumLen);
     BlockClear(DBuf,DBuf+NumLen*2);
     BlockSlowMul(DBuf,Buf1,Buf2,NumLen);
     if (Scale) ScaleCarry=BlockMulBy(DBuf,DBuf,Scale,0,NumLen*2);
     WriteBufIntoNum(DBuf,Prod,ProdLen);
     return ScaleCarry;
    }

  if (FFTLen2 < 16)
    {UINT32 *Buf1=(UINT32*)CoreMemPtr;
     UINT32 *Buf2=Buf1+NumLen;
     UINT32 *DBuf=Buf2+NumLen;
     double *FFTNum1=(double*)(DBuf+NumLen*2);
     int     FFTLen=NumLen*2*2;
     double *FFTNum2=FFTNum1+FFTLen;
     ReadNumIntoBuf(Num1,Buf1,NumLen);
     ReadNumIntoBuf(Num2,Buf2,NumLen);
     BlockClear(DBuf,DBuf+NumLen*2);
     SimpleFFTMul(DBuf,Num1,Num2,NumLen,FFTLen,FFTNum1,FFTNum2);
     if (Scale) ScaleCarry=BlockMulBy(DBuf,DBuf,Scale,0,NumLen*2);
     WriteBufIntoNum(DBuf,Prod,ProdLen);
     return ScaleCarry;
    }


  if (NumLen > FFTLimit)
    {
     if (Cfg.AllowFractalMul)
       {
        FractalMul(FMWork,Num1,Num2,NumLen);
        if (Scale) ScaleCarry=MulBy(Prod,FMWork,Scale,ProdLen);
        else       Copy(Prod,FMWork,ProdLen);
        return ScaleCarry;
       }
     else
       FatalError("Somehow BigMul was called with a length (%lu) longer than FFTLimit (%lu)\n",
                  (ULINT)NumLen,(ULINT)FFTLimit);
    }

  MaxFFTError=0.0;
  if (FFTLen2*2*sizeof(FFT_DATA_TYPE) <= CoreMemAvail)
    {All16=-2;FFTNum2=FFTNum+FFTLen2;}

  if (!IsPow2(NumLen))
    FatalError("The FFT size is not a power of two\n");

  if (NumLen > MaxFFTLen/RawIntDigits)
    FatalError("Somehow FFTMul was called with a number longer than MAX_FFT_LIMIT.\n%lu %lu\n",
               (UINT32)NumLen,(UINT32)MaxFFTLen);

  if (NumLen > FFTLimit)
       FatalError("Somehow BigMul was called with a length (%lu) longer than FFTLimit (%lu)\n",
                  (ULINT)NumLen,(ULINT)FFTLimit);

  DumpDebug("FFT %s ",Num2Str(NumLen*RawIntDigits));
  StartTimer(FFTMulTime);
  FFTDisk-=DiskIOTime;
  if (Num1 == Num2)
    {int Line=0;
     if (Num1IsCached || Num2IsCached)
       Line=CheckFFTCache(Num2,NumLen,Num1IsCached + Num2IsCached,0);
     if (Line) LoadFFTFromCache(Line,FFTNum);
     else
       {
        DumpDebug("F");
        FwdTransform(FFTNum,Num2,NumLen);
        if (SaveNum2FFT || SaveNum1FFT)
          SaveFFTIntoCache(FFTNum, FFTLen2, Num2, NumLen,
                           SaveNum1FFT + SaveNum2FFT,0);
       }
     DoConvolution(FFTNum,-1,FFTLen2);
    }
  else
    {int Line1=0,Line2=0;
     if (Num1IsCached) Line1=CheckFFTCache(Num1,NumLen,Num1IsCached,0);
     if (Num2IsCached) Line2=CheckFFTCache(Num2,NumLen,Num2IsCached,0);
     if (Line1 && Line2)
       {
        DumpDebug("Caches...");
        LoadFFTFromCache(Line1,FFTNum);
        DoConvolution(FFTNum,Line2,FFTLen2);
       }
     else if (Line1)
       {
        DumpDebug("Cache...F");
        FwdTransform(FFTNum,Num2,NumLen);
        if (SaveNum2FFT)
          SaveFFTIntoCache(FFTNum,FFTLen2,Num2,NumLen, SaveNum2FFT,0);
        DoConvolution(FFTNum,Line1,FFTLen2);
       }
     else if (Line2)
       {
        DumpDebug("Cache...F");
        FwdTransform(FFTNum,Num1,NumLen);
        if (SaveNum1FFT)
          SaveFFTIntoCache(FFTNum,FFTLen2,Num1,NumLen, SaveNum1FFT,0);
        DoConvolution(FFTNum,Line2,FFTLen2);
       }
     else
       {
        if (SaveNum1FFT)
          {
           DumpDebug("F");
           FwdTransform(FFTNum,Num1,NumLen);
           Line1=SaveFFTIntoCache(FFTNum,FFTLen2,Num1,NumLen, SaveNum1FFT,0);
           if (All16) Line1=-2;
           else if (Line1==0) SaveFFTIntoCache0(FFTNum,FFTLen2);
           DumpDebug("F");
           FwdTransform(FFTNum2,Num2,NumLen);
           if (SaveNum2FFT)
             SaveFFTIntoCache(FFTNum2,FFTLen2,Num2,NumLen, SaveNum2FFT,0);
           DoConvolution(FFTNum,Line1,FFTLen2);
          }
        else if (SaveNum2FFT)
          {
           DumpDebug("F");
           FwdTransform(FFTNum,Num2,NumLen);
           Line2=SaveFFTIntoCache(FFTNum,FFTLen2,Num2,NumLen, SaveNum2FFT,0);
           if (All16) Line2=-2;
           else if (Line2==0) SaveFFTIntoCache0(FFTNum,FFTLen2);
           DumpDebug("F");
           FwdTransform(FFTNum2,Num1,NumLen);
           if (SaveNum1FFT)
             SaveFFTIntoCache(FFTNum2,FFTLen2,Num1,NumLen, SaveNum1FFT,0);
           DoConvolution(FFTNum,Line2,FFTLen2);
          }
        else
          {
           Line2=All16;
           DumpDebug("F");
           FwdTransform(FFTNum,Num1,NumLen);
           if (!All16) SaveFFTIntoCache0(FFTNum,FFTLen2);
           DumpDebug("F");
           FwdTransform(FFTNum2,Num2,NumLen);
           DoConvolution(FFTNum,Line2,FFTLen2);
          }
       }
    }

  DeleteFFTCache(0); /* get rid of the convolution file */
/*
** Now do an Inverse FFT
*/
  DumpDebug("R");
  RevTransform(FFTNum,NumLen);

  DumpDebug("Carries...");
  StartTimer(CarryTime);
  MaxFFTError=0.0;
  {FFT_DATA_TYPE Carry, Round;
   INT32 *ProdBuf=(INT32*)FixedBuf;
   size_t ProdNdx,ProdPos,ProdBufLen=FIXEDBUF_SIZE/sizeof(INT32);
   double PyramidError;
   int SF=4+(RAW_FFT_DIG*2);
   int q;

   ProdNdx=ProdBufLen;ProdPos=NumLen2;
   F_Clear(&Carry);
   F_Clear(&Round);Round.Data[SF+1]=50000000;
   for (x=0; x<FFTLen2;x++)
     {
      if (FFTNum[x].Data[0] != 0)
        fprintf(stderr,"Warning, FFT appears to be overflow. %ld %d\n",x,FFTNum[x].Data[0]);
      PyramidError=FFTNum[x].Data[SF+1]/1.0e8;
      PyramidError-=0.5;PyramidError=fabs(PyramidError);PyramidError=0.5-PyramidError;
      if (PyramidError > MaxFFTError) MaxFFTError = PyramidError;
      F_Add(&FFTNum[x],&Round,&FFTNum[x]);
      F_Add(&Carry,&FFTNum[x],&Carry);
      ProdNdx-=RAW_FFT_DIG;ProdPos-=RAW_FFT_DIG;
      for (q=RAW_FFT_DIG-1;q>=0;q--)
        {
         ProdBuf[ProdNdx+q]=Carry.Data[SF];
         F_ShiftR(&Carry);
        }
      {int z;for (z=SF+1;z<FIXPOINT_LEN;z++) Carry.Data[z]=0;}
      if (ProdNdx==0)
         {size_t z;
          if (ProdPos >= ProdLen) z=0;
          else if (ProdPos+ProdBufLen < ProdLen) z=ProdBufLen;
          else z=ProdLen-ProdPos;
          if ((Scale) && (z))
            ScaleCarry=BlockMulBy(ProdBuf,ProdBuf,Scale,ScaleCarry,z);
          if (z) WriteBufIntoNum(ProdBuf,Prod+ProdPos,z);
          ProdNdx=ProdBufLen;
         }
     }
   if (ProdNdx!=ProdBufLen)
     {size_t z;
      ProdBufLen=ProdBufLen-ProdNdx;
      if (ProdPos >= ProdLen) z=0;
      else if (ProdPos+ProdBufLen < ProdLen) z=ProdBufLen;
      else z=ProdLen-ProdPos;
      if ((Scale) && (z))
         ScaleCarry=BlockMulBy(ProdBuf+ProdNdx,ProdBuf+ProdNdx,Scale,ScaleCarry,z);
      if (z) WriteBufIntoNum(ProdBuf+ProdNdx,Prod+ProdPos,z);
     }
   StopTimer(CarryTime);
/*
   F_Clear(&Carry);
//   F_Clear(&Round);Round.Data[9]=50000000;
//   F_Clear(&Round);Round.Data[7]=50000000;
   F_Clear(&Round);Round.Data[11]=50000000;
   for (x=0; x<FFTLen2;x++)
     {
      if (FFTNum[x].Data[0] != 0)
        fprintf(stderr,"Warning, FFT appears to be overflow. %ld %d\n",x,FFTNum[x].Data[0]);
//      PyramidError=FFTNum[x].Data[9]/1.0e8;
//      PyramidError=FFTNum[x].Data[7]/1.0e8;
      PyramidError=FFTNum[x].Data[11]/1.0e8;
      PyramidError-=0.5;
      PyramidError=fabs(PyramidError);
      PyramidError=0.5-PyramidError;
      if (PyramidError > MaxFFTError) MaxFFTError = PyramidError;
      F_Add(&FFTNum[x],&Round,&FFTNum[x]);
      F_Add(&Carry,&FFTNum[x],&Carry);
//      P[x]=Carry.Data[8];
//      P[x]=Carry.Data[6];
      P[x]=Carry.Data[10];
      F_ShiftR(&Carry);
//      {int z;for (z=9;z<FIXPOINT_LEN;z++) Carry.Data[z]=0;}
//      {int z;for (z=7;z<FIXPOINT_LEN;z++) Carry.Data[z]=0;}
      {int z;for (z=11;z<FIXPOINT_LEN;z++) Carry.Data[z]=0;}
     }
   StopTimer(CarryTime);
   for (x=0;x<FFTLen2/2;x++) {UINT32 t=P[x];P[x]=P[FFTLen2-x-1];P[FFTLen2-x-1]=t;}
   if (Scale) ScaleCarry=BlockMulBy((INT32*)P,(INT32*)P,Scale,0,Min(ProdLen,NumLen2));
   WriteBufIntoNum((INT32*)P,Prod,Min(ProdLen,NumLen2));
*/
  }

  /*
  ** Do a bit of 'sanity' error checking.  This value
  ** is based on some testing with a 'test jig' and
  ** personal opinion.  Should be good enough to catch
  ** systems with poor FPUs.  However, if the value ever
  ** actually reaches 0.5, then you know for a FACT that
  ** the FFTMul() has failed.
  */
  if (MaxFFTError >= 0.2)
    {
      printf("\n**WARNING** Len=%lu Max FFT Error: %f\n",
             (ULINT)NumLen,(double)MaxFFTError);
      puts("Either the FFT is approaching its limit, or a sofware");
      puts("or hardware error occured.  This can also be caused by");
      puts("a program bug, poor trig, etc.  You may wish to lower");
      puts("the MaxFFTLen limit in fft.h and run it again.");
      ExitPrg(EXIT_FAILURE);
    }

  StopTimer(FFTMulTime);
  FFTDisk+=DiskIOTime;
  DumpDebug("Done FFT.\n");
  return ScaleCarry;
}
コード例 #2
0
	double LogLikGamma(Vec_I_DP &x)
	{
		//This function returns the negative value of the LogLikelihood
		const double dPi=3.1415926535897932384626433832795;
		int i,j;
		double dTemp=0.;

		double dLog10=log(10.);
		RevTransform(x);

		int nSize=g_vHistNode.size();
		int nComponents=g_GammaTrialNode.nNumComponents;
		int nFuncKey=g_GammaTrialNode.nFuncKey;
		double dX,dX0,dX1;
		const double dH=g_GammaTrialNode.dH;

		double dLogLik=0.;
		double dLik=0.,dExp=0.,dDenorm=0.;
		double dR,dW,dArea;

		dX0=g_GammaTrialNode.fFittingRange.fLeft;
		dX1=g_GammaTrialNode.fFittingRange.fRight;
		dArea=0.;
		for(j=0;j<nComponents;j++)
		{
			dR=g_GammaResultNode.dRol[j];
			dW=g_GammaResultNode.dWeights[j];
			dTemp=GammaDistribution_Area(dH,dR,dX0,dX1);
			dArea+=dTemp;
		}

		switch (nFuncKey)
		{
		case 1:
			for(i=0;i<nSize;i++)
			{
				dLik=0.;
				dX=g_vHistNode[i].dLeft;
				for(j=0;j<nComponents;j++)
				{
					dR=g_GammaResultNode.dRol[j];
					dW=g_GammaResultNode.dWeights[j];
					dTemp=GammaDistribution(dH,dR,dX);
					dLik+=dTemp;
				}
				dLogLik+=log(dLik*dArea)/dLog10;
			}
			break;
		case 2:
			for(i=0;i<nSize;i++)
			{
				dLik=0.;
				dX0=g_vHistNode[i].dLeft;
				dX1=g_vHistNode[i].dRight;
				for(j=0;j<nComponents;j++)
				{
					dR=g_GammaResultNode.dRol[j];
					dW=g_GammaResultNode.dWeights[j];
					dTemp=GammaDistribution_Area(dH,dR,dX0,dX1);
					dLik+=dTemp;
				}
				dLogLik+=log(dLik*dArea*g_vHistNode[i].dData)/dLog10;
			}
			break;
		}
		return -dLogLik;
	}