Exemplo n.º 1
0
std::vector<double> tb_lt_invert_Cpp_impl(double t, const std::vector<double>& lambda1,
                                          const std::vector<double>& lambda2, const std::vector<double>& lambda3,
                                          const int Ap1, const int Bp1, const int Cp1, const int direction,
                                          const int nblocks, const double tol, int& Lmax,
                                          ParallelizationScheme& scheme) {

  //  auto start = std::chrono::steady_clock::now();

  const double double_PI  = 3.141592653589793238463, AA = 20.0;
  const int matsize = Ap1*Bp1*Cp1;

  std::vector<mytype::ComplexVector> ig;
  std::vector<double> res(matsize), yvec(matsize);

  for (int i=0; i<matsize; ++i) {
    yvec[i] = lambda1[i] + lambda2[i] + lambda3[i];
  }

  /////////////////////////////////////////////////////////////
  // The following code computes the inverse Laplace transform
  // Algorithm from Abate and Whitt using a Riemann sum
  // Levin tranform is used to accelerate the convergence
  /////////////////////////////////////////////////////////////

  ig.resize(Lmax);

  scheme.for_each( boost::make_counting_iterator(0), boost::make_counting_iterator(Lmax),
                   [&](int w) {
                     mytype::ComplexNumber s(AA/(2*t),double_PI*(w+1)/t);
                     ig[w].resize(matsize);
                     tb_lt_Cpp(s,lambda1,lambda2,lambda3,Ap1,Bp1,Cp1,direction,yvec,ig[w]);
                   });

  mytype::ComplexNumber s(AA/(2*t),0.0);
  mytype::ComplexVector psum0(matsize);
  tb_lt_Cpp(s,lambda1,lambda2,lambda3,Ap1,Bp1,Cp1,direction,yvec,psum0);

  std::for_each(boost::make_counting_iterator(0), boost::make_counting_iterator(matsize),
                [&](int i) {
                  Levin levin(tol); // A struct for Levin transform
                  double term = 1e16, sdiff = 1e16;
                  int k = 1;
                  double psum = real(psum0[i])/(2*t);
                  double sk,sk1;
                  while ((std::abs(sdiff) > 1e-16)||(std::abs(term)>1e-3)) {
                    double sgn = (k%2 == 0) ? 1.0 : -1.0;
                    term = sgn*real(ig[k-1][i])/t;
                    psum += term;
                    double omega = k*term;
                    sk = levin.next(psum,omega,1.0);
                    if (k>1) sdiff = sk - sk1;
                    k++;
                    sk1 = sk;
                    if (k > Lmax) {
                      ig.resize(Lmax+nblocks);

                      scheme.for_each( boost::make_counting_iterator(0), boost::make_counting_iterator(nblocks),
                                       [&](int w) {
                                         mytype::ComplexNumber s(AA/(2*t),double_PI*(w+Lmax+1)/t);
                                         ig[w+Lmax].resize(matsize);
                                         tb_lt_Cpp(s,lambda1,lambda2,lambda3,Ap1,Bp1,Cp1,direction,yvec,ig[w+Lmax]);
                                       });

                      Lmax += nblocks;
                    }
                  }

                  res[i] = sk1*exp(AA/2);
                });

  //    Rcpp::Rcout << "Lmax: " << Lmax;

  //  auto end = std::chrono::steady_clock::now();
  //
  //  using TimingUnits = std::chrono::microseconds;
  //  Rcpp::Rcout << "Time: " << std::chrono::duration_cast<TimingUnits>(end - start).count() << std::endl;

  return(std::move(res));
}
Exemplo n.º 2
0
/** 
 *  Maximum entropy estimate by autocorrelation method.  Implements
 *  Yule-Walker method.
 *
 *  @param r
 *     Vector of correlation coefficients.
 *  @param n
 *     Number of lags used by MEM algorithm.
 *  @param nfft
 *     Size of fft for display.
 *  @param spect
 *     REAL*4 array of length FFT_SIZE in which the spectrum is returned.
 *  @param errmsg
 *     ERROR_MESSAGE  CHARACTER*130 variable containing error message if an
 *                   an error occurs, ' ' otherwise.
 *  @param errmsg_s
 *     Length of \p errmsg
 *  @param aux
 *     REAL*4 scratch array of length FFT_SIZE.
 *
 *  @author  David Harris
 *
 *  @date  December 28, 1984 Last Modified
 * 
 */
void 
mem(float  *r, 
    int     n, 
    int     nfft, 
    float  *spect, 
    char   *errmsg, 
    int     errmsg_s, 
    float  *aux) {

	int i;
        float scale;
        float *a, *reflct;
        float *A;

	float *const Aux = &aux[0] - 1;
	float *const R = &r[0] - 1;
	float *const Spect = &spect[0] - 1;
  UNUSED(errmsg_s);

        if((a = (float *)malloc(n*sizeof(float))) == NULL){
            strcpy(errmsg, "error allocating memory--mem\n");
            return;
	}

        if((reflct = (float *)malloc(n*sizeof(float))) == NULL){
            strcpy(errmsg, "error allocating memory--mem\n");
            free(a);
            return;
	}

        A = a-1;

/*
	if( n > 100 ){
		fstrncpy( errmsg, errmsg_s-1, "MEM *** Maximum order (100) exceeded ***"
		 , 40 );
		return;
		}
*/
	/*  Zero arrays
	 * */
	zero( spect, nfft );
	zero( aux, nfft );

	/*  Invoke Levinson's recursion to compute prediction filter
	 * */
	levin( r, a, reflct, n );

	/*  Compute transfer function of prediction filter
	 * */
	for( i = 1; i <= n; i++ )
	    Spect[i] = A[i];

	fft( spect, aux, nfft, -1 );

	/*  Spectral estimate is reciprocal of filter's power spectrum
	 *
	 *    Scale factor is equal to prediction error
	 * */
	scale = 0.;
	for( i = 1; i <= n; i++ )
	    scale = scale + R[i]*A[i];

	for( i = 1; i <= nfft; i++ )
	    Spect[i] = scale/(powi(Spect[i],2) + powi(Aux[i],2));

	/*  Bye
	 * */

        free(a); free(reflct);

	return;
} /* end of function */