Ejemplo n.º 1
0
/*
 * Invert a toeplitz matrix. Input is the first column of the matrix and also
 * is the output.
 * IMP - size must be a power of two.
 */
void serial_matrix_inversion(size_t size, const fftw_complex *input, fftw_complex *result) {

    if(size < 1) return;

    //base case
    result[0] = 1 / input[0];
    if(size < 2) return;
    result[1] = - result[0] * input[1] * result[0];


    unsigned int current_size = 2;

    while(current_size < size) {

        fftw_complex *reversed_input = alloc_reverse_from_vec(current_size * 2 - 1, input);

        fftw_complex *temporary = alloc_complex(current_size);


        //first convolution
        toeplitz_mult(current_size, reversed_input, result, temporary);


        fftw_complex *reversed_inverted_pad = alloc_complex(current_size * 2 - 1);
        zero_memory(current_size * 2 - 1, reversed_inverted_pad);

        memcpy(reversed_inverted_pad + (current_size-1), result,
               current_size * sizeof(fftw_complex));

        reverse_vec(current_size * 2 - 1, reversed_inverted_pad);


        //second convolution
        reverse_vec(current_size, temporary);
        toeplitz_mult(current_size, reversed_inverted_pad, temporary, reversed_input);

        //complement sign
        for(int i=0; i < current_size; i++)
            reversed_input[i] = - reversed_input[i];

        reverse_vec(current_size, reversed_input);

        //finally copy in result vec
        memcpy(result + current_size, reversed_input, current_size * sizeof(fftw_complex));


        fftw_free(temporary);
        fftw_free(reversed_input);
        fftw_free(reversed_inverted_pad);
        current_size *= 2;
    }
}
Ejemplo n.º 2
0
//' @title Discrete Wavelet Transform
//' @description Calculation of the coefficients for the discrete wavelet transformation. 
//' @param x           A \code{vector} with dimensions \eqn{N\times 1}{N x 1}. 
//' @param filter_name A \code{string} indicating the filter.
//' @param nlevels     An \code{integer}, \eqn{J}, indicating the level of the decomposition.
//' @param boundary    A \code{string} indicating the type of boundary method to use. Either \code{boundary="periodic"} or \code{"reflection"}.
//' @param brickwall   A \code{bool} indicating whether the a brick wall procedure should be applied to the coefficients.
//' @return y A \code{field<vec>} that contains the wavelet coefficients for each decomposition level
//' @details
//' Performs a level J decomposition of the time series using the pyramid algorithm
//' @author JJB
//' @keywords internal
//' @examples
//' set.seed(999)
//' x = rnorm(2^8)
//' dwt_cpp(x, filter_name = "haar", nlevels = 4, boundary = "periodic", brickwall = TRUE)
// [[Rcpp::export]]
arma::field<arma::vec> dwt_cpp(arma::vec x, std::string filter_name, 
                                   unsigned int nlevels, std::string boundary, bool brickwall) {
                                     
  if(boundary == "periodic"){
    //
  }else if(boundary == "reflection"){
    unsigned int temp_N = x.n_elem;
    arma::vec rev_vec = reverse_vec(x);
    x.resize(2*temp_N);
    x.rows(temp_N, 2*temp_N-1) = rev_vec;
  }else{
      Rcpp::stop("The supplied 'boundary' argument is not supported! Choose either periodic or reflection."); 
  }

  unsigned int N = x.n_elem;
  
  unsigned int J = nlevels;
  
  unsigned int tau = pow(2,J);
    
  if(double(N)/double(tau) != floor(double(N)/double(tau))){
    Rcpp::stop("The supplied sample size ('x') must be divisible by 2^(nlevels). Either truncate or expand the number of samples.");
  }
  if(tau > N){
    Rcpp::stop("The number of levels [ 2^(nlevels) ] exceeds sample size ('x'). Supply a lower number of levels.");
  }

  arma::field<arma::vec> filter_info = select_filter(filter_name);
  
  int L = arma::as_scalar(filter_info(0));
  arma::vec h = filter_info(1); //check the pulls
  arma::vec g = filter_info(2);
  
  arma::field<arma::vec> y(J);
  
  for(unsigned int j = 1; j <= J; j++) {
    
    unsigned int M = N/pow(2,(j-1));
    unsigned int M_over_2 = double(M)/2;
    
    arma::vec Wj(M_over_2);
    arma::vec Vj(M_over_2);
    
    for(unsigned t = 0; t < M_over_2; t++) {
      
      int u = 2*t + 1;

      double Wjt = h(0)*x(u);
      double Vjt = g(0)*x(u);
      
      for(int n = 1; n < L; n++){
        u -= 1;
        if(u < 0){
          u = M - 1;
        } 
        Wjt += h(n)*x(u);
        Vjt += g(n)*x(u);
      }
      
      Wj[t] = Wjt;
      Vj[t] = Vjt;
    }
    
    y(j-1) = Wj;
    x = Vj;
  }
  
  
  // Apply brickwall
  if(brickwall){
    y = brick_wall(y, filter_info, "dwt");
  }
  
  return y;
}
Ejemplo n.º 3
0
//' @title Maximum Overlap Discrete Wavelet Transform
//' @description 
//' Calculation of the coefficients for the discrete wavelet transformation
//' @inheritParams dwt_cpp
//' @return y A \code{field<vec>} that contains the wavelet coefficients for each decomposition level
//' @keywords internal
//' @details
//' Performs a level J decomposition of the time series using the pyramid algorithm.
//' Use this implementation to supply custom parameters instead of modwt(x),
//' which serves as a wrapper function.
//' @author JJB
//' @keywords internal
//' @examples
//' set.seed(999)
//' x = rnorm(100)
//' modwt_cpp(x, filter_name = "haar", nlevels = 4, boundary = "periodic", brickwall = TRUE)
// [[Rcpp::export]]
arma::field<arma::vec> modwt_cpp(arma::vec x, std::string filter_name, 
                                   unsigned int nlevels, std::string boundary, bool brickwall){
  
  if(boundary == "periodic"){
    //
  }else if(boundary == "reflection"){
    unsigned int temp_N = x.n_elem;
    arma::vec rev_vec = reverse_vec(x);
    x.resize(2*temp_N);
    x.rows(temp_N, 2*temp_N-1) = rev_vec;
  }else{
    Rcpp::stop("The supplied 'boundary' argument is not supported! Choose either periodic or reflection."); 
  }

  unsigned int N = x.n_elem;
  
  unsigned int J = nlevels;
  
  unsigned int tau = pow(2,J);
  
  if(tau > N) Rcpp::stop("The number of levels [ 2^(nlevels) ] exceeds sample size ('x'). Supply a lower number of levels.");

  arma::field<arma::vec> filter_info = select_filter(filter_name);
  
  int L = arma::as_scalar(filter_info(0));
  arma::vec ht = filter_info(1); 
  arma::vec gt = filter_info(2);
  
  // modwt transform
  double transform_factor = sqrt(2);
  ht /= transform_factor;
  gt /= transform_factor;

  arma::field<arma::vec> y(J);
  
  arma::vec Wj(N);
  arma::vec Vj(N);
  
  for(unsigned int j = 1; j <= J; j++) {
    for(unsigned t = 0; t < N; t++) {
      
      int k = t;

      double Wjt = ht(0)*x(k);
      double Vjt = gt(0)*x(k);
  
      for(int n = 1; n < L; n++){
        k -= pow(2, j-1);
        if(k < 0){
          k += N;
        } 
        Wjt += ht(n)*x(k);
        Vjt += gt(n)*x(k);
      }
      
      Wj[t] = Wjt;
      Vj[t] = Vjt;
    }
    
    y(j-1) = Wj;
    x = Vj;
  }
  
  // Apply brickwall
  if(brickwall){
   y = brick_wall(y, filter_info, "modwt");
  }
  
  return y;
}