TEST(Matrix, CpuSparseMatrixCopyFrom) {
  size_t height = 10;
  size_t width = 8;
  int64_t indices[11] = {0, 1, 5, 5, 9, 13, 15, 17, 19, 30, 32};
  sparse_non_value_t data[32];
  for (size_t i = 0; i < 32; i++) {
    data[i].col = ::rand() % width;
  }
  CpuSparseMatrixPtr mat = std::make_shared<CpuSparseMatrix>(
      height, width, 32, NO_VALUE, SPARSE_CSR, false);
  mat->copyFrom(indices, data);

  /*compare indices*/
  size_t sum = 0;
  CHECK_EQ(sum, size_t(mat->getRows()[0]));
  for (size_t i = 1; i < height + 1; i++) {
    sum += indices[i] - indices[i - 1];
    CHECK_EQ(sum, size_t(mat->getRows()[i]));
  }
  CHECK_EQ(mat->getElementCnt(), size_t(indices[height] - indices[0]));
  for (size_t i = 0; i < mat->getElementCnt(); i++) {
    CHECK_EQ(size_t(mat->getCols()[i]), size_t(data[i].col));
  }
}
TEST(Matrix, SparseMatrixCSCFormatTrimFrom) {
  size_t height = 8;
  size_t width = 10;
  int indices[11] = {0, 1, 5, 5, 9, 13, 15, 17, 19, 27, 32};
  int value[32] = {
      1,                       // col_0 : 1
      5, 3, 1, 6,              // col_1 : 4
      0, 1, 2, 3,              // col_3 : 4
      4, 5, 6, 7,              // col_4 : 4
      2, 3,                    // col_5 : 2
      3, 5,                    // col_6 : 2
      0, 1,                    // col_7 : 2
      0, 1, 2, 3, 4, 5, 6, 7,  // col_8 : 8
      2, 4, 7, 3, 1            // col_9 : 5
  };
  std::vector<int> rows(value, value + 32);
  std::vector<int> cols(indices, indices + 11);
  std::vector<real> values(value, value + 32);
  CpuSparseMatrixPtr mat = std::make_shared<CpuSparseMatrix>(
      height, width, 32, FLOAT_VALUE, SPARSE_CSC, false);
  mat->copyFrom(rows, cols, values);

  /*compare indices*/
  size_t sum = 0;
  CHECK_EQ(sum, size_t(mat->getCols()[0]));
  for (size_t i = 1; i < width + 1; i++) {
    sum += indices[i] - indices[i - 1];
    CHECK_EQ(sum, size_t(mat->getCols()[i]));
  }
  CHECK_EQ(mat->getElementCnt(), size_t(indices[width] - indices[0]));
  for (size_t i = 0; i < mat->getElementCnt(); i++) {
    CHECK_EQ(size_t(mat->getRows()[i]), size_t(value[i]));
  }

  size_t trimedWidth = 5;
  int trimedIndices[6] = {0, 1, 5, 5, 9, 13};
  int trimedValue[13] = {
      1,  // col_0 : 1
      5,
      3,
      1,
      6,  // col_1 : 4
      0,
      1,
      2,
      3,  // col_3 : 4
      4,
      5,
      6,
      7  // col_4 : 4
  };
  std::vector<int> rowsA(trimedValue, trimedValue + 13);
  std::vector<int> colsA(trimedIndices, trimedIndices + 6);
  std::vector<real> valuesA(trimedValue, trimedValue + 13);
  CpuSparseMatrixPtr matA = std::make_shared<CpuSparseMatrix>(
      height, trimedWidth, 13, FLOAT_VALUE, SPARSE_CSC, false);
  matA->copyFrom(rowsA, colsA, valuesA);

  /*compare indices*/
  sum = 0;
  CHECK_EQ(sum, size_t(matA->getCols()[0]));
  for (size_t i = 1; i < trimedWidth + 1; i++) {
    sum += trimedIndices[i] - trimedIndices[i - 1];
    CHECK_EQ(sum, size_t(matA->getCols()[i]));
  }
  CHECK_EQ(matA->getElementCnt(),
           size_t(trimedIndices[trimedWidth] - trimedIndices[0]));
  for (size_t i = 0; i < matA->getElementCnt(); i++) {
    CHECK_EQ(size_t(matA->getRows()[i]), size_t(rowsA[i]));
  }

  CpuSparseMatrixPtr matB = std::make_shared<CpuSparseMatrix>(
      height, trimedWidth, height, FLOAT_VALUE, SPARSE_CSC, false);
  matB->trimFrom(*mat);
  checkSMatrixEqual2(matA, matB);

#ifndef PADDLE_ONLY_CPU
  GpuSparseMatrixPtr matC = std::make_shared<GpuSparseMatrix>(
      height, trimedWidth, height, FLOAT_VALUE, SPARSE_CSC, true);
  matC->trimFrom(*mat);

  CpuSparseMatrixPtr matD =
      std::make_shared<CpuSparseMatrix>(height,
                                        trimedWidth,
                                        matC->getElementCnt(),
                                        FLOAT_VALUE,
                                        SPARSE_CSC,
                                        false);
  matD->copyFrom(*matC, HPPL_STREAM_DEFAULT);
  hl_stream_synchronize(HPPL_STREAM_DEFAULT);
  checkSMatrixEqual2(matA, matD);
#endif
}
TEST(Matrix, SparseMatrixCSRFormatTrimFrom) {
  size_t height = 10;
  size_t width = 8;
  int64_t indices[11] = {0, 1, 5, 5, 9, 13, 15, 17, 19, 27, 32};
  sparse_float_value_t data[32];
  int value[32] = {
      1,                       // row_0 : 1
      5, 3, 1, 6,              // row_1 : 4
      0, 1, 2, 3,              // row_3 : 4
      4, 5, 6, 7,              // row_4 : 4
      2, 3,                    // row_5 : 2
      3, 5,                    // row_6 : 2
      0, 1,                    // row_7 : 2
      0, 1, 2, 3, 4, 5, 6, 7,  // row_8 : 8
      2, 4, 7, 3, 1            // row_9 : 5
  };
  for (size_t i = 0; i < 32; i++) {
    data[i].col = value[i];
    data[i].value = float(value[i]);
  }
  CpuSparseMatrixPtr mat = std::make_shared<CpuSparseMatrix>(
      height, width, 32, FLOAT_VALUE, SPARSE_CSR, false);
  mat->copyFrom(indices, data);

  /*compare indices*/
  size_t sum = 0;
  CHECK_EQ(sum, size_t(mat->getRows()[0]));
  for (size_t i = 1; i < height + 1; i++) {
    sum += indices[i] - indices[i - 1];
    CHECK_EQ(sum, size_t(mat->getRows()[i]));
  }
  CHECK_EQ(mat->getElementCnt(), size_t(indices[height] - indices[0]));
  for (size_t i = 0; i < mat->getElementCnt(); i++) {
    CHECK_EQ(size_t(mat->getCols()[i]), size_t(data[i].col));
  }

  size_t trimedWidth = 4;
  int64_t trimedIndices[11] = {0, 1, 3, 3, 7, 7, 9, 10, 12, 16, 19};
  sparse_float_value_t trimedData[19];
  int trimedValue[19] = {
      1,  // row_0 : 1
      3,
      1,  // row_1 : 2
      0,
      1,
      2,
      3,  // row_3 : 4
      2,
      3,  // row_5 : 2
      3,  // row_6 : 1
      0,
      1,  // row_7 : 2
      0,
      1,
      2,
      3,  // row_8 : 4
      2,
      3,
      1  // row_9 : 3
  };
  for (size_t i = 0; i < 19; i++) {
    trimedData[i].col = trimedValue[i];
    trimedData[i].value = float(trimedValue[i]);
  }
  CpuSparseMatrixPtr matA = std::make_shared<CpuSparseMatrix>(
      height, trimedWidth, 19, FLOAT_VALUE, SPARSE_CSR, false);
  matA->copyFrom(trimedIndices, trimedData);

  /*compare indices*/
  sum = 0;
  CHECK_EQ(sum, size_t(matA->getRows()[0]));
  for (size_t i = 1; i < height + 1; i++) {
    sum += trimedIndices[i] - trimedIndices[i - 1];
    CHECK_EQ(sum, size_t(matA->getRows()[i]));
  }
  CHECK_EQ(matA->getElementCnt(),
           size_t(trimedIndices[height] - trimedIndices[0]));
  for (size_t i = 0; i < matA->getElementCnt(); i++) {
    CHECK_EQ(size_t(matA->getCols()[i]), size_t(trimedData[i].col));
  }

  CpuSparseMatrixPtr matB = std::make_shared<CpuSparseMatrix>(
      height, trimedWidth, height, FLOAT_VALUE, SPARSE_CSR, false);
  matB->trimFrom(*mat);
  checkSMatrixEqual2(matA, matB);

#ifndef PADDLE_ONLY_CPU
  GpuSparseMatrixPtr matC = std::make_shared<GpuSparseMatrix>(
      height, trimedWidth, height, FLOAT_VALUE, SPARSE_CSR, true);
  matC->trimFrom(*mat);

  CpuSparseMatrixPtr matD =
      std::make_shared<CpuSparseMatrix>(height,
                                        trimedWidth,
                                        matC->getElementCnt(),
                                        FLOAT_VALUE,
                                        SPARSE_CSR,
                                        false);
  matD->copyFrom(*matC, HPPL_STREAM_DEFAULT);
  hl_stream_synchronize(HPPL_STREAM_DEFAULT);
  checkSMatrixEqual2(matA, matD);
#endif
}