Пример #1
0
    void Do() {
        int Fst = 1;
        double uinter = 0, dinter = 0, pinter = 0, linter = L, rinter = Ro;
        Result::Ufr = 0;
        Result::Uto = U2;
        Result::Discr = 100;
        clc.Init(Fst ? Mat1 : Mat2, Fst ? U2 : 0, 0, uinter, dinter, pinter, rinter, Fst);
        Result::Clc(&Mat1Result, dinter, pinter, uinter, rinter, PressureMat);
        Fst = !Fst;
        clc.Init(Fst ? Mat1 : Mat2, Fst ? U2 : 0, 0, uinter, dinter, pinter, rinter, Fst);
        Result::Clc(&Mat2Result, dinter, pinter, uinter, rinter, PressureMat);
        Fst = !Fst;

        for(int k = 0; k < Times.SetDim(); k++) {
            dinter = linter / Times[k];
            cout << " Found U " << uinter << " P " << pinter << " Ro " << rinter << " L "
                 << linter << " D " << dinter << "\n";
            clc.Init(
                Fst ? Mat1 : Mat2, Fst ? U2 : 0, 0, uinter, dinter, pinter, rinter, Fst);
            Result::Clc(&(U_P[k]), dinter, pinter, uinter, rinter, PressureInter);
            uinter = U2 / 2;
            if(!Fzero(MisP, 0, U2, uinter, 1e-6, 1e-6, 1000))
                cout << "Fzero error\n";
            clc.GetPar(uinter, pinter, rinter);
            Result::Fin(&(U_P[k]), pinter, uinter, rinter);
            linter = L * Ro / rinter;
            Fst = !Fst;
        }
        cout << " Found U " << uinter << " P " << pinter << " Ro " << rinter << " L "
             << linter << " D " << 0 << "\n";
        OutputRes();
    }
Пример #2
0
map<Stroka, double> MatterStable::TwoPhaseBoundary::MakeBndPnt() {
    VecCl V, D, P;
    int SpinIndMin, SpinIndMax;
    map<Stroka, double> ret;
    ret["T"] = T;
    ret["DSr_T"] = 0;
    ret["DSl_T"] = 0;
    ret["Dr_T"] = 0;
    ret["Dl_T"] = 0;
    ret["P_T"] = 0;
    ret["E_T"] = 0;
    ret["dPdT_T"] = 0;
    if(!SetDP(V, D, P, SpinIndMin, SpinIndMax))
        return ret;
    ret["T"] = T;
    TwoPhaseBoundary *OldPtr = TwoPhaseBoundaryStaticPtr;
    PrepareStatic(P, V);

    double PT_From, PT_To;
    FindMinMax(V, SpinIndMax, ZeroFunc_Spl_Vmin, PT_From, 1);
    ret["DSr_T"] = 1 / ZeroFunc_Spl_Vmin;
    FindMinMax(V, SpinIndMin, ZeroFunc_Spl_Vmax, PT_To, 0);
    ret["DSl_T"] = 1 / ZeroFunc_Spl_Vmax;
    IntegralFunc_Negative = 0;
    double PT_est =
        IntegralFunc_PV_Int_Static((ZeroFunc_Spl_Vmin + ZeroFunc_Spl_Vmax) * 0.5);
    Fzero(
        ZeroFunc_PV_Int_Static,
        max<double>(PT_From, sqrt(MathZer)),
        max<double>(PT_To, sqrt(MathZer)),
        PT_est,
        Mis * 0.1,
        Mis * 0.1,
        100);
    //Fzero(ZeroFunc_PV_Int_Static, PT_From, PT_To, PT_est, Mis*0.1, Mis*0.1, 100);
    ZeroFunc_PV_Int_Static(PT_est);
    //ret["P_T"] = PT_est;
    ret["Dl_T"] = 1 / ZeroFunc_SplRes_Bmax;
    ret["Dr_T"] = 1 / ZeroFunc_SplRes_Bmin;
    ret["P_T"] = 0.5 * (Mat->Pressure(ret["Dr_T"], T) + Mat->Pressure(ret["Dl_T"], T));
    ret["E_T"] = Mat->Energy(ret["Dr_T"], T);

    double E0 = ret["E_T"];   //,P0=Mat->Pressure(ret["Dr_T"],T);
    double E1 = Mat->Energy(ret["Dl_T"], T);
    ret["dPdT_T"] = -(E0 - E1) / (1 / ret["Dr_T"] - 1 / ret["Dl_T"]);

    ret["Pr_T"] = Mat->Pressure(ret["Dr_T"], T);
    ret["Pl_T"] = Mat->Pressure(ret["Dl_T"], T);

    ret["PSr_T"] = Mat->Pressure(ret["DSr_T"], T);
    ret["PSl_T"] = Mat->Pressure(ret["DSl_T"], T);
    //if (fabs(ret["Pr_T"]-ret["Pl_T"])>Mis) cout<<" BinodalBndPres l "<<ret["PSl_T"]<<" r "<<ret["PSr_T"]<<"\n";

    TwoPhaseBoundaryStaticPtr = OldPtr;
    return ret;
}
Пример #3
0
main()
{ int i; float x, Fzero(),Fone();

    for( i=0; i< 100; i++)
    {
        x = i;

        printf("%f %f %f\n",x,Fzero(x*x),Fone(x*x));
    }

}
Пример #4
0
void Hug2(Int_Par &P1, Int_Par &P2, Int_Par &Pr1,
        double &Dr1, Int_Par &Pr2, double &Dr2,
        MatterIO *Mat1, MatterIO *Mat2) {
    double Pest;   //,Delta;
    MatterAdiabat = Mat1;
    P1.Pres = PressurePorous(P1.Dens, P1.Ener);
    MatterAdiabat = Mat2;
    if(!GetInitialPressure)
        P2.Pres = PressurePorous(P2.Dens, P2.Ener);
    else
        P2.Pres = 0.0001;
    if(Norm(P1 - P2) < StndErr) {
        Pr1 = P1;
        Pr2 = P2;
        Dr1 = Mat1->Sound(P1.Dens, P1.Ener) + P1.Velo;
        Dr2 = Dr1;
        return;
    }
    double A1 = max<double>(0.1, P1.Dens * Mat1->Sound(P1.Dens, P1.Ener));
    double A2 = max<double>(0.1, P2.Dens * Mat2->Sound(P2.Dens, P2.Ener));
    Pest = (P2.Pres * A1 + P1.Pres * A2 + A1 * A2 * (P1.Velo - P2.Velo)) / (A1 + A2);

    S_Par1 = P1;
    S_Par2 = P2;
    S_Mat1 = Mat1;
    S_Mat2 = Mat2;
#ifdef FZERO_HUGONIO_SEARCH
    //int Fzero(X_func f,double From,double To,double &Guess,double ErrorAbs,double ErrorRel,
    //                  int MaxIter);
    Fzero(MisU, 1e6, M_Eps2, Pest, StndErr, StndErr, 200);
//   if (3<Fzero(MisU,-1e6,1e6,Pest,StndErr,StndErr,200));
//{ cout <<" Error, could not find Hug2 ZeroFzeroIt\n";}
//int ZeroNewtonIt(X_func Func,double &CurPnt,double Tol,int MaxIter,
//                             double Up,double Down,double MaxStp,double BegStp)
#else
#ifdef NEWTON_HUGONIO_SEARCH
    if(!ZeroNewtonIt(MisU, Pest, StndErr, 100, 1e6, -1e6, 5 * fabs(Pest))) {
        double Ctrl = MisU(Pest);
        cout << " Error, could not find Hug2";
    }
#else
    if(!FindZeroPos(MisU, Pest, Delta, StndErr, 0.5 * Pest))
        cout << " Error, could not find Hug2";
#endif
#endif
    Pr1 = S_Res1;
    Pr2 = S_Res2;
    Dr1 = -S_ResD1 + S_Par1.Velo;
    Dr2 = -S_ResD2 + S_Par2.Velo;
    Pr2.Velo = -Pr2.Velo + 2 * P2.Velo;
    Pr1.Pres = Pest;
    Pr2.Pres = Pest;
};
Пример #5
0
double MatterStable::TwoPhaseBoundary::ZeroFunc_PV_Int(double pres) {
    double Vmin, Vmax, Smin = ZeroFunc_Spl_Vmin, Smax = ZeroFunc_Spl_Vmax,
                       Ds = Smax - Smin;   //,PresInt,ResErr
    Vmin = Smin - Ds / 2;
    Vmax = Smax + Ds / 2;
    IntegralFunc_Negative = 0;
    IntegralFunc_Add = -pres;

    //cout<<" pres "<<pres<<" Vmin "<<1/Dmax<<" pmin "<<Mat->Pressure(Dmax,T)<<" spl "<<IntegralSpline_P_V.Evaluate(1/Dmax)<<" vmax "<<Smin<<" pmax "<<Mat->Pressure(1/Smin,T)<<"\n";

    Fzero(
        IntegralFunc_PV_Int_Static,
        1 / Dmax,
        Smin,
        Vmin,
        ZeroFunc_Misf * 0.1,
        ZeroFunc_Misf * 0.1,
        100);
    Fzero(
        IntegralFunc_PV_Int_Static,
        Smax,
        1 / Dmin,
        Vmax,
        ZeroFunc_Misf * 0.1,
        ZeroFunc_Misf * 0.1,
        100);
    //Fzero(IntegralFunc_PV_Int_Static,Smin-Ds,Smin,Vmin,ZeroFunc_Misf*0.1,ZeroFunc_Misf*0.1,100);
    //Fzero(IntegralFunc_PV_Int_Static,Smax,Smax+10000*Ds,Vmax,ZeroFunc_Misf*0.1,ZeroFunc_Misf*0.1,100);
    ZeroFunc_SplRes_Bmin = Vmin;
    ZeroFunc_SplRes_Bmax = Vmax;
    //double MisPmin=fabs(Mat->Pressure(1/Vmin,T)-pres),
    //       MisPmax=fabs(Mat->Pressure(1/Vmax,T)-pres);
    //if (MisPmin+MisPmax>ZeroFunc_Misf)
    //cout<<" P "<<pres<<"\nmax V "<<Vmax<<" P "<<Mat->Pressure(1/Vmax,T)<<" spl "<<IntegralSpline_P_V.Evaluate(Vmax)<<
    //"\nmin V " <<Vmin<<" Pmin "<<Mat->Pressure(1/Vmin,T)<<" spl "<<IntegralSpline_P_V.Evaluate(Vmin)<<"\n";

    return Mat->FreeE(1 / Vmin, T) - Mat->FreeE(1 / Vmax, T) + pres * (Vmin - Vmax);
}
Пример #6
0
double MatterFreeE::TemperatureFind(double En,double Den,double Low,double Up,
                                    double Start,double Err,int NumIt)
{
   Current=this;
   E=En;D=Den;
   double T0=Start;
   int err;
#ifdef FZERO_TEMPERATURE_ITERATION
      if (4<(err=Fzero(DeltaFree,Low,Up,T0,Err,Err,100)) )
        {cout<<" Bad ZeroFzeroFreeE in MatterFreeE::TemperatureFind Not Zero\nfound T "
             <<T0<<" Mis "<<DeltaFree(T0)<<" err "<<err<<"\n";T0=Zero_Temp;}
#else
#ifdef FZERO_LOGTEMPERATURE_ITERATION
//                   ln(50)=3.91 ln(1e6)=13.8  ln(100)=4.6
    T0=log(Start);Low=log(Low);Up=log(Up);Err=0.1*Err;
    if (4<(err=Fzero(DeltaFreeLog,Low,Up,T0,Err,Err,100)) ) {
        cout<<" Bad ZeroFzeroFreeE in MatterFreeE::Temperature Not Zero\nfound T "
            <<exp(T0)<<" Mis "<<DeltaFreeLog(T0)<<" err "<<err<<"\n";
        T0 = MinimTmin;
    } else 
        T0=exp(T0);
#else
  MinFind1DClass *min1d=new MinFind1DClass(1,NULL);
  double MinError=Err,FoundEMis;
  int Cont=1,MaxIt=7,NumT=MaxIt,it;
  VecCl TmpPar(1),TmpStp(1);TmpPar[1]=L_T;TmpStp[1]=500;
  T0=Start;
#ifdef MULTIDIM_TEMPERATURE_ITERATION
  Derive2DStd *D2=new Derive2DStd(new DeriveStaticFunc(DeltaFree));
  MinFindNDimClass MinNd(D2,min1d,1e-10,1e-8,MinError);
  for (it=1;((it<=NumT)&&(Cont));it++) Cont=MinNd.Execute(TmpPar,TmpStp,1,FoundEMis);
  if (it>MaxIt)
      if (4<(err=Fzero(DeltaFree,Low,Up,T0,Err,Err,100)) )
        {cout<<" Bad ZeroFzeroFreeE in MatterFreeE::TemperatureFind Not Zero\nfound T "
             <<T0<<" Mis "<<DeltaFree(T0)<<" err "<<err<<"\n";T0=Zero_Temp;}
      else T0=TmpPar[1];
#else
  T0=log(Start);Low=log(Low);Up=log(Up);Err=0.1*Err;
  TmpPar[1]=log(TmpPar[1]);TmpStp[1]=log(TmpStp[1]);
  Derive2DStd *D2=new Derive2DStd(new DeriveStaticFunc(DeltaFreeLog));
  MinFindNDimClass MinNd(D2,min1d,1e-10,1e-8,MinError);
  for (it=1;((it<=NumT)&&(Cont));it++) Cont=MinNd.Execute(TmpPar,TmpStp,1,FoundEMis);
  if (it>MaxIt)
    if (4<(err=Fzero(DeltaFreeLog,Low,Up,T0,Err,Err,100)) )
     {cout<<" Bad ZeroFzeroFreeE in MatterFreeE::Temperature Not Zero\nfound T "
          <<exp(T0)<<" Mis "<<DeltaFreeLog(T0)<<" err "<<err<<"\n";T0=Zero_Temp;}
    else T0=exp(T0);
  else T0=exp(TmpPar[1]);

#endif
#endif
#endif
//#ifdef FZERO_TEMPERATURE_ITERATION
////   if (!ZeroNewtonIt(DeltaFree,T0,StndErr*0.1,100,1e6,Zero_Temp,0.8*T0,0.01))
////int Fzero(X_func f,double From,double To,double &Guess,double ErrorAbs,double ErrorRel,
////                  int MaxIter)
//    if (4<(err=Fzero(DeltaFree,50,1e6,T0,StndErr*0.1,StndErr*0.1,100)) )
//     {cout<<" Bad ZeroFzeroFreeE in MatterFreeE::Temperature Not Zero\nfound T "
//          <<T0<<" Mis "<<DeltaFree(T0)<<" err "<<err<<"\n";T0=Zero_Temp;}
////if (err!=0) cout<<" Mis E "<<DeltaFree(T0)<<" T "<<T0<<" err "<<err<<"\n";

  return T0;
}
Пример #7
0
int coarsepitch(
                Float	*xw,
                Float	*xwdm,
                Float	*dfm,		/* (i/o) ellipse low pass filter memory */
                int	cpplast)
{
   
   Float	xwd[LXD];
   Float cor[MAXPPD1], cor2[MAXPPD1], energy[MAXPPD1];
   Float cor2i[HMAXPPD], energyi[HMAXPPD], mplth;
   Float tmp[DFO+FRSZ], threshold;	
   Float *fp0, *fp1, *fp2, *fp3, s, t, a, b, c, deltae;
   Float	cor2max, energymax, cor2m, energym, ci, eni;
   int	i, j, k, n, npeaks, imax, im, idx[HMAXPPD], plag[HMAXPPD];
   int	cpp, maxdev, flag, mpflag;  
   
   /* reset local buffers */
   Fzero(cor, MAXPPD1);
   Fzero(energy, MAXPPD1);
   
   /* LOWPASS FILTER xw() TO 800 Hz; SHIFT & OUTPUT INTO xwd() */
   
   /* copy xwd[] from memory to buffer */
   Fcopy(xwd, xwdm, XDOFF);
   
   /* copy memory to temp buffer */
   Fcopy(tmp, dfm, DFO);
   
   /* AP and AZ filtering and decimation */
   fp0 = xwd + XDOFF;
   fp1 = tmp + DFO;
   fp3 = xw;
   for (i=0;i<FRSZD;i++) {
      for (k=0;k<DECF;k++) {
         t = *fp3++; fp2 = fp1-1;
         for (j=0;j<DFO;j++) t -= adf[j+1]*(*fp2--);
         *fp1++ = t;
      }
      fp2 = fp1-1;
      t = bdf[0] * (*fp2--);
      for (j=0;j<DFO;j++) t += bdf[j+1] * (*fp2--); 
      *fp0++ = t;
   }
   
   /* copy temp buffer to memory */
   fp1 -= DFO;
   for (i=0;i<DFO;i++) dfm[i] = *fp1++;
   
   /* update xwd() memory */
   Fcopy(xwdm, xwd+FRSZD, XDOFF);
   
   /* COMPUTE CORRELATION & ENERGY OF PREDICTION BASIS VECTOR */
   
   fp0 = xwd+MAXPPD1;
   fp1 = xwd+MAXPPD1-M1;
   s = t = 0.; 
   for (i=0;i<(LXD-MAXPPD1);i++) {
      s += (*fp1) * (*fp1);
      t += (*fp0++)*(*fp1++);
   }
   energy[M1-1] = s;
   cor[M1-1] = t;
   if (t > 0.0F)
      cor2[M1-1] = t*t;
   else
      cor2[M1-1] = -t*t;
   
   
   fp2 = xwd+LXD-M1-1;
   fp3 = xwd+MAXPPD1-M1-1;
   
   for (i=M1;i<M2;i++) {
      fp0 = xwd+MAXPPD1;
      fp1 = xwd+MAXPPD1-i-1;
      t = 0.;
      for (j=0;j<(LXD-MAXPPD1);j++) t += (*fp0++) * (*fp1++); 
      cor[i] = t;
      if (t > 0.0F)
         cor2[i] = t*t;
      else
         cor2[i] = -t*t;
      s = s - (*fp2)*(*fp2) + (*fp3)*(*fp3);
      fp2--; fp3--;
      energy[i] = s;
   }
   
   /* FIND POSITIVE COR*COR/ENERGY PEAKS */
   npeaks = 0;
   n = MINPPD-1;
   while ((n<MAXPPD) && (npeaks<MAX_NPEAKS)) {
      if ((cor2[n]*energy[n-1]>cor2[n-1]*energy[n]) && 
         (cor2[n]*energy[n+1]>cor2[n+1]*energy[n]) && (cor2[n]>0)) {
         idx[npeaks] = n;
         npeaks++;
      }
      n++;
   }
   
   /* RETURN EARLY IF THERE IS NO PEAK OR ONLY ONE PEAK */
   if (npeaks == 0)   /* if there are no positive peak, */
      return MINPPD*cpp_scale; /* minimum pitch period in decimated domain */
   if (npeaks == 1)   /* if there is exactly one peak, */
      return (idx[0]+1)*cpp_scale; /* the time lag for this single peak */
   
   /* IF PROGRAM PROCEEDS TO HERE, THERE ARE 2 OR MORE PEAKS */
   cor2max=-1e30;
   energymax=1.0F;
   imax=0;
   for (i=0; i < npeaks; i++) {
      
   /* USE QUADRATIC INTERPOLATION TO FIND THE INTERPOLATED cor[] AND
      energy[] CORRESPONDING TO INTERPOLATED PEAK OF cor2[]/energy[] */
      /* first calculate coefficients of y(x)=ax^2+bx+c; */
      n=idx[i];
      a=0.5F*(cor[n+1] + cor[n-1]) - cor[n];
      b=0.5F*(cor[n+1] - cor[n-1]);
      c=cor[n];
      
      /* INITIALIZE VARIABLES BEFORE SEARCHING FOR INTERPOLATED PEAK */
      im=0;
      cor2m=cor2[n];
      energym=energy[n];
      eni=energy[n];
      
      /* DERTERMINE WHICH SIDE THE INTERPOLATED PEAK FALLS IN, THEN
      DO THE SEARCH IN THE APPROPRIATE RANGE */
      if (cor2[n+1]*energy[n-1] > cor2[n-1]*energy[n+1]) { /* if right side */
         deltae=(energy[n+1] - eni) * INVDECF; /*increment for linear interp.*/
         for (k = 0; k < HDECF; k++) {
            ci = a*x2[k] + b*x[k] + c; /* quadratically interpolated cor[] */
            eni += deltae;             /* linearly interpolated energy[] */
            if (ci*ci*energym > cor2m*eni) {
               im = k+1;
               cor2m=ci*ci;
               energym=eni;
            }
         }        
      } else {    /* if interpolated peak is on the left side */
         deltae=(energy[n-1] - eni) * INVDECF; /*increment for linear interp.*/
         for (k = 0; k < HDECF; k++) {
            ci = a*x2[k] - b*x[k] + c;
            eni += deltae;
            if (ci*ci*energym > cor2m*eni) {
               im = -k-1;
               cor2m=ci*ci;
               energym=eni;
            }
         }        
      }
      
      /* SEARCH DONE; ASSIGN cor2[] AND energy[] CORRESPONDING TO 
      INTERPOLATED PEAK */ 
      plag[i]=(idx[i]+1)*cpp_scale + im; /* lag of interp. peak */
      cor2i[i]=cor2m; /* interpolated cor2[] of i-th interpolated peak */
      energyi[i]=energym; /* interpolated energy[] of i-th interpolated peak */
      
      /* SEARCH FOR GLOBAL MAXIMUM OF INTERPOLATED cor2[]/energy[] peak */
      if (cor2m*energymax > cor2max*energym) {
         imax=i;
         cor2max=cor2m;
         energymax=energym;
      }
   }
   cpp=plag[imax];	/* first candidate for coarse pitch period */
   mplth=plag[npeaks-1]*1./DECF;	/* plag[] is Q2 */
   
   /* FIND THE LARGEST PEAK (IF THERE IS ANY) AROUND THE LAST PITCH */
   maxdev=(int) (DEVTH*cpplast); /* maximum deviation from last pitch */
   im = -1;
   cor2m = -1e30;
   energym = 1.0F;
   for (i=0;i<npeaks;i++) {  /* loop thru the peaks before the largest peak */
      if (abs(plag[i]-cpplast) <= maxdev) {
         if (cor2i[i]*energym > cor2m*energyi[i]) {
            im=i;
            cor2m=cor2i[i];
            energym=energyi[i];
         }	
      }
   } /* if there is no peaks around last pitch, then im is still -1 */
   
   /* NOW SEE IF WE SHOULD PICK ANY ALTERNATICE PEAK */
   /* FIRST, SEARCH FIRST HALF OF PITCH RANGE, SEE IF ANY QUALIFIED PEAK
   HAS LARGE ENOUGH PEAKS AT EVERY MULTIPLE OF ITS LAG */
   i=0;
   while (plag[i] < 0.5*mplth*DECF) {
      
      /* DETERMINE THE APPROPRIATE THRESHOLD FOR THIS PEAK */
      if (i != im) {  /* if not around last pitch, */
         threshold = TH1;    /* use a higher threshold */
      } else {        /* if around last pitch */
         threshold = TH2;    /* use a lower threshold */
      }
      
      /* IF THRESHOLD EXCEEDED, TEST PEAKS AT MULTIPLES OF THIS LAG */
      if (cor2i[i]*energymax > threshold*cor2max*energyi[i]) { 
         flag=1;  
         j=i+1;
         k=0;
         s=2.0F*plag[i]; /* initialize t to twice the current lag */
         while (s<=mplth*DECF) { /* loop thru all multiple lag <= mplth */
            mpflag=0;   /* initialize multiple pitch flag to 0 */
            a=MPR1*s;   /* multiple pitch range lower bound */
            b=MPR2*s;   /* multiple pitch range upper bound */
            while (j < npeaks) { /* loop thru peaks with larger lags */
               if (plag[j] > b) { /* if range exceeded, */
                  break;          /* break the innermost while loop */
               }       /* if didn't break, then plag[j] <= b */
               if (plag[j] > a) { /* if current peak lag within range, */
                  /* then check if peak value large enough */
                  if (k < 4) {
                     c = MPTH[k];
                  } else {
                     c = MPTH4;
                  }
                  if (cor2i[j]*energymax > c*cor2max*energyi[j]) {
                     mpflag=1; /* if peak large enough, set mpflag, */
                     break; /* and break the innermost while loop */
                  } 
               }
               j++;
            }
            /* if no qualified peak found at this multiple lag */
            if (mpflag == 0) { 
               flag=0;     /* disqualify the lag plag[i] */
               break;      /* and break the while (s<=mplth) loop */
            }
            k++;
            s += plag[i]; /* update s to the next multiple pitch lag */
         }
         /* if there is a qualified peak at every multiple of plag[i], */
         if (flag == 1) { 
            return plag[i];     /* and return to calling function */
         }
      }       
      i++;
      if (i == npeaks)
         break;      /* to avoid out of array bound error */
   }
   
   /* IF PROGRAM PROCEEDS TO HERE, NONE OF THE PEAKS WITH LAGS < 0.5*mplth
   QUALIFIES AS THE FINAL PITCH. IN THIS CASE, CHECK IF
   THERE IS ANY PEAK LARGE ENOUGH AROUND LAST PITCH.  IF SO, USE ITS
   LAG AS THE FINAL PITCH. */
   if (im != -1) {   /* if there is at least one peak around last pitch */
      if (im == imax) { /* if this peak is also the global maximum, */
         return cpp;   /* return first pitch candidate at global max */
      }
      if (im < imax) { /* if lag of this peak < lag of global max, */
         if (cor2m*energymax > LPTH2*cor2max*energym) { 
            if (plag[im] > HMAXPPD*cpp_scale) {
               return plag[im];
            }
            for (k=2; k<=5;k++) { /* check if current candidate pitch */
               s=plag[imax]/(float)(k); /* is a sub-multiple of */
               a=SMDTH1*s;             /* the time lag of */
               b=SMDTH2*s;             /* the global maximum peak */
               if (plag[im]>a && plag[im]<b) {     /* if so, */
                  return plag[im];         /* and return as pitch */
               }
            }
         }
      } else {           /* if lag of this peak > lag of global max, */
         if (cor2m*energymax > LPTH1*cor2max*energym) { 
            return plag[im];         /* accept its lag */ 
         }
      }
   }
   
   /* IF PROGRAM PROCEEDS TO HERE, WE HAVE NO CHOICE BUT TO ACCEPT THE
   LAG OF THE GLOBAL MAXIMUM */
   return cpp;
   
}