// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2023 Google Inc. All rights reserved.
// http://ceres-solver.org/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of Google Inc. nor the names of its contributors may be
//   used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Authors: dmitriy.korchemkin@gmail.com (Dmitriy Korchemkin)

#include "ceres/internal/config.h"

#ifndef CERES_NO_CUDA

#include <numeric>

#include "ceres/block_sparse_matrix.h"
#include "ceres/cuda_block_structure.h"
#include "gtest/gtest.h"

namespace ceres::internal {

class CudaBlockStructureTest : public ::testing::Test {
 protected:
  void SetUp() final {
    std::string message;
    ASSERT_TRUE(context_.InitCuda(&message))
        << "InitCuda() failed because: " << message;

    BlockSparseMatrix::RandomMatrixOptions options;
    options.num_row_blocks = 1234;
    options.min_row_block_size = 1;
    options.max_row_block_size = 10;
    options.num_col_blocks = 567;
    options.min_col_block_size = 1;
    options.max_col_block_size = 10;
    options.block_density = 0.2;
    std::mt19937 rng;
    A_ = BlockSparseMatrix::CreateRandomMatrix(options, rng);
    std::iota(
        A_->mutable_values(), A_->mutable_values() + A_->num_nonzeros(), 1);
  }

  std::vector<Cell> GetCells(const CudaBlockSparseStructure& structure) {
    const auto& cuda_buffer = structure.cells_;
    std::vector<Cell> cells(cuda_buffer.size());
    cuda_buffer.CopyToCpu(cells.data(), cells.size());
    return cells;
  }
  std::vector<Block> GetRowBlocks(const CudaBlockSparseStructure& structure) {
    const auto& cuda_buffer = structure.row_blocks_;
    std::vector<Block> blocks(cuda_buffer.size());
    cuda_buffer.CopyToCpu(blocks.data(), blocks.size());
    return blocks;
  }
  std::vector<Block> GetColBlocks(const CudaBlockSparseStructure& structure) {
    const auto& cuda_buffer = structure.col_blocks_;
    std::vector<Block> blocks(cuda_buffer.size());
    cuda_buffer.CopyToCpu(blocks.data(), blocks.size());
    return blocks;
  }
  std::vector<int> GetRowBlockOffsets(
      const CudaBlockSparseStructure& structure) {
    const auto& cuda_buffer = structure.first_cell_in_row_block_;
    std::vector<int> first_cell_in_row_block(cuda_buffer.size());
    cuda_buffer.CopyToCpu(first_cell_in_row_block.data(),
                          first_cell_in_row_block.size());
    return first_cell_in_row_block;
  }

  std::unique_ptr<BlockSparseMatrix> A_;
  ContextImpl context_;
};

TEST_F(CudaBlockStructureTest, StructureIdentity) {
  auto block_structure = A_->block_structure();
  const int num_row_blocks = block_structure->rows.size();
  const int num_col_blocks = block_structure->cols.size();

  CudaBlockSparseStructure cuda_block_structure(*block_structure, &context_);

  ASSERT_EQ(cuda_block_structure.num_rows(), A_->num_rows());
  ASSERT_EQ(cuda_block_structure.num_cols(), A_->num_cols());
  ASSERT_EQ(cuda_block_structure.num_nonzeros(), A_->num_nonzeros());
  ASSERT_EQ(cuda_block_structure.num_row_blocks(), num_row_blocks);
  ASSERT_EQ(cuda_block_structure.num_col_blocks(), num_col_blocks);

  std::vector<Block> blocks = GetColBlocks(cuda_block_structure);
  ASSERT_EQ(blocks.size(), num_col_blocks);
  for (int i = 0; i < num_col_blocks; ++i) {
    EXPECT_EQ(block_structure->cols[i].position, blocks[i].position);
    EXPECT_EQ(block_structure->cols[i].size, blocks[i].size);
  }

  std::vector<Cell> cells = GetCells(cuda_block_structure);
  std::vector<int> first_cell_in_row_block =
      GetRowBlockOffsets(cuda_block_structure);
  blocks = GetRowBlocks(cuda_block_structure);

  ASSERT_EQ(blocks.size(), num_row_blocks);
  ASSERT_EQ(first_cell_in_row_block.size(), num_row_blocks + 1);
  ASSERT_EQ(first_cell_in_row_block.back(), cells.size());

  for (int i = 0; i < num_row_blocks; ++i) {
    const int num_cells = block_structure->rows[i].cells.size();
    EXPECT_EQ(blocks[i].position, block_structure->rows[i].block.position);
    EXPECT_EQ(blocks[i].size, block_structure->rows[i].block.size);
    const int first_cell = first_cell_in_row_block[i];
    const int last_cell = first_cell_in_row_block[i + 1];
    ASSERT_EQ(last_cell - first_cell, num_cells);
    for (int j = 0; j < num_cells; ++j) {
      EXPECT_EQ(cells[first_cell + j].block_id,
                block_structure->rows[i].cells[j].block_id);
      EXPECT_EQ(cells[first_cell + j].position,
                block_structure->rows[i].cells[j].position);
    }
  }
}

}  // namespace ceres::internal

#endif  // CERES_NO_CUDA
