// Ceres Solver - A fast non-linear least squares minimizer
// Copyright 2017 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 <memory>

#include "ceres/casts.h"
#include "ceres/context_impl.h"
#include "ceres/internal/config.h"
#include "ceres/linear_least_squares_problems.h"
#include "ceres/linear_solver.h"
#include "ceres/triplet_sparse_matrix.h"
#include "ceres/types.h"
#include "glog/logging.h"
#include "gtest/gtest.h"

namespace ceres {
namespace internal {

using Param = ::testing::
    tuple<LinearSolverType, DenseLinearAlgebraLibraryType, bool, int>;

static std::string ParamInfoToString(testing::TestParamInfo<Param> info) {
  Param param = info.param;
  std::stringstream ss;
  ss << LinearSolverTypeToString(::testing::get<0>(param)) << "_"
     << DenseLinearAlgebraLibraryTypeToString(::testing::get<1>(param)) << "_"
     << (::testing::get<2>(param) ? "Regularized" : "Unregularized") << "_"
     << ::testing::get<3>(param);
  return ss.str();
}

class DenseLinearSolverTest : public ::testing::TestWithParam<Param> {};

TEST_P(DenseLinearSolverTest, _) {
  Param param = GetParam();
  const bool regularized = testing::get<2>(param);

  std::unique_ptr<LinearLeastSquaresProblem> problem =
      CreateLinearLeastSquaresProblemFromId(testing::get<3>(param));
  DenseSparseMatrix lhs(*down_cast<TripletSparseMatrix*>(problem->A.get()));

  const int num_cols = lhs.num_cols();
  const int num_rows = lhs.num_rows();

  Vector rhs = Vector::Zero(num_rows + num_cols);
  rhs.head(num_rows) = ConstVectorRef(problem->b.get(), num_rows);

  LinearSolver::Options options;
  options.type = ::testing::get<0>(param);
  options.dense_linear_algebra_library_type = ::testing::get<1>(param);
  ContextImpl context;
  options.context = &context;
  std::unique_ptr<LinearSolver> solver(LinearSolver::Create(options));

  LinearSolver::PerSolveOptions per_solve_options;
  if (regularized) {
    per_solve_options.D = problem->D.get();
  }

  Vector solution(num_cols);
  LinearSolver::Summary summary =
      solver->Solve(&lhs, rhs.data(), per_solve_options, solution.data());
  EXPECT_EQ(summary.termination_type, LINEAR_SOLVER_SUCCESS);

  Vector normal_rhs = lhs.matrix().transpose() * rhs.head(num_rows);
  Matrix normal_lhs = lhs.matrix().transpose() * lhs.matrix();

  if (regularized) {
    ConstVectorRef diagonal(problem->D.get(), num_cols);
    normal_lhs += diagonal.array().square().matrix().asDiagonal();
  }

  Vector actual_normal_rhs = normal_lhs * solution;

  const double normalized_residual =
      (normal_rhs - actual_normal_rhs).norm() / normal_rhs.norm();

  EXPECT_NEAR(
      normalized_residual, 0.0, 10 * std::numeric_limits<double>::epsilon())
      << "\nexpected: " << normal_rhs.transpose()
      << "\nactual: " << actual_normal_rhs.transpose();
}

namespace {

// TODO(sameeragarwal): Should we move away from hard coded linear
// least squares problem to randomly generated ones?
#ifndef CERES_NO_LAPACK

INSTANTIATE_TEST_SUITE_P(
    DenseLinearSolver,
    DenseLinearSolverTest,
    ::testing::Combine(::testing::Values(DENSE_QR, DENSE_NORMAL_CHOLESKY),
                       ::testing::Values(EIGEN, LAPACK),
                       ::testing::Values(true, false),
                       ::testing::Values(0, 1)),
    ParamInfoToString);

#else

INSTANTIATE_TEST_SUITE_P(
    DenseLinearSolver,
    DenseLinearSolverTest,
    ::testing::Combine(::testing::Values(DENSE_QR, DENSE_NORMAL_CHOLESKY),
                       ::testing::Values(EIGEN),
                       ::testing::Values(true, false),
                       ::testing::Values(0, 1)),
    ParamInfoToString);

#endif
}  // namespace
}  // namespace internal
}  // namespace ceres
