From 55d27f25d73b2246ad70b44ed14e6f518cc4fa41 Mon Sep 17 00:00:00 2001 From: Krad Date: Tue, 25 Apr 2023 09:41:40 +0800 Subject: [PATCH] Add sort, sortrows, median and their unit test. --- src/Function2D.cpp | 93 +++++++++++++++++++++++++++++++++++++++- src/Function2D.h | 7 +++ test/Function2D_Test.cpp | 65 ++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) diff --git a/src/Function2D.cpp b/src/Function2D.cpp index 21cfee8..0353dc9 100644 --- a/src/Function2D.cpp +++ b/src/Function2D.cpp @@ -424,4 +424,95 @@ Matrix Aurora::mean(const Matrix &aMatrix, FunctionDirection direction, bool aIn } } } -} \ No newline at end of file +} + +Matrix Aurora::sort(const Matrix &aMatrix) { + if (aMatrix.getDimSize(2)>1 || aMatrix.isComplex()) { + std::cerr + << (aMatrix.getDimSize(2) > 1 ? "sort() not support 3D data!" : "sort() not support complex value type!") + << std::endl; + return Matrix(); + } + return sort(std::forward(aMatrix.deepCopy())); +} +Matrix Aurora::sort(Matrix &&aMatrix) { + if (aMatrix.getDimSize(2)>1 || aMatrix.isComplex()) { + std::cerr + << (aMatrix.getDimSize(2) > 1 ? "sort() not support 3D data!" : "sort() not support complex value type!") + << std::endl; + return Matrix(); + } + if (aMatrix.getDimSize(0)>=100000){ + #pragma omp parallel for + for (int i = 0; i < aMatrix.getDimSize(1); ++i) { + Eigen::Map srcV(aMatrix.getData()+i*aMatrix.getDimSize(0),aMatrix.getDimSize(0)); + std::sort(srcV.array().begin(),srcV.array().end()); + } + } + else + { + for (int i = 0; i < aMatrix.getDimSize(1); ++i) { + Eigen::Map srcV(aMatrix.getData()+i*aMatrix.getDimSize(0),aMatrix.getDimSize(0)); + std::sort(srcV.array().begin(),srcV.array().end()); + } + } + + return aMatrix; +} + +Matrix Aurora::sortrows(const Matrix &aMatrix) { + if (aMatrix.getDimSize(2)>1 || aMatrix.isComplex()) { + std::cerr + << (aMatrix.getDimSize(2) > 1 ? "sortrows() not support 3D data!" : "sortrows() not support complex value type!") + << std::endl; + return Matrix(); + } + return sortrows(std::forward(aMatrix.deepCopy())); +} + +Matrix Aurora::sortrows(Matrix &&aMatrix) { + if (aMatrix.getDimSize(2)>1 || aMatrix.isComplex()) { + std::cerr + << (aMatrix.getDimSize(2) > 1 ? "sortrows() not support 3D data!" : "sortrows() not support complex value type!") + << std::endl; + return Matrix(); + } + Eigen::Map srcM(aMatrix.getData(),aMatrix.getDimSize(0),aMatrix.getDimSize(1)); + if (aMatrix.getDimSize(1)>=100000){ + #pragma omp parallel for + for (int i = 0; i < aMatrix.getDimSize(0); ++i) { + std::sort(srcM.row(i).array().begin(),srcM.row(i).array().end()); + } + } + else + { + for (int i = 0; i < aMatrix.getDimSize(0); ++i) { + std::sort(srcM.row(i).array().begin(),srcM.row(i).array().end()); + } + } + + return aMatrix; +} + +Matrix Aurora::median(const Matrix &aMatrix) { + if (aMatrix.getDimSize(2) > 1 || aMatrix.isComplex()) { + std::cerr + << (aMatrix.getDimSize(2) > 1 ? "median() not support 3D data!" + : "median() not support complex value type!") + << std::endl; + return Matrix(); + } + Matrix sorted = sort(aMatrix); + Eigen::Map srcM(sorted.getData(),sorted.getDimSize(0),sorted.getDimSize(1)); + bool flag = aMatrix.getDimSize(0) % 2 == 1; + double* ret = malloc(aMatrix.getDimSize(1)); + Eigen::Map retV(ret,aMatrix.getDimSize(1)); + if (flag) { + retV = srcM.row(aMatrix.getDimSize(0)/2); + return Matrix::New(ret,1,aMatrix.getDimSize(1)); + } else { + retV = (srcM.row(aMatrix.getDimSize(0)/2-1).array()+srcM.row(aMatrix.getDimSize(0)/2).array())/2; + return Matrix::New(ret,1,aMatrix.getDimSize(1)); + } +} + diff --git a/src/Function2D.h b/src/Function2D.h index 10f2e9d..1286f76 100644 --- a/src/Function2D.h +++ b/src/Function2D.h @@ -64,6 +64,13 @@ namespace Aurora { */ Matrix mean(const Matrix& aMatrix,FunctionDirection direction = Column, bool aIncludeNan = true); + Matrix sort(const Matrix& aMatrix); + Matrix sort(Matrix&& aMatrix); + + Matrix sortrows(const Matrix& aMatrix); + Matrix sortrows(Matrix&& aMatrix); + + Matrix median(const Matrix& aMatrix); }; diff --git a/test/Function2D_Test.cpp b/test/Function2D_Test.cpp index a929cae..92196eb 100644 --- a/test/Function2D_Test.cpp +++ b/test/Function2D_Test.cpp @@ -245,6 +245,71 @@ TEST_F(Function2D_Test, mean) { } } +TEST_F(Function2D_Test, sort) { + double *dataB = new double[16]{1.1, 2.6, 6.2, 3.8, + 4.3, 10.6, 5.7, 6.9, + 7.1, 8.3, 9.7, 11.2, + 17.8, 13.3,7 , -7.7}; + auto B = Aurora::Matrix::fromRawData(dataB, 4, 4); + auto ret = Aurora::sort(B); + EXPECT_EQ(4, ret.getDimSize(0)); + EXPECT_EQ(4, ret.getDimSize(1)); + EXPECT_DOUBLE_EQ(3.8, ret.getData()[2]); + EXPECT_DOUBLE_EQ(5.7, ret.getData()[5]); + EXPECT_DOUBLE_EQ(-7.7, ret.getData()[12]); + ret = Aurora::sort(B*5); + EXPECT_EQ(4, ret.getDimSize(0)); + EXPECT_EQ(4, ret.getDimSize(1)); + EXPECT_DOUBLE_EQ(19, ret.getData()[2]); + EXPECT_DOUBLE_EQ(28.5, ret.getData()[5]); + EXPECT_DOUBLE_EQ(-38.5, ret.getData()[12]); + //big sort 10w以上多线程快 + double * dataA = Aurora::random(1000000*4); + auto A = Aurora::Matrix::New(dataA, 1000000, 4); + ret = Aurora::sort(A); +} + +TEST_F(Function2D_Test, sortrows) { + double *dataB = new double[16]{1.1, 2.6, 6.2, 3.8, + 4.3, 10.6, 5.7, 6.9, + 7.1, 8.3, 9.7, 11.2, + 17.8, 13.3,7 , -7.7}; + auto B = Aurora::Matrix::fromRawData(dataB, 4, 4); + auto ret = Aurora::sortrows(B); + EXPECT_EQ(4, ret.getDimSize(0)); + EXPECT_EQ(4, ret.getDimSize(1)); + EXPECT_DOUBLE_EQ(5.7, ret.getData()[2]); + EXPECT_DOUBLE_EQ(8.3, ret.getData()[5]); + EXPECT_DOUBLE_EQ(17.8, ret.getData()[12]); + ret = Aurora::sortrows(B*5); + EXPECT_EQ(4, ret.getDimSize(0)); + EXPECT_EQ(4, ret.getDimSize(1)); + EXPECT_DOUBLE_EQ(28.5, ret.getData()[2]); + EXPECT_DOUBLE_EQ(41.5, ret.getData()[5]); + EXPECT_DOUBLE_EQ(89, ret.getData()[12]); + //big sort 10w以上多线程快 + double * dataA = Aurora::random(1000000*4); + auto A = Aurora::Matrix::New(dataA, 4, 1000000); + ret = Aurora::sortrows(A); +} + +TEST_F(Function2D_Test, median) { + double *dataB = new double[20]{1.1, 2.6, 3.8, 6.2, + 4.3, 5.7, 6.9, 10.6, + 7.1, 8.3, 9.7, 11.2, + 17.8, 13.3,26.5 , -7.7, + 9.9, 8.2, 6.3, 5.1}; + auto B = Aurora::Matrix::fromRawData(dataB, 4, 5); + auto ret = Aurora::median(B); + EXPECT_EQ(1, ret.getDimSize(0)); + EXPECT_EQ(5, ret.getDimSize(1)); + EXPECT_DOUBLE_EQ(3.2, ret.getData()[0]); + EXPECT_DOUBLE_EQ(6.3, ret.getData()[1]); + EXPECT_DOUBLE_EQ(9, ret.getData()[2]); + EXPECT_DOUBLE_EQ(15.55, ret.getData()[3]); + EXPECT_DOUBLE_EQ(7.25, ret.getData()[4]); +} + TEST_F(Function2D_Test, fftAndComplexAndIfft){ // double input[10]{1,1,0,2,2,0,1,1,0,2}; // std::complex* complexInput = Aurora::complex(10,input);