
#ifndef __CUDAMATRIX_CUH__
#define __CUDAMATRIX_CUH__

#include <complex>
#include "AuroraDefs.h"
namespace{
    enum CompareType
    {
        G,GE,E,NE,LE,L
    };
    enum VecType
    {
        COL,ROW
    };
}

/**
 * @brief 矩阵逐元素加一个float值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryAdd(float *aMatrixIn, const float &aValue, float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素加一个complex<float>值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue complex<float>值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryAddc(std::complex<float> *aMatrixIn,
               const std::complex<float> &aValue,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/** 
 * @brief 两相同大小矩阵逐元素相加
 * @param aMatrixIn1 矩阵1数据指针
 * @param aMatrixIn2 矩阵2数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 * @param aValType1 矩阵1数据类型
 * @param aValType2 矩阵2数据类型
 */
void unaryAddmm(float *aMatrixIn1, float *aMatrixIn2, float *aMatrixOut,
                unsigned long aLength,
                Aurora::ValueType aValType1 = Aurora::Normal,
                Aurora::ValueType aValType2 = Aurora::Normal);

/**
 * @brief 矩阵与向量点对点相加
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aVectorIn 向量数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aMatrixLength 矩阵数据总长度
 * @param aVectorLength 向量数据总长度
 * @param aMatValType 矩阵数据类型，normal or complex
 * @param aVecValType 向量数据类型
 * @param aFuncType 函数执行方向，只支持 Row or Column
 */
void unaryAddmv(float *aMatrixIn, float *aVectorIn, float *aMatrixOut,
              unsigned long aMatrixLength,unsigned long aVectorLength,
              Aurora::ValueType aMatValType, Aurora::ValueType aVecValType, 
              Aurora::FunctionDirection aFuncType = Aurora::FunctionDirection::Column);

/**
 * @brief 矩阵逐元素乘一个float值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryMul(float *aMatrixIn, const float &aValue, float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素乘一个complex<float>值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue complex<float>值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryMulc(std::complex<float> *aMatrixIn,
               const std::complex<float> &aValue,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/** 
 * @brief 两相同大小矩阵逐元素相乘
 *
 * @param aMatrixIn1 矩阵1数据指针
 * @param aMatrixIn2 矩阵2数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 * @param aValType1 矩阵1数据类型
 * @param aValType2 矩阵2数据类型
 */
void unaryMulmm(float *aMatrixIn1, float *aMatrixIn2, float *aMatrixOut,
                unsigned long aLength,
                Aurora::ValueType aValType1 = Aurora::Normal,
                Aurora::ValueType aValType2 = Aurora::Normal);

/**
 * @brief 矩阵与向量点对点相乘
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aVectorIn 向量数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aMatrixLength 矩阵数据总长度
 * @param aVectorLength 向量数据总长度
 * @param aMatValType 矩阵数据类型，normal or complex
 * @param aVecValType 向量数据类型
 * @param aFuncType 函数执行方向，只支持 Row or Column
 */
void unaryMulmv(float *aMatrixIn1, float *aVectorIn2, float *aMatrixOut,
              unsigned long aMatrixLength,unsigned long aVectorLength,
              Aurora::ValueType aValType1, Aurora::ValueType aValType2, 
              Aurora::FunctionDirection aVectype = Aurora::FunctionDirection::Column);

/**
 * @brief 矩阵逐元素减一个float值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unarySub(float *aMatrixIn, const float &aValue, float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素被一个float值减
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unarySub(const float &aValue,float *aMatrixIn,  float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素减一个complex<float>值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue complex<float>值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unarySubc(std::complex<float> *aMatrixIn,
               const std::complex<float> &aValue,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/**
 * @brief 矩阵逐元素被一个complex<float>值减
 * 
 * @param aValue complex<float>值
  * @param aMatrixIn 矩阵数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unarySubc(const std::complex<float> &aValue,
                std::complex<float> *aMatrixIn,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/** 
 * @brief 两相同大小矩阵逐元素相减
 *
 * @param aMatrixIn1 矩阵1数据指针
 * @param aMatrixIn2 矩阵2数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 * @param aValType1 矩阵1数据类型
 * @param aValType2 矩阵2数据类型
 */
void unarySubmm(float *aMatrixIn1, float *aMatrixIn2, float *aMatrixOut,
                unsigned long aLength,
                Aurora::ValueType aValType1 = Aurora::Normal,
                Aurora::ValueType aValType2 = Aurora::Normal);

/**
 * @brief 矩阵与向量点对点相减
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aVectorIn 向量数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aMatrixLength 矩阵数据总长度
 * @param aVectorLength 向量数据总长度
 * @param aMatValType 矩阵数据类型，normal or complex
 * @param aVecValType 向量数据类型
 * @param aFuncType 函数执行方向，只支持 Row or Column
 * @param direction 减法执行方向, 0 mat - vec, 1 vec- mat
 */
void unarySubmv(float *aMatrixIn1, float *aVectorIn2, float *aMatrixOut,
              unsigned long aMatrixLength,unsigned long aVectorLength,
              Aurora::ValueType aValType1, Aurora::ValueType aValType2, 
              Aurora::FunctionDirection aVectype = Aurora::FunctionDirection::Column,
              int direction = 0);

/**
 * @brief 矩阵逐元素除以一个float值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryDiv(float *aMatrixIn, const float &aValue, float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素被一个float值除
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue float值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryDiv(const float &aValue,float *aMatrixIn,  float *aMatrixOut,
              unsigned long aLength);

/**
 * @brief 矩阵逐元素除以一个complex<float>值
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aValue complex<float>值
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryDivc(std::complex<float> *aMatrixIn,
               const std::complex<float> &aValue,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/**
 * @brief 矩阵逐元素被一个complex<float>值除
 * 
 * @param aValue complex<float>值
  * @param aMatrixIn 矩阵数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 */
void unaryDivc(const std::complex<float> &aValue,
                std::complex<float> *aMatrixIn,
               std::complex<float> *aMatrixOut, unsigned long aLength);

/** 
 * @brief 两相同大小矩阵逐元素相除
 *
 * @param aMatrixIn1 矩阵1数据指针
 * @param aMatrixIn2 矩阵2数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aLength 矩阵总元素长度
 * @param aValType1 矩阵1数据类型
 * @param aValType2 矩阵2数据类型
 */
void unaryDivmm(float *aMatrixIn1, float *aMatrixIn2, float *aMatrixOut,
                unsigned long aLength,
                Aurora::ValueType aValType1 = Aurora::Normal,
                Aurora::ValueType aValType2 = Aurora::Normal);

/**
 * @brief 矩阵与向量点对点相除
 * 
 * @param aMatrixIn 矩阵数据指针
 * @param aVectorIn 向量数据指针
 * @param aMatrixOut 输出矩阵数据指针
 * @param aMatrixLength 矩阵数据总长度
 * @param aVectorLength 向量数据总长度
 * @param aMatValType 矩阵数据类型，normal or complex
 * @param aVecValType 向量数据类型
 * @param aFuncType 函数执行方向，只支持 Row or Column
 * @param direction 减法执行方向, 0 mat - vec, 1 vec- mat
 */
void unaryDivmv(float *aMatrixIn1, float *aVectorIn2, float *aMatrixOut,
              unsigned long aMatrixLength,unsigned long aVectorLength,
              Aurora::ValueType aValType1, Aurora::ValueType aValType2, 
              Aurora::FunctionDirection aVectype = Aurora::FunctionDirection::Column,
              int direction = 0);

void unaryNeg(float* in1, float* out, unsigned long length);
void unaryPow(float* in1, float N,float* out, unsigned long length);

void unaryCompare(float* in1, const float& in2, float* out, unsigned long length,int type);
void unaryCompare(const float& in1, float* in2, float* out, unsigned long length, int type);
void unaryCompare(float* in1, float* in2, float* out, unsigned long length, int type);


void thrustFill(float* aBegin, float* aEnd, float aValue);
void thrustFill(float* aBegin, float* aEnd, std::complex<float> aValue);


#endif // __CUDAMATRIX_H__