// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2015 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_jacobi_preconditioner.h"

#include <memory>
#include <vector>

#include "Eigen/Dense"
#include "ceres/block_random_access_diagonal_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/linear_least_squares_problems.h"
#include "gtest/gtest.h"

namespace ceres {
namespace internal {

class BlockJacobiPreconditionerTest : public ::testing::Test {
 protected:
  void SetUpFromProblemId(int problem_id) {
    std::unique_ptr<LinearLeastSquaresProblem> problem =
        CreateLinearLeastSquaresProblemFromId(problem_id);

    CHECK(problem != nullptr);
    A.reset(down_cast<BlockSparseMatrix*>(problem->A.release()));
    D = std::move(problem->D);

    Matrix dense_a;
    A->ToDenseMatrix(&dense_a);
    dense_ata = dense_a.transpose() * dense_a;
    dense_ata += VectorRef(D.get(), A->num_cols())
                     .array()
                     .square()
                     .matrix()
                     .asDiagonal();
  }

  void VerifyDiagonalBlocks(const int problem_id) {
    SetUpFromProblemId(problem_id);

    BlockJacobiPreconditioner pre(*A);
    pre.Update(*A, D.get());
    auto* m = const_cast<BlockRandomAccessDiagonalMatrix*>(&pre.matrix());
    EXPECT_EQ(m->num_rows(), A->num_cols());
    EXPECT_EQ(m->num_cols(), A->num_cols());

    const CompressedRowBlockStructure* bs = A->block_structure();
    for (int i = 0; i < bs->cols.size(); ++i) {
      const int block_size = bs->cols[i].size;
      int r, c, row_stride, col_stride;
      CellInfo* cell_info = m->GetCell(i, i, &r, &c, &row_stride, &col_stride);
      MatrixRef m(cell_info->values, row_stride, col_stride);
      Matrix actual_block_inverse = m.block(r, c, block_size, block_size);
      Matrix expected_block = dense_ata.block(
          bs->cols[i].position, bs->cols[i].position, block_size, block_size);
      const double residual = (actual_block_inverse * expected_block -
                               Matrix::Identity(block_size, block_size))
                                  .norm();
      EXPECT_NEAR(residual, 0.0, 1e-12) << "Block: " << i;
    }
  }

  std::unique_ptr<BlockSparseMatrix> A;
  std::unique_ptr<double[]> D;
  Matrix dense_ata;
};

TEST_F(BlockJacobiPreconditionerTest, SmallProblem) { VerifyDiagonalBlocks(2); }

TEST_F(BlockJacobiPreconditionerTest, LargeProblem) { VerifyDiagonalBlocks(3); }

}  // namespace internal
}  // namespace ceres
