// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the SUPERLU_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// SUPERLU_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef SUPERLU_EXPORTS
#define SUPERLU_API __declspec(dllexport)
#else
#define SUPERLU_API __declspec(dllimport)
#endif

#include "Common.h"
#include "slu_ddefs.h"
#include <vector>

class d_SuperLU 
	{

	private:	
	
	public:
		//Функция для транспонирования прямоугольной матрицы (CSR_to_CSC). 
		static void d_CSR_to_CSC(int m, int n, int nnz, 
		double *a, int *colind, int *rowptr,
		double **at, int **rowind, int **colptr);
	
		//Функция для получения матрицы усиления.
		static int d_Get_Gain_Matrix(int *M, int *N, int *nnz_J, 
			double *csrMatrix_J, int *csrColInd_J, int *csrRowPtr_J,
			double *Weight,
			int *nnz_G, double **csrMatrix_G, int **csrColInd_G, int **csrRowPtr_G);

		//Решатель от SuperLU предоставляющий две фазы: анализ, факторизацию и решение.
		static int SUPERLU_API d_SuperLU_Solver(int *M, int *nnz_LDMatrix, 
				double *csr_LDMatrix, int *csrColInd_LDMatrix, int *csrRowPtr_LDMatrix, 
				double *RHS, double **Solution,
				int *Phase, int *nrhs, bool UsePerm);

		static void SUPERLU_API Free_Memory_d_SuperLU_Solver(void);
	};

//Решатель от SuperLU предоставляющий три фазы: анализ, факторизация, решение.
//Решатель для вектора решения не выделяет память.
int d_SuperLU_Solver2(_MKL_DSS_HANDLE_t *ptr, int *M, int *nnz_A,
	double *csr_A, int *csrColInd_A, int *csrRowPtr_A,
	double *RHS, double *Solution,
	int *Phase, int *nrhs, bool UsePerm, double DiagPivotThreshold = 1.0);


struct Interal_SuperLU
{
	superlu_options_t options;

	SuperLUStat_t stat;

	std::vector<int> etree;
	std::vector<int> perm_c;
	std::vector<int> perm_r;

	SuperMatrix l;
	SuperMatrix u;
};

void dss_sym_destroy(Interal_SuperLU *sup);

Interal_SuperLU *dss_sym_create();

void dss_sym_reorder(Interal_SuperLU *sup, int dim, int nnz, int *csc_columns, int *csc_rows, double *csc_values);

/*
relax(input) int
To control degree of relaxing supernodes.If the number
of nodes(columns) in a subtree of the elimination tree is less
than relax, this subtree is considered as one supernode,
regardless of the row structures of those columns.

panel_size(input) int
A panel consists of at most panel_size consecutive columns.
*/
int dss_sym_factor(Interal_SuperLU *sup, int dim, int nnz, int *csc_columns, int *csc_rows, double *csc_values,
	int relax, int panel_size);

int dss_sym_refactor(Interal_SuperLU *sup, int dim, int nnz, int *csc_columns, int *csc_rows, double *csc_values,
	int relax, int panel_size);

int dss_sym_solve(Interal_SuperLU *sup, int dim, double *b, double *x);
