#pragma once

#include <mkl_types.h>

#ifdef PARDISO_EXPORTS
#define PARDISO_API __declspec(dllexport) 
#else
#define PARDISO_API __declspec(dllimport) 
#endif

namespace Monitel
{
	namespace MathNative
	{

		namespace Pardiso
		{
			/// <summary>
			/// Блочная матрица
			/// </summary>
			typedef struct
			{
				double f00; //= a00;
				double f01; //= a01;
				double f10;//= a10;
				double f11;/// = a11;
			}Block2x2;

			class INativePardisoProvider
			{
			public:

				/*Методы*/	
				virtual int Initialization(int n, int nrhs, Block2x2 * a, int * ja, int * ia, float *executionTime) = 0;				
				virtual int Initialization(int n, int nrhs, MKL_Complex16 * a, int * ja, int * ia, float *executionTime) = 0;
				virtual int Initialization(int n, int nrhs, double * a, int * ja, int * ia, float *executionTime) = 0;
				
				virtual int Factorization(int n, Block2x2 * a, int * ja, int * ia, float *converterTime, float *factorizationTime, int PivotingPerturbation) = 0;
				virtual int Factorization(int n, MKL_Complex16 * a, int * ja, int * ia, float *executionTime, int PivotingPerturbation) = 0;
				virtual int Factorization(int n, double * a, int * ja, int * ia, float *executionTime, int PivotingPerturbation) = 0;

				virtual int Solve(MKL_Complex16 * rhs, MKL_Complex16 * solution, float *executionTime) = 0;
				virtual int Solve(double * rhs, double * solution, float *executionTime) = 0;
				
				/*Cлужебные методы*/
				/// <summary>
				/// Получить вектор перестановок. Длина вектора равна n.
				/// </summary>
				/// <returns></returns>
				virtual int* GetPermutations() = 0;
				/// <summary>
				/// Получить диагональ факторизованной матрицы. Длина вектора равна n.
				/// </summary>
				/// <returns></returns>
				virtual void* GetFactorizedMatrixDiagonal() = 0;
				/// <summary>
				/// Получить диагональ исходной матрицы. Длина вектора равна n.
				/// </summary>
				/// <returns></returns>
				virtual void* GetInitialMatrixDiagonal() = 0;
				
				/*Свойства*/
				virtual void SetPermutationMethod(int method) = 0;
				virtual void SetIterativeRefinementStepNumber(int steps) = 0;
				virtual void SetUseAVX(bool status) = 0;
				
				virtual ~INativePardisoProvider(){ }
			};
			/// <summary>
			/// Создать экземпляр провайдера
			/// </summary>
			extern "C" PARDISO_API INativePardisoProvider *CreatePardisoSolverInstanse();
			/// <summary>
			/// Удалить экземпляр провайдера
			/// </summary>
			extern "C" PARDISO_API void ReleasePardisoSolverInstanse(INativePardisoProvider *pardisoProvider);
		}

	}
}
