
#include <cmath>
#include <algorithm>
#include <functional>
#include <iostream>
#include <fstream>
#include <string>
#include <tuple>

#include <stdio.h>
#include <stdlib.h>

#include <cstdlib>
#include <string.h>

#include "hark-lib/node/LocalizationFunction.hpp"


/********************************************************************************/
float MaxOfAbsValueFvector(std::vector<float>& A)
{
    float max = 0.0f;
    for(size_t i = 0; i < A.size(); i++) {
        if(std::abs(A[i]) > max){
            max = std::abs(A[i]);
        }
    }
    return max;
}

void mulfcomplex(std::complex<float>& a, std::complex<float>& b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = a.real() * b.real() - a.imag() * b.imag();
    tmp2 = a.real() * b.imag() + a.imag() * b.real();
    c = std::complex<float>(tmp1,tmp2);
}

void addfcomplex(std::complex<float>& a, std::complex<float>& b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = a.real() + b.real();
    tmp2 = b.imag() + a.imag();
    c = std::complex<float>(tmp1, tmp2);
}

void subfcomplex(std::complex<float>& a, std::complex<float>& b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = a.real() - b.real();
    tmp2 = a.imag() - b.imag();
    c = std::complex<float>(tmp1, tmp2);
}

void devfcomplex(std::complex<float>& a, std::complex<float>& b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = (a.real() * b.real() + a.imag() * b.imag()) / (b.real() * b.real() + b.imag() * b.imag());
    tmp2 = (a.imag() * b.real() - a.real() * b.imag()) / (b.real() * b.real() + b.imag() * b.imag());
    c = std::complex<float>(tmp1, tmp2);
}

void mulfcomplex_const(std::complex<float> a, std::complex<float> b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = a.real() * b.real() - a.imag() * b.imag();
    tmp2 = a.real() * b.imag() + a.imag() * b.real();
    c = std::complex<float>(tmp1, tmp2);
}

void addfcomplex_const(std::complex<float> a, std::complex<float> b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = a.real() + b.real();
    tmp2 = b.imag() + a.imag();
    c = std::complex<float>(tmp1, tmp2);
}

void subfcomplex_const(std::complex<float> a, std::complex<float> b, std::complex<float>& c)
{
    float tmp1,tmp2;
    tmp1 = a.real() - b.real();
    tmp2 = a.imag() - b.imag();
    c = std::complex<float>(tmp1,tmp2);
}

void devfcomplex_const(std::complex<float> a, std::complex<float> b, std::complex<float>& c)
{
    float tmp1, tmp2;
    tmp1 = (a.real() * b.real() + a.imag() * b.imag()) / (b.real() * b.real() + b.imag() * b.imag());
    tmp2 = (a.imag() * b.real() - a.real() * b.imag()) / (b.real() * b.real() + b.imag() * b.imag());
    c = std::complex<float>(tmp1, tmp2);
}

//////////////////////////

/*Multiplying 2 matrices :  a[d,e] * b[e,f] = c[d,f] */
 void mulMAT(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& b, Matrix<std::complex<float> >& c)
{
    //std::complex<float> z = 0.0f;
    //std::complex<float> tmpfc = 0.0f;

    //if(a.cols() == b.rows()){
    //    for(size_t i = 0; i < a.rows(); i++){
    //        for(size_t j = 0; j < b.cols(); j++){
    //            for(size_t k = 0; k < a.cols(); k++){
    //                mulfcomplex_const(a(i, k), b(k, j), tmpfc);
    //                addfcomplex(z, tmpfc, z);
    //            }
    //            c(i, j) = z;
    //            z = 0.0f;
    //        }
    //    }
    //}
    //else{
    //    printf("Error : mulMAT : Not an appropriate size.\n");
    //}
    c.noalias() = a * b;
}

/*derive the inverse matrix :  inv(a) = c */
void invMAT(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& c)
{
    //Matrix<std::complex<float> > tmpa = a;
    //std::complex<float> x,y=0.0f;
    //std::complex<float> tmpfc = 0.0f;
    //std::complex<float> tmpfc2 = 0.0f;

    //if(a.rows() == a.cols()){
    //    // Make a Unit Matrix
    //    for(size_t i = 0; i < a.rows(); i++){
    //        for(size_t j = 0; j < a.rows(); j++){
    //            if(i==j){
    //                c(i, j) = std::complex<float>(1.0f, 0.0f);
    //            }
    //            else{
    //                c(i, j) = std::complex<float>(0.0f, 0.0f);
    //            }
    //        }
    //    }
    //    for(size_t i = 0; i < a.rows(); i++){
    //        if((tmpa(i, i).real() == 0.0f) && (tmpa(i, i).imag() == 0.0f)){
    //            bool err = true;
    //            for(size_t j = i; j < a.rows(); j++){
    //                if((tmpa(j, i).real() != 0.0f) || (tmpa.(j, i).imag() != 0.0f)){
    //                    for(size_t k = 0; k < a.rows(); k++){
    //                        y = tmpa(i, k);
    //                        tmpa(i, k) = tmpa(j, k);
    //                        tmpa(j, k) = y;
    //                        y = c(i,k);
    //                        c(i, k) = c(j, k);
    //                        c(j, k) = y;
    //                    }
    //                    err = false;
    //                    break;
    //                };
    //            }
    //            if(err){
    //                printf("ERROR!!No inverse matrix available.\n");
    //            }
    //        }
    //        for(size_t j = 0; j < a.rows(); j++){
    //            devfcomplex_const(tmpa(j, i), tmpa(i, i), tmpfc);
    //            x = -tmpfc;
    //            if(i == j){
    //                x = std::complex<float>(0.0f, 0.0f);
    //            }
    //            for(size_t k = 0; k < a.rows(); k++){
    //                mulfcomplex_const(x, c(i, k), tmpfc);
    //                addfcomplex_const(c(j, k), tmpfc, tmpfc2);
    //                c(j, k) = tmpfc2;
    //                mulfcomplex_const(x, tmpa(i, k), tmpfc);
    //                addfcomplex_const(tmpa(j, k), tmpfc, tmpfc2);
    //                tmpa(j, k) = tmpfc2;
    //            }
    //        }
    //        x = tmpa(i, i);
    //        for(size_t k = 0; k < a.rows(); k++){
    //            devfcomplex_const(tmpa(i, k), x, tmpfc);
    //            tmpa(i, k) = tmpfc;
    //            devfcomplex_const(c(i, k), x, tmpfc);
    //            c(i, k) = tmpfc;
    //        }
    //    }
    //}
    //else{
    //    printf("Error : invMAT : Not a square matrix.\n");
    //}
    c.noalias() = a.inverse();
}

/*Multiplying 2 matrices by each element :  a[m,n] .* b[m,n] = c[m,n] */
 void mulMATdot(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& b, Matrix<std::complex<float> >& c)
{
    //for(size_t i = 0; i < a.rows(); i++){
    //    for(size_t j = 0; j < a.cols(); j++){
    //        mulfcomplex_const(a(i, j), b(i, j), c(i, j));
    //    }
    //}
    c.noalias() = a;
    c.cwiseProduct(b);
}

/*Deviding 2 matrices by each element :  a[m,n] ./ b[m,n] = c[m,n] */
void devMATdot(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& b, Matrix<std::complex<float> >& c)
{
    //for(size_t i = 0; i < a.rows(); i++){
    //    for(size_t j = 0; j < a.cols(); j++){
    //        devfcomplex_const(a(i, j), b(i, j), c(i, j));
    //    }
    //}
    c.noalias() = a;
    c.cwiseQuotient(b);
}


/********************************************************************************/

/* make a zero matrix which is the same size of "a" and substitute it to "c" */
void zeroMAT(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& c)
{
    //for(size_t i = 0; i < a.rows(); i++) {
    //    for(size_t j = 0; j < a.cols(); j++) {
    //        c(i, j) = std::complex<float>(0.0f, 0.0f);
    //    }
    //}
    c.resize(a.rows(), a.cols());
    c.setZero();
}

/* make an identity matrix which is the same size of "a" and substitute it to "c" */
void identityMAT(Matrix<std::complex<float> >& a, Matrix<std::complex<float> >& c)
{
    //for(size_t i = 0; i < a.rows(); i++) {
    //    for(size_t j = 0; j < a.cols(); j++) {
    //        if(i==j){
    //            c(i, j) = std::complex<float>(1.0f, 0.0f);
    //        }
    //        else{
    //            c(i, j) = std::complex<float>(0.0f, 0.0f);
    //        }
    //    }
    //}
    c.resize(a.rows(), a.cols());
    c.setIdentity();
}


/********************************************************************************/

// Display a matrix
void display_fcmat(Matrix<std::complex<float> >& a)
{
    printf("*************************************************************\n");
    for(size_t i = 0; i < a.rows(); i++){
        for(size_t j = 0; j < a.cols(); j++){
            printf("%f + %f i\t", a(i, j).real(), a(i, j).imag());
        }
        printf("\n\n");
    }
}

/********************************************************************************/

/*Load matrix data*/
//char name1[80] = "data1.mat";
//char name2[80] = "data2.mat";
//read_fcmat(name1,name2,A);
void read_fcmat(char *name1,char *name2, Matrix<std::complex<float> >& a)
{  
    FILE *fp1;
    FILE *fp2;
    float tmp1 = 1.0000010e-002;
    float tmp2 = 1.1234567e-001;
    //printf("%f\n",tmp1);
    //printf("%f\n",tmp2);

    if(NULL == (fp1=fopen(name1, "r"))) {
        printf("no such file '%s'.\n", name1);
    }
    if(NULL == (fp2=fopen(name2, "r"))) {
        printf("no such file '%s'.\n", name2);
    }

    for(size_t i = 0; i < a.rows(); i++){
        for(size_t j = 0; j < a.cols(); j++){
            fscanf(fp1, "%f", &tmp1);
            fscanf(fp2, "%f", &tmp2);
            //printf("%f\n",tmp2);
            a(i, j) = std::complex<float>(tmp1, tmp2);
        }
        fscanf(fp1, "\n");
        fscanf(fp2, "\n");
    }
    //printf("%f + %f i\n",a(4, 4).real(), a(4, 4).imag());
    fclose(fp1);
    fclose(fp2);
}

/* Save matrix data */
int save_mat_fcmat(char *name1, char *name2, Matrix<std::complex<float> >& a)
{
    FILE *fp1;
    FILE *fp2;

    fp1 = fopen(name1, "w");
    fp2 = fopen(name2, "w");
    for(size_t i = 0; i < a.rows(); i++){
        for(size_t j = 0; j < a.cols(); j++){
            fprintf(fp1, "%8.6e ", a(i, j).real());
            fprintf(fp2, "%8.6e ", a(i, j).imag());
        }
        fprintf(fp1, "\n");
        fprintf(fp2, "\n");
    }

    fclose(fp1);
    fclose(fp2);

    return 0;
}

int save_mat_fcmat_real(char *name1, Matrix<std::complex<float> >& a)
{
    FILE *fp1;

    fp1 = fopen(name1, "w");
    for(size_t i = 0; i < a.rows(); i++){
        for(size_t j = 0; j < a.cols(); j++){
            fprintf(fp1, "%8.6e ", a(i, j).real());
        }
        fprintf(fp1, "\n");
    }

    fclose(fp1);

    return 0;
}

void save_mat_fmat_real(char *name1, Matrix<float>& a)
{
    FILE *fp1;

    fp1=fopen(name1, "w");
    for(size_t i = 0; i < a.rows(); i++){
        for(size_t j = 0; j < a.cols(); j++){
            fprintf(fp1, "%8.6e ", a(i, j));
        }
        fprintf(fp1, "\n");
    }

    fclose(fp1);
}

/********************************************************************************/

void AddToCorrelationAllFreq(std::vector<Matrix<std::complex<float> > >& Rxx, int FreqLength, Matrix<std::complex<float> >& X)
{
    for(size_t k = 0; k < FreqLength; k++) {
        Rxx[k] = Rxx[k] + X.col(k) * X.col(k).transpose();
        //Rxx[k] += outer_prod(ublas::column(X, k), ublas::herm(ublas::column(X, k)));
    }
}

void NormalizeCorrelationAllFreq(std::vector<Matrix<std::complex<float> > >& Rxx, int FreqLength, int sum_count)
{
    float sum_count_1 = 1.0f / sum_count;
    for(size_t k = 0; k < FreqLength; k++) {
        Rxx[k] = Rxx[k] * sum_count_1;
    }
}

void ClearCorrelationAllFreq(std::vector<Matrix<std::complex<float> > >& Rxx, int FreqLength)
{
    for(size_t k = 0; k < FreqLength; k++) {
        //for(size_t i = 0; i < Rxx[k].rows(); i++){
        //    for(size_t j = 0; j < Rxx[k].cols(); j++){
        //        Rxx[k](i, j) = 0.0f;
        //    }
        //}
        Rxx[k].setZero();
    }
}

/********************************************************************************/

/* make diag(a) */
void makeLambda(std::vector<float>& a, Matrix<std::complex<float> >& b, float decay)
{
    //std::complex<float> z = 0.0f;
    //for(size_t i = 0; i < b.rows(); i++){
    //    for(size_t j = 0; j < b.cols(); j++){
    //        b(i, j) = z;
    //        if(i == j) {
    //            if(a[i] >= 0.0f) {
    //                b(i, i) = std::complex<float>(std::pow(a[i], decay), 0.0f);
    //            }
    //            if(a[i] < 0.0f) {
    //                b(i, i) = std::complex<float>(-1.0f * std::pow(-1.0f * a[i], decay), 0.0f);
    //            }
    //        }
    //    }
    //}
    b.setZero();
    for(size_t i = 0; i < std::min(b.rows(), b.cols()); i++){
        if(a[i] >= 0.0f) {
            b(i, i) = std::complex<float>(std::pow(a[i], decay), 0.0f);
        }
        else {
            b(i, i) = std::complex<float>(-1.0f * std::pow(-1.0f * a[i], decay), 0.0f);
        }
    }
}

/********************************************************************************/

// Matrix norm display
void norm_display_fcmat(Matrix<std::complex<float> >& a)
{
  for(size_t m = 0; m < a.cols(); m++){
    float eigvec_norm = a.col(m).cwiseProduct(a.col(m)).sum().real(); 
    //float eigvec_norm = norm(ublas::inner_prod(ublas::herm(ublas::column(a, m)),ublas::column(a, m)));
    printf("%f\t", eigvec_norm);
  }
  printf("\n");
}


struct eigenvalue_ascending_sort : public std::binary_function<std::pair<float, Matrix<std::complex<float> > >, std::pair<float, Matrix<std::complex<float> > >, bool> {
  bool operator()(const std::pair<float, Matrix<std::complex<float> > >& x, const std::pair<float, Matrix<std::complex<float> > >& y) const {
    return x.first < y.first;
  }
};

struct eigenvalue_descending_sort : public std::binary_function<std::pair<float, Matrix<std::complex<float> > >, std::pair<float, Matrix<std::complex<float> > >, bool> {
    bool operator()(const std::pair<float, Matrix<std::complex<float> > >& x, const std::pair<float, Matrix<std::complex<float> > >& y) const {
        return x.first > y.first;
    }
};

// Sort eigenvectors depending on their eigenvalue (ascending order)
void sort_eig_fvec_ascending(std::vector<float>& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::pair<float, Matrix<std::complex<float> > > > result;

    // make pair
    for(size_t i = 0; i < ai.size(); i++){
        result.push_back(std::make_pair(ai[i], bi.col(i)));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_ascending_sort());

    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = result[i].first;
        bf.col(i).noalias() = result[i].second;
    }
}

// Sort eigenvectors depending on their eigenvalue (descending order)
void sort_eig_fvec_descending(std::vector<float>& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::pair<float, Matrix<std::complex<float> > > > result;

    // make tuple
    for(size_t i = 0; i < ai.size(); i++){
        result.push_back(std::make_pair(ai[i], bi.col(i)));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_descending_sort());

    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = result[i].first;
        bf.col(i).noalias() = result[i].second;
    }
}

/* tuple version
struct eigenvalue_ascending_sort : public binary_function<std::tuple<float, std::vector<std::complex<float> > >, std::tuple<float, std::vector<std::complex<float> > >, bool> {
    bool operator()(const std::tuple<float, std::vector<std::complex<float> > >& x, const std::tuple<float, std::vector<std::complex<float> > >& y) const {
        return std::get<0>(x) < std::get<0>(y);
    }
};

struct eigenvalue_descending_sort : public binary_function<std::tuple<float, std::vector<std::complex<float> > >, std::tuple<float, std::vector<std::complex<float> > >, bool> {
    bool operator()(const std::tuple<float, std::vector<std::complex<float> > >& x, const std::tuple<float, std::vector<std::complex<float> > >& y) const {
        return std::get<0>(x) > std::get<0>(y);
    }
};

// Sort eigenvectors depending on their eigenvalue (ascending order)
void sort_eig_fvec_ascending(std::vector<float>& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::tuple<float, std::vector<std::complex<float> > > > result;

    // make tuple
    for(size_t i = 0; i < ai.size(); i++){
        result.push_back(std::make_tuple(ai[i], bi.col(i)));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_ascending_sort());

    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = std::get<0>(result[i]);
        bf.col(i).noalias() = std::get<1>(result[i]);
    }
}

// Sort eigenvectors depending on their eigenvalue (ascending order)
void sort_eig_fcvec_ascending(std::vector<std::complex<float> >& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::tuple<float, std::vector<std::complex<float> > > > result;

    // make tuple
    for(size_t i = 0; i < ai.size(); i++){
        float eigval = std::sqrt(ai[i].real() * ai[i].real() + ai[i].imag() * ai[i].imag());
        result.push_back(std::make_tuple(eigval, bi.col(i)));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_ascending_sort());
  
    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = std::get<0>(result[i]);
        bf.col(i).noalias() = std::get<1>(result[i]);
    }
}

// Sort eigenvectors depending on their eigenvalue (descending order)
void sort_eig_fvec_descending(std::vector<float>& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::tuple<float, std::vector<std::complex<float> > > > result;

    // make tuple
    for(size_t i = 0; i < ai.size(); i++){
        result.push_back(std::make_tuple(ai[i], bi.col(i)));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_descending_sort());

    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = std::get<0>(result[i]);
        bf.col(i).noalias() = std::get<1>(result[i]);
    }
}

// Sort eigenvectors depending on their eigenvalue (descending order)
void sort_eig_fcvec_descending(std::vector<std::complex<float> >& ai, Matrix<std::complex<float> >& bi, std::vector<float>& af, Matrix<std::complex<float> >& bf)
{
    std::vector<std::tuple<float, std::vector<std::complex<float> > > > result;

    // make tuple
    for(size_t i = 0; i < ai.size(); i++){
        float eigval = std::sqrt(ai[i].real() * ai[i].real() + ai[i].imag() * ai[i].imag());
        result.push_back(std::make_tuple(eigval, bi.col(i));
    }

    // sort
    std::sort(result.begin(), result.end(), eigenvalue_descending_sort());

    // make finalized eigenvalues and eigenvectors
    for(size_t i = 0; i < ai.size(); i++){
        af[i] = std::get<0>(result[i]);
        bf.col(i).noalias() = std::get<1>(result[i]);
    }
}
*/


/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/

/*Load Correlation Matrix*/
//char name1[80] = "data1.mat";
//char name2[80] = "data2.mat";
//read_fcmat(name1,name2,A);
/*
void LoadCorrelation(char *name1, char *name2, std::vector<Matrix<std::complex<float> > >& Rxx)
{
    std::ifstream fin1;
    std::ifstream fin2;
    std::ifstream::pos_type cp1;
    std::ifstream::pos_type cp2;
    std::string buffer1;
    std::string buffer2;
    std::vector<std::string> tokens1;
    std::vector<std::string> tokens2;

    typedef boost::tokenizer<boost::char_separator<char> > tokenizer_space;
    boost::char_separator<char> sep(" ");

    Rxx.resize(0);

    fin1.open(name1);
    if(fin1.fail()) {
        printf("no such file '%s'.\n", name1);
        exit(1);
    }

    fin2.open(name2);
    if(fin2.fail()) {
        printf("no such file '%s'.\n", name2);
        exit(1);
    }

    while(1){
        cp1=fin1.tellg();
        getline(fin1, buffer1);

        cp2=fin2.tellg();
        getline(fin2, buffer2);

        if(fin1.eof() || fin2.eof()) return;

        tokens1.resize(0);
        tokenizer_space tokenizer1(buffer1, sep);
        for(tokenizer_space::iterator it1 = tokenizer1.begin(); it1 != tokenizer1.end(); ++it1) {
            tokens1.push_back(*it1);
        }

        tokens2.resize(0);
        tokenizer_space tokenizer2(buffer2, sep);
        for(tokenizer_space::iterator it2 = tokenizer2.begin(); it2 != tokenizer2.end(); ++it2) {
            tokens2.push_back(*it2);
        }

        int nb_channels1 = (int)(floor(sqrtf((float)tokens1.size())));
        int nb_channels2 = (int)(floor(sqrtf((float)tokens2.size())));
        if(nb_channels1 != nb_channels2) {
            printf("CMLoad. Size mismatched. (%d, %d)\n", nb_channels1, nb_channels2);
            exit(1);
        }
        if(tokens1.size() != nb_channels1 * nb_channels1){
            printf("CMLoad. Size mismatched. (%d, %d)\n", tokens1.size(), nb_channels1 * nb_channels1);
            exit(1);
        }
        Matrix<std::complex<float> > cormat(nb_channels1, nb_channels1);
        for(int i=0; i < nb_channels1; i++){
            for(int j=0; j < nb_channels1; j++){
                float tmp1 = lexical_cast<float>(tokens1[j + nb_channels1 * i]);
                float tmp2 = lexical_cast<float>(tokens2[j + nb_channels1 * i]);
                cormat(i,j) = std::complex<float>(tmp1, tmp2);
            }
        }

        Rxx.push_back(cormat);
    }

    fin1.close();
    fin2.close();
}
*/

/*Save Correlation Matrix*/
//char name1[80] = "data1.mat";
//char name2[80] = "data2.mat";
/*
void SaveCorrelation(char *name1, char *name2, vector<Matrix<std::complex<float> > >& Rxx)
{  
  FILE *fp1;
  FILE *fp2;

  int k, i, j;
  int veccol = Rxx.size();
  int row = Rxx[0].rows();
  int col = Rxx[0].cols();

  fp1=fopen(name1, "w");
  fp2=fopen(name2, "w");

    for(size_t k = 0; k < Rxx.size(); k++){
        for(size_t i = 0; i < Rxx[0].rows(); i++){
            for(size_t j = 0; j < Rxx[0].cols(); j++){
                fprintf(fp1, "%8.6e ", Rxx[k](i, j).real());
                fprintf(fp2, "%8.6e ", Rxx[k](i, j).imag());
            }
        }
        fprintf(fp1, "\n");
        fprintf(fp2, "\n");
    }
    fclose(fp1);
    fclose(fp2);
}
*/

/* end of file */
