// 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.
//
// Author: sameeragarwal@google.com (Sameer Agarwal)

#include "ceres/block_random_access_sparse_matrix.h"

#include <limits>
#include <memory>
#include <utility>
#include <vector>

#include "absl/container/btree_set.h"
#include "ceres/internal/eigen.h"
#include "gtest/gtest.h"

namespace ceres::internal {

TEST(BlockRandomAccessSparseMatrix, GetCell) {
  ContextImpl context;
  constexpr int num_threads = 1;
  std::vector<Block> blocks;
  blocks.emplace_back(3, 0);
  blocks.emplace_back(4, 3);
  blocks.emplace_back(5, 7);
  constexpr int num_rows = 3 + 4 + 5;

  absl::btree_set<std::pair<int, int>> block_pairs;
  int num_nonzeros = 0;
  block_pairs.emplace(0, 0);
  num_nonzeros += blocks[0].size * blocks[0].size;

  block_pairs.emplace(1, 1);
  num_nonzeros += blocks[1].size * blocks[1].size;

  block_pairs.emplace(1, 2);
  num_nonzeros += blocks[1].size * blocks[2].size;

  block_pairs.emplace(0, 2);
  num_nonzeros += blocks[2].size * blocks[0].size;

  BlockRandomAccessSparseMatrix m(blocks, block_pairs, &context, num_threads);
  EXPECT_EQ(m.num_rows(), num_rows);
  EXPECT_EQ(m.num_cols(), num_rows);

  for (const auto& block_pair : block_pairs) {
    const int row_block_id = block_pair.first;
    const int col_block_id = block_pair.second;
    int row;
    int col;
    int row_stride;
    int col_stride;
    CellInfo* cell = m.GetCell(
        row_block_id, col_block_id, &row, &col, &row_stride, &col_stride);
    EXPECT_TRUE(cell != nullptr);
    EXPECT_EQ(row, 0);
    EXPECT_EQ(col, 0);
    EXPECT_EQ(row_stride, blocks[row_block_id].size);
    EXPECT_EQ(col_stride, blocks[col_block_id].size);

    // Write into the block
    MatrixRef(cell->values, row_stride, col_stride)
        .block(row, col, blocks[row_block_id].size, blocks[col_block_id].size) =
        (row_block_id + 1) * (col_block_id + 1) *
        Matrix::Ones(blocks[row_block_id].size, blocks[col_block_id].size);
  }

  const BlockSparseMatrix* bsm = m.matrix();
  EXPECT_EQ(bsm->num_nonzeros(), num_nonzeros);

  Matrix dense;
  bsm->ToDenseMatrix(&dense);

  double kTolerance = 1e-14;

  // (0, 0)
  EXPECT_NEAR(
      (dense.block(0, 0, 3, 3) - Matrix::Ones(3, 3)).norm(), 0.0, kTolerance);
  // (1, 1)
  EXPECT_NEAR((dense.block(3, 3, 4, 4) - 2 * 2 * Matrix::Ones(4, 4)).norm(),
              0.0,
              kTolerance);
  // (1, 2)
  EXPECT_NEAR((dense.block(3, 3 + 4, 4, 5) - 2 * 3 * Matrix::Ones(4, 5)).norm(),
              0.0,
              kTolerance);
  // (0, 2)
  EXPECT_NEAR((dense.block(0, 3 + 4, 3, 5) - 3 * 1 * Matrix::Ones(3, 5)).norm(),
              0.0,
              kTolerance);

  // There is nothing else in the matrix besides these four blocks.
  EXPECT_NEAR(
      dense.norm(), sqrt(9. + 16. * 16. + 36. * 20. + 9. * 15.), kTolerance);

  Vector x = Vector::Ones(dense.rows());
  Vector actual_y = Vector::Zero(dense.rows());
  Vector expected_y = Vector::Zero(dense.rows());

  expected_y += dense.selfadjointView<Eigen::Upper>() * x;
  m.SymmetricRightMultiplyAndAccumulate(x.data(), actual_y.data());
  EXPECT_NEAR((expected_y - actual_y).norm(), 0.0, kTolerance)
      << "actual: " << actual_y.transpose() << "\n"
      << "expected: " << expected_y.transpose() << "matrix: \n " << dense;
}

// IntPairToInt64 is private, thus this fixture is needed to access and
// test it.
class BlockRandomAccessSparseMatrixTest : public ::testing::Test {
 public:
  void SetUp() final {
    std::vector<Block> blocks;
    blocks.emplace_back(1, 0);
    absl::btree_set<std::pair<int, int>> block_pairs;
    block_pairs.emplace(0, 0);
    m_ = std::make_unique<BlockRandomAccessSparseMatrix>(
        blocks, block_pairs, &context_, 1);
  }

  void CheckIntPairToInt64(int a, int b) {
    int64_t value = m_->IntPairToInt64(a, b);
    EXPECT_GT(value, 0) << "Overflow a = " << a << " b = " << b;
    EXPECT_GT(value, a) << "Overflow a = " << a << " b = " << b;
    EXPECT_GT(value, b) << "Overflow a = " << a << " b = " << b;
  }

  void CheckInt64ToIntPair() {
    uint64_t max_rows = m_->kRowShift;
    for (int row = max_rows - 10; row < max_rows; ++row) {
      for (int col = 0; col < 10; ++col) {
        int row_computed;
        int col_computed;
        m_->Int64ToIntPair(
            m_->IntPairToInt64(row, col), &row_computed, &col_computed);
        EXPECT_EQ(row, row_computed);
        EXPECT_EQ(col, col_computed);
      }
    }
  }

 private:
  ContextImpl context_;
  std::unique_ptr<BlockRandomAccessSparseMatrix> m_;
};

TEST_F(BlockRandomAccessSparseMatrixTest, IntPairToInt64Overflow) {
  CheckIntPairToInt64(std::numeric_limits<int32_t>::max(),
                      std::numeric_limits<int32_t>::max());
}

TEST_F(BlockRandomAccessSparseMatrixTest, Int64ToIntPair) {
  CheckInt64ToIntPair();
}

}  // namespace ceres::internal
