#include "Matrix.h" #include #include #include #include //必须在mkl.h和Eigen的头之前,之后 #define MKL_Complex16 std::complex #include "mkl.h" #include "Function.h" namespace Aurora{ typedef void(*CalcFuncD)(const MKL_INT n, const double a[], const MKL_INT inca, const double b[], const MKL_INT incb, double r[], const MKL_INT incr); typedef void(*CalcFuncZ)(const MKL_INT n, const MKL_Complex16 a[], const MKL_INT inca, const MKL_Complex16 b[], const MKL_INT incb, MKL_Complex16 r[], const MKL_INT incr); inline Matrix operatorMxA(CalcFuncD aFunc, double aScalar, const Matrix &aMatrix) { double *output = malloc(aMatrix.getDataSize(), aMatrix.getValueType() == Complex); aFunc(aMatrix.getDataSize(), aMatrix.getData(), 1, &aScalar, 0, output, 1); if (aMatrix.getValueType() == Complex) { aFunc(aMatrix.getDataSize(), aMatrix.getData() + 1, 1, &aScalar, 0, output + 1, 1); } return Matrix::New(output, aMatrix.getDimSize(0), aMatrix.getDimSize(1), aMatrix.getDimSize(2), aMatrix.getValueType()); } inline Matrix operatorMxM(CalcFuncD aFuncD, CalcFuncZ aFuncZ, const Matrix &aMatrix, const Matrix &aOther) { if (!aMatrix.compareShape(aOther))return Matrix(); if (aMatrix.getValueType() != aOther.getValueType()) { double *output = malloc(aMatrix.getDataSize(), true); if (aMatrix.getValueType() == Complex) { aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData(), 1, output, 1); aFuncD(aMatrix.getDataSize(), aMatrix.getData() + 1, 1, aOther.getData(), 1, output + 1, 1); return Matrix::New(output, aMatrix); } aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData(), 1, output, 1); aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData() + 1, 1, output + 1, 1); return Matrix::New(output, aOther); } else if (aMatrix.getValueType() == Normal) { double *output = malloc(aMatrix.getDataSize()); aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData(), 1, output, 1); return Matrix::New(output, aMatrix); } else { double *output = malloc(aMatrix.getDataSize(), true); aFuncZ(aMatrix.getDataSize(), (std::complex *) aMatrix.getData(), 1, (std::complex *) aOther.getData(), 1, (std::complex *) output, 1); return Matrix::New(output, aOther); } } inline Matrix &operatorMxA_RR(CalcFuncD aFunc, double aScalar, Aurora::Matrix &&aMatrix) { std::cout << "use right ref operation" << std::endl; std::cout << "before operation" << std::endl; aMatrix.printf(); if (aMatrix.getValueType() == Complex) { aFunc(aMatrix.getDataSize(), aMatrix.getData(), 1, &aScalar, 0, aMatrix.getData(), 1); aFunc(aMatrix.getDataSize(), aMatrix.getData() + 1, 1, &aScalar, 0, aMatrix.getData() + 1, 1); } else { aFunc(aMatrix.getDataSize(), aMatrix.getData(), 1, &aScalar, 0, aMatrix.getData(), 1); } std::cout << "after operation" << std::endl; aMatrix.printf(); return aMatrix; } inline Matrix operatorMxM_RR(CalcFuncD aFuncD, CalcFuncZ aFuncZ, const Aurora::Matrix &aMatrix, Aurora::Matrix &&aOther) { if (!aMatrix.compareShape(aOther))return Matrix(); std::cout << "use right ref operation m" << std::endl; if (aMatrix.getValueType() != aOther.getValueType()) { //aOther is not a complex matrix if (aMatrix.getValueType() == Complex) { double *output = malloc(aMatrix.getDataSize(), true); aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData(), 1, output, 1); aFuncD(aMatrix.getDataSize(), aMatrix.getData() + 1,1, aOther.getData(), 1, output + 1, 1); return Matrix::New(output, aOther); } //aOther is a complex matrix, use aOther as output aFuncD(aMatrix.getDataSize(), aMatrix.getData(),1, aOther.getData(), 1, aOther.getData(), 1); aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData() + 1, 1, aOther.getData() + 1, 1); return aOther; } else if (aMatrix.getValueType() == Normal) { aFuncD(aMatrix.getDataSize(), aMatrix.getData(), 1, aOther.getData(), 1, aOther.getData(), 1); return aOther; } else { aFuncZ(aMatrix.getDataSize(), (std::complex *) aMatrix.getData(), 1, (std::complex *) aOther.getData(), 1, (std::complex *) aOther.getData(), 1); return aOther; } } }; namespace Aurora { Matrix::Matrix(std::shared_ptr aData, std::vector aInfo) : mData(aData), mInfo(aInfo) { } Matrix::Matrix(const Matrix::MatrixSlice& slice) { auto temp = slice.toMatrix(); this->mData = temp.mData; this->mInfo = temp.mInfo; this->mValueType = temp.mValueType; } bool Matrix::isNull() const { return !mData || mInfo.empty(); } int Matrix::getDims() const { return mInfo.size(); } double *Matrix::getData() const { return mData.get(); } int Matrix::getDimSize(int aIndex) const { if (aIndex >= 0 && aIndex < 3 && aIndex < getDims()) { return mInfo.at(aIndex); } return 0; } size_t Matrix::getDataSize() const { if (!mData.get())return 0; size_t ret = 1; for (auto v: mInfo) { ret *= v; } return ret; } bool Matrix::compareShape(const Matrix &other) const { if (mInfo.size() != other.mInfo.size()) return false; for (int i = 0; i < mInfo.size(); ++i) { if (mInfo[i] != other.mInfo[i]) return false; } return true; } Matrix Matrix::getDataFromDims2(int aColumn) { if (2 != getDims() || aColumn > mInfo.back()) { return Matrix(); } int rows = mInfo.at(0); std::shared_ptr resultData = std::shared_ptr(new double[rows], std::default_delete()); std::copy(mData.get() + (aColumn - 1) * rows, mData.get() + aColumn * rows, resultData.get()); std::vector resultInfo = {rows}; Matrix result(resultData, resultInfo); return result; } Matrix Matrix::getDataFromDims1(int aRow) { if (1 != getDims() || aRow > mInfo.back()) { return Matrix(); } std::shared_ptr resultData = std::shared_ptr(new double[1], std::default_delete()); resultData.get()[0] = mData.get()[aRow - 1]; std::vector resultInfo{1}; Matrix result(resultData, resultInfo); return result; } Matrix Matrix::New(double *data, int rows, int cols, int slices, ValueType type) { if (!data) return Matrix(); std::vector vector; vector.push_back(rows); if (cols > 0)vector.push_back(cols); if (slices > 0)vector.push_back(slices); Matrix ret({data, free}, vector); if (type != Normal)ret.setValueType(type); return ret; } Matrix Matrix::New(double *data, const Matrix &shapeMatrix) { return New(data, shapeMatrix.getDimSize(0), shapeMatrix.getDimSize(1), shapeMatrix.getDimSize(2), shapeMatrix.getValueType()); } Matrix Matrix::New(const Matrix &shapeMatrix) { double *newBuffer = malloc(shapeMatrix.getDataSize(), shapeMatrix.getValueType()); return New(newBuffer, shapeMatrix); } Matrix Matrix::deepCopy() const { double *newBuffer = malloc(getDataSize(), getValueType()); memcpy(newBuffer, getData(), sizeof(double) * getDataSize() * getValueType()); return New(newBuffer, getDimSize(0), getDimSize(1), getDimSize(2), getValueType()); } //operation + Matrix Matrix::operator+(double aScalar) const { return operatorMxA(&vdAddI, aScalar, *this);} Matrix operator+(double aScalar, const Matrix &matrix) {return matrix + aScalar;} Matrix Matrix::operator+(const Matrix &matrix) const {return operatorMxM(vdAddI, vzAddI, *this, matrix);} Matrix &operator+(double aScalar, Matrix &&matrix) { return operatorMxA_RR(&vdAddI,aScalar, std::forward(matrix)); } Matrix &operator+(Matrix &&matrix,double aScalar) { return operatorMxA_RR(&vdAddI,aScalar, std::forward(matrix)); } Matrix Matrix::operator+(Matrix &&aMatrix) const { return operatorMxM_RR(&vdAddI,&vzAddI,*this,std::forward(aMatrix)); } Matrix operator+(Matrix &&aMatrix, const Matrix &aOther) { return operatorMxM_RR(&vdAddI,&vzAddI,aOther,std::forward(aMatrix)); } //operation - Matrix Matrix::operator-(double aScalar) const { return operatorMxA(&vdSubI, aScalar, *this);} Matrix operator-(double aScalar, const Matrix &matrix) {return matrix - aScalar;} Matrix Matrix::operator-(const Matrix &matrix) const {return operatorMxM(vdSubI, vzSubI, *this, matrix);} Matrix &operator-(double aScalar, Matrix &&matrix) { return operatorMxA_RR(&vdSubI,aScalar, std::forward(matrix)); } Matrix &operator-(Matrix &&matrix,double aScalar) { return operatorMxA_RR(&vdSubI,aScalar, std::forward(matrix)); } Matrix Matrix::operator-(Matrix &&aMatrix) const { return operatorMxM_RR(&vdSubI,&vzSubI,*this,std::forward(aMatrix)); } Matrix operator-(Matrix &&aMatrix, const Matrix &aOther) { return operatorMxM_RR(&vdSubI,&vzSubI,aOther,std::forward(aMatrix)); } //operation * Matrix Matrix::operator*(double aScalar) const { return operatorMxA(&vdMulI, aScalar, *this);} Matrix operator*(double aScalar, const Matrix &matrix) {return matrix * aScalar;} Matrix Matrix::operator*(const Matrix &matrix) const {return operatorMxM(vdMulI, vzMulI, *this, matrix);} Matrix &operator*(double aScalar, Matrix &&matrix) { return operatorMxA_RR(&vdMulI,aScalar, std::forward(matrix)); } Matrix &operator*(Matrix &&matrix,double aScalar) { return operatorMxA_RR(&vdMulI,aScalar, std::forward(matrix)); } Matrix Matrix::operator*(Matrix &&aMatrix) const { return operatorMxM_RR(&vdMulI,&vzMulI,*this,std::forward(aMatrix)); } Matrix operator*(Matrix &&aMatrix, const Matrix &aOther) { return operatorMxM_RR(&vdMulI,&vzMulI,aOther,std::forward(aMatrix)); } //operation / Matrix Matrix::operator/(double aScalar) const { return operatorMxA(&vdDivI, aScalar, *this);} Matrix operator/(double aScalar, const Matrix &matrix) {return matrix / aScalar;} Matrix Matrix::operator/(const Matrix &matrix) const {return operatorMxM(vdDivI, vzDivI, *this, matrix);} Matrix &operator/(double aScalar, Matrix &&matrix) { return operatorMxA_RR(&vdDivI,aScalar, std::forward(matrix)); } Matrix &operator/(Matrix &&matrix,double aScalar) { return operatorMxA_RR(&vdDivI,aScalar, std::forward(matrix)); } Matrix Matrix::operator/(Matrix &&aMatrix) const { return operatorMxM_RR(&vdDivI,&vzDivI,*this,std::forward(aMatrix)); } Matrix operator/(Matrix &&aMatrix, const Matrix &aOther) { return operatorMxM_RR(&vdDivI,&vzDivI,aOther,std::forward(aMatrix)); } //operator ^ (pow) Matrix Matrix::operator^(int times) const { return operatorMxA(&vdPowI, times, *this);} Matrix operator^( Matrix &&matrix,int times) { return operatorMxA(&vdPowI, times, std::forward(matrix)); } void Matrix::printf() { int k_count = getDimSize(2)==0?1:getDimSize(2); int j_count = getDimSize(1)==0?1:getDimSize(1); for (int k = 0; k dims = {aRowIdx, aColIdx, aSliceIdx}; std::vector allDimIndex; int mode = 0; for (int j = 0; j < 3; ++j) { if (dims[j]==$ && this->getDims()>j){ ++mode; allDimIndex.push_back(j); } } int rowStride = 1; int colStride = getDimSize(0); int sliceStride = getDimSize(0)*getDimSize(1); int strides[3] = {rowStride, colStride, sliceStride}; int rowOffset = aRowIdx == $ ? 0 : aRowIdx; int colOffset = aColIdx == $ ? 0 : aColIdx; int sliceOffset = aSliceIdx == $ ? 0 : aSliceIdx; double *startPointer = getData() + (rowStride * rowOffset + colStride * colOffset + sliceStride * sliceOffset) * getValueType(); int size1 = getDimSize(allDimIndex[0]); int stride1 = strides[allDimIndex[0]]; switch (mode) { //matrix mode case 2:{ int size2 = getDimSize(allDimIndex[1]); int stride2 = strides[allDimIndex[1]]; return Matrix::MatrixSlice(size1, stride1, startPointer, getValueType(), mode, size2, stride2); } //vector mode & default case 1: { return Matrix::MatrixSlice(size1, stride1, startPointer, getValueType(), mode); } //scalar mode or ALL $ case 0: default: { return Matrix::MatrixSlice(1 , 1, startPointer,getValueType(), mode); } } } Matrix::MatrixSlice::MatrixSlice(int aSize,int aStride, double* aData, ValueType aType, int aSliceMode,int aSize2, int aStride2): mSliceMode(aSliceMode),mData(aData), mSize(aSize),mSize2(aSize2), mStride(aStride),mStride2(aStride2), mType(aType) { } Matrix::MatrixSlice &Matrix::MatrixSlice::operator=(const Matrix::MatrixSlice &slice) { if (this==&slice) return *this; if(!mData){ std::cerr <<"Assign value fail!Des data pointer is null!"; return *this; } if(!slice.mData){ std::cerr <<"Assign value fail!Src data pointer is null!"; return *this; } if (slice.mSliceMode!=mSliceMode) { std::cerr <<"Assign value fail!Src slice(dims count:"<< slice.mSliceMode <<"), not match of des(dims count:"<*)slice.mData,slice.mStride,slice.mStride2, (std::complex*)mData,mStride,mStride2,mSize2); } break; } case 1:{ if (mType== Normal){ cblas_dcopy(mSize,slice.mData,slice.mStride,mData,mStride); } else { cblas_zcopy(mSize, (std::complex *) slice.mData, slice.mStride, (std::complex *) mData, mStride); } break; } case 0: default:{ mData[0] = slice.mData[0]; if (mType != Normal)mData[1] = slice.mData[1]; } } return *this; } Matrix::MatrixSlice &Matrix::MatrixSlice::operator=(const Matrix &matrix) { if(!mData){ std::cerr <<"Assign value fail!Des data pointer is null!"; return *this; } if(!matrix.getData()){ std::cerr <<"Assign value fail!Src data pointer is null!"; return *this; } if (matrix.getDims()!=mSliceMode) { std::cerr <<"Assign value fail!Src matrix(dims count:"<< matrix.getDims() <<"), not match of des(dims count:"<*)matrix.getData(),1,matrix.getDimSize(0), (std::complex*)mData,mStride,mStride2,mSize2); } break; } case 1:{ if (mType== Normal){ cblas_dcopy(mSize,matrix.getData(),1,mData,mStride); } else { cblas_zcopy(mSize, (std::complex *) matrix.getData(),1, (std::complex *) mData, mStride); } break; } case 0: default:{ mData[0] = matrix.getData()[0]; if (mType != Normal)mData[1] = matrix.getData()[1]; } } return *this; } Matrix Matrix::MatrixSlice::toMatrix() const { double * data = (double *) mkl_malloc(mSize*(mSize2>0?mSize2:1) * sizeof(double)*mType, 64); switch (mSliceMode) { case 2:{ if (mType== Normal) { cblas_dcopy_batch_strided(mSize, mData, mStride, mStride2,data, 1, mSize, mSize2); } else { cblas_zcopy_batch_strided(mSize, (std::complex *) mData, mStride, mStride2, (std::complex *) data, 1, mSize, mSize2); } break; } case 1:{ if (mType== Normal){ cblas_dcopy(mSize,mData,mStride,data,1); } else { cblas_zcopy(mSize, (std::complex *) mData, mStride, (std::complex *) data, 1); } break; } case 0: default:{ data[0]= mData[0]; if (mType != Normal) data[1] = mData[1]; } } return Matrix::New(data,mSize,mSize2,0,mType); } }