#if defined(TBPM_USE_MKL)
#include<mkl.h>
#endif
#include <time.h>
#include <eigen3/Eigen/Sparse>
#include <numeric>
#include "base/consts.h"
#include "base/datatypes.h"
#include "tbpm/csr.h"
#include "tbpm/dense.h"
#include "tbpm/utils.h"
#include "base/utils.h"
#include "base/parallel.h"
#include "builder/advanced.h"
#include "builder/base.h"
#include "builder/materials.h"
#include "builder/primitive.h"
#include "diag/base.h"
#include "diag/lindhard.h"
#include "diag/magnetic.h"
#include "diag/z2.h"
#include "tbpm/solver.h"

using namespace tbplas::base;
using namespace tbplas::builder;
using namespace tbplas::builder;
using namespace tbplas::diag;
using namespace tbplas::tbpm;
using tbplas::base::complex_t;
using tbplas::base::INFINITESIMAL;
using tbplas::tbpm::CSRMatrixSquare;
using tbplas::tbpm::RandomGenerator;
using model_t = PrimitiveCell<complex_t>;
#define N 1
#define EXTEND 1000
#define C 40000


std::list<double> mv;
std::list<double> amv;
std::list<double> amvsy;
std::list<double> amvpby;
std::list<double> amvsy_out;
std::list<double> xmy;

// template <typename idx_t, typename value_t, typename vx_t, typename vy_t>
// double test_mv(const std::vector<idx_t>& indptr,const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values, const Eigen::MatrixBase<vx_t>& x,Eigen::MatrixBase<vy_t>& y)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //MKL_INT rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     //mat.print();
//     mat.mv(x, y);
//     end = clock();   
//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }

// template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t>
// double test_amv(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const sa_t& a, const Eigen::MatrixBase<vx_t>& x,Eigen::MatrixBase<vy_t>& y)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.amv(a,x, y);
//     end = clock();

//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }

// template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t>
// double test_amvpy(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const sa_t& a, const Eigen::MatrixBase<vx_t>& x, Eigen::MatrixBase<vy_t>& y)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.amxpy(a, x, y);
//     end = clock();

//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }

// template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t,typename vout_t>
// double test_amvpy_out(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const sa_t& a, const Eigen::MatrixBase<vx_t>& x, const Eigen::MatrixBase<vy_t>& y, Eigen::MatrixBase<vout_t>& out)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.amxpy_out(a, x, y, out);
//     end = clock();
//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }



// template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t, typename vout_t>
// double test_amvmy_out(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const sa_t& a, const Eigen::MatrixBase<vx_t>& x, const Eigen::MatrixBase<vy_t>& y, Eigen::MatrixBase<vout_t>& out)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.amxmy_out(a, x, y, out);
//     end = clock();
//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }

// template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename sb_t, typename vy_t>
// double test_amvpby(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const sa_t& a, const Eigen::MatrixBase<vx_t>& x, const sb_t& b,
//     Eigen::MatrixBase<vy_t>& y)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.amxpby(a, x, b, y);
//     end = clock();
//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }

// template <typename idx_t, typename value_t,  typename vx_t, typename vy_t>
// double test_xmy(const std::vector<idx_t>& indptr, const std::vector<idx_t>& indices,
//     const Eigen::MatrixBase<value_t>& values,
//     const Eigen::MatrixBase<vx_t>& x,const Eigen::MatrixBase<vy_t>& y)
// {
//     clock_t start, end;

//     start = clock();
//     CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
//     //long long rows, cols;
//     //std::tie(rows, cols) = mat.get_matrix_size();
//     //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
//     mat.xmy(x,y);
//     end = clock();
//     double time = double(end - start) / CLOCKS_PER_SEC;
//     //std::cout << "  time " << time << "s" << std::endl;
//     return time;
// }



//不生成仅计算
template <typename idx_t, typename value_t, typename vx_t, typename vy_t>
double test_mv_cal(const CSRMatrixSquare<idx_t, value_t>&mat, const Eigen::MatrixBase<vx_t>& x, Eigen::MatrixBase<vy_t>& y)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //MKL_INT rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    //mat.print();
    mat.mv(x, y);
    end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}

template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t>
double test_amv_cal(const CSRMatrixSquare<idx_t, value_t>& mat,
    const sa_t& a, const Eigen::MatrixBase<vx_t>& x, Eigen::MatrixBase<vy_t>& y)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //long long rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    mat.amv(a, x, y);
    end = clock();

    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}

template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t>
double test_amvsy_cal(const CSRMatrixSquare<idx_t, value_t>& mat,
    const sa_t& a, const Eigen::MatrixBase<vx_t>& x, Eigen::MatrixBase<vy_t>& y)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //long long rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    mat.amxsy(a, x, y);
    end = clock();

    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}


template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename vy_t, typename vout_t>
double test_amvsy_out_cal(const CSRMatrixSquare<idx_t, value_t>& mat,
    const sa_t& a, const Eigen::MatrixBase<vx_t>& x, const Eigen::MatrixBase<vy_t>& y, Eigen::MatrixBase<vout_t>& out)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //long long rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    mat.amxsy_out(a, x, y, out);
    end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}

template <typename idx_t, typename value_t, typename sa_t, typename vx_t, typename sb_t, typename vy_t>
double test_amvpby_cal(const CSRMatrixSquare<idx_t, value_t>& mat,
    const sa_t& a, const Eigen::MatrixBase<vx_t>& x, const sb_t& b,
    Eigen::MatrixBase<vy_t>& y)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //long long rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    mat.amxpby(a, x, b, y);
    end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}

template <typename idx_t, typename value_t, typename vx_t, typename vy_t>
double test_xmy_cal(const CSRMatrixSquare<idx_t, value_t>& mat,
    const Eigen::MatrixBase<vx_t>& x, const Eigen::MatrixBase<vy_t>& y)
{
    clock_t start, end;

    start = clock();
    //CSRMatrixSquare<idx_t, value_t> mat(indptr, indices, values);
    //long long rows, cols;
    //std::tie(rows, cols) = mat.get_matrix_size();
    //std::cout << "mat_size:" << rows<<"*"<<cols << std::endl;
    mat.xmy(x, y);
    end = clock();
    double time = double(end - start) / CLOCKS_PER_SEC;
    //std::cout << "  time " << time << "s" << std::endl;
    return time;
}









void average(std::list<double>& l)
{
    if (!l.empty()) {
        double sum = std::accumulate(l.begin(), l.end(), 0.0);
        double average = sum / (1.0 * l.size());
        l.push_back(sum);
        l.push_back(average);
    }
    else {
        std::cout << "List is empty." << std::endl;
    }
}

double total(std::list<double>& l)
{
    if (!l.empty()) {
        double sum = std::accumulate(l.begin(), l.end(), 0.0);
        l.push_back(sum);
        return sum;
    }
    else {
        std::cout << "List is empty." << std::endl;
    }
}


double calc_hop(const Term& term)
{
    constexpr double a0 = 0.1418;
    constexpr double a1 = 0.3349;
    constexpr double r_c = 0.6140;
    constexpr double l_c = 0.0265;
    constexpr double gamma0 = 2.7;
    constexpr double gamma1 = 0.48;
    constexpr double decay = 22.18;
    constexpr double q_pi = decay * a0;
    constexpr double q_sigma = decay * a1;
    double dr = term.distance;
    double n = term.rij(2) / dr;
    double v_pp_pi = -gamma0 * exp(q_pi * (1 - dr / a0));
    double v_pp_sigma = gamma1 * exp(q_sigma * (1 - dr / a1));
    double fc = 1 / (1 + exp((dr - r_c) / l_c));
    double hop = (n * n * v_pp_sigma + (1 - n * n) * v_pp_pi) * fc;
    return hop;
}

PrimitiveCell<complex_t> test_tbg()
{
    Timer timer;
    timer.tic("tbg");

    // Build layers
    auto fixed_cell = make_graphene_diamond();
    PrimitiveCell<complex_t> twisted_cell = fixed_cell;
    for (int i = 0; i < 2; ++i) {
        twisted_cell.set_orbital_energy(i, -1.0);
    }

    // Twist top layer
    int tbg_idx = 100;
    double cos_ang = (3 * tbg_idx * tbg_idx + 3 * tbg_idx + 0.5) / (3 * tbg_idx * tbg_idx + 3 * tbg_idx + 1);
    double angle = acos(cos_ang);
    double shift = 0.3349;
    twisted_cell.rotate(angle, Eigen::Vector3d::Zero(), shift);

    // Evaluate hetero-lattice
    double i = tbg_idx * 1.0;
    Eigen::Matrix3d hetero_lattice{ { i, i + 1, 0 }, { -(i + 1), 2 * i + 1, 0 }, { 0, 0, 1 } };
    hetero_lattice = frac2cart(fixed_cell.get_lattice(), hetero_lattice.transpose()).transpose();

    // Build layers
    PrimitiveCell<complex_t> layer_fixed = make_hetero_layer(fixed_cell, hetero_lattice, 1e-5);
    PrimitiveCell<complex_t> layer_twisted = make_hetero_layer(twisted_cell, hetero_lattice, 1e-5);

    // // Build inter-hopping terms
    PCInterHopping<complex_t> inter_hop(0, 1);
    std::list<Term> neighbors =find_neighbors(layer_fixed, layer_twisted, 1, 1, 0, 0.75);
    for (const auto& n : neighbors) {
        cell_index_t ra, rb, rc;
        orbital_index_t orb_i, orb_j;
        std::tie(ra, rb, rc) = n.rn;
        std::tie(orb_i, orb_j) = n.pair;
        inter_hop.add_hopping(ra, rb, rc, orb_i, orb_j, calc_hop(n));
    }

    // Merge cells
    std::vector<const PrimitiveCell<complex_t>*> prim_cells = { &layer_fixed, &layer_twisted };
    std::vector<const PCInterHopping<complex_t>*> inter_hops = { &inter_hop };
    PrimitiveCell<complex_t> merged_cell = merge_prim_cell(prim_cells, inter_hops);
    return merged_cell;
}

//ldos_haydock
PrimitiveCell<complex_t> test_tbpm_dos()
{
    double t = 2.7;
    model_t model = make_graphene_diamond(t);
    model.set_orbital_energy(0, 1.0);
    model.set_orbital_energy(1, -1.0);
    model = extend_prim_cell(model, { EXTEND, EXTEND, 1 });
    return model;
}

// //省略
// PrimitiveCell<complex_t> test_ac_cond()
// {
    // double t = -2.7;
    // model_t model = make_graphene_diamond(t);
    // // model.set_orbital_energy(0, 1.0);
    // // model.set_orbital_energy(1, -1.0);
    // model = extend_prim_cell(model, { EXTEND, EXTEND, 1 });
    // return model;
// }




//int main()
//{
//    mkl_set_dynamic( 1 );
//    int threads = mkl_get_max_threads();
//    std::cout << "Intel MKL employs " << threads << " threading\n" << std::endl;
//    for (int k = 0; k < N; ++k)
//    {
//        for (int j = 0; j < 2; j++)
//        {
//
//            std::vector<orbital_index_t> indptr;
//            std::vector<orbital_index_t> indices;
//            Eigen::VectorXcd values;
//            PrimitiveCell<complex_t> fix_cell_;
//            if (j == 0)
//            {
//                std::cout << "tbg" << std::endl;
//                 fix_cell_ = test_tbg();
//            }
//            //else if (j == 1)
//            //{
//            //    std::cout << "ac_cond" << std::endl;
//            //    fix_cell_ = test_ac_cond();
//            //}
//            else
//            {
//                std::cout << "tbpm_dos" << std::endl;
//                fix_cell_ = test_tbpm_dos();
//            }
//            fix_cell_.build_ham_csr(indptr, indices, values);
//            std::cout << "indptr.size:" << indptr.size() << std::endl;
//            //std::cout << "indices.size:" << indices.size() << std::endl;
//            std::cout << "values.size:" << values.rows() << "*1" << std::endl;
//            //{100,100,1} mat 20000*20000 8000个非零元素
//                // 使用.array()方法判断是否存在元素(0.0, 0.0),存在1，不存在0
//            bool containsZero = (values.array() == std::complex<double>(0.0, 0.0)).any();
//            std::cout << "containsZero==" << containsZero << std::endl;
//
//            CSRMatrixSquare<orbital_index_t, Eigen::VectorXcd> mat(indptr, indices, values);
//            RandomGenerator rand;
//            Eigen::VectorXcd x(indptr.size() - 1), y(indptr.size() - 1);
//            Eigen::VectorXcd out(indptr.size() - 1);
//            double t = 0;
//            mv.clear();
//            amv.clear();
//            amvsy.clear();
//            amvpby.clear();
//            amvsy_out.clear();
//            xmy.clear();
//            for (int i = 0; i < C; i += 2)
//            {
//                rand.random_state(x, i);
//                rand.random_state(y, i + 1);
//                // t = test_mv_cal(mat, x, out);
//                // mv.push_back(t);
//                 complex_t a = (rand.random_number(i), rand.random_number(i + 1));
//                // t = test_amv_cal(mat, a, x, out);
//                // amv.push_back(t);
//                // t = test_amvpy_out_cal(mat, a, x, y, out);
//                // amvsy_out.push_back(t);
//                // t = test_xmy_cal(mat, x, y);
//                // xmy.push_back(t);
//                // t = test_amvsy_cal(mat, a, x, y);
//                // amvsy.push_back(t);
//                complex_t b = (rand.random_number(i + 2), rand.random_number(i + 3));
//                rand.random_state(out, i + 1);
            //    t = test_amvpby_cal(mat, a, x, b, out);
            //    amvpby.push_back(t);
            //}
            //double sum = 0.0;
            //double tt = 0.0;
            //double ii=0.0;
            // tt = total(mv);
            // sum += tt;
            // ii++;
            // std::cout << "mv_total:" << tt << "s" << std::endl;
//
            // tt = total(amv);
            // std::cout << "amv_total:" << tt << "s" << std::endl;
            // sum += tt;
            // ii++;
//
            // tt = total(amvsy);
            // std::cout << "amvsy_total:" << tt << "s" << std::endl;
            // sum += tt;
            // ii++;
//
            // tt = total(amvsy_out);
            // std::cout << "amvsy_out_total:" << tt << "s" << std::endl;
            // sum += tt;
            // ii++;
//
            //tt = total(amvpby);
            //std::cout << "amvby_total:" << tt << "s" << std::endl;
            //sum += tt;
            //ii++;
//
            // tt = total(xmy);
            // std::cout << "xmy_total:" << tt << "s" << std::endl;
            // sum += tt;
            // ii++;
//
//            double avrg = sum / ii;
//            std::cout << "total_average:" << avrg << "s" << std::endl;
//        }
//    }
//    return 0;
//}

//int main()
//{
//    for (int j = 0; j < 2; j++)
//    {
//        
//        std::vector<orbital_index_t> indptr;
//        std::vector<orbital_index_t> indices;
//        Eigen::VectorXcd values;
//        PrimitiveCell<complex_t> fix_cell_;
//        if (j == 0)
//        {
//            std::cout << "tbg" << std::endl;
//            fix_cell_=test_tbg();
//        }
//        //else if (j == 1)
//        //{
//        //    std::cout << "ac_cond" << std::endl;
//        //    fix_cell_ = test_ac_cond();
//        //}
//        else 
//        {
//            std::cout << "tbpm_dos" << std::endl;
//            fix_cell_=test_tbpm_dos();
//        }
//        fix_cell_.build_ham_csr(indptr, indices, values);
//        std::cout << "indptr.size:" << indptr.size() << std::endl;
//        //std::cout << "indices.size:" << indices.size() << std::endl;
//        std::cout << "values.size:" << values.rows() << "*1" << std::endl;
//        //{100,100,1} mat 20000*20000 8000个非零元素
//            // 使用.array()方法判断是否存在元素(0.0, 0.0),存在1，不存在0
//        bool containsZero = (values.array() == std::complex<double>(0.0, 0.0)).any();
//        std::cout << "containsZero==" << containsZero << std::endl;
//        RandomGenerator rand;
//        Eigen::VectorXcd x(indptr.size() - 1), y(indptr.size() - 1);
//        Eigen::VectorXcd out(indptr.size() - 1);
//        double t = 0;
//        mv.clear();
//        amv.clear();
//        amvpy.clear();
//        amvpy_out.clear();
//        amvpby.clear();
//        amvmy_out.clear();
//        xmy.clear();
//        for (int i = 0; i < N; i += 2)
//        {
//            rand.random_state(x, i);
//            rand.random_state(y, i + 1);
//            t = test_mv(indptr, indices, values, x, out);
//            mv.push_back(t);
//            complex_t a = (rand.random_number(i), rand.random_number(i + 1));
//            t = test_amv(indptr, indices, values, a, x, out);
//            amv.push_back(t);
//            t = test_amvpy_out(indptr, indices, values, a, x, y, out);
//            amvpy_out.push_back(t);
//            t = test_amvmy_out(indptr, indices, values, a, x, y, out);
//            amvmy_out.push_back(t);
//            t = test_xmy(indptr, indices, values, x, y);
//            xmy.push_back(t);
//            t = test_amvpy(indptr, indices, values, a, x, y);
//            amvpy.push_back(t);
//            complex_t b = (rand.random_number(i + 2), rand.random_number(i + 3));
//            rand.random_state(out, i + 1);
//            t = test_amvpby(indptr, indices, values, a, x, b, out);
//            amvpby.push_back(t);
//        }
//        average(mv);
//        std::cout << "mv_average:" << mv.back() << "s" << std::endl;
//        average(amv);
//        std::cout << "amv_average:" << amv.back() << "s" << std::endl;
//        average(amvpy);
//        std::cout << "amvpy_average:" << amvpy.back() << "s" << std::endl;
//        average(amvpy_out);
//        std::cout << "amvpy_out_average:" << amvpy_out.back() << "s" << std::endl;
//        average(amvmy_out);
//        std::cout << "amvmy_out_average:" << amvmy_out.back() << "s" << std::endl;
//        average(amvpby);
//        std::cout << "amvby_average:" << amvpby.back() << "s" << std::endl;
//        average(xmy);
//        std::cout << "xmy_average:" << xmy.back()<<"s" << std::endl;
//    }
//    return 0;
//}



//void print_sparse_matrix(sparse_matrix_t A) {
//    // 提取矩阵信息
//    sparse_index_base_t indexing;
//    MKL_INT rows, cols;
//    MKL_INT* rows_start, * rows_end, * col_indx;
//    MKL_Complex16* values;
//
//    // 获取 CSR 格式的数据
//    sparse_status_t status = mkl_sparse_z_export_csr(A, &indexing, &rows, &cols,
//        &rows_start, &rows_end,
//        &col_indx, &values);
//    if (status != SPARSE_STATUS_SUCCESS) {
//        printf("无法导出CSR格式的数据。\n");
//        return;
//    }
//    std::complex<double>* values_ = (std::complex<double>*)values;
//    // 打印稀疏矩阵信息
//    printf("稀疏矩阵 A:\n");
//    for (MKL_INT i = 0; i < rows; i++) {
//        for (MKL_INT j = rows_start[i]; j < rows_end[i]; j++) {
//            printf("A[%d, %d] = ", i + (indexing == SPARSE_INDEX_BASE_ONE), col_indx[j] + (indexing == SPARSE_INDEX_BASE_ONE));
//            std::cout << values_[j] << std::endl;
//        }
//    }
//}
//
//int main()
//{
//    MKL_INT rows_start[] = { 0, 3, 5, 6, 8 };
//    MKL_INT columns[] = { 0, 2, 3, 1, 3, 2, 0, 3 };
//    double values[] = { 2.0, 1.0, 7.0, 3.0, 2.0, 1.0, 3.0, 2.0 };
//    std::complex<double> values_1[] = { 2.0, 1.0, 7.0, 3.0, 2.0, 1.0, 3.0, 2.0 };
//    //MKL_Complex16 values_1[] = { {2.0,0.0}, {1.0,0.0}, {7.0,0.0}, {3.0,0.0}, {2.0,0.0}, {1.0,0.0}, {3.0,0.0}, {2.0,0.0} };
//    //
//    //// 矩阵维度
//    MKL_INT rows = sizeof(rows_start) / sizeof(rows_start[0]) - 1;
//    MKL_INT cols = *std::max_element(columns, columns + sizeof(columns) / sizeof(columns[0])) + 1;
//
//    //创建稀疏矩阵
//    sparse_matrix_t A;
//    sparse_status_t status = mkl_sparse_z_create_csr(&A, SPARSE_INDEX_BASE_ZERO,
//        rows, cols,
//        rows_start,
//        rows_start + 1,
//        columns,
//        (MKL_Complex16*)values_1);
//    //sparse_status_t status = mkl_sparse_z_create_csr(&A, SPARSE_INDEX_BASE_ZERO,
//    //    rows, cols,
//    //    rows_start,
//    //    rows_start + 1,
//    //    columns,
//    //    values_1);
//
//    if (status != SPARSE_STATUS_SUCCESS) {
//        std::cerr << "Failed to create sparse matrix" << std::endl;
//        exit(2);
//    }
//
//    std::cout << "A:" << std::endl;
//    print_sparse_matrix(A);
//        struct matrix_descr descr= DESC_HERMITIAN_UPPER_NONUNIT;
//
//        std::complex<double> x[] = { {1.0,0.0}, {2.0,0.0}, {3.0,0.0}, {4.0,0.0} };  // 输入向量
//        std::complex<double> y[4] = { {0.0,0.0 }, { 0.0,0.0 }, { 0.0,0.0 }, { 0.0,0.0 } };
//
//        std::complex<double> alpha = 1.0;                  // 缩放因子
//        std::complex<double> beta = 0.0;                   // 缩放因子]
//
//
//            // 执行稀疏矩阵-向量乘法
//        status = mkl_sparse_z_mv(SPARSE_OPERATION_NON_TRANSPOSE,
//            (MKL_Complex16)(*(MKL_Complex16*)(&alpha)), A, descr,
//            (MKL_Complex16*)x, (MKL_Complex16)(*(MKL_Complex16*)(&beta)), (MKL_Complex16*)y);
//
//        //MKL_Complex16 x[] = { {1.0,0.0}, {2.0,0.0}, {3.0,0.0}, {4.0,0.0} };  // 输入向量
//        //MKL_Complex16 y[4] = { {0.0,0.0 }, { 0.0,0.0 }, { 0.0,0.0 }, { 0.0,0.0 } };
//
//        //MKL_Complex16 alpha = { 1.0,0.0 };                  // 缩放因子
//        //MKL_Complex16 beta = { 0.0,0.0 };                   // 缩放因子]
//
//
//        //    // 执行稀疏矩阵-向量乘法
//        //status = mkl_sparse_z_mv(SPARSE_OPERATION_NON_TRANSPOSE,
//        //    alpha, A, descr,x, beta, y);
//
//        if (status != SPARSE_STATUS_SUCCESS) {
//            std::cerr << "Failed to perform sparse matrix-vector multiplication" << std::endl;
//            exit(1);
//        }
//        std::complex<double>* y_=(std::complex<double>*)y;
//
//        // 打印结果
//        std::cout << "Resulting vector y:\n";
//        for (int i = 0; i < 4; ++i) {
//            std::cout << y_[i] << " ";
//        }
//        std::cout << std::endl;
//
//        // 释放稀疏矩阵
//        mkl_sparse_destroy(A);
//    
//    return 0;
//}


// int main()
// {
//    std::vector<int> indptr = { 0, 3, 6, 8, 11 };
//    std::vector<int> indices = { 1, 2, 3,0, 1, 3,0, 2, 0, 1,3 };
//    Eigen::VectorXcd values_2{ { 2.0 }, { 1.0 }, { 7.0 }, {2.0}, { 3.0 }, { 2.0 },{1.0}, { 1.0 }, {7.0}, { 2.0 }, { 2.0 } };
   
//    CSRMatrixSquare<int, Eigen::VectorXcd> mat3(indptr, indices, values_2);


//    Eigen::Vector4cd vec_in(1.0, 2.0, 3.0, 4.0);
//    Eigen::Vector4cd vec_out2;
//    Eigen::Vector4cd vec_y(1.0, 2.0, 3.0, 4.0);
//    mat3.mv(vec_in, vec_out2);
//    std::cout<<vec_out2<<std::endl;
//    mat3.amv(1.0,vec_in, vec_out2);
//    std::cout<<vec_out2<<std::endl;
//    Eigen::Vector4cd vec_out1;
//    vec_out1.setZero();
//    mat3.amxpy(1.0, vec_in, vec_out1);
//    std::cout<<vec_out1<<std::endl;
//    mat3.amxpy_out(1.0, vec_in, vec_y, vec_out1);
//    std::cout<<vec_out1<<std::endl;
//    mat3.amxmy_out(1.0, vec_in, vec_y, vec_out1);
//    std::cout<<vec_out1<<std::endl;
//    std::complex<double>xmy = mat3.xmy(vec_in, vec_in);
//    std::cout<<xmy<<std::endl;
//    mat3.amxpby(1.0, vec_in, 1.0, vec_y);
//    std::cout<<vec_y<<std::endl;
// }
