diff options
Diffstat (limited to 'extern/ceres/internal')
260 files changed, 4383 insertions, 3420 deletions
diff --git a/extern/ceres/internal/ceres/accelerate_sparse.cc b/extern/ceres/internal/ceres/accelerate_sparse.cc index d2b642bf5dc..74adfaf9afc 100644 --- a/extern/ceres/internal/ceres/accelerate_sparse.cc +++ b/extern/ceres/internal/ceres/accelerate_sparse.cc @@ -29,11 +29,12 @@ // Author: alexs.mac@gmail.com (Alex Stewart) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_ACCELERATE_SPARSE #include <algorithm> +#include <memory> #include <string> #include <vector> @@ -196,17 +197,17 @@ template <typename Scalar> LinearSolverTerminationType AppleAccelerateCholesky<Scalar>::Factorize( CompressedRowSparseMatrix* lhs, std::string* message) { CHECK_EQ(lhs->storage_type(), StorageType()); - if (lhs == NULL) { - *message = "Failure: Input lhs is NULL."; + if (lhs == nullptr) { + *message = "Failure: Input lhs is nullptr."; return LINEAR_SOLVER_FATAL_ERROR; } typename SparseTypesTrait<Scalar>::SparseMatrix as_lhs = as_.CreateSparseMatrixTransposeView(lhs); if (!symbolic_factor_) { - symbolic_factor_.reset( - new typename SparseTypesTrait<Scalar>::SymbolicFactorization( - as_.AnalyzeCholesky(&as_lhs))); + symbolic_factor_ = std::make_unique< + typename SparseTypesTrait<Scalar>::SymbolicFactorization>( + as_.AnalyzeCholesky(&as_lhs)); if (symbolic_factor_->status != SparseStatusOK) { *message = StringPrintf( "Apple Accelerate Failure : Symbolic factorisation failed: %s", @@ -217,9 +218,9 @@ LinearSolverTerminationType AppleAccelerateCholesky<Scalar>::Factorize( } if (!numeric_factor_) { - numeric_factor_.reset( - new typename SparseTypesTrait<Scalar>::NumericFactorization( - as_.Cholesky(&as_lhs, symbolic_factor_.get()))); + numeric_factor_ = std::make_unique< + typename SparseTypesTrait<Scalar>::NumericFactorization>( + as_.Cholesky(&as_lhs, symbolic_factor_.get())); } else { // Recycle memory from previous numeric factorization. as_.Cholesky(&as_lhs, numeric_factor_.get()); @@ -265,7 +266,7 @@ template <typename Scalar> void AppleAccelerateCholesky<Scalar>::FreeSymbolicFactorization() { if (symbolic_factor_) { SparseCleanup(*symbolic_factor_); - symbolic_factor_.reset(); + symbolic_factor_ = nullptr; } } @@ -273,7 +274,7 @@ template <typename Scalar> void AppleAccelerateCholesky<Scalar>::FreeNumericFactorization() { if (numeric_factor_) { SparseCleanup(*numeric_factor_); - numeric_factor_.reset(); + numeric_factor_ = nullptr; } } diff --git a/extern/ceres/internal/ceres/accelerate_sparse.h b/extern/ceres/internal/ceres/accelerate_sparse.h index e53758dfa15..29d78e8c261 100644 --- a/extern/ceres/internal/ceres/accelerate_sparse.h +++ b/extern/ceres/internal/ceres/accelerate_sparse.h @@ -32,7 +32,7 @@ #define CERES_INTERNAL_ACCELERATE_SPARSE_H_ // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_ACCELERATE_SPARSE @@ -111,7 +111,7 @@ class AccelerateSparse { // An implementation of SparseCholesky interface using Apple's Accelerate // framework. template <typename Scalar> -class AppleAccelerateCholesky : public SparseCholesky { +class AppleAccelerateCholesky final : public SparseCholesky { public: // Factory static std::unique_ptr<SparseCholesky> Create(OrderingType ordering_type); diff --git a/extern/ceres/internal/ceres/array_utils.cc b/extern/ceres/internal/ceres/array_utils.cc index 6bffd840f4b..113d41c927e 100644 --- a/extern/ceres/internal/ceres/array_utils.cc +++ b/extern/ceres/internal/ceres/array_utils.cc @@ -44,7 +44,7 @@ namespace internal { using std::string; bool IsArrayValid(const int size, const double* x) { - if (x != NULL) { + if (x != nullptr) { for (int i = 0; i < size; ++i) { if (!std::isfinite(x[i]) || (x[i] == kImpossibleValue)) { return false; @@ -55,7 +55,7 @@ bool IsArrayValid(const int size, const double* x) { } int FindInvalidValue(const int size, const double* x) { - if (x == NULL) { + if (x == nullptr) { return size; } @@ -69,7 +69,7 @@ int FindInvalidValue(const int size, const double* x) { } void InvalidateArray(const int size, double* x) { - if (x != NULL) { + if (x != nullptr) { for (int i = 0; i < size; ++i) { x[i] = kImpossibleValue; } @@ -78,7 +78,7 @@ void InvalidateArray(const int size, double* x) { void AppendArrayToString(const int size, const double* x, string* result) { for (int i = 0; i < size; ++i) { - if (x == NULL) { + if (x == nullptr) { StringAppendF(result, "Not Computed "); } else { if (x[i] == kImpossibleValue) { diff --git a/extern/ceres/internal/ceres/array_utils.h b/extern/ceres/internal/ceres/array_utils.h index 68feca5e792..d2fc7914e1b 100644 --- a/extern/ceres/internal/ceres/array_utils.h +++ b/extern/ceres/internal/ceres/array_utils.h @@ -45,29 +45,30 @@ #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { // Fill the array x with an impossible value that the user code is // never expected to compute. -CERES_EXPORT_INTERNAL void InvalidateArray(int size, double* x); +CERES_NO_EXPORT void InvalidateArray(int size, double* x); // Check if all the entries of the array x are valid, i.e. all the // values in the array should be finite and none of them should be // equal to the "impossible" value used by InvalidateArray. -CERES_EXPORT_INTERNAL bool IsArrayValid(int size, const double* x); +CERES_NO_EXPORT bool IsArrayValid(int size, const double* x); // If the array contains an invalid value, return the index for it, // otherwise return size. -CERES_EXPORT_INTERNAL int FindInvalidValue(const int size, const double* x); +CERES_NO_EXPORT int FindInvalidValue(const int size, const double* x); // Utility routine to print an array of doubles to a string. If the -// array pointer is NULL, it is treated as an array of zeros. -CERES_EXPORT_INTERNAL void AppendArrayToString(const int size, - const double* x, - std::string* result); +// array pointer is nullptr, it is treated as an array of zeros. +CERES_NO_EXPORT void AppendArrayToString(const int size, + const double* x, + std::string* result); // This routine takes an array of integer values, sorts and uniques // them and then maps each value in the array to its position in the @@ -82,9 +83,11 @@ CERES_EXPORT_INTERNAL void AppendArrayToString(const int size, // gets mapped to // // [1 0 2 3 0 1 3] -CERES_EXPORT_INTERNAL void MapValuesToContiguousRange(int size, int* array); +CERES_NO_EXPORT void MapValuesToContiguousRange(int size, int* array); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_ARRAY_UTILS_H_ diff --git a/extern/ceres/internal/ceres/block_evaluate_preparer.cc b/extern/ceres/internal/ceres/block_evaluate_preparer.cc index 7db96d94e0a..56c97b60cc4 100644 --- a/extern/ceres/internal/ceres/block_evaluate_preparer.cc +++ b/extern/ceres/internal/ceres/block_evaluate_preparer.cc @@ -53,7 +53,7 @@ void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block, SparseMatrix* jacobian, double** jacobians) { // If the overall jacobian is not available, use the scratch space. - if (jacobian == NULL) { + if (jacobian == nullptr) { scratch_evaluate_preparer_.Prepare( residual_block, residual_block_index, jacobian, jacobians); return; @@ -73,7 +73,7 @@ void BlockEvaluatePreparer::Prepare(const ResidualBlock* residual_block, // parameters. Instead, bump the pointer for active parameters only. jacobian_block_offset++; } else { - jacobians[j] = NULL; + jacobians[j] = nullptr; } } } diff --git a/extern/ceres/internal/ceres/block_evaluate_preparer.h b/extern/ceres/internal/ceres/block_evaluate_preparer.h index 4378689729f..d72e41ba3e4 100644 --- a/extern/ceres/internal/ceres/block_evaluate_preparer.h +++ b/extern/ceres/internal/ceres/block_evaluate_preparer.h @@ -36,6 +36,7 @@ #ifndef CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ #define CERES_INTERNAL_BLOCK_EVALUATE_PREPARER_H_ +#include "ceres/internal/export.h" #include "ceres/scratch_evaluate_preparer.h" namespace ceres { @@ -44,7 +45,7 @@ namespace internal { class ResidualBlock; class SparseMatrix; -class BlockEvaluatePreparer { +class CERES_NO_EXPORT BlockEvaluatePreparer { public: // Using Init() instead of a constructor allows for allocating this structure // with new[]. This is because C++ doesn't allow passing arguments to objects diff --git a/extern/ceres/internal/ceres/block_jacobi_preconditioner.cc b/extern/ceres/internal/ceres/block_jacobi_preconditioner.cc index 6f37aca553c..6e979dea93b 100644 --- a/extern/ceres/internal/ceres/block_jacobi_preconditioner.cc +++ b/extern/ceres/internal/ceres/block_jacobi_preconditioner.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -47,10 +47,10 @@ BlockJacobiPreconditioner::BlockJacobiPreconditioner( blocks[i] = bs->cols[i].size; } - m_.reset(new BlockRandomAccessDiagonalMatrix(blocks)); + m_ = std::make_unique<BlockRandomAccessDiagonalMatrix>(blocks); } -BlockJacobiPreconditioner::~BlockJacobiPreconditioner() {} +BlockJacobiPreconditioner::~BlockJacobiPreconditioner() = default; bool BlockJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A, const double* D) { @@ -60,21 +60,20 @@ bool BlockJacobiPreconditioner::UpdateImpl(const BlockSparseMatrix& A, for (int i = 0; i < bs->rows.size(); ++i) { const int row_block_size = bs->rows[i].block.size; const std::vector<Cell>& cells = bs->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - const int block_id = cells[j].block_id; + for (const auto& cell : cells) { + const int block_id = cell.block_id; const int col_block_size = bs->cols[block_id].size; int r, c, row_stride, col_stride; CellInfo* cell_info = m_->GetCell(block_id, block_id, &r, &c, &row_stride, &col_stride); MatrixRef m(cell_info->values, row_stride, col_stride); - ConstMatrixRef b( - values + cells[j].position, row_block_size, col_block_size); + ConstMatrixRef b(values + cell.position, row_block_size, col_block_size); m.block(r, c, col_block_size, col_block_size) += b.transpose() * b; } } - if (D != NULL) { + if (D != nullptr) { // Add the diagonal. int position = 0; for (int i = 0; i < bs->cols.size(); ++i) { diff --git a/extern/ceres/internal/ceres/block_jacobi_preconditioner.h b/extern/ceres/internal/ceres/block_jacobi_preconditioner.h index 18f749533e0..e0a512a1469 100644 --- a/extern/ceres/internal/ceres/block_jacobi_preconditioner.h +++ b/extern/ceres/internal/ceres/block_jacobi_preconditioner.h @@ -34,7 +34,8 @@ #include <memory> #include "ceres/block_random_access_diagonal_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/preconditioner.h" namespace ceres { @@ -53,7 +54,7 @@ struct CompressedRowBlockStructure; // update the matrix by running Update(A, D). The values of the matrix A are // inspected to construct the preconditioner. The vector D is applied as the // D^TD diagonal term. -class CERES_EXPORT_INTERNAL BlockJacobiPreconditioner +class CERES_NO_EXPORT BlockJacobiPreconditioner : public BlockSparseMatrixPreconditioner { public: // A must remain valid while the BlockJacobiPreconditioner is. @@ -61,7 +62,7 @@ class CERES_EXPORT_INTERNAL BlockJacobiPreconditioner BlockJacobiPreconditioner(const BlockJacobiPreconditioner&) = delete; void operator=(const BlockJacobiPreconditioner&) = delete; - virtual ~BlockJacobiPreconditioner(); + ~BlockJacobiPreconditioner() override; // Preconditioner interface void RightMultiply(const double* x, double* y) const final; @@ -78,4 +79,6 @@ class CERES_EXPORT_INTERNAL BlockJacobiPreconditioner } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_BLOCK_JACOBI_PRECONDITIONER_H_ diff --git a/extern/ceres/internal/ceres/block_jacobian_writer.cc b/extern/ceres/internal/ceres/block_jacobian_writer.cc index 17c157b47f9..a70660f860a 100644 --- a/extern/ceres/internal/ceres/block_jacobian_writer.cc +++ b/extern/ceres/internal/ceres/block_jacobian_writer.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -30,10 +30,13 @@ #include "ceres/block_jacobian_writer.h" +#include <algorithm> +#include <memory> + #include "ceres/block_evaluate_preparer.h" #include "ceres/block_sparse_matrix.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" @@ -66,8 +69,7 @@ void BuildJacobianLayout(const Program& program, // matrix. Also compute the number of jacobian blocks. int f_block_pos = 0; int num_jacobian_blocks = 0; - for (int i = 0; i < residual_blocks.size(); ++i) { - ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { const int num_residuals = residual_block->NumResiduals(); const int num_parameter_blocks = residual_block->NumParameterBlocks(); @@ -78,7 +80,7 @@ void BuildJacobianLayout(const Program& program, // Only count blocks for active parameters. num_jacobian_blocks++; if (parameter_block->index() < num_eliminate_blocks) { - f_block_pos += num_residuals * parameter_block->LocalSize(); + f_block_pos += num_residuals * parameter_block->TangentSize(); } } } @@ -107,7 +109,7 @@ void BuildJacobianLayout(const Program& program, continue; } const int jacobian_block_size = - num_residuals * parameter_block->LocalSize(); + num_residuals * parameter_block->TangentSize(); if (parameter_block_index < num_eliminate_blocks) { *jacobian_pos = e_block_pos; e_block_pos += jacobian_block_size; @@ -136,20 +138,20 @@ BlockJacobianWriter::BlockJacobianWriter(const Evaluator::Options& options, // Create evaluate prepareres that point directly into the final jacobian. This // makes the final Write() a nop. -BlockEvaluatePreparer* BlockJacobianWriter::CreateEvaluatePreparers( - int num_threads) { +std::unique_ptr<BlockEvaluatePreparer[]> +BlockJacobianWriter::CreateEvaluatePreparers(int num_threads) { int max_derivatives_per_residual_block = program_->MaxDerivativesPerResidualBlock(); - BlockEvaluatePreparer* preparers = new BlockEvaluatePreparer[num_threads]; + auto preparers = std::make_unique<BlockEvaluatePreparer[]>(num_threads); for (int i = 0; i < num_threads; i++) { preparers[i].Init(&jacobian_layout_[0], max_derivatives_per_residual_block); } return preparers; } -SparseMatrix* BlockJacobianWriter::CreateJacobian() const { - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; +std::unique_ptr<SparseMatrix> BlockJacobianWriter::CreateJacobian() const { + auto* bs = new CompressedRowBlockStructure; const vector<ParameterBlock*>& parameter_blocks = program_->parameter_blocks(); @@ -159,7 +161,7 @@ SparseMatrix* BlockJacobianWriter::CreateJacobian() const { for (int i = 0, cursor = 0; i < parameter_blocks.size(); ++i) { CHECK_NE(parameter_blocks[i]->index(), -1); CHECK(!parameter_blocks[i]->IsConstant()); - bs->cols[i].size = parameter_blocks[i]->LocalSize(); + bs->cols[i].size = parameter_blocks[i]->TangentSize(); bs->cols[i].position = cursor; cursor += bs->cols[i].size; } @@ -201,12 +203,10 @@ SparseMatrix* BlockJacobianWriter::CreateJacobian() const { } } - sort(row->cells.begin(), row->cells.end(), CellLessThan); + std::sort(row->cells.begin(), row->cells.end(), CellLessThan); } - BlockSparseMatrix* jacobian = new BlockSparseMatrix(bs); - CHECK(jacobian != nullptr); - return jacobian; + return std::make_unique<BlockSparseMatrix>(bs); } } // namespace internal diff --git a/extern/ceres/internal/ceres/block_jacobian_writer.h b/extern/ceres/internal/ceres/block_jacobian_writer.h index 8054d7b33aa..b2d0aaa3b73 100644 --- a/extern/ceres/internal/ceres/block_jacobian_writer.h +++ b/extern/ceres/internal/ceres/block_jacobian_writer.h @@ -38,10 +38,11 @@ #ifndef CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ #define CERES_INTERNAL_BLOCK_JACOBIAN_WRITER_H_ +#include <memory> #include <vector> #include "ceres/evaluator.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -51,7 +52,7 @@ class Program; class SparseMatrix; // TODO(sameeragarwal): This class needs documemtation. -class BlockJacobianWriter { +class CERES_NO_EXPORT BlockJacobianWriter { public: BlockJacobianWriter(const Evaluator::Options& options, Program* program); @@ -59,9 +60,10 @@ class BlockJacobianWriter { // Create evaluate prepareres that point directly into the final jacobian. // This makes the final Write() a nop. - BlockEvaluatePreparer* CreateEvaluatePreparers(int num_threads); + std::unique_ptr<BlockEvaluatePreparer[]> CreateEvaluatePreparers( + int num_threads); - SparseMatrix* CreateJacobian() const; + std::unique_ptr<SparseMatrix> CreateJacobian() const; void Write(int /* residual_id */, int /* residual_offset */, diff --git a/extern/ceres/internal/ceres/block_random_access_dense_matrix.cc b/extern/ceres/internal/ceres/block_random_access_dense_matrix.cc index 386f81eae77..ed172de1d82 100644 --- a/extern/ceres/internal/ceres/block_random_access_dense_matrix.cc +++ b/extern/ceres/internal/ceres/block_random_access_dense_matrix.cc @@ -48,9 +48,9 @@ BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix( num_rows_ += blocks[i]; } - values_.reset(new double[num_rows_ * num_rows_]); + values_ = std::make_unique<double[]>(num_rows_ * num_rows_); - cell_infos_.reset(new CellInfo[num_blocks * num_blocks]); + cell_infos_ = std::make_unique<CellInfo[]>(num_blocks * num_blocks); for (int i = 0; i < num_blocks * num_blocks; ++i) { cell_infos_[i].values = values_.get(); } @@ -60,7 +60,7 @@ BlockRandomAccessDenseMatrix::BlockRandomAccessDenseMatrix( // Assume that the user does not hold any locks on any cell blocks // when they are calling SetZero. -BlockRandomAccessDenseMatrix::~BlockRandomAccessDenseMatrix() {} +BlockRandomAccessDenseMatrix::~BlockRandomAccessDenseMatrix() = default; CellInfo* BlockRandomAccessDenseMatrix::GetCell(const int row_block_id, const int col_block_id, diff --git a/extern/ceres/internal/ceres/block_random_access_dense_matrix.h b/extern/ceres/internal/ceres/block_random_access_dense_matrix.h index 9e555242994..171a6d694b5 100644 --- a/extern/ceres/internal/ceres/block_random_access_dense_matrix.h +++ b/extern/ceres/internal/ceres/block_random_access_dense_matrix.h @@ -35,7 +35,8 @@ #include <vector> #include "ceres/block_random_access_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -46,11 +47,11 @@ namespace internal { // num_rows x num_cols. // // This class is NOT thread safe. Since all n^2 cells are stored, -// GetCell never returns NULL for any (row_block_id, col_block_id) +// GetCell never returns nullptr for any (row_block_id, col_block_id) // pair. // // ReturnCell is a nop. -class CERES_EXPORT_INTERNAL BlockRandomAccessDenseMatrix +class CERES_NO_EXPORT BlockRandomAccessDenseMatrix : public BlockRandomAccessMatrix { public: // blocks is a vector of block sizes. The resulting matrix has @@ -61,7 +62,7 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessDenseMatrix // The destructor is not thread safe. It assumes that no one is // modifying any cells when the matrix is being destroyed. - virtual ~BlockRandomAccessDenseMatrix(); + ~BlockRandomAccessDenseMatrix() override; // BlockRandomAccessMatrix interface. CellInfo* GetCell(int row_block_id, @@ -94,4 +95,6 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessDenseMatrix } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DENSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.cc b/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.cc index 08f6d7f1750..f55f3b30c61 100644 --- a/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.cc +++ b/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -31,12 +31,13 @@ #include "ceres/block_random_access_diagonal_matrix.h" #include <algorithm> +#include <memory> #include <set> #include <utility> #include <vector> #include "Eigen/Dense" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/stl_util.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" @@ -57,16 +58,17 @@ BlockRandomAccessDiagonalMatrix::BlockRandomAccessDiagonalMatrix( int num_cols = 0; int num_nonzeros = 0; vector<int> block_positions; - for (int i = 0; i < blocks_.size(); ++i) { + for (int block_size : blocks_) { block_positions.push_back(num_cols); - num_cols += blocks_[i]; - num_nonzeros += blocks_[i] * blocks_[i]; + num_cols += block_size; + num_nonzeros += block_size * block_size; } VLOG(1) << "Matrix Size [" << num_cols << "," << num_cols << "] " << num_nonzeros; - tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros)); + tsm_ = + std::make_unique<TripletSparseMatrix>(num_cols, num_cols, num_nonzeros); tsm_->set_num_nonzeros(num_nonzeros); int* rows = tsm_->mutable_rows(); int* cols = tsm_->mutable_cols(); @@ -99,7 +101,7 @@ CellInfo* BlockRandomAccessDiagonalMatrix::GetCell(int row_block_id, int* row_stride, int* col_stride) { if (row_block_id != col_block_id) { - return NULL; + return nullptr; } const int stride = blocks_[row_block_id]; @@ -121,8 +123,7 @@ void BlockRandomAccessDiagonalMatrix::SetZero() { void BlockRandomAccessDiagonalMatrix::Invert() { double* values = tsm_->mutable_values(); - for (int i = 0; i < blocks_.size(); ++i) { - const int block_size = blocks_[i]; + for (int block_size : blocks_) { MatrixRef block(values, block_size, block_size); block = block.selfadjointView<Eigen::Upper>().llt().solve( Matrix::Identity(block_size, block_size)); @@ -135,8 +136,7 @@ void BlockRandomAccessDiagonalMatrix::RightMultiply(const double* x, CHECK(x != nullptr); CHECK(y != nullptr); const double* values = tsm_->values(); - for (int i = 0; i < blocks_.size(); ++i) { - const int block_size = blocks_[i]; + for (int block_size : blocks_) { ConstMatrixRef block(values, block_size, block_size); VectorRef(y, block_size).noalias() += block * ConstVectorRef(x, block_size); x += block_size; diff --git a/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.h b/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.h index 3fe7c1e5b22..3d36c378320 100644 --- a/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.h +++ b/extern/ceres/internal/ceres/block_random_access_diagonal_matrix.h @@ -37,7 +37,8 @@ #include <vector> #include "ceres/block_random_access_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" @@ -46,7 +47,7 @@ namespace internal { // A thread safe block diagonal matrix implementation of // BlockRandomAccessMatrix. -class CERES_EXPORT_INTERNAL BlockRandomAccessDiagonalMatrix +class CERES_NO_EXPORT BlockRandomAccessDiagonalMatrix : public BlockRandomAccessMatrix { public: // blocks is an array of block sizes. @@ -57,7 +58,7 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessDiagonalMatrix // The destructor is not thread safe. It assumes that no one is // modifying any cells when the matrix is being destroyed. - virtual ~BlockRandomAccessDiagonalMatrix(); + ~BlockRandomAccessDiagonalMatrix() override; // BlockRandomAccessMatrix Interface. CellInfo* GetCell(int row_block_id, @@ -98,4 +99,6 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessDiagonalMatrix } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_DIAGONAL_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/block_random_access_matrix.cc b/extern/ceres/internal/ceres/block_random_access_matrix.cc index ea88855b59a..8e70c049796 100644 --- a/extern/ceres/internal/ceres/block_random_access_matrix.cc +++ b/extern/ceres/internal/ceres/block_random_access_matrix.cc @@ -33,7 +33,7 @@ namespace ceres { namespace internal { -BlockRandomAccessMatrix::~BlockRandomAccessMatrix() {} +BlockRandomAccessMatrix::~BlockRandomAccessMatrix() = default; } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/block_random_access_matrix.h b/extern/ceres/internal/ceres/block_random_access_matrix.h index f190622eafe..48759b79a18 100644 --- a/extern/ceres/internal/ceres/block_random_access_matrix.h +++ b/extern/ceres/internal/ceres/block_random_access_matrix.h @@ -35,7 +35,7 @@ #include <mutex> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -62,7 +62,7 @@ namespace internal { // // There is no requirement that all cells be present, i.e. the matrix // itself can be block sparse. When a cell is not present, the GetCell -// method will return a NULL pointer. +// method will return a nullptr pointer. // // There is no requirement about how the cells are stored beyond that // form a dense submatrix of a larger dense matrix. Like everywhere @@ -77,7 +77,7 @@ namespace internal { // &row, &col, // &row_stride, &col_stride); // -// if (cell != NULL) { +// if (cell != nullptr) { // MatrixRef m(cell->values, row_stride, col_stride); // std::lock_guard<std::mutex> l(&cell->m); // m.block(row, col, row_block_size, col_block_size) = ... @@ -85,21 +85,21 @@ namespace internal { // Structure to carry a pointer to the array containing a cell and the // mutex guarding it. -struct CellInfo { - CellInfo() : values(nullptr) {} +struct CERES_NO_EXPORT CellInfo { + CellInfo() = default; explicit CellInfo(double* values) : values(values) {} - double* values; + double* values{nullptr}; std::mutex m; }; -class CERES_EXPORT_INTERNAL BlockRandomAccessMatrix { +class CERES_NO_EXPORT BlockRandomAccessMatrix { public: virtual ~BlockRandomAccessMatrix(); // If the cell (row_block_id, col_block_id) is present, then return // a CellInfo with a pointer to the dense matrix containing it, - // otherwise return NULL. The dense matrix containing this cell has + // otherwise return nullptr. The dense matrix containing this cell has // size row_stride, col_stride and the cell is located at position // (row, col) within this matrix. // diff --git a/extern/ceres/internal/ceres/block_random_access_sparse_matrix.cc b/extern/ceres/internal/ceres/block_random_access_sparse_matrix.cc index c28b7cef3f4..a026daa5dac 100644 --- a/extern/ceres/internal/ceres/block_random_access_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/block_random_access_sparse_matrix.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -36,7 +36,7 @@ #include <utility> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" #include "glog/logging.h" @@ -58,9 +58,9 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( // rows/columns. int num_cols = 0; block_positions_.reserve(blocks_.size()); - for (int i = 0; i < blocks_.size(); ++i) { + for (int block_size : blocks_) { block_positions_.push_back(num_cols); - num_cols += blocks_[i]; + num_cols += block_size; } // Count the number of scalar non-zero entries and build the layout @@ -76,7 +76,8 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( VLOG(1) << "Matrix Size [" << num_cols << "," << num_cols << "] " << num_nonzeros; - tsm_.reset(new TripletSparseMatrix(num_cols, num_cols, num_nonzeros)); + tsm_ = + std::make_unique<TripletSparseMatrix>(num_cols, num_cols, num_nonzeros); tsm_->set_num_nonzeros(num_nonzeros); int* rows = tsm_->mutable_rows(); int* cols = tsm_->mutable_cols(); @@ -86,7 +87,7 @@ BlockRandomAccessSparseMatrix::BlockRandomAccessSparseMatrix( for (const auto& block_pair : block_pairs) { const int row_block_size = blocks_[block_pair.first]; const int col_block_size = blocks_[block_pair.second]; - cell_values_.push_back(make_pair(block_pair, values + pos)); + cell_values_.emplace_back(block_pair, values + pos); layout_[IntPairToLong(block_pair.first, block_pair.second)] = new CellInfo(values + pos); pos += row_block_size * col_block_size; @@ -129,7 +130,7 @@ CellInfo* BlockRandomAccessSparseMatrix::GetCell(int row_block_id, const LayoutType::iterator it = layout_.find(IntPairToLong(row_block_id, col_block_id)); if (it == layout_.end()) { - return NULL; + return nullptr; } // Each cell is stored contiguously as its own little dense matrix. diff --git a/extern/ceres/internal/ceres/block_random_access_sparse_matrix.h b/extern/ceres/internal/ceres/block_random_access_sparse_matrix.h index 0e58bbb6b42..b31a2ade843 100644 --- a/extern/ceres/internal/ceres/block_random_access_sparse_matrix.h +++ b/extern/ceres/internal/ceres/block_random_access_sparse_matrix.h @@ -39,7 +39,8 @@ #include <vector> #include "ceres/block_random_access_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/small_blas.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" @@ -51,7 +52,7 @@ namespace internal { // BlockRandomAccessMatrix. Internally a TripletSparseMatrix is used // for doing the actual storage. This class augments this matrix with // an unordered_map that allows random read/write access. -class CERES_EXPORT_INTERNAL BlockRandomAccessSparseMatrix +class CERES_NO_EXPORT BlockRandomAccessSparseMatrix : public BlockRandomAccessMatrix { public: // blocks is an array of block sizes. block_pairs is a set of @@ -65,7 +66,7 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessSparseMatrix // The destructor is not thread safe. It assumes that no one is // modifying any cells when the matrix is being destroyed. - virtual ~BlockRandomAccessSparseMatrix(); + ~BlockRandomAccessSparseMatrix() override; // BlockRandomAccessMatrix Interface. CellInfo* GetCell(int row_block_id, @@ -111,7 +112,7 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessSparseMatrix // A mapping from <row_block_id, col_block_id> to the position in // the values array of tsm_ where the block is stored. - typedef std::unordered_map<long int, CellInfo*> LayoutType; + using LayoutType = std::unordered_map<long, CellInfo*>; LayoutType layout_; // In order traversal of contents of the matrix. This allows us to @@ -127,4 +128,6 @@ class CERES_EXPORT_INTERNAL BlockRandomAccessSparseMatrix } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_BLOCK_RANDOM_ACCESS_SPARSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/block_sparse_matrix.cc b/extern/ceres/internal/ceres/block_sparse_matrix.cc index 5efd2e1ecfb..31ea39daeea 100644 --- a/extern/ceres/internal/ceres/block_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/block_sparse_matrix.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ #include <algorithm> #include <cstddef> +#include <memory> #include <vector> #include "ceres/block_structure.h" @@ -46,8 +47,6 @@ namespace internal { using std::vector; -BlockSparseMatrix::~BlockSparseMatrix() {} - BlockSparseMatrix::BlockSparseMatrix( CompressedRowBlockStructure* block_structure) : num_rows_(0), @@ -57,8 +56,8 @@ BlockSparseMatrix::BlockSparseMatrix( CHECK(block_structure_ != nullptr); // Count the number of columns in the matrix. - for (int i = 0; i < block_structure_->cols.size(); ++i) { - num_cols_ += block_structure_->cols[i].size; + for (auto& col : block_structure_->cols) { + num_cols_ += col.size; } // Count the number of non-zero entries and the number of rows in @@ -68,8 +67,8 @@ BlockSparseMatrix::BlockSparseMatrix( num_rows_ += row_block_size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; num_nonzeros_ += col_block_size * row_block_size; } @@ -80,7 +79,7 @@ BlockSparseMatrix::BlockSparseMatrix( CHECK_GE(num_nonzeros_, 0); VLOG(2) << "Allocating values array with " << num_nonzeros_ * sizeof(double) << " bytes."; // NOLINT - values_.reset(new double[num_nonzeros_]); + values_ = std::make_unique<double[]>(num_nonzeros_); max_num_nonzeros_ = num_nonzeros_; CHECK(values_ != nullptr); } @@ -97,12 +96,12 @@ void BlockSparseMatrix::RightMultiply(const double* x, double* y) const { int row_block_pos = block_structure_->rows[i].block.position; int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - values_.get() + cells[j].position, + values_.get() + cell.position, row_block_size, col_block_size, x + col_block_pos, @@ -119,12 +118,12 @@ void BlockSparseMatrix::LeftMultiply(const double* x, double* y) const { int row_block_pos = block_structure_->rows[i].block.position; int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - values_.get() + cells[j].position, + values_.get() + cell.position, row_block_size, col_block_size, x + row_block_pos, @@ -139,12 +138,12 @@ void BlockSparseMatrix::SquaredColumnNorm(double* x) const { for (int i = 0; i < block_structure_->rows.size(); ++i) { int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; const MatrixRef m( - values_.get() + cells[j].position, row_block_size, col_block_size); + values_.get() + cell.position, row_block_size, col_block_size); VectorRef(x + col_block_pos, col_block_size) += m.colwise().squaredNorm(); } } @@ -156,12 +155,12 @@ void BlockSparseMatrix::ScaleColumns(const double* scale) { for (int i = 0; i < block_structure_->rows.size(); ++i) { int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; MatrixRef m( - values_.get() + cells[j].position, row_block_size, col_block_size); + values_.get() + cell.position, row_block_size, col_block_size); m *= ConstVectorRef(scale + col_block_pos, col_block_size).asDiagonal(); } } @@ -178,11 +177,11 @@ void BlockSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { int row_block_pos = block_structure_->rows[i].block.position; int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; - int jac_pos = cells[j].position; + int jac_pos = cell.position; m.block(row_block_pos, col_block_pos, row_block_size, col_block_size) += MatrixRef(values_.get() + jac_pos, row_block_size, col_block_size); } @@ -201,11 +200,11 @@ void BlockSparseMatrix::ToTripletSparseMatrix( int row_block_pos = block_structure_->rows[i].block.position; int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + int col_block_id = cell.block_id; int col_block_size = block_structure_->cols[col_block_id].size; int col_block_pos = block_structure_->cols[col_block_id].position; - int jac_pos = cells[j].position; + int jac_pos = cell.position; for (int r = 0; r < row_block_size; ++r) { for (int c = 0; c < col_block_size; ++c, ++jac_pos) { matrix->mutable_rows()[jac_pos] = row_block_pos + r; @@ -230,11 +229,11 @@ void BlockSparseMatrix::ToTextFile(FILE* file) const { const int row_block_pos = block_structure_->rows[i].block.position; const int row_block_size = block_structure_->rows[i].block.size; const vector<Cell>& cells = block_structure_->rows[i].cells; - for (int j = 0; j < cells.size(); ++j) { - const int col_block_id = cells[j].block_id; + for (const auto& cell : cells) { + const int col_block_id = cell.block_id; const int col_block_size = block_structure_->cols[col_block_id].size; const int col_block_pos = block_structure_->cols[col_block_id].position; - int jac_pos = cells[j].position; + int jac_pos = cell.position; for (int r = 0; r < row_block_size; ++r) { for (int c = 0; c < col_block_size; ++c) { fprintf(file, @@ -248,10 +247,10 @@ void BlockSparseMatrix::ToTextFile(FILE* file) const { } } -BlockSparseMatrix* BlockSparseMatrix::CreateDiagonalMatrix( +std::unique_ptr<BlockSparseMatrix> BlockSparseMatrix::CreateDiagonalMatrix( const double* diagonal, const std::vector<Block>& column_blocks) { // Create the block structure for the diagonal matrix. - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure(); + auto* bs = new CompressedRowBlockStructure(); bs->cols = column_blocks; int position = 0; bs->rows.resize(column_blocks.size(), CompressedRow(1)); @@ -265,13 +264,13 @@ BlockSparseMatrix* BlockSparseMatrix::CreateDiagonalMatrix( } // Create the BlockSparseMatrix with the given block structure. - BlockSparseMatrix* matrix = new BlockSparseMatrix(bs); + auto matrix = std::make_unique<BlockSparseMatrix>(bs); matrix->SetZero(); // Fill the values array of the block sparse matrix. double* values = matrix->mutable_values(); - for (int i = 0; i < column_blocks.size(); ++i) { - const int size = column_blocks[i].size; + for (const auto& column_block : column_blocks) { + const int size = column_block.size; for (int j = 0; j < size; ++j) { // (j + 1) * size is compact way of accessing the (j,j) entry. values[j * (size + 1)] = diagonal[j]; @@ -308,9 +307,10 @@ void BlockSparseMatrix::AppendRows(const BlockSparseMatrix& m) { } if (num_nonzeros_ > max_num_nonzeros_) { - double* new_values = new double[num_nonzeros_]; - std::copy(values_.get(), values_.get() + old_num_nonzeros, new_values); - values_.reset(new_values); + std::unique_ptr<double[]> new_values = + std::make_unique<double[]>(num_nonzeros_); + std::copy_n(values_.get(), old_num_nonzeros, new_values.get()); + values_ = std::move(new_values); max_num_nonzeros_ = num_nonzeros_; } @@ -337,7 +337,7 @@ void BlockSparseMatrix::DeleteRowBlocks(const int delta_row_blocks) { block_structure_->rows.resize(num_row_blocks - delta_row_blocks); } -BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( +std::unique_ptr<BlockSparseMatrix> BlockSparseMatrix::CreateRandomMatrix( const BlockSparseMatrix::RandomMatrixOptions& options) { CHECK_GT(options.num_row_blocks, 0); CHECK_GT(options.min_row_block_size, 0); @@ -346,7 +346,7 @@ BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( CHECK_GT(options.block_density, 0.0); CHECK_LE(options.block_density, 1.0); - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure(); + auto* bs = new CompressedRowBlockStructure(); if (options.col_blocks.empty()) { CHECK_GT(options.num_col_blocks, 0); CHECK_GT(options.min_col_block_size, 0); @@ -360,7 +360,7 @@ BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( const int delta_block_size = Uniform(options.max_col_block_size - options.min_col_block_size); const int col_block_size = options.min_col_block_size + delta_block_size; - bs->cols.push_back(Block(col_block_size, col_block_position)); + bs->cols.emplace_back(col_block_size, col_block_position); col_block_position += col_block_size; } } else { @@ -377,7 +377,7 @@ BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( const int delta_block_size = Uniform(options.max_row_block_size - options.min_row_block_size); const int row_block_size = options.min_row_block_size + delta_block_size; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = row_block_size; row.block.position = row_block_position; @@ -385,7 +385,7 @@ BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( for (int c = 0; c < bs->cols.size(); ++c) { if (RandDouble() > options.block_density) continue; - row.cells.push_back(Cell()); + row.cells.emplace_back(); Cell& cell = row.cells.back(); cell.block_id = c; cell.position = value_position; @@ -395,7 +395,7 @@ BlockSparseMatrix* BlockSparseMatrix::CreateRandomMatrix( } } - BlockSparseMatrix* matrix = new BlockSparseMatrix(bs); + auto matrix = std::make_unique<BlockSparseMatrix>(bs); double* values = matrix->mutable_values(); for (int i = 0; i < matrix->num_nonzeros(); ++i) { values[i] = RandNormal(); diff --git a/extern/ceres/internal/ceres/block_sparse_matrix.h b/extern/ceres/internal/ceres/block_sparse_matrix.h index e5b3634c3cc..75b0deb59e6 100644 --- a/extern/ceres/internal/ceres/block_sparse_matrix.h +++ b/extern/ceres/internal/ceres/block_sparse_matrix.h @@ -37,8 +37,9 @@ #include <memory> #include "ceres/block_structure.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/sparse_matrix.h" namespace ceres { @@ -54,7 +55,7 @@ class TripletSparseMatrix; // // internal/ceres/block_structure.h // -class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix { +class CERES_NO_EXPORT BlockSparseMatrix final : public SparseMatrix { public: // Construct a block sparse matrix with a fully initialized // CompressedRowBlockStructure objected. The matrix takes over @@ -68,8 +69,6 @@ class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix { BlockSparseMatrix(const BlockSparseMatrix&) = delete; void operator=(const BlockSparseMatrix&) = delete; - virtual ~BlockSparseMatrix(); - // Implementation of SparseMatrix interface. void SetZero() final; void RightMultiply(const double* x, double* y) const final; @@ -97,7 +96,7 @@ class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix { // Delete the bottom delta_rows_blocks. void DeleteRowBlocks(int delta_row_blocks); - static BlockSparseMatrix* CreateDiagonalMatrix( + static std::unique_ptr<BlockSparseMatrix> CreateDiagonalMatrix( const double* diagonal, const std::vector<Block>& column_blocks); struct RandomMatrixOptions { @@ -122,9 +121,7 @@ class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix { // Create a random BlockSparseMatrix whose entries are normally // distributed and whose structure is determined by // RandomMatrixOptions. - // - // Caller owns the result. - static BlockSparseMatrix* CreateRandomMatrix( + static std::unique_ptr<BlockSparseMatrix> CreateRandomMatrix( const RandomMatrixOptions& options); private: @@ -142,9 +139,9 @@ class CERES_EXPORT_INTERNAL BlockSparseMatrix : public SparseMatrix { // // BlockSparseDataMatrix a struct that carries these two bits of // information -class BlockSparseMatrixData { +class CERES_NO_EXPORT BlockSparseMatrixData { public: - BlockSparseMatrixData(const BlockSparseMatrix& m) + explicit BlockSparseMatrixData(const BlockSparseMatrix& m) : block_structure_(m.block_structure()), values_(m.values()){}; BlockSparseMatrixData(const CompressedRowBlockStructure* block_structure, @@ -164,4 +161,6 @@ class BlockSparseMatrixData { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_BLOCK_SPARSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/block_structure.h b/extern/ceres/internal/ceres/block_structure.h index d49d7d3f3a4..fe7574c6817 100644 --- a/extern/ceres/internal/ceres/block_structure.h +++ b/extern/ceres/internal/ceres/block_structure.h @@ -41,54 +41,54 @@ #include <cstdint> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { -typedef int32_t BlockSize; +using BlockSize = int32_t; -struct Block { - Block() : size(-1), position(-1) {} +struct CERES_NO_EXPORT Block { + Block() = default; Block(int size_, int position_) : size(size_), position(position_) {} - BlockSize size; - int position; // Position along the row/column. + BlockSize size{-1}; + int position{-1}; // Position along the row/column. }; -struct Cell { - Cell() : block_id(-1), position(-1) {} +struct CERES_NO_EXPORT Cell { + Cell() = default; Cell(int block_id_, int position_) : block_id(block_id_), position(position_) {} // Column or row block id as the case maybe. - int block_id; + int block_id{-1}; // Where in the values array of the jacobian is this cell located. - int position; + int position{-1}; }; // Order cell by their block_id; -bool CellLessThan(const Cell& lhs, const Cell& rhs); +CERES_NO_EXPORT bool CellLessThan(const Cell& lhs, const Cell& rhs); -struct CompressedList { - CompressedList() {} +struct CERES_NO_EXPORT CompressedList { + CompressedList() = default; // Construct a CompressedList with the cells containing num_cells // entries. - CompressedList(int num_cells) : cells(num_cells) {} + explicit CompressedList(int num_cells) : cells(num_cells) {} Block block; std::vector<Cell> cells; }; -typedef CompressedList CompressedRow; -typedef CompressedList CompressedColumn; +using CompressedRow = CompressedList; +using CompressedColumn = CompressedList; -struct CompressedRowBlockStructure { +struct CERES_NO_EXPORT CompressedRowBlockStructure { std::vector<Block> cols; std::vector<CompressedRow> rows; }; -struct CompressedColumnBlockStructure { +struct CERES_NO_EXPORT CompressedColumnBlockStructure { std::vector<Block> rows; std::vector<CompressedColumn> cols; }; diff --git a/extern/ceres/internal/ceres/c_api.cc b/extern/ceres/internal/ceres/c_api.cc index 251cde42101..8ea344dd54a 100644 --- a/extern/ceres/internal/ceres/c_api.cc +++ b/extern/ceres/internal/ceres/c_api.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -35,6 +35,7 @@ #include "ceres/c_api.h" #include <iostream> +#include <memory> #include <string> #include <vector> @@ -64,7 +65,7 @@ void ceres_free_problem(ceres_problem_t* problem) { // This cost function wraps a C-level function pointer from the user, to bridge // between C and C++. -class CallbackCostFunction : public ceres::CostFunction { +class CERES_NO_EXPORT CallbackCostFunction final : public ceres::CostFunction { public: CallbackCostFunction(ceres_cost_function_t cost_function, void* user_data, @@ -78,8 +79,6 @@ class CallbackCostFunction : public ceres::CostFunction { } } - virtual ~CallbackCostFunction() {} - bool Evaluate(double const* const* parameters, double* residuals, double** jacobians) const final { @@ -94,7 +93,7 @@ class CallbackCostFunction : public ceres::CostFunction { // This loss function wraps a C-level function pointer from the user, to bridge // between C and C++. -class CallbackLossFunction : public ceres::LossFunction { +class CallbackLossFunction final : public ceres::LossFunction { public: explicit CallbackLossFunction(ceres_loss_function_t loss_function, void* user_data) @@ -146,30 +145,31 @@ ceres_residual_block_id_t* ceres_problem_add_residual_block( int num_parameter_blocks, int* parameter_block_sizes, double** parameters) { - Problem* ceres_problem = reinterpret_cast<Problem*>(problem); - - ceres::CostFunction* callback_cost_function = - new CallbackCostFunction(cost_function, - cost_function_data, - num_residuals, - num_parameter_blocks, - parameter_block_sizes); - - ceres::LossFunction* callback_loss_function = NULL; - if (loss_function != NULL) { - callback_loss_function = - new CallbackLossFunction(loss_function, loss_function_data); + auto* ceres_problem = reinterpret_cast<Problem*>(problem); + + auto callback_cost_function = + std::make_unique<CallbackCostFunction>(cost_function, + cost_function_data, + num_residuals, + num_parameter_blocks, + parameter_block_sizes); + + std::unique_ptr<ceres::LossFunction> callback_loss_function; + if (loss_function != nullptr) { + callback_loss_function = std::make_unique<CallbackLossFunction>( + loss_function, loss_function_data); } std::vector<double*> parameter_blocks(parameters, parameters + num_parameter_blocks); return reinterpret_cast<ceres_residual_block_id_t*>( - ceres_problem->AddResidualBlock( - callback_cost_function, callback_loss_function, parameter_blocks)); + ceres_problem->AddResidualBlock(callback_cost_function.release(), + callback_loss_function.release(), + parameter_blocks)); } void ceres_solve(ceres_problem_t* c_problem) { - Problem* problem = reinterpret_cast<Problem*>(c_problem); + auto* problem = reinterpret_cast<Problem*>(c_problem); // TODO(keir): Obviously, this way of setting options won't scale or last. // Instead, figure out a way to specify some of the options without diff --git a/extern/ceres/internal/ceres/callbacks.cc b/extern/ceres/internal/ceres/callbacks.cc index 0e0df9d91b1..7a4381c293f 100644 --- a/extern/ceres/internal/ceres/callbacks.cc +++ b/extern/ceres/internal/ceres/callbacks.cc @@ -30,6 +30,7 @@ #include "ceres/callbacks.h" +#include <algorithm> #include <iostream> // NO LINT #include "ceres/program.h" @@ -45,7 +46,7 @@ StateUpdatingCallback::StateUpdatingCallback(Program* program, double* parameters) : program_(program), parameters_(parameters) {} -StateUpdatingCallback::~StateUpdatingCallback() {} +StateUpdatingCallback::~StateUpdatingCallback() = default; CallbackReturnType StateUpdatingCallback::operator()( const IterationSummary& summary) { @@ -64,14 +65,12 @@ GradientProblemSolverStateUpdatingCallback:: user_parameters_(user_parameters) {} GradientProblemSolverStateUpdatingCallback:: - ~GradientProblemSolverStateUpdatingCallback() {} + ~GradientProblemSolverStateUpdatingCallback() = default; CallbackReturnType GradientProblemSolverStateUpdatingCallback::operator()( const IterationSummary& summary) { if (summary.step_is_successful) { - std::copy(internal_parameters_, - internal_parameters_ + num_parameters_, - user_parameters_); + std::copy_n(internal_parameters_, num_parameters_, user_parameters_); } return SOLVER_CONTINUE; } @@ -80,44 +79,42 @@ LoggingCallback::LoggingCallback(const MinimizerType minimizer_type, const bool log_to_stdout) : minimizer_type(minimizer_type), log_to_stdout_(log_to_stdout) {} -LoggingCallback::~LoggingCallback() {} +LoggingCallback::~LoggingCallback() = default; CallbackReturnType LoggingCallback::operator()( const IterationSummary& summary) { string output; if (minimizer_type == LINE_SEARCH) { - const char* kReportRowFormat = - "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e " - "s:% 3.2e e:% 3d it:% 3.2e tt:% 3.2e"; - output = StringPrintf(kReportRowFormat, - summary.iteration, - summary.cost, - summary.cost_change, - summary.gradient_max_norm, - summary.step_norm, - summary.step_size, - summary.line_search_function_evaluations, - summary.iteration_time_in_seconds, - summary.cumulative_time_in_seconds); + output = StringPrintf( + "% 4d: f:% 8e d:% 3.2e g:% 3.2e h:% 3.2e s:% 3.2e e:% 3d it:% 3.2e " + "tt:% 3.2e", + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.step_size, + summary.line_search_function_evaluations, + summary.iteration_time_in_seconds, + summary.cumulative_time_in_seconds); } else if (minimizer_type == TRUST_REGION) { // clang-format off if (summary.iteration == 0) { output = "iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time\n"; // NOLINT } - const char* kReportRowFormat = - "% 4d % 8e % 3.2e % 3.2e % 3.2e % 3.2e % 3.2e % 4d % 3.2e % 3.2e"; // NOLINT - // clang-format on - output += StringPrintf(kReportRowFormat, - summary.iteration, - summary.cost, - summary.cost_change, - summary.gradient_max_norm, - summary.step_norm, - summary.relative_decrease, - summary.trust_region_radius, - summary.linear_solver_iterations, - summary.iteration_time_in_seconds, - summary.cumulative_time_in_seconds); + output += StringPrintf( + "% 4d % 8e % 3.2e % 3.2e % 3.2e % 3.2e % 3.2e % 4d % 3.2e % 3.2e", // NOLINT + // clang-format on + summary.iteration, + summary.cost, + summary.cost_change, + summary.gradient_max_norm, + summary.step_norm, + summary.relative_decrease, + summary.trust_region_radius, + summary.linear_solver_iterations, + summary.iteration_time_in_seconds, + summary.cumulative_time_in_seconds); } else { LOG(FATAL) << "Unknown minimizer type."; } diff --git a/extern/ceres/internal/ceres/callbacks.h b/extern/ceres/internal/ceres/callbacks.h index 47112b88fd8..3b1d10cfa7f 100644 --- a/extern/ceres/internal/ceres/callbacks.h +++ b/extern/ceres/internal/ceres/callbacks.h @@ -33,7 +33,7 @@ #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/iteration_callback.h" namespace ceres { @@ -43,10 +43,10 @@ class Program; // Callback for updating the externally visible state of parameter // blocks. -class StateUpdatingCallback : public IterationCallback { +class CERES_NO_EXPORT StateUpdatingCallback final : public IterationCallback { public: StateUpdatingCallback(Program* program, double* parameters); - virtual ~StateUpdatingCallback(); + ~StateUpdatingCallback() override; CallbackReturnType operator()(const IterationSummary& summary) final; private: @@ -56,12 +56,13 @@ class StateUpdatingCallback : public IterationCallback { // Callback for updating the externally visible state of the // parameters vector for GradientProblemSolver. -class GradientProblemSolverStateUpdatingCallback : public IterationCallback { +class CERES_NO_EXPORT GradientProblemSolverStateUpdatingCallback final + : public IterationCallback { public: GradientProblemSolverStateUpdatingCallback(int num_parameters, const double* internal_parameters, double* user_parameters); - virtual ~GradientProblemSolverStateUpdatingCallback(); + ~GradientProblemSolverStateUpdatingCallback() override; CallbackReturnType operator()(const IterationSummary& summary) final; private: @@ -72,10 +73,10 @@ class GradientProblemSolverStateUpdatingCallback : public IterationCallback { // Callback for logging the state of the minimizer to STDERR or // STDOUT depending on the user's preferences and logging level. -class LoggingCallback : public IterationCallback { +class CERES_NO_EXPORT LoggingCallback final : public IterationCallback { public: LoggingCallback(MinimizerType minimizer_type, bool log_to_stdout); - virtual ~LoggingCallback(); + ~LoggingCallback() override; CallbackReturnType operator()(const IterationSummary& summary) final; private: diff --git a/extern/ceres/internal/ceres/canonical_views_clustering.cc b/extern/ceres/internal/ceres/canonical_views_clustering.cc index c193735f106..01b8ad38ae0 100644 --- a/extern/ceres/internal/ceres/canonical_views_clustering.cc +++ b/extern/ceres/internal/ceres/canonical_views_clustering.cc @@ -35,6 +35,7 @@ #include <unordered_set> #include "ceres/graph.h" +#include "ceres/internal/export.h" #include "ceres/map_util.h" #include "glog/logging.h" @@ -43,13 +44,11 @@ namespace internal { using std::vector; -typedef std::unordered_map<int, int> IntMap; -typedef std::unordered_set<int> IntSet; +using IntMap = std::unordered_map<int, int>; +using IntSet = std::unordered_set<int>; -class CanonicalViewsClustering { +class CERES_NO_EXPORT CanonicalViewsClustering { public: - CanonicalViewsClustering() {} - // Compute the canonical views clustering of the vertices of the // graph. centers will contain the vertices that are the identified // as the canonical views/cluster centers, and membership is a map @@ -85,11 +84,11 @@ void ComputeCanonicalViewsClustering( const WeightedGraph<int>& graph, vector<int>* centers, IntMap* membership) { - time_t start_time = time(NULL); + time_t start_time = time(nullptr); CanonicalViewsClustering cv; cv.ComputeClustering(options, graph, centers, membership); VLOG(2) << "Canonical views clustering time (secs): " - << time(NULL) - start_time; + << time(nullptr) - start_time; } // Implementation of CanonicalViewsClustering @@ -107,7 +106,7 @@ void CanonicalViewsClustering::ComputeClustering( IntSet valid_views; FindValidViews(&valid_views); - while (valid_views.size() > 0) { + while (!valid_views.empty()) { // Find the next best canonical view. double best_difference = -std::numeric_limits<double>::max(); int best_view = 0; @@ -174,9 +173,9 @@ double CanonicalViewsClustering::ComputeClusteringQualityDifference( difference -= options_.size_penalty_weight; // Orthogonality. - for (int i = 0; i < centers.size(); ++i) { + for (int center : centers) { difference -= options_.similarity_penalty_weight * - graph_->EdgeWeight(centers[i], candidate); + graph_->EdgeWeight(center, candidate); } return difference; diff --git a/extern/ceres/internal/ceres/canonical_views_clustering.h b/extern/ceres/internal/ceres/canonical_views_clustering.h index 465233ddfcd..00a6a739d29 100644 --- a/extern/ceres/internal/ceres/canonical_views_clustering.h +++ b/extern/ceres/internal/ceres/canonical_views_clustering.h @@ -45,7 +45,8 @@ #include <vector> #include "ceres/graph.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -95,13 +96,13 @@ struct CanonicalViewsClusteringOptions; // It is possible depending on the configuration of the clustering // algorithm that some of the vertices may not be assigned to any // cluster. In this case they are assigned to a cluster with id = -1; -CERES_EXPORT_INTERNAL void ComputeCanonicalViewsClustering( +CERES_NO_EXPORT void ComputeCanonicalViewsClustering( const CanonicalViewsClusteringOptions& options, const WeightedGraph<int>& graph, std::vector<int>* centers, std::unordered_map<int, int>* membership); -struct CERES_EXPORT_INTERNAL CanonicalViewsClusteringOptions { +struct CERES_NO_EXPORT CanonicalViewsClusteringOptions { // The minimum number of canonical views to compute. int min_views = 3; @@ -122,4 +123,6 @@ struct CERES_EXPORT_INTERNAL CanonicalViewsClusteringOptions { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_CANONICAL_VIEWS_CLUSTERING_H_ diff --git a/extern/ceres/internal/ceres/casts.h b/extern/ceres/internal/ceres/casts.h index d13707131c2..04d8ba4fe33 100644 --- a/extern/ceres/internal/ceres/casts.h +++ b/extern/ceres/internal/ceres/casts.h @@ -32,14 +32,13 @@ #define CERES_INTERNAL_CASTS_H_ #include <cassert> -#include <cstddef> // For NULL. namespace ceres { // Identity metafunction. template <class T> struct identity_ { - typedef T type; + using type = T; }; // Use implicit_cast as a safe version of static_cast or const_cast @@ -86,6 +85,7 @@ inline To implicit_cast(typename identity_<From>::type const& f) { // if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo); // You should design the code some other way not to need this. +// TODO(sameeragarwal): Modernize this. template <typename To, typename From> // use like this: down_cast<T*>(foo); inline To down_cast(From* f) { // so we only accept pointers // Ensures that To is a sub-type of From *. This test is here only @@ -95,11 +95,11 @@ inline To down_cast(From* f) { // so we only accept pointers // TODO(csilvers): This should use COMPILE_ASSERT. if (false) { - implicit_cast<From*, To>(NULL); + implicit_cast<From*, To>(nullptr); } // uses RTTI in dbg and fastbuild. asserts are disabled in opt builds. - assert(f == NULL || dynamic_cast<To>(f) != NULL); // NOLINT + assert(f == nullptr || dynamic_cast<To>(f) != nullptr); // NOLINT return static_cast<To>(f); } diff --git a/extern/ceres/internal/ceres/cgnr_linear_operator.h b/extern/ceres/internal/ceres/cgnr_linear_operator.h index beb8bbc2c2a..d708efca24c 100644 --- a/extern/ceres/internal/ceres/cgnr_linear_operator.h +++ b/extern/ceres/internal/ceres/cgnr_linear_operator.h @@ -34,7 +34,9 @@ #include <algorithm> #include <memory> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/linear_operator.h" namespace ceres { @@ -78,11 +80,10 @@ class SparseMatrix; // and z = A^T b // // Note: This class is not thread safe, since it uses some temporary storage. -class CgnrLinearOperator : public LinearOperator { +class CERES_NO_EXPORT CgnrLinearOperator final : public LinearOperator { public: CgnrLinearOperator(const LinearOperator& A, const double* D) : A_(A), D_(D), z_(new double[A.num_rows()]) {} - virtual ~CgnrLinearOperator() {} void RightMultiply(const double* x, double* y) const final { std::fill(z_.get(), z_.get() + A_.num_rows(), 0.0); @@ -94,7 +95,7 @@ class CgnrLinearOperator : public LinearOperator { A_.LeftMultiply(z_.get(), y); // y = y + DtDx - if (D_ != NULL) { + if (D_ != nullptr) { int n = A_.num_cols(); VectorRef(y, n).array() += ConstVectorRef(D_, n).array().square() * ConstVectorRef(x, n).array(); @@ -117,4 +118,6 @@ class CgnrLinearOperator : public LinearOperator { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_CGNR_LINEAR_OPERATOR_H_ diff --git a/extern/ceres/internal/ceres/cgnr_solver.cc b/extern/ceres/internal/ceres/cgnr_solver.cc index 9dba1cfb4a8..cca72bca988 100644 --- a/extern/ceres/internal/ceres/cgnr_solver.cc +++ b/extern/ceres/internal/ceres/cgnr_solver.cc @@ -30,6 +30,9 @@ #include "ceres/cgnr_solver.h" +#include <memory> +#include <utility> + #include "ceres/block_jacobi_preconditioner.h" #include "ceres/cgnr_linear_operator.h" #include "ceres/conjugate_gradients_solver.h" @@ -42,8 +45,8 @@ namespace ceres { namespace internal { -CgnrSolver::CgnrSolver(const LinearSolver::Options& options) - : options_(options) { +CgnrSolver::CgnrSolver(LinearSolver::Options options) + : options_(std::move(options)) { if (options_.preconditioner_type != JACOBI && options_.preconditioner_type != IDENTITY && options_.preconditioner_type != SUBSET) { @@ -54,7 +57,7 @@ CgnrSolver::CgnrSolver(const LinearSolver::Options& options) } } -CgnrSolver::~CgnrSolver() {} +CgnrSolver::~CgnrSolver() = default; LinearSolver::Summary CgnrSolver::SolveImpl( BlockSparseMatrix* A, @@ -70,7 +73,7 @@ LinearSolver::Summary CgnrSolver::SolveImpl( if (!preconditioner_) { if (options_.preconditioner_type == JACOBI) { - preconditioner_.reset(new BlockJacobiPreconditioner(*A)); + preconditioner_ = std::make_unique<BlockJacobiPreconditioner>(*A); } else if (options_.preconditioner_type == SUBSET) { Preconditioner::Options preconditioner_options; preconditioner_options.type = SUBSET; @@ -81,8 +84,8 @@ LinearSolver::Summary CgnrSolver::SolveImpl( preconditioner_options.use_postordering = options_.use_postordering; preconditioner_options.num_threads = options_.num_threads; preconditioner_options.context = options_.context; - preconditioner_.reset( - new SubsetPreconditioner(preconditioner_options, *A)); + preconditioner_ = + std::make_unique<SubsetPreconditioner>(preconditioner_options, *A); } } diff --git a/extern/ceres/internal/ceres/cgnr_solver.h b/extern/ceres/internal/ceres/cgnr_solver.h index bc701c0e9ed..25e62e9abd9 100644 --- a/extern/ceres/internal/ceres/cgnr_solver.h +++ b/extern/ceres/internal/ceres/cgnr_solver.h @@ -33,6 +33,7 @@ #include <memory> +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -49,12 +50,12 @@ class BlockJacobiPreconditioner; // // as required for solving for x in the least squares sense. Currently only // block diagonal preconditioning is supported. -class CgnrSolver : public BlockSparseMatrixSolver { +class CERES_NO_EXPORT CgnrSolver final : public BlockSparseMatrixSolver { public: - explicit CgnrSolver(const LinearSolver::Options& options); + explicit CgnrSolver(LinearSolver::Options options); CgnrSolver(const CgnrSolver&) = delete; void operator=(const CgnrSolver&) = delete; - virtual ~CgnrSolver(); + ~CgnrSolver() override; Summary SolveImpl(BlockSparseMatrix* A, const double* b, diff --git a/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.cc b/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.cc index e1f6bb8ff9d..94e7e9aa446 100644 --- a/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.cc +++ b/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.cc @@ -33,7 +33,7 @@ #include <algorithm> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "glog/logging.h" namespace ceres { diff --git a/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.h b/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.h index d442e1a9bb8..f88a5bd9588 100644 --- a/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.h +++ b/extern/ceres/internal/ceres/compressed_col_sparse_matrix_utils.h @@ -31,9 +31,11 @@ #ifndef CERES_INTERNAL_COMPRESSED_COL_SPARSE_MATRIX_UTILS_H_ #define CERES_INTERNAL_COMPRESSED_COL_SPARSE_MATRIX_UTILS_H_ +#include <algorithm> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -48,7 +50,7 @@ namespace internal { // and column block j, then it is expected that A contains at least // one non-zero entry corresponding to the top left entry of c_ij, // as that entry is used to detect the presence of a non-zero c_ij. -CERES_EXPORT_INTERNAL void CompressedColumnScalarMatrixToBlockMatrix( +CERES_NO_EXPORT void CompressedColumnScalarMatrixToBlockMatrix( const int* scalar_rows, const int* scalar_cols, const std::vector<int>& row_blocks, @@ -59,7 +61,7 @@ CERES_EXPORT_INTERNAL void CompressedColumnScalarMatrixToBlockMatrix( // Given a set of blocks and a permutation of these blocks, compute // the corresponding "scalar" ordering, where the scalar ordering of // size sum(blocks). -CERES_EXPORT_INTERNAL void BlockOrderingToScalarOrdering( +CERES_NO_EXPORT void BlockOrderingToScalarOrdering( const std::vector<int>& blocks, const std::vector<int>& block_ordering, std::vector<int>* scalar_ordering); @@ -142,4 +144,6 @@ void SolveRTRWithSparseRHS(IntegerType num_cols, } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_COMPRESSED_COL_SPARSE_MATRIX_UTILS_H_ diff --git a/extern/ceres/internal/ceres/compressed_row_jacobian_writer.cc b/extern/ceres/internal/ceres/compressed_row_jacobian_writer.cc index 8e7e3e7e7e6..55b30a290f9 100644 --- a/extern/ceres/internal/ceres/compressed_row_jacobian_writer.cc +++ b/extern/ceres/internal/ceres/compressed_row_jacobian_writer.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -30,7 +30,10 @@ #include "ceres/compressed_row_jacobian_writer.h" +#include <algorithm> #include <iterator> +#include <memory> +#include <string> #include <utility> #include <vector> @@ -55,7 +58,7 @@ void CompressedRowJacobianWriter::PopulateJacobianRowAndColumnBlockVectors( vector<int>& col_blocks = *(jacobian->mutable_col_blocks()); col_blocks.resize(parameter_blocks.size()); for (int i = 0; i < parameter_blocks.size(); ++i) { - col_blocks[i] = parameter_blocks[i]->LocalSize(); + col_blocks[i] = parameter_blocks[i]->TangentSize(); } const vector<ResidualBlock*>& residual_blocks = program->residual_blocks(); @@ -81,10 +84,12 @@ void CompressedRowJacobianWriter::GetOrderedParameterBlocks( make_pair(parameter_block->index(), j)); } } - sort(evaluated_jacobian_blocks->begin(), evaluated_jacobian_blocks->end()); + std::sort(evaluated_jacobian_blocks->begin(), + evaluated_jacobian_blocks->end()); } -SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { +std::unique_ptr<SparseMatrix> CompressedRowJacobianWriter::CreateJacobian() + const { const vector<ResidualBlock*>& residual_blocks = program_->residual_blocks(); int total_num_residuals = program_->NumResiduals(); @@ -92,14 +97,13 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { // Count the number of jacobian nonzeros. int num_jacobian_nonzeros = 0; - for (int i = 0; i < residual_blocks.size(); ++i) { - ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { const int num_residuals = residual_block->NumResiduals(); const int num_parameter_blocks = residual_block->NumParameterBlocks(); for (int j = 0; j < num_parameter_blocks; ++j) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; if (!parameter_block->IsConstant()) { - num_jacobian_nonzeros += num_residuals * parameter_block->LocalSize(); + num_jacobian_nonzeros += num_residuals * parameter_block->TangentSize(); } } } @@ -108,10 +112,11 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { // Allocate more space than needed to store the jacobian so that when the LM // algorithm adds the diagonal, no reallocation is necessary. This reduces // peak memory usage significantly. - CompressedRowSparseMatrix* jacobian = new CompressedRowSparseMatrix( - total_num_residuals, - total_num_effective_parameters, - num_jacobian_nonzeros + total_num_effective_parameters); + std::unique_ptr<CompressedRowSparseMatrix> jacobian = + std::make_unique<CompressedRowSparseMatrix>( + total_num_residuals, + total_num_effective_parameters, + num_jacobian_nonzeros + total_num_effective_parameters); // At this stage, the CompressedRowSparseMatrix is an invalid state. But this // seems to be the only way to construct it without doing a memory copy. @@ -120,8 +125,7 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { int row_pos = 0; rows[0] = 0; - for (int i = 0; i < residual_blocks.size(); ++i) { - const ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { const int num_parameter_blocks = residual_block->NumParameterBlocks(); // Count the number of derivatives for a row of this residual block and @@ -132,7 +136,7 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; if (!parameter_block->IsConstant()) { parameter_indices.push_back(parameter_block->index()); - num_derivatives += parameter_block->LocalSize(); + num_derivatives += parameter_block->TangentSize(); } } @@ -163,10 +167,10 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { // parameter vector. This code mirrors that in Write(), where jacobian // values are updated. int col_pos = 0; - for (int j = 0; j < parameter_indices.size(); ++j) { + for (int parameter_index : parameter_indices) { ParameterBlock* parameter_block = - program_->parameter_blocks()[parameter_indices[j]]; - const int parameter_block_size = parameter_block->LocalSize(); + program_->parameter_blocks()[parameter_index]; + const int parameter_block_size = parameter_block->TangentSize(); for (int r = 0; r < num_residuals; ++r) { // This is the position in the values array of the jacobian where this @@ -183,7 +187,7 @@ SparseMatrix* CompressedRowJacobianWriter::CreateJacobian() const { } CHECK_EQ(num_jacobian_nonzeros, rows[total_num_residuals]); - PopulateJacobianRowAndColumnBlockVectors(program_, jacobian); + PopulateJacobianRowAndColumnBlockVectors(program_, jacobian.get()); return jacobian; } @@ -192,8 +196,7 @@ void CompressedRowJacobianWriter::Write(int residual_id, int residual_offset, double** jacobians, SparseMatrix* base_jacobian) { - CompressedRowSparseMatrix* jacobian = - down_cast<CompressedRowSparseMatrix*>(base_jacobian); + auto* jacobian = down_cast<CompressedRowSparseMatrix*>(base_jacobian); double* jacobian_values = jacobian->mutable_values(); const int* jacobian_rows = jacobian->rows(); @@ -210,11 +213,11 @@ void CompressedRowJacobianWriter::Write(int residual_id, // Iterate over the jacobian blocks in increasing order of their // positions in the reduced parameter vector. - for (int i = 0; i < evaluated_jacobian_blocks.size(); ++i) { + for (auto& evaluated_jacobian_block : evaluated_jacobian_blocks) { const ParameterBlock* parameter_block = - program_->parameter_blocks()[evaluated_jacobian_blocks[i].first]; - const int argument = evaluated_jacobian_blocks[i].second; - const int parameter_block_size = parameter_block->LocalSize(); + program_->parameter_blocks()[evaluated_jacobian_block.first]; + const int argument = evaluated_jacobian_block.second; + const int parameter_block_size = parameter_block->TangentSize(); // Copy one row of the jacobian block at a time. for (int r = 0; r < num_residuals; ++r) { diff --git a/extern/ceres/internal/ceres/compressed_row_jacobian_writer.h b/extern/ceres/internal/ceres/compressed_row_jacobian_writer.h index b1251ca5cf5..7badab71b04 100644 --- a/extern/ceres/internal/ceres/compressed_row_jacobian_writer.h +++ b/extern/ceres/internal/ceres/compressed_row_jacobian_writer.h @@ -33,10 +33,12 @@ #ifndef CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ #define CERES_INTERNAL_COMPRESSED_ROW_JACOBIAN_WRITER_H_ +#include <memory> #include <utility> #include <vector> #include "ceres/evaluator.h" +#include "ceres/internal/export.h" #include "ceres/scratch_evaluate_preparer.h" namespace ceres { @@ -46,7 +48,7 @@ class CompressedRowSparseMatrix; class Program; class SparseMatrix; -class CompressedRowJacobianWriter { +class CERES_NO_EXPORT CompressedRowJacobianWriter { public: CompressedRowJacobianWriter(Evaluator::Options /* ignored */, Program* program) @@ -89,11 +91,12 @@ class CompressedRowJacobianWriter { // assumed by the cost functions, use scratch space to store the // jacobians temporarily then copy them over to the larger jacobian // in the Write() function. - ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + std::unique_ptr<ScratchEvaluatePreparer[]> CreateEvaluatePreparers( + int num_threads) { return ScratchEvaluatePreparer::Create(*program_, num_threads); } - SparseMatrix* CreateJacobian() const; + std::unique_ptr<SparseMatrix> CreateJacobian() const; void Write(int residual_id, int residual_offset, diff --git a/extern/ceres/internal/ceres/compressed_row_sparse_matrix.cc b/extern/ceres/internal/ceres/compressed_row_sparse_matrix.cc index 900586c2c45..db103d9c0fa 100644 --- a/extern/ceres/internal/ceres/compressed_row_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/compressed_row_sparse_matrix.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2017 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -31,11 +31,12 @@ #include "ceres/compressed_row_sparse_matrix.h" #include <algorithm> +#include <memory> #include <numeric> #include <vector> #include "ceres/crs_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/random.h" #include "ceres/triplet_sparse_matrix.h" #include "glog/logging.h" @@ -104,7 +105,7 @@ void TransposeForCompressedRowSparseStructure(const int num_rows, const int c = cols[idx]; const int transpose_idx = transpose_rows[c]++; transpose_cols[transpose_idx] = r; - if (values != NULL && transpose_values != NULL) { + if (values != nullptr && transpose_values != nullptr) { transpose_values[transpose_idx] = values[idx]; } } @@ -174,18 +175,20 @@ CompressedRowSparseMatrix::CompressedRowSparseMatrix(int num_rows, cols_.size() * sizeof(double); // NOLINT } -CompressedRowSparseMatrix* CompressedRowSparseMatrix::FromTripletSparseMatrix( +std::unique_ptr<CompressedRowSparseMatrix> +CompressedRowSparseMatrix::FromTripletSparseMatrix( const TripletSparseMatrix& input) { return CompressedRowSparseMatrix::FromTripletSparseMatrix(input, false); } -CompressedRowSparseMatrix* +std::unique_ptr<CompressedRowSparseMatrix> CompressedRowSparseMatrix::FromTripletSparseMatrixTransposed( const TripletSparseMatrix& input) { return CompressedRowSparseMatrix::FromTripletSparseMatrix(input, true); } -CompressedRowSparseMatrix* CompressedRowSparseMatrix::FromTripletSparseMatrix( +std::unique_ptr<CompressedRowSparseMatrix> +CompressedRowSparseMatrix::FromTripletSparseMatrix( const TripletSparseMatrix& input, bool transpose) { int num_rows = input.num_rows(); int num_cols = input.num_cols(); @@ -214,8 +217,9 @@ CompressedRowSparseMatrix* CompressedRowSparseMatrix::FromTripletSparseMatrix( input.num_nonzeros() * sizeof(int) + // NOLINT input.num_nonzeros() * sizeof(double)); // NOLINT - CompressedRowSparseMatrix* output = - new CompressedRowSparseMatrix(num_rows, num_cols, input.num_nonzeros()); + std::unique_ptr<CompressedRowSparseMatrix> output = + std::make_unique<CompressedRowSparseMatrix>( + num_rows, num_cols, input.num_nonzeros()); if (num_rows == 0) { // No data to copy. @@ -266,7 +270,7 @@ CompressedRowSparseMatrix::CompressedRowSparseMatrix(const double* diagonal, CHECK_EQ(num_nonzeros(), num_rows); } -CompressedRowSparseMatrix::~CompressedRowSparseMatrix() {} +CompressedRowSparseMatrix::~CompressedRowSparseMatrix() = default; void CompressedRowSparseMatrix::SetZero() { std::fill(values_.begin(), values_.end(), 0); @@ -533,17 +537,19 @@ void CompressedRowSparseMatrix::SetMaxNumNonZeros(int num_nonzeros) { values_.resize(num_nonzeros); } -CompressedRowSparseMatrix* CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( +std::unique_ptr<CompressedRowSparseMatrix> +CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( const double* diagonal, const vector<int>& blocks) { int num_rows = 0; int num_nonzeros = 0; - for (int i = 0; i < blocks.size(); ++i) { - num_rows += blocks[i]; - num_nonzeros += blocks[i] * blocks[i]; + for (int block_size : blocks) { + num_rows += block_size; + num_nonzeros += block_size * block_size; } - CompressedRowSparseMatrix* matrix = - new CompressedRowSparseMatrix(num_rows, num_rows, num_nonzeros); + std::unique_ptr<CompressedRowSparseMatrix> matrix = + std::make_unique<CompressedRowSparseMatrix>( + num_rows, num_rows, num_nonzeros); int* rows = matrix->mutable_rows(); int* cols = matrix->mutable_cols(); @@ -552,8 +558,7 @@ CompressedRowSparseMatrix* CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( int idx_cursor = 0; int col_cursor = 0; - for (int i = 0; i < blocks.size(); ++i) { - const int block_size = blocks[i]; + for (int block_size : blocks) { for (int r = 0; r < block_size; ++r) { *(rows++) = idx_cursor; values[idx_cursor + r] = diagonal[col_cursor + r]; @@ -573,9 +578,11 @@ CompressedRowSparseMatrix* CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( return matrix; } -CompressedRowSparseMatrix* CompressedRowSparseMatrix::Transpose() const { - CompressedRowSparseMatrix* transpose = - new CompressedRowSparseMatrix(num_cols_, num_rows_, num_nonzeros()); +std::unique_ptr<CompressedRowSparseMatrix> +CompressedRowSparseMatrix::Transpose() const { + std::unique_ptr<CompressedRowSparseMatrix> transpose = + std::make_unique<CompressedRowSparseMatrix>( + num_cols_, num_rows_, num_nonzeros()); switch (storage_type_) { case UNSYMMETRIC: @@ -612,7 +619,8 @@ CompressedRowSparseMatrix* CompressedRowSparseMatrix::Transpose() const { return transpose; } -CompressedRowSparseMatrix* CompressedRowSparseMatrix::CreateRandomMatrix( +std::unique_ptr<CompressedRowSparseMatrix> +CompressedRowSparseMatrix::CreateRandomMatrix( CompressedRowSparseMatrix::RandomMatrixOptions options) { CHECK_GT(options.num_row_blocks, 0); CHECK_GT(options.min_row_block_size, 0); @@ -714,7 +722,7 @@ CompressedRowSparseMatrix* CompressedRowSparseMatrix::CreateRandomMatrix( const int num_rows = std::accumulate(row_blocks.begin(), row_blocks.end(), 0); const int num_cols = std::accumulate(col_blocks.begin(), col_blocks.end(), 0); const bool kDoNotTranspose = false; - CompressedRowSparseMatrix* matrix = + std::unique_ptr<CompressedRowSparseMatrix> matrix = CompressedRowSparseMatrix::FromTripletSparseMatrix( TripletSparseMatrix( num_rows, num_cols, tsm_rows, tsm_cols, tsm_values), diff --git a/extern/ceres/internal/ceres/compressed_row_sparse_matrix.h b/extern/ceres/internal/ceres/compressed_row_sparse_matrix.h index 0a1b945193d..3d7d385b185 100644 --- a/extern/ceres/internal/ceres/compressed_row_sparse_matrix.h +++ b/extern/ceres/internal/ceres/compressed_row_sparse_matrix.h @@ -31,9 +31,11 @@ #ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ #define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ +#include <memory> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/sparse_matrix.h" #include "ceres/types.h" #include "glog/logging.h" @@ -46,7 +48,7 @@ namespace internal { class TripletSparseMatrix; -class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { +class CERES_NO_EXPORT CompressedRowSparseMatrix : public SparseMatrix { public: enum StorageType { UNSYMMETRIC, @@ -63,9 +65,7 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { // entries. // // The storage type of the matrix is set to UNSYMMETRIC. - // - // Caller owns the result. - static CompressedRowSparseMatrix* FromTripletSparseMatrix( + static std::unique_ptr<CompressedRowSparseMatrix> FromTripletSparseMatrix( const TripletSparseMatrix& input); // Create a matrix with the same content as the TripletSparseMatrix @@ -73,10 +73,8 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { // entries. // // The storage type of the matrix is set to UNSYMMETRIC. - // - // Caller owns the result. - static CompressedRowSparseMatrix* FromTripletSparseMatrixTransposed( - const TripletSparseMatrix& input); + static std::unique_ptr<CompressedRowSparseMatrix> + FromTripletSparseMatrixTransposed(const TripletSparseMatrix& input); // Use this constructor only if you know what you are doing. This // creates a "blank" matrix with the appropriate amount of memory @@ -100,7 +98,7 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { CompressedRowSparseMatrix(const double* diagonal, int num_rows); // SparseMatrix interface. - virtual ~CompressedRowSparseMatrix(); + ~CompressedRowSparseMatrix() override; void SetZero() final; void RightMultiply(const double* x, double* y) const final; void LeftMultiply(const double* x, double* y) const final; @@ -124,7 +122,7 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { void ToCRSMatrix(CRSMatrix* matrix) const; - CompressedRowSparseMatrix* Transpose() const; + std::unique_ptr<CompressedRowSparseMatrix> Transpose() const; // Destructive array resizing method. void SetMaxNumNonZeros(int num_nonzeros); @@ -140,7 +138,7 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { const int* rows() const { return &rows_[0]; } int* mutable_rows() { return &rows_[0]; } - const StorageType storage_type() const { return storage_type_; } + StorageType storage_type() const { return storage_type_; } void set_storage_type(const StorageType storage_type) { storage_type_ = storage_type; } @@ -154,9 +152,7 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { // Create a block diagonal CompressedRowSparseMatrix with the given // block structure. The individual blocks are assumed to be laid out // contiguously in the diagonal array, one block at a time. - // - // Caller owns the result. - static CompressedRowSparseMatrix* CreateBlockDiagonalMatrix( + static std::unique_ptr<CompressedRowSparseMatrix> CreateBlockDiagonalMatrix( const double* diagonal, const std::vector<int>& blocks); // Options struct to control the generation of random block sparse @@ -198,13 +194,11 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { // Create a random CompressedRowSparseMatrix whose entries are // normally distributed and whose structure is determined by // RandomMatrixOptions. - // - // Caller owns the result. - static CompressedRowSparseMatrix* CreateRandomMatrix( + static std::unique_ptr<CompressedRowSparseMatrix> CreateRandomMatrix( RandomMatrixOptions options); private: - static CompressedRowSparseMatrix* FromTripletSparseMatrix( + static std::unique_ptr<CompressedRowSparseMatrix> FromTripletSparseMatrix( const TripletSparseMatrix& input, bool transpose); int num_rows_; @@ -226,4 +220,6 @@ class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/concurrent_queue.h b/extern/ceres/internal/ceres/concurrent_queue.h index a04d147c5c0..1e74153566a 100644 --- a/extern/ceres/internal/ceres/concurrent_queue.h +++ b/extern/ceres/internal/ceres/concurrent_queue.h @@ -78,7 +78,7 @@ template <typename T> class ConcurrentQueue { public: // Defaults the queue to blocking on Wait calls. - ConcurrentQueue() : wait_(true) {} + ConcurrentQueue() = default; // Atomically push an element onto the queue. If a thread was waiting for an // element, wake it up. @@ -149,7 +149,7 @@ class ConcurrentQueue { std::queue<T> queue_; // If true, signals that callers of Wait will block waiting to pop an // element off the queue. - bool wait_; + bool wait_{true}; }; } // namespace internal diff --git a/extern/ceres/internal/ceres/conditioned_cost_function.cc b/extern/ceres/internal/ceres/conditioned_cost_function.cc index fb4c52af084..a9013a23d0a 100644 --- a/extern/ceres/internal/ceres/conditioned_cost_function.cc +++ b/extern/ceres/internal/ceres/conditioned_cost_function.cc @@ -98,7 +98,7 @@ bool ConditionedCostFunction::Evaluate(double const* const* parameters, double** conditioner_derivative_pointer2 = &conditioner_derivative_pointer; if (!jacobians) { - conditioner_derivative_pointer2 = NULL; + conditioner_derivative_pointer2 = nullptr; } double unconditioned_residual = residuals[r]; diff --git a/extern/ceres/internal/ceres/conjugate_gradients_solver.cc b/extern/ceres/internal/ceres/conjugate_gradients_solver.cc index 3019628a16c..62ae9201cb5 100644 --- a/extern/ceres/internal/ceres/conjugate_gradients_solver.cc +++ b/extern/ceres/internal/ceres/conjugate_gradients_solver.cc @@ -41,6 +41,7 @@ #include <cmath> #include <cstddef> +#include <utility> #include "ceres/internal/eigen.h" #include "ceres/linear_operator.h" @@ -57,8 +58,8 @@ bool IsZeroOrInfinity(double x) { return ((x == 0.0) || std::isinf(x)); } } // namespace ConjugateGradientsSolver::ConjugateGradientsSolver( - const LinearSolver::Options& options) - : options_(options) {} + LinearSolver::Options options) + : options_(std::move(options)) {} LinearSolver::Summary ConjugateGradientsSolver::Solve( LinearOperator* A, @@ -112,7 +113,7 @@ LinearSolver::Summary ConjugateGradientsSolver::Solve( for (summary.num_iterations = 1;; ++summary.num_iterations) { // Apply preconditioner - if (per_solve_options.preconditioner != NULL) { + if (per_solve_options.preconditioner != nullptr) { z.setZero(); per_solve_options.preconditioner->RightMultiply(r.data(), z.data()); } else { diff --git a/extern/ceres/internal/ceres/conjugate_gradients_solver.h b/extern/ceres/internal/ceres/conjugate_gradients_solver.h index f79ca496531..99ddb5d485b 100644 --- a/extern/ceres/internal/ceres/conjugate_gradients_solver.h +++ b/extern/ceres/internal/ceres/conjugate_gradients_solver.h @@ -34,7 +34,8 @@ #ifndef CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ #define CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -55,9 +56,9 @@ class LinearOperator; // For more details see the documentation for // LinearSolver::PerSolveOptions::r_tolerance and // LinearSolver::PerSolveOptions::q_tolerance in linear_solver.h. -class CERES_EXPORT_INTERNAL ConjugateGradientsSolver : public LinearSolver { +class CERES_NO_EXPORT ConjugateGradientsSolver final : public LinearSolver { public: - explicit ConjugateGradientsSolver(const LinearSolver::Options& options); + explicit ConjugateGradientsSolver(LinearSolver::Options options); Summary Solve(LinearOperator* A, const double* b, const LinearSolver::PerSolveOptions& per_solve_options, @@ -70,4 +71,6 @@ class CERES_EXPORT_INTERNAL ConjugateGradientsSolver : public LinearSolver { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_CONJUGATE_GRADIENTS_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/context.cc b/extern/ceres/internal/ceres/context.cc index 55e76351219..fde16b84bca 100644 --- a/extern/ceres/internal/ceres/context.cc +++ b/extern/ceres/internal/ceres/context.cc @@ -34,6 +34,8 @@ namespace ceres { +Context::Context() = default; Context* Context::Create() { return new internal::ContextImpl(); } +Context::~Context() = default; } // namespace ceres diff --git a/extern/ceres/internal/ceres/context_impl.cc b/extern/ceres/internal/ceres/context_impl.cc index 20fe5cbab2a..a4b3c842da1 100644 --- a/extern/ceres/internal/ceres/context_impl.cc +++ b/extern/ceres/internal/ceres/context_impl.cc @@ -30,9 +30,75 @@ #include "ceres/context_impl.h" +#include <string> + +#include "ceres/internal/config.h" + +#ifndef CERES_NO_CUDA +#include "cublas_v2.h" +#include "cuda_runtime.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA + namespace ceres { namespace internal { +ContextImpl::ContextImpl() = default; + +#ifndef CERES_NO_CUDA +bool ContextImpl::InitCUDA(std::string* message) { + if (cuda_initialized_) { + return true; + } + if (cublasCreate(&cublas_handle_) != CUBLAS_STATUS_SUCCESS) { + *message = "cuBLAS::cublasCreate failed."; + cublas_handle_ = nullptr; + return false; + } + if (cusolverDnCreate(&cusolver_handle_) != CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnCreate failed."; + cusolver_handle_ = nullptr; + cublasDestroy(cublas_handle_); + cublas_handle_ = nullptr; + return false; + } + if (cudaStreamCreateWithFlags(&stream_, cudaStreamNonBlocking) != + cudaSuccess) { + *message = "CUDA::cudaStreamCreateWithFlags failed."; + cusolverDnDestroy(cusolver_handle_); + cublasDestroy(cublas_handle_); + cusolver_handle_ = nullptr; + cublas_handle_ = nullptr; + stream_ = nullptr; + return false; + } + if (cusolverDnSetStream(cusolver_handle_, stream_) != + CUSOLVER_STATUS_SUCCESS || + cublasSetStream(cublas_handle_, stream_) != CUBLAS_STATUS_SUCCESS) { + *message = + "cuSolverDN::cusolverDnSetStream or cuBLAS::cublasSetStream failed."; + cusolverDnDestroy(cusolver_handle_); + cublasDestroy(cublas_handle_); + cudaStreamDestroy(stream_); + cusolver_handle_ = nullptr; + cublas_handle_ = nullptr; + stream_ = nullptr; + return false; + } + cuda_initialized_ = true; + return true; +} +#endif // CERES_NO_CUDA + +ContextImpl::~ContextImpl() { +#ifndef CERES_NO_CUDA + if (cuda_initialized_) { + cusolverDnDestroy(cusolver_handle_); + cublasDestroy(cublas_handle_); + cudaStreamDestroy(stream_); + } +#endif // CERES_NO_CUDA +} void ContextImpl::EnsureMinimumThreads(int num_threads) { #ifdef CERES_USE_CXX_THREADS thread_pool.Resize(num_threads); diff --git a/extern/ceres/internal/ceres/context_impl.h b/extern/ceres/internal/ceres/context_impl.h index 574d1efcc6d..8e9a03fb4ae 100644 --- a/extern/ceres/internal/ceres/context_impl.h +++ b/extern/ceres/internal/ceres/context_impl.h @@ -33,10 +33,20 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" -// clanf-format on +#include "ceres/internal/config.h" +// clang-format on + +#include <string> #include "ceres/context.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" + +#ifndef CERES_NO_CUDA +#include "cublas_v2.h" +#include "cuda_runtime.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA #ifdef CERES_USE_CXX_THREADS #include "ceres/thread_pool.h" @@ -45,14 +55,13 @@ namespace ceres { namespace internal { -class CERES_EXPORT_INTERNAL ContextImpl : public Context { +class CERES_NO_EXPORT ContextImpl final : public Context { public: - ContextImpl() {} + ContextImpl(); + ~ContextImpl() override; ContextImpl(const ContextImpl&) = delete; void operator=(const ContextImpl&) = delete; - virtual ~ContextImpl() {} - // When compiled with C++ threading support, resize the thread pool to have // at min(num_thread, num_hardware_threads) where num_hardware_threads is // defined by the hardware. Otherwise this call is a no-op. @@ -61,9 +70,28 @@ class CERES_EXPORT_INTERNAL ContextImpl : public Context { #ifdef CERES_USE_CXX_THREADS ThreadPool thread_pool; #endif // CERES_USE_CXX_THREADS + +#ifndef CERES_NO_CUDA + // Initializes the cuSolverDN context, creates an asynchronous stream, and + // associates the stream with cuSolverDN. Returns true iff initialization was + // successful, else it returns false and a human-readable error message is + // returned. + bool InitCUDA(std::string* message); + + // Handle to the cuSOLVER context. + cusolverDnHandle_t cusolver_handle_ = nullptr; + // Handle to cuBLAS context. + cublasHandle_t cublas_handle_ = nullptr; + // CUDA device stream. + cudaStream_t stream_ = nullptr; + // Indicates whether all the CUDA resources have been initialized. + bool cuda_initialized_ = false; +#endif // CERES_NO_CUDA }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_CONTEXT_IMPL_H_ diff --git a/extern/ceres/internal/ceres/coordinate_descent_minimizer.cc b/extern/ceres/internal/ceres/coordinate_descent_minimizer.cc index 93096ac0728..a6e149d1cee 100644 --- a/extern/ceres/internal/ceres/coordinate_descent_minimizer.cc +++ b/extern/ceres/internal/ceres/coordinate_descent_minimizer.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -64,7 +64,7 @@ CoordinateDescentMinimizer::CoordinateDescentMinimizer(ContextImpl* context) CHECK(context_ != nullptr); } -CoordinateDescentMinimizer::~CoordinateDescentMinimizer() {} +CoordinateDescentMinimizer::~CoordinateDescentMinimizer() = default; bool CoordinateDescentMinimizer::Init( const Program& program, @@ -94,9 +94,9 @@ bool CoordinateDescentMinimizer::Init( // assign zero offsets/empty independent sets to these parameter // blocks. const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - if (!ordering.IsMember(parameter_blocks[i]->mutable_user_state())) { - parameter_blocks_.push_back(parameter_blocks[i]); + for (auto* parameter_block : parameter_blocks) { + if (!ordering.IsMember(parameter_block->mutable_user_state())) { + parameter_blocks_.push_back(parameter_block); independent_set_offsets_.push_back(independent_set_offsets_.back()); } } @@ -105,8 +105,7 @@ bool CoordinateDescentMinimizer::Init( // block. residual_blocks_.resize(parameter_block_index.size()); const vector<ResidualBlock*>& residual_blocks = program.residual_blocks(); - for (int i = 0; i < residual_blocks.size(); ++i) { - ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { const int num_parameter_blocks = residual_block->NumParameterBlocks(); for (int j = 0; j < num_parameter_blocks; ++j) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; @@ -129,14 +128,15 @@ void CoordinateDescentMinimizer::Minimize(const Minimizer::Options& options, double* parameters, Solver::Summary* summary) { // Set the state and mark all parameter blocks constant. - for (int i = 0; i < parameter_blocks_.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks_[i]; + for (auto* parameter_block : parameter_blocks_) { parameter_block->SetState(parameters + parameter_block->state_offset()); parameter_block->SetConstant(); } - std::unique_ptr<LinearSolver*[]> linear_solvers( - new LinearSolver*[options.num_threads]); + std::vector<std::unique_ptr<LinearSolver>> linear_solvers( + options.num_threads); + // std::unique_ptr<LinearSolver*[]> linear_solvers( + // new LinearSolver*[options.num_threads]); LinearSolver::Options linear_solver_options; linear_solver_options.type = DENSE_QR; @@ -188,7 +188,7 @@ void CoordinateDescentMinimizer::Minimize(const Minimizer::Options& options, // we are fine. Solver::Summary inner_summary; Solve(&inner_program, - linear_solvers[thread_id], + linear_solvers[thread_id].get(), parameters + parameter_block->state_offset(), &inner_summary); @@ -200,13 +200,13 @@ void CoordinateDescentMinimizer::Minimize(const Minimizer::Options& options, }); } - for (int i = 0; i < parameter_blocks_.size(); ++i) { - parameter_blocks_[i]->SetVarying(); + for (auto* parameter_block : parameter_blocks_) { + parameter_block->SetVarying(); } - for (int i = 0; i < options.num_threads; ++i) { - delete linear_solvers[i]; - } + // for (int i = 0; i < options.num_threads; ++i) { + // delete linear_solvers[i]; + //} } // Solve the optimization problem for one parameter block. @@ -221,17 +221,16 @@ void CoordinateDescentMinimizer::Solve(Program* program, string error; Minimizer::Options minimizer_options; - minimizer_options.evaluator.reset( - Evaluator::Create(evaluator_options_, program, &error)); + minimizer_options.evaluator = + Evaluator::Create(evaluator_options_, program, &error); CHECK(minimizer_options.evaluator != nullptr); - minimizer_options.jacobian.reset( - minimizer_options.evaluator->CreateJacobian()); + minimizer_options.jacobian = minimizer_options.evaluator->CreateJacobian(); CHECK(minimizer_options.jacobian != nullptr); TrustRegionStrategy::Options trs_options; trs_options.linear_solver = linear_solver; - minimizer_options.trust_region_strategy.reset( - TrustRegionStrategy::Create(trs_options)); + minimizer_options.trust_region_strategy = + TrustRegionStrategy::Create(trs_options); CHECK(minimizer_options.trust_region_strategy != nullptr); minimizer_options.is_silent = true; @@ -263,12 +262,12 @@ bool CoordinateDescentMinimizer::IsOrderingValid( // of independent sets of decreasing size and invert it. This // seems to work better in practice, i.e., Cameras before // points. -ParameterBlockOrdering* CoordinateDescentMinimizer::CreateOrdering( - const Program& program) { - std::unique_ptr<ParameterBlockOrdering> ordering(new ParameterBlockOrdering); +std::shared_ptr<ParameterBlockOrdering> +CoordinateDescentMinimizer::CreateOrdering(const Program& program) { + auto ordering = std::make_shared<ParameterBlockOrdering>(); ComputeRecursiveIndependentSetOrdering(program, ordering.get()); ordering->Reverse(); - return ordering.release(); + return ordering; } } // namespace internal diff --git a/extern/ceres/internal/ceres/coordinate_descent_minimizer.h b/extern/ceres/internal/ceres/coordinate_descent_minimizer.h index 7d17d53eb0f..75f26480c88 100644 --- a/extern/ceres/internal/ceres/coordinate_descent_minimizer.h +++ b/extern/ceres/internal/ceres/coordinate_descent_minimizer.h @@ -56,7 +56,7 @@ class LinearSolver; // // The minimizer assumes that none of the parameter blocks in the // program are constant. -class CoordinateDescentMinimizer : public Minimizer { +class CERES_NO_EXPORT CoordinateDescentMinimizer final : public Minimizer { public: explicit CoordinateDescentMinimizer(ContextImpl* context); @@ -66,7 +66,7 @@ class CoordinateDescentMinimizer : public Minimizer { std::string* error); // Minimizer interface. - virtual ~CoordinateDescentMinimizer(); + ~CoordinateDescentMinimizer() override; void Minimize(const Minimizer::Options& options, double* parameters, @@ -81,7 +81,8 @@ class CoordinateDescentMinimizer : public Minimizer { // of independent sets of decreasing size and invert it. This // seems to work better in practice, i.e., Cameras before // points. - static ParameterBlockOrdering* CreateOrdering(const Program& program); + static std::shared_ptr<ParameterBlockOrdering> CreateOrdering( + const Program& program); private: void Solve(Program* program, diff --git a/extern/ceres/internal/ceres/corrector.cc b/extern/ceres/internal/ceres/corrector.cc index 6a79a06a544..bf3ba9c5714 100644 --- a/extern/ceres/internal/ceres/corrector.cc +++ b/extern/ceres/internal/ceres/corrector.cc @@ -111,7 +111,7 @@ Corrector::Corrector(const double sq_norm, const double rho[3]) { } void Corrector::CorrectResiduals(const int num_rows, double* residuals) { - DCHECK(residuals != NULL); + DCHECK(residuals != nullptr); // Equation 11 in BANS. VectorRef(residuals, num_rows) *= residual_scaling_; } @@ -120,8 +120,8 @@ void Corrector::CorrectJacobian(const int num_rows, const int num_cols, double* residuals, double* jacobian) { - DCHECK(residuals != NULL); - DCHECK(jacobian != NULL); + DCHECK(residuals != nullptr); + DCHECK(jacobian != nullptr); // The common case (rho[2] <= 0). if (alpha_sq_norm_ == 0.0) { diff --git a/extern/ceres/internal/ceres/corrector.h b/extern/ceres/internal/ceres/corrector.h index 3e11cdce1ae..44379a3ea7a 100644 --- a/extern/ceres/internal/ceres/corrector.h +++ b/extern/ceres/internal/ceres/corrector.h @@ -35,7 +35,8 @@ #ifndef CERES_INTERNAL_CORRECTOR_H_ #define CERES_INTERNAL_CORRECTOR_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -48,7 +49,7 @@ namespace internal { // gauss newton approximation and then take its square root to get the // corresponding corrections to the residual and jacobian. For the // full expressions see Eq. 10 and 11 in BANS by Triggs et al. -class CERES_EXPORT_INTERNAL Corrector { +class CERES_NO_EXPORT Corrector { public: // The constructor takes the squared norm, the value, the first and // second derivatives of the LossFunction. It precalculates some of @@ -89,4 +90,6 @@ class CERES_EXPORT_INTERNAL Corrector { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_CORRECTOR_H_ diff --git a/extern/ceres/internal/ceres/split.h b/extern/ceres/internal/ceres/cost_function.cc index f513023ec69..7597b431ec9 100644 --- a/extern/ceres/internal/ceres/split.h +++ b/extern/ceres/internal/ceres/cost_function.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -26,27 +26,14 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Author: keir@google.com (Keir Mierle) +// Author: sameeragarwal@google.com (Sameer Agarwal) +// keir@google.m (Keir Mierle) -#ifndef CERES_INTERNAL_SPLIT_H_ -#define CERES_INTERNAL_SPLIT_H_ - -#include <string> -#include <vector> - -#include "ceres/internal/port.h" +#include "ceres/cost_function.h" namespace ceres { -namespace internal { -// Split a string using one or more character delimiters, presented as a -// nul-terminated c string. Append the components to 'result'. If there are -// consecutive delimiters, this function skips over all of them. -void SplitStringUsing(const std::string& full, - const char* delim, - std::vector<std::string>* res); +CostFunction::CostFunction() : num_residuals_(0) {} +CostFunction::~CostFunction() = default; -} // namespace internal } // namespace ceres - -#endif // CERES_INTERNAL_SPLIT_H_ diff --git a/extern/ceres/internal/ceres/covariance.cc b/extern/ceres/internal/ceres/covariance.cc index 8e240ff317c..d63dd3789c3 100644 --- a/extern/ceres/internal/ceres/covariance.cc +++ b/extern/ceres/internal/ceres/covariance.cc @@ -39,15 +39,14 @@ namespace ceres { -using std::make_pair; using std::pair; using std::vector; Covariance::Covariance(const Covariance::Options& options) { - impl_.reset(new internal::CovarianceImpl(options)); + impl_ = std::make_unique<internal::CovarianceImpl>(options); } -Covariance::~Covariance() {} +Covariance::~Covariance() = default; bool Covariance::Compute( const vector<pair<const double*, const double*>>& covariance_blocks, diff --git a/extern/ceres/internal/ceres/covariance_impl.cc b/extern/ceres/internal/ceres/covariance_impl.cc index 1f86707f5a7..324b5531a04 100644 --- a/extern/ceres/internal/ceres/covariance_impl.cc +++ b/extern/ceres/internal/ceres/covariance_impl.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -79,13 +79,12 @@ CovarianceImpl::CovarianceImpl(const Covariance::Options& options) evaluate_options_.apply_loss_function = options_.apply_loss_function; } -CovarianceImpl::~CovarianceImpl() {} +CovarianceImpl::~CovarianceImpl() = default; template <typename T> void CheckForDuplicates(std::vector<T> blocks) { - sort(blocks.begin(), blocks.end()); - typename std::vector<T>::iterator it = - std::adjacent_find(blocks.begin(), blocks.end()); + std::sort(blocks.begin(), blocks.end()); + auto it = std::adjacent_find(blocks.begin(), blocks.end()); if (it != blocks.end()) { // In case there are duplicates, we search for their location. std::map<T, std::vector<int>> blocks_map; @@ -117,7 +116,7 @@ bool CovarianceImpl::Compute(const CovarianceBlocks& covariance_blocks, covariance_blocks); problem_ = problem; parameter_block_to_row_index_.clear(); - covariance_matrix_.reset(NULL); + covariance_matrix_ = nullptr; is_valid_ = (ComputeCovarianceSparsity(covariance_blocks, problem) && ComputeCovarianceValues()); is_computed_ = true; @@ -162,10 +161,10 @@ bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace( const int block1_size = block1->Size(); const int block2_size = block2->Size(); - const int block1_local_size = block1->LocalSize(); - const int block2_local_size = block2->LocalSize(); + const int block1_tangent_size = block1->TangentSize(); + const int block2_tangent_size = block2->TangentSize(); if (!lift_covariance_to_ambient_space) { - MatrixRef(covariance_block, block1_local_size, block2_local_size) + MatrixRef(covariance_block, block1_tangent_size, block2_tangent_size) .setZero(); } else { MatrixRef(covariance_block, block1_size, block2_size).setZero(); @@ -209,34 +208,34 @@ bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace( FindOrDie(parameter_map, const_cast<double*>(parameter_block1)); ParameterBlock* block2 = FindOrDie(parameter_map, const_cast<double*>(parameter_block2)); - const LocalParameterization* local_param1 = block1->local_parameterization(); - const LocalParameterization* local_param2 = block2->local_parameterization(); + const Manifold* manifold1 = block1->manifold(); + const Manifold* manifold2 = block2->manifold(); const int block1_size = block1->Size(); - const int block1_local_size = block1->LocalSize(); + const int block1_tangent_size = block1->TangentSize(); const int block2_size = block2->Size(); - const int block2_local_size = block2->LocalSize(); + const int block2_tangent_size = block2->TangentSize(); - ConstMatrixRef cov( - covariance_matrix_->values() + rows[row_begin], block1_size, row_size); + ConstMatrixRef cov(covariance_matrix_->values() + rows[row_begin], + block1_tangent_size, + row_size); - // Fast path when there are no local parameterizations or if the - // user does not want it lifted to the ambient space. - if ((local_param1 == NULL && local_param2 == NULL) || + // Fast path when there are no manifolds or if the user does not want it + // lifted to the ambient space. + if ((manifold1 == nullptr && manifold2 == nullptr) || !lift_covariance_to_ambient_space) { if (transpose) { - MatrixRef(covariance_block, block2_local_size, block1_local_size) = - cov.block(0, offset, block1_local_size, block2_local_size) + MatrixRef(covariance_block, block2_tangent_size, block1_tangent_size) = + cov.block(0, offset, block1_tangent_size, block2_tangent_size) .transpose(); } else { - MatrixRef(covariance_block, block1_local_size, block2_local_size) = - cov.block(0, offset, block1_local_size, block2_local_size); + MatrixRef(covariance_block, block1_tangent_size, block2_tangent_size) = + cov.block(0, offset, block1_tangent_size, block2_tangent_size); } return true; } - // If local parameterizations are used then the covariance that has - // been computed is in the tangent space and it needs to be lifted - // back to the ambient space. + // If manifolds are used then the covariance that has been computed is in the + // tangent space and it needs to be lifted back to the ambient space. // // This is given by the formula // @@ -249,36 +248,37 @@ bool CovarianceImpl::GetCovarianceBlockInTangentOrAmbientSpace( // See Result 5.11 on page 142 of Hartley & Zisserman (2nd Edition) // for a proof. // - // TODO(sameeragarwal): Add caching of local parameterization, so - // that they are computed just once per parameter block. - Matrix block1_jacobian(block1_size, block1_local_size); - if (local_param1 == NULL) { + // TODO(sameeragarwal): Add caching the manifold plus_jacobian, so that they + // are computed just once per parameter block. + Matrix block1_jacobian(block1_size, block1_tangent_size); + if (manifold1 == nullptr) { block1_jacobian.setIdentity(); } else { - local_param1->ComputeJacobian(parameter_block1, block1_jacobian.data()); + manifold1->PlusJacobian(parameter_block1, block1_jacobian.data()); } - Matrix block2_jacobian(block2_size, block2_local_size); + Matrix block2_jacobian(block2_size, block2_tangent_size); // Fast path if the user is requesting a diagonal block. if (parameter_block1 == parameter_block2) { block2_jacobian = block1_jacobian; } else { - if (local_param2 == NULL) { + if (manifold2 == nullptr) { block2_jacobian.setIdentity(); } else { - local_param2->ComputeJacobian(parameter_block2, block2_jacobian.data()); + manifold2->PlusJacobian(parameter_block2, block2_jacobian.data()); } } if (transpose) { MatrixRef(covariance_block, block2_size, block1_size) = block2_jacobian * - cov.block(0, offset, block1_local_size, block2_local_size).transpose() * + cov.block(0, offset, block1_tangent_size, block2_tangent_size) + .transpose() * block1_jacobian.transpose(); } else { MatrixRef(covariance_block, block1_size, block2_size) = block1_jacobian * - cov.block(0, offset, block1_local_size, block2_local_size) * + cov.block(0, offset, block1_tangent_size, block2_tangent_size) * block2_jacobian.transpose(); } @@ -309,7 +309,7 @@ bool CovarianceImpl::GetCovarianceMatrixInTangentOrAmbientSpace( if (lift_covariance_to_ambient_space) { parameter_sizes.push_back(block->Size()); } else { - parameter_sizes.push_back(block->LocalSize()); + parameter_sizes.push_back(block->TangentSize()); } } std::partial_sum(parameter_sizes.begin(), @@ -383,8 +383,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( std::vector<ResidualBlock*> residual_blocks; problem->GetResidualBlocks(&residual_blocks); - for (int i = 0; i < residual_blocks.size(); ++i) { - ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { parameter_blocks_in_use.insert(residual_block->parameter_blocks(), residual_block->parameter_blocks() + residual_block->NumParameterBlocks()); @@ -394,8 +393,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( std::vector<double*>& active_parameter_blocks = evaluate_options_.parameter_blocks; active_parameter_blocks.clear(); - for (int i = 0; i < all_parameter_blocks.size(); ++i) { - double* parameter_block = all_parameter_blocks[i]; + for (auto* parameter_block : all_parameter_blocks) { ParameterBlock* block = FindOrDie(parameter_map, parameter_block); if (!block->IsConstant() && (parameter_blocks_in_use.count(block) > 0)) { active_parameter_blocks.push_back(parameter_block); @@ -411,10 +409,9 @@ bool CovarianceImpl::ComputeCovarianceSparsity( // ordering of parameter blocks just constructed. int num_rows = 0; parameter_block_to_row_index_.clear(); - for (int i = 0; i < active_parameter_blocks.size(); ++i) { - double* parameter_block = active_parameter_blocks[i]; + for (auto* parameter_block : active_parameter_blocks) { const int parameter_block_size = - problem->ParameterBlockLocalSize(parameter_block); + problem->ParameterBlockTangentSize(parameter_block); parameter_block_to_row_index_[parameter_block] = num_rows; num_rows += parameter_block_size; } @@ -424,9 +421,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( // triangular part of the matrix. int num_nonzeros = 0; CovarianceBlocks covariance_blocks; - for (int i = 0; i < original_covariance_blocks.size(); ++i) { - const std::pair<const double*, const double*>& block_pair = - original_covariance_blocks[i]; + for (const auto& block_pair : original_covariance_blocks) { if (constant_parameter_blocks_.count(block_pair.first) > 0 || constant_parameter_blocks_.count(block_pair.second) > 0) { continue; @@ -434,8 +429,8 @@ bool CovarianceImpl::ComputeCovarianceSparsity( int index1 = FindOrDie(parameter_block_to_row_index_, block_pair.first); int index2 = FindOrDie(parameter_block_to_row_index_, block_pair.second); - const int size1 = problem->ParameterBlockLocalSize(block_pair.first); - const int size2 = problem->ParameterBlockLocalSize(block_pair.second); + const int size1 = problem->ParameterBlockTangentSize(block_pair.first); + const int size2 = problem->ParameterBlockTangentSize(block_pair.second); num_nonzeros += size1 * size2; // Make sure we are constructing a block upper triangular matrix. @@ -447,9 +442,9 @@ bool CovarianceImpl::ComputeCovarianceSparsity( } } - if (covariance_blocks.size() == 0) { + if (covariance_blocks.empty()) { VLOG(2) << "No non-zero covariance blocks found"; - covariance_matrix_.reset(NULL); + covariance_matrix_ = nullptr; return true; } @@ -459,8 +454,8 @@ bool CovarianceImpl::ComputeCovarianceSparsity( std::sort(covariance_blocks.begin(), covariance_blocks.end()); // Fill the sparsity pattern of the covariance matrix. - covariance_matrix_.reset( - new CompressedRowSparseMatrix(num_rows, num_rows, num_nonzeros)); + covariance_matrix_ = std::make_unique<CompressedRowSparseMatrix>( + num_rows, num_rows, num_nonzeros); int* rows = covariance_matrix_->mutable_rows(); int* cols = covariance_matrix_->mutable_cols(); @@ -480,7 +475,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( int cursor = 0; // index into the covariance matrix. for (const auto& entry : parameter_block_to_row_index_) { const double* row_block = entry.first; - const int row_block_size = problem->ParameterBlockLocalSize(row_block); + const int row_block_size = problem->ParameterBlockTangentSize(row_block); int row_begin = entry.second; // Iterate over the covariance blocks contained in this row block @@ -493,7 +488,7 @@ bool CovarianceImpl::ComputeCovarianceSparsity( if (block_pair.first != row_block) { break; } - num_columns += problem->ParameterBlockLocalSize(block_pair.second); + num_columns += problem->ParameterBlockTangentSize(block_pair.second); } // Fill out all the compressed rows for this parameter block. @@ -501,7 +496,8 @@ bool CovarianceImpl::ComputeCovarianceSparsity( rows[row_begin + r] = cursor; for (int c = 0; c < num_col_blocks; ++c) { const double* col_block = covariance_blocks[i + c].second; - const int col_block_size = problem->ParameterBlockLocalSize(col_block); + const int col_block_size = + problem->ParameterBlockTangentSize(col_block); int col_begin = FindOrDie(parameter_block_to_row_index_, col_block); for (int k = 0; k < col_block_size; ++k) { cols[cursor++] = col_begin++; @@ -556,13 +552,13 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { "CovarianceImpl::ComputeCovarianceValuesUsingSparseQR"); #ifndef CERES_NO_SUITESPARSE - if (covariance_matrix_.get() == NULL) { + if (covariance_matrix_ == nullptr) { // Nothing to do, all zeros covariance matrix. return true; } CRSMatrix jacobian; - problem_->Evaluate(evaluate_options_, NULL, NULL, NULL, &jacobian); + problem_->Evaluate(evaluate_options_, nullptr, nullptr, nullptr, &jacobian); event_logger.AddEvent("Evaluate"); // Construct a compressed column form of the Jacobian. @@ -601,11 +597,11 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { cholmod_jacobian.nrow = num_rows; cholmod_jacobian.ncol = num_cols; cholmod_jacobian.nzmax = num_nonzeros; - cholmod_jacobian.nz = NULL; + cholmod_jacobian.nz = nullptr; cholmod_jacobian.p = reinterpret_cast<void*>(&transpose_rows[0]); cholmod_jacobian.i = reinterpret_cast<void*>(&transpose_cols[0]); cholmod_jacobian.x = reinterpret_cast<void*>(&transpose_values[0]); - cholmod_jacobian.z = NULL; + cholmod_jacobian.z = nullptr; cholmod_jacobian.stype = 0; // Matrix is not symmetric. cholmod_jacobian.itype = CHOLMOD_LONG; cholmod_jacobian.xtype = CHOLMOD_REAL; @@ -616,8 +612,8 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { cholmod_common cc; cholmod_l_start(&cc); - cholmod_sparse* R = NULL; - SuiteSparse_long* permutation = NULL; + cholmod_sparse* R = nullptr; + SuiteSparse_long* permutation = nullptr; // Compute a Q-less QR factorization of the Jacobian. Since we are // only interested in inverting J'J = R'R, we do not need Q. This @@ -648,9 +644,9 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { } if (rank < cholmod_jacobian.ncol) { - LOG(ERROR) << "Jacobian matrix is rank deficient. " - << "Number of columns: " << cholmod_jacobian.ncol - << " rank: " << rank; + LOG(WARNING) << "Jacobian matrix is rank deficient. " + << "Number of columns: " << cholmod_jacobian.ncol + << " rank: " << rank; free(permutation); cholmod_l_free_sparse(&R, &cc); cholmod_l_finish(&cc); @@ -721,13 +717,13 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() { EventLogger event_logger( "CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD"); - if (covariance_matrix_.get() == NULL) { + if (covariance_matrix_ == nullptr) { // Nothing to do, all zeros covariance matrix. return true; } CRSMatrix jacobian; - problem_->Evaluate(evaluate_options_, NULL, NULL, NULL, &jacobian); + problem_->Evaluate(evaluate_options_, nullptr, nullptr, nullptr, &jacobian); event_logger.AddEvent("Evaluate"); Matrix dense_jacobian(jacobian.num_rows, jacobian.num_cols); @@ -812,20 +808,20 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingDenseSVD() { bool CovarianceImpl::ComputeCovarianceValuesUsingEigenSparseQR() { EventLogger event_logger( "CovarianceImpl::ComputeCovarianceValuesUsingEigenSparseQR"); - if (covariance_matrix_.get() == NULL) { + if (covariance_matrix_ == nullptr) { // Nothing to do, all zeros covariance matrix. return true; } CRSMatrix jacobian; - problem_->Evaluate(evaluate_options_, NULL, NULL, NULL, &jacobian); + problem_->Evaluate(evaluate_options_, nullptr, nullptr, nullptr, &jacobian); event_logger.AddEvent("Evaluate"); - typedef Eigen::SparseMatrix<double, Eigen::ColMajor> EigenSparseMatrix; + using EigenSparseMatrix = Eigen::SparseMatrix<double, Eigen::ColMajor>; // Convert the matrix to column major order as required by SparseQR. EigenSparseMatrix sparse_jacobian = - Eigen::MappedSparseMatrix<double, Eigen::RowMajor>( + Eigen::Map<Eigen::SparseMatrix<double, Eigen::RowMajor>>( jacobian.num_rows, jacobian.num_cols, static_cast<int>(jacobian.values.size()), diff --git a/extern/ceres/internal/ceres/covariance_impl.h b/extern/ceres/internal/ceres/covariance_impl.h index 394a04bbc78..fc029ce25b7 100644 --- a/extern/ceres/internal/ceres/covariance_impl.h +++ b/extern/ceres/internal/ceres/covariance_impl.h @@ -38,7 +38,8 @@ #include <vector> #include "ceres/covariance.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/problem_impl.h" #include "ceres/suitesparse.h" @@ -47,7 +48,7 @@ namespace internal { class CompressedRowSparseMatrix; -class CERES_EXPORT_INTERNAL CovarianceImpl { +class CERES_NO_EXPORT CovarianceImpl { public: explicit CovarianceImpl(const Covariance::Options& options); ~CovarianceImpl(); @@ -98,4 +99,6 @@ class CERES_EXPORT_INTERNAL CovarianceImpl { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_COVARIANCE_IMPL_H_ diff --git a/extern/ceres/internal/ceres/cuda_buffer.h b/extern/ceres/internal/ceres/cuda_buffer.h new file mode 100644 index 00000000000..a1cf78420d5 --- /dev/null +++ b/extern/ceres/internal/ceres/cuda_buffer.h @@ -0,0 +1,107 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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: joydeepb@cs.utexas.edu (Joydeep Biswas) + +#ifndef CERES_INTERNAL_CUDA_BUFFER_H_ +#define CERES_INTERNAL_CUDA_BUFFER_H_ + +#include "ceres/internal/config.h" + +#ifndef CERES_NO_CUDA + +#include <vector> + +#include "cuda_runtime.h" +#include "glog/logging.h" + +// An encapsulated buffer to maintain GPU memory, and handle transfers between +// GPU and system memory. It is the responsibility of the user to ensure that +// the appropriate GPU device is selected before each subroutine is called. This +// is particularly important when using multiple GPU devices on different CPU +// threads, since active Cuda devices are determined by the cuda runtime on a +// per-thread basis. Note that unless otherwise specified, all methods use the +// default stream, and are synchronous. +template <typename T> +class CudaBuffer { + public: + CudaBuffer() = default; + CudaBuffer(const CudaBuffer&) = delete; + CudaBuffer& operator=(const CudaBuffer&) = delete; + + ~CudaBuffer() { + if (data_ != nullptr) { + CHECK_EQ(cudaFree(data_), cudaSuccess); + } + } + + // Grow the GPU memory buffer if needed to accommodate data of the specified + // size + void Reserve(const size_t size) { + if (size > size_) { + if (data_ != nullptr) { + CHECK_EQ(cudaFree(data_), cudaSuccess); + } + CHECK_EQ(cudaMalloc(&data_, size * sizeof(T)), cudaSuccess); + size_ = size; + } + } + + // Perform an asynchronous copy from CPU memory to GPU memory using the stream + // provided. + void CopyToGpuAsync(const T* data, const size_t size, cudaStream_t stream) { + Reserve(size); + CHECK_EQ(cudaMemcpyAsync( + data_, data, size * sizeof(T), cudaMemcpyHostToDevice, stream), + cudaSuccess); + } + + // Copy data from the GPU to CPU memory. This is necessarily synchronous since + // any potential GPU kernels that may be writing to the buffer must finish + // before the transfer happens. + void CopyToHost(T* data, const size_t size) { + CHECK(data_ != nullptr); + CHECK_EQ(cudaMemcpy(data, data_, size * sizeof(T), cudaMemcpyDeviceToHost), + cudaSuccess); + } + + void CopyToGpu(const std::vector<T>& data) { + CopyToGpu(data.data(), data.size()); + } + + T* data() { return data_; } + size_t size() const { return size_; } + + private: + T* data_ = nullptr; + size_t size_ = 0; +}; + +#endif // CERES_NO_CUDA + +#endif // CERES_INTERNAL_CUDA_BUFFER_H_
\ No newline at end of file diff --git a/extern/ceres/internal/ceres/cxsparse.cc b/extern/ceres/internal/ceres/cxsparse.cc index 0167f988648..b1eb2055e35 100644 --- a/extern/ceres/internal/ceres/cxsparse.cc +++ b/extern/ceres/internal/ceres/cxsparse.cc @@ -29,10 +29,11 @@ // Author: strandmark@google.com (Petter Strandmark) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_CXSPARSE +#include <memory> #include <string> #include <vector> @@ -47,7 +48,7 @@ namespace internal { using std::vector; -CXSparse::CXSparse() : scratch_(NULL), scratch_size_(0) {} +CXSparse::CXSparse() : scratch_(nullptr), scratch_size_(0) {} CXSparse::~CXSparse() { if (scratch_size_ > 0) { @@ -116,7 +117,7 @@ cs_dis* CXSparse::BlockAnalyzeCholesky(cs_di* A, block_matrix.nzmax = block_rows.size(); block_matrix.p = &block_cols[0]; block_matrix.i = &block_rows[0]; - block_matrix.x = NULL; + block_matrix.x = nullptr; int* ordering = cs_amd(1, &block_matrix); vector<int> block_ordering(num_row_blocks, -1); @@ -126,7 +127,7 @@ cs_dis* CXSparse::BlockAnalyzeCholesky(cs_di* A, vector<int> scalar_ordering; BlockOrderingToScalarOrdering(row_blocks, block_ordering, &scalar_ordering); - cs_dis* symbolic_factor = + auto* symbolic_factor = reinterpret_cast<cs_dis*>(cs_calloc(1, sizeof(cs_dis))); symbolic_factor->pinv = cs_pinv(&scalar_ordering[0], A->n); cs* permuted_A = cs_symperm(A, symbolic_factor->pinv, 0); @@ -138,7 +139,7 @@ cs_dis* CXSparse::BlockAnalyzeCholesky(cs_di* A, cs_free(postordering); cs_spfree(permuted_A); - symbolic_factor->cp = (int*)cs_malloc(A->n + 1, sizeof(int)); + symbolic_factor->cp = static_cast<int*>(cs_malloc(A->n + 1, sizeof(int))); symbolic_factor->lnz = cs_cumsum(symbolic_factor->cp, column_counts, A->n); symbolic_factor->unz = symbolic_factor->lnz; @@ -146,7 +147,7 @@ cs_dis* CXSparse::BlockAnalyzeCholesky(cs_di* A, if (symbolic_factor->lnz < 0) { cs_sfree(symbolic_factor); - symbolic_factor = NULL; + symbolic_factor = nullptr; } return symbolic_factor; @@ -206,8 +207,8 @@ CompressedRowSparseMatrix::StorageType CXSparseCholesky::StorageType() const { CXSparseCholesky::CXSparseCholesky(const OrderingType ordering_type) : ordering_type_(ordering_type), - symbolic_factor_(NULL), - numeric_factor_(NULL) {} + symbolic_factor_(nullptr), + numeric_factor_(nullptr) {} CXSparseCholesky::~CXSparseCholesky() { FreeSymbolicFactorization(); @@ -217,14 +218,14 @@ CXSparseCholesky::~CXSparseCholesky() { LinearSolverTerminationType CXSparseCholesky::Factorize( CompressedRowSparseMatrix* lhs, std::string* message) { CHECK_EQ(lhs->storage_type(), StorageType()); - if (lhs == NULL) { - *message = "Failure: Input lhs is NULL."; + if (lhs == nullptr) { + *message = "Failure: Input lhs is nullptr."; return LINEAR_SOLVER_FATAL_ERROR; } cs_di cs_lhs = cs_.CreateSparseMatrixTransposeView(lhs); - if (symbolic_factor_ == NULL) { + if (symbolic_factor_ == nullptr) { if (ordering_type_ == NATURAL) { symbolic_factor_ = cs_.AnalyzeCholeskyWithNaturalOrdering(&cs_lhs); } else { @@ -236,7 +237,7 @@ LinearSolverTerminationType CXSparseCholesky::Factorize( } } - if (symbolic_factor_ == NULL) { + if (symbolic_factor_ == nullptr) { *message = "CXSparse Failure : Symbolic factorization failed."; return LINEAR_SOLVER_FATAL_ERROR; } @@ -244,7 +245,7 @@ LinearSolverTerminationType CXSparseCholesky::Factorize( FreeNumericFactorization(); numeric_factor_ = cs_.Cholesky(&cs_lhs, symbolic_factor_); - if (numeric_factor_ == NULL) { + if (numeric_factor_ == nullptr) { *message = "CXSparse Failure : Numeric factorization failed."; return LINEAR_SOLVER_FAILURE; } @@ -255,7 +256,7 @@ LinearSolverTerminationType CXSparseCholesky::Factorize( LinearSolverTerminationType CXSparseCholesky::Solve(const double* rhs, double* solution, std::string* message) { - CHECK(numeric_factor_ != NULL) + CHECK(numeric_factor_ != nullptr) << "Solve called without a call to Factorize first."; const int num_cols = numeric_factor_->L->n; memcpy(solution, rhs, num_cols * sizeof(*solution)); @@ -264,16 +265,16 @@ LinearSolverTerminationType CXSparseCholesky::Solve(const double* rhs, } void CXSparseCholesky::FreeSymbolicFactorization() { - if (symbolic_factor_ != NULL) { + if (symbolic_factor_ != nullptr) { cs_.Free(symbolic_factor_); - symbolic_factor_ = NULL; + symbolic_factor_ = nullptr; } } void CXSparseCholesky::FreeNumericFactorization() { - if (numeric_factor_ != NULL) { + if (numeric_factor_ != nullptr) { cs_.Free(numeric_factor_); - numeric_factor_ = NULL; + numeric_factor_ = nullptr; } } diff --git a/extern/ceres/internal/ceres/cxsparse.h b/extern/ceres/internal/ceres/cxsparse.h index d3f76e0575e..97fc0459464 100644 --- a/extern/ceres/internal/ceres/cxsparse.h +++ b/extern/ceres/internal/ceres/cxsparse.h @@ -32,7 +32,7 @@ #define CERES_INTERNAL_CXSPARSE_H_ // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_CXSPARSE @@ -40,6 +40,7 @@ #include <string> #include <vector> +#include "ceres/internal/disable_warnings.h" #include "ceres/linear_solver.h" #include "ceres/sparse_cholesky.h" #include "cs.h" @@ -54,7 +55,7 @@ class TripletSparseMatrix; // factorization with a known symbolic factorization. This features does not // explicitly exist in CXSparse. The methods in the class are nonstatic because // the class manages internal scratch space. -class CXSparse { +class CERES_NO_EXPORT CXSparse { public: CXSparse(); ~CXSparse(); @@ -80,7 +81,7 @@ class CXSparse { cs_di CreateSparseMatrixTransposeView(CompressedRowSparseMatrix* A); // Creates a new matrix from a triplet form. Deallocate the returned matrix - // with Free. May return NULL if the compression or allocation fails. + // with Free. May return nullptr if the compression or allocation fails. cs_di* CreateSparseMatrix(TripletSparseMatrix* A); // B = A' @@ -122,7 +123,7 @@ class CXSparse { const std::vector<int>& col_blocks); // Compute an fill-reducing approximate minimum degree ordering of - // the matrix A. ordering should be non-NULL and should point to + // the matrix A. ordering should be non-nullptr and should point to // enough memory to hold the ordering for the rows of A. void ApproximateMinimumDegreeOrdering(cs_di* A, int* ordering); @@ -138,13 +139,13 @@ class CXSparse { // An implementation of SparseCholesky interface using the CXSparse // library. -class CXSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT CXSparseCholesky final : public SparseCholesky { public: // Factory static std::unique_ptr<SparseCholesky> Create(OrderingType ordering_type); // SparseCholesky interface. - virtual ~CXSparseCholesky(); + ~CXSparseCholesky() override; CompressedRowSparseMatrix::StorageType StorageType() const final; LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, std::string* message) final; @@ -153,7 +154,7 @@ class CXSparseCholesky : public SparseCholesky { std::string* message) final; private: - CXSparseCholesky(const OrderingType ordering_type); + explicit CXSparseCholesky(const OrderingType ordering_type); void FreeSymbolicFactorization(); void FreeNumericFactorization(); @@ -166,6 +167,8 @@ class CXSparseCholesky : public SparseCholesky { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #else typedef void cs_dis; diff --git a/extern/ceres/internal/ceres/dense_cholesky.cc b/extern/ceres/internal/ceres/dense_cholesky.cc new file mode 100644 index 00000000000..0e0bba7873b --- /dev/null +++ b/extern/ceres/internal/ceres/dense_cholesky.cc @@ -0,0 +1,327 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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/dense_cholesky.h" + +#include <algorithm> +#include <memory> +#include <string> +#include <vector> + +#include "ceres/internal/config.h" + +#ifndef CERES_NO_CUDA +#include "ceres/context_impl.h" +#include "cuda_runtime.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA + +#ifndef CERES_NO_LAPACK + +// C interface to the LAPACK Cholesky factorization and triangular solve. +extern "C" void dpotrf_( + const char* uplo, const int* n, double* a, const int* lda, int* info); + +extern "C" void dpotrs_(const char* uplo, + const int* n, + const int* nrhs, + const double* a, + const int* lda, + double* b, + const int* ldb, + int* info); +#endif + +namespace ceres { +namespace internal { + +DenseCholesky::~DenseCholesky() = default; + +std::unique_ptr<DenseCholesky> DenseCholesky::Create( + const LinearSolver::Options& options) { + std::unique_ptr<DenseCholesky> dense_cholesky; + + switch (options.dense_linear_algebra_library_type) { + case EIGEN: + dense_cholesky = std::make_unique<EigenDenseCholesky>(); + break; + + case LAPACK: +#ifndef CERES_NO_LAPACK + dense_cholesky = std::make_unique<LAPACKDenseCholesky>(); + break; +#else + LOG(FATAL) << "Ceres was compiled without support for LAPACK."; +#endif + + case CUDA: +#ifndef CERES_NO_CUDA + dense_cholesky = CUDADenseCholesky::Create(options); + break; +#else + LOG(FATAL) << "Ceres was compiled without support for CUDA."; +#endif + + default: + LOG(FATAL) << "Unknown dense linear algebra library type : " + << DenseLinearAlgebraLibraryTypeToString( + options.dense_linear_algebra_library_type); + } + return dense_cholesky; +} + +LinearSolverTerminationType DenseCholesky::FactorAndSolve( + int num_cols, + double* lhs, + const double* rhs, + double* solution, + std::string* message) { + LinearSolverTerminationType termination_type = + Factorize(num_cols, lhs, message); + if (termination_type == LINEAR_SOLVER_SUCCESS) { + termination_type = Solve(rhs, solution, message); + } + return termination_type; +} + +LinearSolverTerminationType EigenDenseCholesky::Factorize( + int num_cols, double* lhs, std::string* message) { + Eigen::Map<Eigen::MatrixXd> m(lhs, num_cols, num_cols); + llt_ = std::make_unique<LLTType>(m); + if (llt_->info() != Eigen::Success) { + *message = "Eigen failure. Unable to perform dense Cholesky factorization."; + return LINEAR_SOLVER_FAILURE; + } + + *message = "Success."; + return LINEAR_SOLVER_SUCCESS; +} + +LinearSolverTerminationType EigenDenseCholesky::Solve(const double* rhs, + double* solution, + std::string* message) { + if (llt_->info() != Eigen::Success) { + *message = "Eigen failure. Unable to perform dense Cholesky factorization."; + return LINEAR_SOLVER_FAILURE; + } + + VectorRef(solution, llt_->cols()) = + llt_->solve(ConstVectorRef(rhs, llt_->cols())); + *message = "Success."; + return LINEAR_SOLVER_SUCCESS; +} + +#ifndef CERES_NO_LAPACK +LinearSolverTerminationType LAPACKDenseCholesky::Factorize( + int num_cols, double* lhs, std::string* message) { + lhs_ = lhs; + num_cols_ = num_cols; + + const char uplo = 'L'; + int info = 0; + dpotrf_(&uplo, &num_cols_, lhs_, &num_cols_, &info); + + if (info < 0) { + termination_type_ = LINEAR_SOLVER_FATAL_ERROR; + LOG(FATAL) << "Congratulations, you found a bug in Ceres. " + << "Please report it. " + << "LAPACK::dpotrf fatal error. " + << "Argument: " << -info << " is invalid."; + } else if (info > 0) { + termination_type_ = LINEAR_SOLVER_FAILURE; + *message = StringPrintf( + "LAPACK::dpotrf numerical failure. " + "The leading minor of order %d is not positive definite.", + info); + } else { + termination_type_ = LINEAR_SOLVER_SUCCESS; + *message = "Success."; + } + return termination_type_; +} + +LinearSolverTerminationType LAPACKDenseCholesky::Solve(const double* rhs, + double* solution, + std::string* message) { + const char uplo = 'L'; + const int nrhs = 1; + int info = 0; + + std::copy_n(rhs, num_cols_, solution); + dpotrs_( + &uplo, &num_cols_, &nrhs, lhs_, &num_cols_, solution, &num_cols_, &info); + + if (info < 0) { + termination_type_ = LINEAR_SOLVER_FATAL_ERROR; + LOG(FATAL) << "Congratulations, you found a bug in Ceres. " + << "Please report it. " + << "LAPACK::dpotrs fatal error. " + << "Argument: " << -info << " is invalid."; + } + + *message = "Success"; + termination_type_ = LINEAR_SOLVER_SUCCESS; + + return termination_type_; +} + +#endif // CERES_NO_LAPACK + +#ifndef CERES_NO_CUDA + +bool CUDADenseCholesky::Init(ContextImpl* context, std::string* message) { + if (!context->InitCUDA(message)) { + return false; + } + cusolver_handle_ = context->cusolver_handle_; + stream_ = context->stream_; + error_.Reserve(1); + *message = "CUDADenseCholesky::Init Success."; + return true; +} + +LinearSolverTerminationType CUDADenseCholesky::Factorize(int num_cols, + double* lhs, + std::string* message) { + factorize_result_ = LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + lhs_.Reserve(num_cols * num_cols); + num_cols_ = num_cols; + lhs_.CopyToGpuAsync(lhs, num_cols * num_cols, stream_); + int device_workspace_size = 0; + if (cusolverDnDpotrf_bufferSize(cusolver_handle_, + CUBLAS_FILL_MODE_LOWER, + num_cols, + lhs_.data(), + num_cols, + &device_workspace_size) != + CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDpotrf_bufferSize failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + device_workspace_.Reserve(device_workspace_size); + if (cusolverDnDpotrf(cusolver_handle_, + CUBLAS_FILL_MODE_LOWER, + num_cols, + lhs_.data(), + num_cols, + reinterpret_cast<double*>(device_workspace_.data()), + device_workspace_.size(), + error_.data()) != CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDpotrf failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + if (cudaDeviceSynchronize() != cudaSuccess || + cudaStreamSynchronize(stream_) != cudaSuccess) { + *message = "Cuda device synchronization failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + int error = 0; + error_.CopyToHost(&error, 1); + if (error < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres - " + << "please report it. " + << "cuSolverDN::cusolverDnXpotrf fatal error. " + << "Argument: " << -error << " is invalid."; + // The following line is unreachable, but return failure just to be + // pedantic, since the compiler does not know that. + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } else if (error > 0) { + *message = StringPrintf( + "cuSolverDN::cusolverDnDpotrf numerical failure. " + "The leading minor of order %d is not positive definite.", + error); + factorize_result_ = LinearSolverTerminationType::LINEAR_SOLVER_FAILURE; + return LinearSolverTerminationType::LINEAR_SOLVER_FAILURE; + } + *message = "Success"; + factorize_result_ = LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; + return LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; +} + +LinearSolverTerminationType CUDADenseCholesky::Solve(const double* rhs, + double* solution, + std::string* message) { + if (factorize_result_ != LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS) { + *message = "Factorize did not complete succesfully previously."; + return factorize_result_; + } + rhs_.CopyToGpuAsync(rhs, num_cols_, stream_); + if (cusolverDnDpotrs(cusolver_handle_, + CUBLAS_FILL_MODE_LOWER, + num_cols_, + 1, + lhs_.data(), + num_cols_, + rhs_.data(), + num_cols_, + error_.data()) != CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDpotrs failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + if (cudaDeviceSynchronize() != cudaSuccess || + cudaStreamSynchronize(stream_) != cudaSuccess) { + *message = "Cuda device synchronization failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + int error = 0; + error_.CopyToHost(&error, 1); + if (error != 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres. " + << "Please report it." + << "cuSolverDN::cusolverDnDpotrs fatal error. " + << "Argument: " << -error << " is invalid."; + } + rhs_.CopyToHost(solution, num_cols_); + *message = "Success"; + return LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; +} + +std::unique_ptr<CUDADenseCholesky> CUDADenseCholesky::Create( + const LinearSolver::Options& options) { + if (options.dense_linear_algebra_library_type != CUDA) { + // The user called the wrong factory method. + return nullptr; + } + auto cuda_dense_cholesky = + std::unique_ptr<CUDADenseCholesky>(new CUDADenseCholesky()); + std::string cuda_error; + if (cuda_dense_cholesky->Init(options.context, &cuda_error)) { + return cuda_dense_cholesky; + } + // Initialization failed, destroy the object (done automatically) and return a + // nullptr. + LOG(ERROR) << "CUDADenseCholesky::Init failed: " << cuda_error; + return nullptr; +} + +#endif // CERES_NO_CUDA + +} // namespace internal +} // namespace ceres diff --git a/extern/ceres/internal/ceres/dense_cholesky.h b/extern/ceres/internal/ceres/dense_cholesky.h new file mode 100644 index 00000000000..655a2f815ee --- /dev/null +++ b/extern/ceres/internal/ceres/dense_cholesky.h @@ -0,0 +1,183 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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) + +#ifndef CERES_INTERNAL_DENSE_CHOLESKY_H_ +#define CERES_INTERNAL_DENSE_CHOLESKY_H_ + +// This include must come before any #ifndef check on Ceres compile options. +// clang-format off +#include "ceres/internal/config.h" +// clang-format on + +#include <memory> +#include <vector> + +#include "Eigen/Dense" +#include "ceres/cuda_buffer.h" +#include "ceres/linear_solver.h" +#include "glog/logging.h" +#ifndef CERES_NO_CUDA +#include "ceres/context_impl.h" +#include "cuda_runtime.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA + +namespace ceres { +namespace internal { + +// An interface that abstracts away the internal details of various dense linear +// algebra libraries and offers a simple API for solving dense symmetric +// positive definite linear systems using a Cholesky factorization. +class CERES_NO_EXPORT DenseCholesky { + public: + static std::unique_ptr<DenseCholesky> Create( + const LinearSolver::Options& options); + + virtual ~DenseCholesky(); + + // Computes the Cholesky factorization of the given matrix. + // + // The input matrix lhs is assumed to be a column-major num_cols x num_cols + // matrix, that is symmetric positive definite with its lower triangular part + // containing the left hand side of the linear system being solved. + // + // The input matrix lhs may be modified by the implementation to store the + // factorization, irrespective of whether the factorization succeeds or not. + // As a result it is the user's responsibility to ensure that lhs is valid + // when Solve is called. + virtual LinearSolverTerminationType Factorize(int num_cols, + double* lhs, + std::string* message) = 0; + + // Computes the solution to the equation + // + // lhs * solution = rhs + // + // Calling Solve without calling Factorize is undefined behaviour. It is the + // user's responsibility to ensure that the input matrix lhs passed to + // Factorize has not been freed/modified when Solve is called. + virtual LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) = 0; + + // Convenience method which combines a call to Factorize and Solve. Solve is + // only called if Factorize returns LINEAR_SOLVER_SUCCESS. + // + // The input matrix lhs may be modified by the implementation to store the + // factorization, irrespective of whether the method succeeds or not. It is + // the user's responsibility to ensure that lhs is valid if and when Solve is + // called again after this call. + LinearSolverTerminationType FactorAndSolve(int num_cols, + double* lhs, + const double* rhs, + double* solution, + std::string* message); +}; + +class CERES_NO_EXPORT EigenDenseCholesky final : public DenseCholesky { + public: + LinearSolverTerminationType Factorize(int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + using LLTType = Eigen::LLT<Eigen::Ref<Eigen::MatrixXd>, Eigen::Lower>; + std::unique_ptr<LLTType> llt_; +}; + +#ifndef CERES_NO_LAPACK +class CERES_NO_EXPORT LAPACKDenseCholesky final : public DenseCholesky { + public: + LinearSolverTerminationType Factorize(int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + double* lhs_ = nullptr; + int num_cols_ = -1; + LinearSolverTerminationType termination_type_ = LINEAR_SOLVER_FATAL_ERROR; +}; +#endif // CERES_NO_LAPACK + +#ifndef CERES_NO_CUDA +// CUDA implementation of DenseCholesky using the cuSolverDN library using the +// 32-bit legacy interface for maximum compatibility. +class CERES_NO_EXPORT CUDADenseCholesky final : public DenseCholesky { + public: + static std::unique_ptr<CUDADenseCholesky> Create( + const LinearSolver::Options& options); + CUDADenseCholesky(const CUDADenseCholesky&) = delete; + CUDADenseCholesky& operator=(const CUDADenseCholesky&) = delete; + LinearSolverTerminationType Factorize(int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + CUDADenseCholesky() = default; + // Picks up the cuSolverDN and cuStream handles from the context. If + // the context is unable to initialize CUDA, returns false with a + // human-readable message indicating the reason. + bool Init(ContextImpl* context, std::string* message); + + // Handle to the cuSOLVER context. + cusolverDnHandle_t cusolver_handle_ = nullptr; + // CUDA device stream. + cudaStream_t stream_ = nullptr; + // Number of columns in the A matrix, to be cached between calls to *Factorize + // and *Solve. + size_t num_cols_ = 0; + // GPU memory allocated for the A matrix (lhs matrix). + CudaBuffer<double> lhs_; + // GPU memory allocated for the B matrix (rhs vector). + CudaBuffer<double> rhs_; + // Scratch space for cuSOLVER on the GPU. + CudaBuffer<double> device_workspace_; + // Required for error handling with cuSOLVER. + CudaBuffer<int> error_; + // Cache the result of Factorize to ensure that when Solve is called, the + // factiorization of lhs is valid. + LinearSolverTerminationType factorize_result_ = LINEAR_SOLVER_FATAL_ERROR; +}; + +#endif // CERES_NO_CUDA + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_DENSE_CHOLESKY_H_ diff --git a/extern/ceres/internal/ceres/dense_jacobian_writer.h b/extern/ceres/internal/ceres/dense_jacobian_writer.h index 28c60e20a1b..0020937124e 100644 --- a/extern/ceres/internal/ceres/dense_jacobian_writer.h +++ b/extern/ceres/internal/ceres/dense_jacobian_writer.h @@ -33,9 +33,13 @@ #ifndef CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ #define CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ +#include <memory> + #include "ceres/casts.h" #include "ceres/dense_sparse_matrix.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" @@ -44,7 +48,7 @@ namespace ceres { namespace internal { -class DenseJacobianWriter { +class CERES_NO_EXPORT DenseJacobianWriter { public: DenseJacobianWriter(Evaluator::Options /* ignored */, Program* program) : program_(program) {} @@ -54,13 +58,14 @@ class DenseJacobianWriter { // Since the dense matrix has different layout than that assumed by the cost // functions, use scratch space to store the jacobians temporarily then copy // them over to the larger jacobian later. - ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads) { + std::unique_ptr<ScratchEvaluatePreparer[]> CreateEvaluatePreparers( + int num_threads) { return ScratchEvaluatePreparer::Create(*program_, num_threads); } - SparseMatrix* CreateJacobian() const { - return new DenseSparseMatrix( - program_->NumResiduals(), program_->NumEffectiveParameters(), true); + std::unique_ptr<SparseMatrix> CreateJacobian() const { + return std::make_unique<DenseSparseMatrix>( + program_->NumResiduals(), program_->NumEffectiveParameters()); } void Write(int residual_id, @@ -82,14 +87,14 @@ class DenseJacobianWriter { continue; } - const int parameter_block_size = parameter_block->LocalSize(); + const int parameter_block_size = parameter_block->TangentSize(); ConstMatrixRef parameter_jacobian( jacobians[j], num_residuals, parameter_block_size); - dense_jacobian->mutable_matrix().block(residual_offset, - parameter_block->delta_offset(), - num_residuals, - parameter_block_size) = + dense_jacobian->mutable_matrix()->block(residual_offset, + parameter_block->delta_offset(), + num_residuals, + parameter_block_size) = parameter_jacobian; } } @@ -101,4 +106,6 @@ class DenseJacobianWriter { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DENSE_JACOBIAN_WRITER_H_ diff --git a/extern/ceres/internal/ceres/dense_normal_cholesky_solver.cc b/extern/ceres/internal/ceres/dense_normal_cholesky_solver.cc index 51c639097b6..30a0c023f51 100644 --- a/extern/ceres/internal/ceres/dense_normal_cholesky_solver.cc +++ b/extern/ceres/internal/ceres/dense_normal_cholesky_solver.cc @@ -30,13 +30,11 @@ #include "ceres/dense_normal_cholesky_solver.h" -#include <cstddef> +#include <utility> #include "Eigen/Dense" -#include "ceres/blas.h" #include "ceres/dense_sparse_matrix.h" #include "ceres/internal/eigen.h" -#include "ceres/lapack.h" #include "ceres/linear_solver.h" #include "ceres/types.h" #include "ceres/wall_time.h" @@ -45,32 +43,20 @@ namespace ceres { namespace internal { DenseNormalCholeskySolver::DenseNormalCholeskySolver( - const LinearSolver::Options& options) - : options_(options) {} + LinearSolver::Options options) + : options_(std::move(options)), + cholesky_(DenseCholesky::Create(options_)) {} LinearSolver::Summary DenseNormalCholeskySolver::SolveImpl( DenseSparseMatrix* A, const double* b, const LinearSolver::PerSolveOptions& per_solve_options, double* x) { - if (options_.dense_linear_algebra_library_type == EIGEN) { - return SolveUsingEigen(A, b, per_solve_options, x); - } else { - return SolveUsingLAPACK(A, b, per_solve_options, x); - } -} - -LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingEigen( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x) { EventLogger event_logger("DenseNormalCholeskySolver::Solve"); const int num_rows = A->num_rows(); const int num_cols = A->num_cols(); - ConstColMajorMatrixRef Aref = A->matrix(); Matrix lhs(num_cols, num_cols); lhs.setZero(); @@ -81,12 +67,12 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingEigen( // Using rankUpdate instead of GEMM, exposes the fact that its the // same matrix being multiplied with itself and that the product is // symmetric. - lhs.selfadjointView<Eigen::Upper>().rankUpdate(Aref.transpose()); + lhs.selfadjointView<Eigen::Upper>().rankUpdate(A->matrix().transpose()); // rhs = A'b - Vector rhs = Aref.transpose() * ConstVectorRef(b, num_rows); + Vector rhs = A->matrix().transpose() * ConstVectorRef(b, num_rows); - if (per_solve_options.D != NULL) { + if (per_solve_options.D != nullptr) { ConstVectorRef D(per_solve_options.D, num_cols); lhs += D.array().square().matrix().asDiagonal(); } @@ -94,64 +80,12 @@ LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingEigen( LinearSolver::Summary summary; summary.num_iterations = 1; - summary.termination_type = LINEAR_SOLVER_SUCCESS; - Eigen::LLT<Matrix, Eigen::Upper> llt = - lhs.selfadjointView<Eigen::Upper>().llt(); - - if (llt.info() != Eigen::Success) { - summary.termination_type = LINEAR_SOLVER_FAILURE; - summary.message = "Eigen LLT decomposition failed."; - } else { - summary.termination_type = LINEAR_SOLVER_SUCCESS; - summary.message = "Success."; - } + summary.termination_type = cholesky_->FactorAndSolve( + num_cols, lhs.data(), rhs.data(), x, &summary.message); + event_logger.AddEvent("FactorAndSolve"); - VectorRef(x, num_cols) = llt.solve(rhs); - event_logger.AddEvent("Solve"); return summary; } -LinearSolver::Summary DenseNormalCholeskySolver::SolveUsingLAPACK( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x) { - EventLogger event_logger("DenseNormalCholeskySolver::Solve"); - - if (per_solve_options.D != NULL) { - // Temporarily append a diagonal block to the A matrix, but undo - // it before returning the matrix to the user. - A->AppendDiagonal(per_solve_options.D); - } - - const int num_cols = A->num_cols(); - Matrix lhs(num_cols, num_cols); - event_logger.AddEvent("Setup"); - - // lhs = A'A - // - // Note: This is a bit delicate, it assumes that the stride on this - // matrix is the same as the number of rows. - BLAS::SymmetricRankKUpdate( - A->num_rows(), num_cols, A->values(), true, 1.0, 0.0, lhs.data()); - - if (per_solve_options.D != NULL) { - // Undo the modifications to the matrix A. - A->RemoveDiagonal(); - } - - // TODO(sameeragarwal): Replace this with a gemv call for true blasness. - // rhs = A'b - VectorRef(x, num_cols) = - A->matrix().transpose() * ConstVectorRef(b, A->num_rows()); - event_logger.AddEvent("Product"); - - LinearSolver::Summary summary; - summary.num_iterations = 1; - summary.termination_type = LAPACK::SolveInPlaceUsingCholesky( - num_cols, lhs.data(), x, &summary.message); - event_logger.AddEvent("Solve"); - return summary; -} } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/dense_normal_cholesky_solver.h b/extern/ceres/internal/ceres/dense_normal_cholesky_solver.h index 68ea611299f..5b3c74069f0 100644 --- a/extern/ceres/internal/ceres/dense_normal_cholesky_solver.h +++ b/extern/ceres/internal/ceres/dense_normal_cholesky_solver.h @@ -34,6 +34,11 @@ #ifndef CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ #define CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ +#include <memory> + +#include "ceres/dense_cholesky.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -73,9 +78,10 @@ class DenseSparseMatrix; // library. This solver always returns a solution, it is the user's // responsibility to judge if the solution is good enough for their // purposes. -class DenseNormalCholeskySolver : public DenseSparseMatrixSolver { +class CERES_NO_EXPORT DenseNormalCholeskySolver + : public DenseSparseMatrixSolver { public: - explicit DenseNormalCholeskySolver(const LinearSolver::Options& options); + explicit DenseNormalCholeskySolver(LinearSolver::Options options); private: LinearSolver::Summary SolveImpl( @@ -84,22 +90,13 @@ class DenseNormalCholeskySolver : public DenseSparseMatrixSolver { const LinearSolver::PerSolveOptions& per_solve_options, double* x) final; - LinearSolver::Summary SolveUsingLAPACK( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x); - - LinearSolver::Summary SolveUsingEigen( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x); - const LinearSolver::Options options_; + std::unique_ptr<DenseCholesky> cholesky_; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DENSE_NORMAL_CHOLESKY_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/dense_qr.cc b/extern/ceres/internal/ceres/dense_qr.cc new file mode 100644 index 00000000000..4b9c8a4a035 --- /dev/null +++ b/extern/ceres/internal/ceres/dense_qr.cc @@ -0,0 +1,481 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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/dense_qr.h" + +#include <algorithm> +#include <memory> +#include <string> +#ifndef CERES_NO_CUDA +#include "ceres/context_impl.h" +#include "cublas_v2.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA + +#ifndef CERES_NO_LAPACK + +// LAPACK routines for solving a linear least squares problem using QR +// factorization. This is done in three stages: +// +// A * x = b +// Q * R * x = b (dgeqrf) +// R * x = Q' * b (dormqr) +// x = R^{-1} * Q'* b (dtrtrs) + +// clang-format off + +// Compute the QR factorization of a. +// +// a is an m x n column major matrix (Denoted by "A" in the above description) +// lda is the leading dimension of a. lda >= max(1, num_rows) +// tau is an array of size min(m,n). It contains the scalar factors of the +// elementary reflectors. +// work is an array of size max(1,lwork). On exit, if info=0, work[0] contains +// the optimal size of work. +// +// if lwork >= 1 it is the size of work. If lwork = -1, then a workspace query is assumed. +// dgeqrf computes the optimal size of the work array and returns it as work[0]. +// +// info = 0, successful exit. +// info < 0, if info = -i, then the i^th argument had illegal value. +extern "C" void dgeqrf_(const int* m, const int* n, double* a, const int* lda, + double* tau, double* work, const int* lwork, int* info); + +// Apply Q or Q' to b. +// +// b is a m times n column major matrix. +// size = 'L' applies Q or Q' on the left, size = 'R' applies Q or Q' on the right. +// trans = 'N', applies Q, trans = 'T', applies Q'. +// k is the number of elementary reflectors whose product defines the matrix Q. +// If size = 'L', m >= k >= 0 and if side = 'R', n >= k >= 0. +// a is an lda x k column major matrix containing the reflectors as returned by dgeqrf. +// ldb is the leading dimension of b. +// work is an array of size max(1, lwork) +// lwork if positive is the size of work. If lwork = -1, then a +// workspace query is assumed. +// +// info = 0, successful exit. +// info < 0, if info = -i, then the i^th argument had illegal value. +extern "C" void dormqr_(const char* side, const char* trans, const int* m, + const int* n ,const int* k, double* a, const int* lda, + double* tau, double* b, const int* ldb, double* work, + const int* lwork, int* info); + +// Solve a triangular system of the form A * x = b +// +// uplo = 'U', A is upper triangular. uplo = 'L' is lower triangular. +// trans = 'N', 'T', 'C' specifies the form - A, A^T, A^H. +// DIAG = 'N', A is not unit triangular. 'U' is unit triangular. +// n is the order of the matrix A. +// nrhs number of columns of b. +// a is a column major lda x n. +// b is a column major matrix of ldb x nrhs +// +// info = 0 succesful. +// = -i < 0 i^th argument is an illegal value. +// = i > 0, i^th diagonal element of A is zero. +extern "C" void dtrtrs_(const char* uplo, const char* trans, const char* diag, + const int* n, const int* nrhs, double* a, const int* lda, + double* b, const int* ldb, int* info); +// clang-format on + +#endif + +namespace ceres { +namespace internal { + +DenseQR::~DenseQR() = default; + +std::unique_ptr<DenseQR> DenseQR::Create(const LinearSolver::Options& options) { + std::unique_ptr<DenseQR> dense_qr; + + switch (options.dense_linear_algebra_library_type) { + case EIGEN: + dense_qr = std::make_unique<EigenDenseQR>(); + break; + + case LAPACK: +#ifndef CERES_NO_LAPACK + dense_qr = std::make_unique<LAPACKDenseQR>(); + break; +#else + LOG(FATAL) << "Ceres was compiled without support for LAPACK."; +#endif + + case CUDA: +#ifndef CERES_NO_CUDA + dense_qr = CUDADenseQR::Create(options); + break; +#else + LOG(FATAL) << "Ceres was compiled without support for CUDA."; +#endif + + default: + LOG(FATAL) << "Unknown dense linear algebra library type : " + << DenseLinearAlgebraLibraryTypeToString( + options.dense_linear_algebra_library_type); + } + return dense_qr; +} + +LinearSolverTerminationType DenseQR::FactorAndSolve(int num_rows, + int num_cols, + double* lhs, + const double* rhs, + double* solution, + std::string* message) { + LinearSolverTerminationType termination_type = + Factorize(num_rows, num_cols, lhs, message); + if (termination_type == LINEAR_SOLVER_SUCCESS) { + termination_type = Solve(rhs, solution, message); + } + return termination_type; +} + +LinearSolverTerminationType EigenDenseQR::Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) { + Eigen::Map<ColMajorMatrix> m(lhs, num_rows, num_cols); + qr_ = std::make_unique<QRType>(m); + *message = "Success."; + return LINEAR_SOLVER_SUCCESS; +} + +LinearSolverTerminationType EigenDenseQR::Solve(const double* rhs, + double* solution, + std::string* message) { + VectorRef(solution, qr_->cols()) = + qr_->solve(ConstVectorRef(rhs, qr_->rows())); + *message = "Success."; + return LINEAR_SOLVER_SUCCESS; +} + +#ifndef CERES_NO_LAPACK +LinearSolverTerminationType LAPACKDenseQR::Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) { + int lwork = -1; + double work_size; + int info = 0; + + // Compute the size of the temporary workspace needed to compute the QR + // factorization in the dgeqrf call below. + dgeqrf_(&num_rows, + &num_cols, + lhs_, + &num_rows, + tau_.data(), + &work_size, + &lwork, + &info); + if (info < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres." + << "Please report it." + << "LAPACK::dgels fatal error." + << "Argument: " << -info << " is invalid."; + } + + lhs_ = lhs; + num_rows_ = num_rows; + num_cols_ = num_cols; + + lwork = static_cast<int>(work_size); + + if (work_.size() < lwork) { + work_.resize(lwork); + } + if (tau_.size() < num_cols) { + tau_.resize(num_cols); + } + + if (q_transpose_rhs_.size() < num_rows) { + q_transpose_rhs_.resize(num_rows); + } + + // Factorize the lhs_ using the workspace that we just constructed above. + dgeqrf_(&num_rows, + &num_cols, + lhs_, + &num_rows, + tau_.data(), + work_.data(), + &lwork, + &info); + + if (info < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres." + << "Please report it. dgeqrf fatal error." + << "Argument: " << -info << " is invalid."; + } + + termination_type_ = LINEAR_SOLVER_SUCCESS; + *message = "Success."; + return termination_type_; +} + +LinearSolverTerminationType LAPACKDenseQR::Solve(const double* rhs, + double* solution, + std::string* message) { + if (termination_type_ != LINEAR_SOLVER_SUCCESS) { + *message = "QR factorization failed and solve called."; + return termination_type_; + } + + std::copy_n(rhs, num_rows_, q_transpose_rhs_.data()); + + const char side = 'L'; + char trans = 'T'; + const int num_c_cols = 1; + const int lwork = work_.size(); + int info = 0; + dormqr_(&side, + &trans, + &num_rows_, + &num_c_cols, + &num_cols_, + lhs_, + &num_rows_, + tau_.data(), + q_transpose_rhs_.data(), + &num_rows_, + work_.data(), + &lwork, + &info); + if (info < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres." + << "Please report it. dormr fatal error." + << "Argument: " << -info << " is invalid."; + } + + const char uplo = 'U'; + trans = 'N'; + const char diag = 'N'; + dtrtrs_(&uplo, + &trans, + &diag, + &num_cols_, + &num_c_cols, + lhs_, + &num_rows_, + q_transpose_rhs_.data(), + &num_rows_, + &info); + + if (info < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres." + << "Please report it. dormr fatal error." + << "Argument: " << -info << " is invalid."; + } else if (info > 0) { + *message = + "QR factorization failure. The factorization is not full rank. R has " + "zeros on the diagonal."; + termination_type_ = LINEAR_SOLVER_FAILURE; + } else { + std::copy_n(q_transpose_rhs_.data(), num_cols_, solution); + termination_type_ = LINEAR_SOLVER_SUCCESS; + } + + return termination_type_; +} + +#endif // CERES_NO_LAPACK + +#ifndef CERES_NO_CUDA + +bool CUDADenseQR::Init(ContextImpl* context, std::string* message) { + if (!context->InitCUDA(message)) { + return false; + } + cublas_handle_ = context->cublas_handle_; + cusolver_handle_ = context->cusolver_handle_; + stream_ = context->stream_; + error_.Reserve(1); + *message = "CUDADenseQR::Init Success."; + return true; +} + +LinearSolverTerminationType CUDADenseQR::Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) { + factorize_result_ = LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + lhs_.Reserve(num_rows * num_cols); + tau_.Reserve(std::min(num_rows, num_cols)); + num_rows_ = num_rows; + num_cols_ = num_cols; + lhs_.CopyToGpuAsync(lhs, num_rows * num_cols, stream_); + int device_workspace_size = 0; + if (cusolverDnDgeqrf_bufferSize(cusolver_handle_, + num_rows, + num_cols, + lhs_.data(), + num_rows, + &device_workspace_size) != + CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDgeqrf_bufferSize failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + device_workspace_.Reserve(device_workspace_size); + if (cusolverDnDgeqrf(cusolver_handle_, + num_rows, + num_cols, + lhs_.data(), + num_rows, + tau_.data(), + reinterpret_cast<double*>(device_workspace_.data()), + device_workspace_.size(), + error_.data()) != CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDgeqrf failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + if (cudaDeviceSynchronize() != cudaSuccess || + cudaStreamSynchronize(stream_) != cudaSuccess) { + *message = "Cuda device synchronization failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + int error = 0; + error_.CopyToHost(&error, 1); + if (error < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres - " + << "please report it. " + << "cuSolverDN::cusolverDnDgeqrf fatal error. " + << "Argument: " << -error << " is invalid."; + // The following line is unreachable, but return failure just to be + // pedantic, since the compiler does not know that. + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + + *message = "Success"; + factorize_result_ = LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; + return LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; +} + +LinearSolverTerminationType CUDADenseQR::Solve(const double* rhs, + double* solution, + std::string* message) { + if (factorize_result_ != LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS) { + *message = "Factorize did not complete succesfully previously."; + return factorize_result_; + } + rhs_.CopyToGpuAsync(rhs, num_rows_, stream_); + int device_workspace_size = 0; + if (cusolverDnDormqr_bufferSize(cusolver_handle_, + CUBLAS_SIDE_LEFT, + CUBLAS_OP_T, + num_rows_, + 1, + num_cols_, + lhs_.data(), + num_rows_, + tau_.data(), + rhs_.data(), + num_rows_, + &device_workspace_size) != + CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDormqr_bufferSize failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + device_workspace_.Reserve(device_workspace_size); + // Compute rhs = Q^T * rhs, assuming that lhs has already been factorized. + // The result of factorization would have stored Q in a packed form in lhs_. + if (cusolverDnDormqr(cusolver_handle_, + CUBLAS_SIDE_LEFT, + CUBLAS_OP_T, + num_rows_, + 1, + num_cols_, + lhs_.data(), + num_rows_, + tau_.data(), + rhs_.data(), + num_rows_, + reinterpret_cast<double*>(device_workspace_.data()), + device_workspace_.size(), + error_.data()) != CUSOLVER_STATUS_SUCCESS) { + *message = "cuSolverDN::cusolverDnDormqr failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + int error = 0; + error_.CopyToHost(&error, 1); + if (error < 0) { + LOG(FATAL) << "Congratulations, you found a bug in Ceres. " + << "Please report it." + << "cuSolverDN::cusolverDnDormqr fatal error. " + << "Argument: " << -error << " is invalid."; + } + // Compute the solution vector as x = R \ (Q^T * rhs). Since the previous step + // replaced rhs by (Q^T * rhs), this is just x = R \ rhs. + if (cublasDtrsv(cublas_handle_, + CUBLAS_FILL_MODE_UPPER, + CUBLAS_OP_N, + CUBLAS_DIAG_NON_UNIT, + num_cols_, + lhs_.data(), + num_rows_, + rhs_.data(), + 1) != CUBLAS_STATUS_SUCCESS) { + *message = "cuBLAS::cublasDtrsv failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + if (cudaDeviceSynchronize() != cudaSuccess || + cudaStreamSynchronize(stream_) != cudaSuccess) { + *message = "Cuda device synchronization failed."; + return LinearSolverTerminationType::LINEAR_SOLVER_FATAL_ERROR; + } + rhs_.CopyToHost(solution, num_cols_); + *message = "Success"; + return LinearSolverTerminationType::LINEAR_SOLVER_SUCCESS; +} + +std::unique_ptr<CUDADenseQR> CUDADenseQR::Create( + const LinearSolver::Options& options) { + if (options.dense_linear_algebra_library_type != CUDA) { + // The user called the wrong factory method. + return nullptr; + } + auto cuda_dense_qr = std::unique_ptr<CUDADenseQR>(new CUDADenseQR()); + std::string cuda_error; + if (cuda_dense_qr->Init(options.context, &cuda_error)) { + return cuda_dense_qr; + } + // Initialization failed, destroy the object (done automatically) and return a + // nullptr. + LOG(ERROR) << "CUDADenseQR::Init failed: " << cuda_error; + return nullptr; +} + +CUDADenseQR::CUDADenseQR() = default; + +#endif // CERES_NO_CUDA + +} // namespace internal +} // namespace ceres diff --git a/extern/ceres/internal/ceres/dense_qr.h b/extern/ceres/internal/ceres/dense_qr.h new file mode 100644 index 00000000000..7a2ffb52ae6 --- /dev/null +++ b/extern/ceres/internal/ceres/dense_qr.h @@ -0,0 +1,207 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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) + +#ifndef CERES_INTERNAL_DENSE_QR_H_ +#define CERES_INTERNAL_DENSE_QR_H_ + +// This include must come before any #ifndef check on Ceres compile options. +// clang-format off +#include "ceres/internal/config.h" +// clang-format on + +#include <memory> +#include <vector> + +#include "Eigen/Dense" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" +#include "ceres/linear_solver.h" +#include "glog/logging.h" + +#ifndef CERES_NO_CUDA +#include "ceres/context_impl.h" +#include "ceres/cuda_buffer.h" +#include "cublas_v2.h" +#include "cuda_runtime.h" +#include "cusolverDn.h" +#endif // CERES_NO_CUDA + +namespace ceres { +namespace internal { + +// An interface that abstracts away the internal details of various dense linear +// algebra libraries and offers a simple API for solving dense linear systems +// using a QR factorization. +class CERES_NO_EXPORT DenseQR { + public: + static std::unique_ptr<DenseQR> Create(const LinearSolver::Options& options); + + virtual ~DenseQR(); + + // Computes the QR factorization of the given matrix. + // + // The input matrix lhs is assumed to be a column-major num_rows x num_cols + // matrix. + // + // The input matrix lhs may be modified by the implementation to store the + // factorization, irrespective of whether the factorization succeeds or not. + // As a result it is the user's responsibility to ensure that lhs is valid + // when Solve is called. + virtual LinearSolverTerminationType Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) = 0; + + // Computes the solution to the equation + // + // lhs * solution = rhs + // + // Calling Solve without calling Factorize is undefined behaviour. It is the + // user's responsibility to ensure that the input matrix lhs passed to + // Factorize has not been freed/modified when Solve is called. + virtual LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) = 0; + + // Convenience method which combines a call to Factorize and Solve. Solve is + // only called if Factorize returns LINEAR_SOLVER_SUCCESS. + // + // The input matrix lhs may be modified by the implementation to store the + // factorization, irrespective of whether the method succeeds or not. It is + // the user's responsibility to ensure that lhs is valid if and when Solve is + // called again after this call. + LinearSolverTerminationType FactorAndSolve(int num_rows, + int num_cols, + double* lhs, + const double* rhs, + double* solution, + std::string* message); +}; + +class CERES_NO_EXPORT EigenDenseQR final : public DenseQR { + public: + LinearSolverTerminationType Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + using QRType = Eigen::HouseholderQR<Eigen::Ref<ColMajorMatrix>>; + std::unique_ptr<QRType> qr_; +}; + +#ifndef CERES_NO_LAPACK +class CERES_NO_EXPORT LAPACKDenseQR final : public DenseQR { + public: + LinearSolverTerminationType Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + double* lhs_ = nullptr; + int num_rows_; + int num_cols_; + LinearSolverTerminationType termination_type_ = LINEAR_SOLVER_FATAL_ERROR; + Vector work_; + Vector tau_; + Vector q_transpose_rhs_; +}; +#endif // CERES_NO_LAPACK + +#ifndef CERES_NO_CUDA +// Implementation of DenseQR using the 32-bit cuSolverDn interface. A +// requirement for using this solver is that the lhs must not be rank deficient. +// This is because cuSolverDn does not implement the singularity-checking +// wrapper trtrs, hence this solver directly uses trsv from CUBLAS for the +// backsubstitution. +class CERES_NO_EXPORT CUDADenseQR final : public DenseQR { + public: + static std::unique_ptr<CUDADenseQR> Create( + const LinearSolver::Options& options); + CUDADenseQR(const CUDADenseQR&) = delete; + CUDADenseQR& operator=(const CUDADenseQR&) = delete; + LinearSolverTerminationType Factorize(int num_rows, + int num_cols, + double* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; + + private: + CUDADenseQR(); + // Picks up the cuSolverDN, cuBLAS, and cuStream handles from the context. If + // the context is unable to initialize CUDA, returns false with a + // human-readable message indicating the reason. + bool Init(ContextImpl* context, std::string* message); + + // Handle to the cuSOLVER context. + cusolverDnHandle_t cusolver_handle_ = nullptr; + // Handle to cuBLAS context. + cublasHandle_t cublas_handle_ = nullptr; + // CUDA device stream. + cudaStream_t stream_ = nullptr; + // Number of rowns in the A matrix, to be cached between calls to *Factorize + // and *Solve. + size_t num_rows_ = 0; + // Number of columns in the A matrix, to be cached between calls to *Factorize + // and *Solve. + size_t num_cols_ = 0; + // GPU memory allocated for the A matrix (lhs matrix). + CudaBuffer<double> lhs_; + // GPU memory allocated for the B matrix (rhs vector). + CudaBuffer<double> rhs_; + // GPU memory allocated for the TAU matrix (scaling of householder vectors). + CudaBuffer<double> tau_; + // Scratch space for cuSOLVER on the GPU. + CudaBuffer<double> device_workspace_; + // Required for error handling with cuSOLVER. + CudaBuffer<int> error_; + // Cache the result of Factorize to ensure that when Solve is called, the + // factiorization of lhs is valid. + LinearSolverTerminationType factorize_result_ = LINEAR_SOLVER_FATAL_ERROR; +}; + +#endif // CERES_NO_CUDA + +} // namespace internal +} // namespace ceres + +#include "ceres/internal/reenable_warnings.h" + +#endif // CERES_INTERNAL_DENSE_QR_H_ diff --git a/extern/ceres/internal/ceres/dense_qr_solver.cc b/extern/ceres/internal/ceres/dense_qr_solver.cc index 44388f30aee..24cb25abd8e 100644 --- a/extern/ceres/internal/ceres/dense_qr_solver.cc +++ b/extern/ceres/internal/ceres/dense_qr_solver.cc @@ -33,9 +33,9 @@ #include <cstddef> #include "Eigen/Dense" +#include "ceres/dense_qr.h" #include "ceres/dense_sparse_matrix.h" #include "ceres/internal/eigen.h" -#include "ceres/lapack.h" #include "ceres/linear_solver.h" #include "ceres/types.h" #include "ceres/wall_time.h" @@ -44,124 +44,40 @@ namespace ceres { namespace internal { DenseQRSolver::DenseQRSolver(const LinearSolver::Options& options) - : options_(options) { - work_.resize(1); -} + : options_(options), dense_qr_(DenseQR::Create(options)) {} LinearSolver::Summary DenseQRSolver::SolveImpl( DenseSparseMatrix* A, const double* b, const LinearSolver::PerSolveOptions& per_solve_options, double* x) { - if (options_.dense_linear_algebra_library_type == EIGEN) { - return SolveUsingEigen(A, b, per_solve_options, x); - } else { - return SolveUsingLAPACK(A, b, per_solve_options, x); - } -} - -LinearSolver::Summary DenseQRSolver::SolveUsingLAPACK( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x) { EventLogger event_logger("DenseQRSolver::Solve"); const int num_rows = A->num_rows(); const int num_cols = A->num_cols(); + const int num_augmented_rows = + num_rows + ((per_solve_options.D != nullptr) ? num_cols : 0); - if (per_solve_options.D != NULL) { - // Temporarily append a diagonal block to the A matrix, but undo - // it before returning the matrix to the user. - A->AppendDiagonal(per_solve_options.D); + if (lhs_.rows() != num_augmented_rows || lhs_.cols() != num_cols) { + lhs_.resize(num_augmented_rows, num_cols); + rhs_.resize(num_augmented_rows); } - // TODO(sameeragarwal): Since we are copying anyways, the diagonal - // can be appended to the matrix instead of doing it on A. - lhs_ = A->matrix(); - - if (per_solve_options.D != NULL) { - // Undo the modifications to the matrix A. - A->RemoveDiagonal(); - } - - // rhs = [b;0] to account for the additional rows in the lhs. - if (rhs_.rows() != lhs_.rows()) { - rhs_.resize(lhs_.rows()); - } - rhs_.setZero(); + lhs_.topRows(num_rows) = A->matrix(); rhs_.head(num_rows) = ConstVectorRef(b, num_rows); - if (work_.rows() == 1) { - const int work_size = - LAPACK::EstimateWorkSizeForQR(lhs_.rows(), lhs_.cols()); - VLOG(3) << "Working memory for Dense QR factorization: " - << work_size * sizeof(double); - work_.resize(work_size); + if (num_rows != num_augmented_rows) { + lhs_.bottomRows(num_cols) = + ConstVectorRef(per_solve_options.D, num_cols).asDiagonal(); + rhs_.tail(num_cols).setZero(); } LinearSolver::Summary summary; + summary.termination_type = dense_qr_->FactorAndSolve( + lhs_.rows(), lhs_.cols(), lhs_.data(), rhs_.data(), x, &summary.message); summary.num_iterations = 1; - summary.termination_type = LAPACK::SolveInPlaceUsingQR(lhs_.rows(), - lhs_.cols(), - lhs_.data(), - work_.rows(), - work_.data(), - rhs_.data(), - &summary.message); event_logger.AddEvent("Solve"); - if (summary.termination_type == LINEAR_SOLVER_SUCCESS) { - VectorRef(x, num_cols) = rhs_.head(num_cols); - } - - event_logger.AddEvent("TearDown"); - return summary; -} - -LinearSolver::Summary DenseQRSolver::SolveUsingEigen( - DenseSparseMatrix* A, - const double* b, - const LinearSolver::PerSolveOptions& per_solve_options, - double* x) { - EventLogger event_logger("DenseQRSolver::Solve"); - - const int num_rows = A->num_rows(); - const int num_cols = A->num_cols(); - - if (per_solve_options.D != NULL) { - // Temporarily append a diagonal block to the A matrix, but undo - // it before returning the matrix to the user. - A->AppendDiagonal(per_solve_options.D); - } - - // rhs = [b;0] to account for the additional rows in the lhs. - const int augmented_num_rows = - num_rows + ((per_solve_options.D != NULL) ? num_cols : 0); - if (rhs_.rows() != augmented_num_rows) { - rhs_.resize(augmented_num_rows); - rhs_.setZero(); - } - rhs_.head(num_rows) = ConstVectorRef(b, num_rows); - event_logger.AddEvent("Setup"); - - // Solve the system. - VectorRef(x, num_cols) = A->matrix().householderQr().solve(rhs_); - event_logger.AddEvent("Solve"); - - if (per_solve_options.D != NULL) { - // Undo the modifications to the matrix A. - A->RemoveDiagonal(); - } - - // We always succeed, since the QR solver returns the best solution - // it can. It is the job of the caller to determine if the solution - // is good enough or not. - LinearSolver::Summary summary; - summary.num_iterations = 1; - summary.termination_type = LINEAR_SOLVER_SUCCESS; - summary.message = "Success."; - event_logger.AddEvent("TearDown"); return summary; } diff --git a/extern/ceres/internal/ceres/dense_qr_solver.h b/extern/ceres/internal/ceres/dense_qr_solver.h index 980243bd6c6..39922a2692b 100644 --- a/extern/ceres/internal/ceres/dense_qr_solver.h +++ b/extern/ceres/internal/ceres/dense_qr_solver.h @@ -32,8 +32,12 @@ #ifndef CERES_INTERNAL_DENSE_QR_SOLVER_H_ #define CERES_INTERNAL_DENSE_QR_SOLVER_H_ +#include <memory> + +#include "ceres/dense_qr.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -79,7 +83,7 @@ class DenseSparseMatrix; // library. This solver always returns a solution, it is the user's // responsibility to judge if the solution is good enough for their // purposes. -class CERES_EXPORT_INTERNAL DenseQRSolver : public DenseSparseMatrixSolver { +class CERES_NO_EXPORT DenseQRSolver final : public DenseSparseMatrixSolver { public: explicit DenseQRSolver(const LinearSolver::Options& options); @@ -105,10 +109,12 @@ class CERES_EXPORT_INTERNAL DenseQRSolver : public DenseSparseMatrixSolver { const LinearSolver::Options options_; ColMajorMatrix lhs_; Vector rhs_; - Vector work_; + std::unique_ptr<DenseQR> dense_qr_; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DENSE_QR_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/dense_sparse_matrix.cc b/extern/ceres/internal/ceres/dense_sparse_matrix.cc index 53207fe300e..8b967f2ade7 100644 --- a/extern/ceres/internal/ceres/dense_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/dense_sparse_matrix.cc @@ -31,9 +31,10 @@ #include "ceres/dense_sparse_matrix.h" #include <algorithm> +#include <utility> #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/triplet_sparse_matrix.h" #include "glog/logging.h" @@ -41,28 +42,10 @@ namespace ceres { namespace internal { DenseSparseMatrix::DenseSparseMatrix(int num_rows, int num_cols) - : has_diagonal_appended_(false), has_diagonal_reserved_(false) { - m_.resize(num_rows, num_cols); - m_.setZero(); -} - -DenseSparseMatrix::DenseSparseMatrix(int num_rows, - int num_cols, - bool reserve_diagonal) - : has_diagonal_appended_(false), has_diagonal_reserved_(reserve_diagonal) { - if (reserve_diagonal) { - // Allocate enough space for the diagonal. - m_.resize(num_rows + num_cols, num_cols); - } else { - m_.resize(num_rows, num_cols); - } - m_.setZero(); -} + : m_(Matrix(num_rows, num_cols)) {} DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m) - : m_(Eigen::MatrixXd::Zero(m.num_rows(), m.num_cols())), - has_diagonal_appended_(false), - has_diagonal_reserved_(false) { + : m_(Matrix::Zero(m.num_rows(), m.num_cols())) { const double* values = m.values(); const int* rows = m.rows(); const int* cols = m.cols(); @@ -73,8 +56,7 @@ DenseSparseMatrix::DenseSparseMatrix(const TripletSparseMatrix& m) } } -DenseSparseMatrix::DenseSparseMatrix(const ColMajorMatrix& m) - : m_(m), has_diagonal_appended_(false), has_diagonal_reserved_(false) {} +DenseSparseMatrix::DenseSparseMatrix(Matrix m) : m_(std::move(m)) {} void DenseSparseMatrix::SetZero() { m_.setZero(); } @@ -96,72 +78,22 @@ void DenseSparseMatrix::ScaleColumns(const double* scale) { } void DenseSparseMatrix::ToDenseMatrix(Matrix* dense_matrix) const { - *dense_matrix = m_.block(0, 0, num_rows(), num_cols()); + *dense_matrix = m_; } -void DenseSparseMatrix::AppendDiagonal(double* d) { - CHECK(!has_diagonal_appended_); - if (!has_diagonal_reserved_) { - ColMajorMatrix tmp = m_; - m_.resize(m_.rows() + m_.cols(), m_.cols()); - m_.setZero(); - m_.block(0, 0, tmp.rows(), tmp.cols()) = tmp; - has_diagonal_reserved_ = true; - } - - m_.bottomLeftCorner(m_.cols(), m_.cols()) = - ConstVectorRef(d, m_.cols()).asDiagonal(); - has_diagonal_appended_ = true; -} - -void DenseSparseMatrix::RemoveDiagonal() { - CHECK(has_diagonal_appended_); - has_diagonal_appended_ = false; - // Leave the diagonal reserved. -} - -int DenseSparseMatrix::num_rows() const { - if (has_diagonal_reserved_ && !has_diagonal_appended_) { - return m_.rows() - m_.cols(); - } - return m_.rows(); -} +int DenseSparseMatrix::num_rows() const { return m_.rows(); } int DenseSparseMatrix::num_cols() const { return m_.cols(); } -int DenseSparseMatrix::num_nonzeros() const { - if (has_diagonal_reserved_ && !has_diagonal_appended_) { - return (m_.rows() - m_.cols()) * m_.cols(); - } - return m_.rows() * m_.cols(); -} +int DenseSparseMatrix::num_nonzeros() const { return m_.rows() * m_.cols(); } -ConstColMajorMatrixRef DenseSparseMatrix::matrix() const { - return ConstColMajorMatrixRef( - m_.data(), - ((has_diagonal_reserved_ && !has_diagonal_appended_) - ? m_.rows() - m_.cols() - : m_.rows()), - m_.cols(), - Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1)); -} +const Matrix& DenseSparseMatrix::matrix() const { return m_; } -ColMajorMatrixRef DenseSparseMatrix::mutable_matrix() { - return ColMajorMatrixRef(m_.data(), - ((has_diagonal_reserved_ && !has_diagonal_appended_) - ? m_.rows() - m_.cols() - : m_.rows()), - m_.cols(), - Eigen::Stride<Eigen::Dynamic, 1>(m_.rows(), 1)); -} +Matrix* DenseSparseMatrix::mutable_matrix() { return &m_; } void DenseSparseMatrix::ToTextFile(FILE* file) const { CHECK(file != nullptr); - const int active_rows = (has_diagonal_reserved_ && !has_diagonal_appended_) - ? (m_.rows() - m_.cols()) - : m_.rows(); - - for (int r = 0; r < active_rows; ++r) { + for (int r = 0; r < m_.rows(); ++r) { for (int c = 0; c < m_.cols(); ++c) { fprintf(file, "% 10d % 10d %17f\n", r, c, m_(r, c)); } diff --git a/extern/ceres/internal/ceres/dense_sparse_matrix.h b/extern/ceres/internal/ceres/dense_sparse_matrix.h index 94064b3eddc..655cbb8a3db 100644 --- a/extern/ceres/internal/ceres/dense_sparse_matrix.h +++ b/extern/ceres/internal/ceres/dense_sparse_matrix.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -33,8 +33,9 @@ #ifndef CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ #define CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/sparse_matrix.h" #include "ceres/types.h" @@ -43,17 +44,13 @@ namespace internal { class TripletSparseMatrix; -class CERES_EXPORT_INTERNAL DenseSparseMatrix : public SparseMatrix { +class CERES_NO_EXPORT DenseSparseMatrix final : public SparseMatrix { public: // Build a matrix with the same content as the TripletSparseMatrix // m. This assumes that m does not have any repeated entries. explicit DenseSparseMatrix(const TripletSparseMatrix& m); - explicit DenseSparseMatrix(const ColMajorMatrix& m); - + explicit DenseSparseMatrix(Matrix m); DenseSparseMatrix(int num_rows, int num_cols); - DenseSparseMatrix(int num_rows, int num_cols, bool reserve_diagonal); - - virtual ~DenseSparseMatrix() {} // SparseMatrix interface. void SetZero() final; @@ -69,40 +66,16 @@ class CERES_EXPORT_INTERNAL DenseSparseMatrix : public SparseMatrix { const double* values() const final { return m_.data(); } double* mutable_values() final { return m_.data(); } - ConstColMajorMatrixRef matrix() const; - ColMajorMatrixRef mutable_matrix(); - - // Only one diagonal can be appended at a time. The diagonal is appended to - // as a new set of rows, e.g. - // - // Original matrix: - // - // x x x - // x x x - // x x x - // - // After append diagonal (1, 2, 3): - // - // x x x - // x x x - // x x x - // 1 0 0 - // 0 2 0 - // 0 0 3 - // - // Calling RemoveDiagonal removes the block. It is a fatal error to append a - // diagonal to a matrix that already has an appended diagonal, and it is also - // a fatal error to remove a diagonal from a matrix that has none. - void AppendDiagonal(double* d); - void RemoveDiagonal(); + const Matrix& matrix() const; + Matrix* mutable_matrix(); private: - ColMajorMatrix m_; - bool has_diagonal_appended_; - bool has_diagonal_reserved_; + Matrix m_; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DENSE_SPARSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/detect_structure.h b/extern/ceres/internal/ceres/detect_structure.h index 06242307ca8..6151c042256 100644 --- a/extern/ceres/internal/ceres/detect_structure.h +++ b/extern/ceres/internal/ceres/detect_structure.h @@ -32,7 +32,8 @@ #define CERES_INTERNAL_DETECT_STRUCTURE_H_ #include "ceres/block_structure.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -56,13 +57,15 @@ namespace internal { // Note: The structure of rows without any e-blocks has no effect on // the values returned by this function. It is entirely possible that // the f_block_size and row_blocks_size is not constant in such rows. -void CERES_EXPORT DetectStructure(const CompressedRowBlockStructure& bs, - const int num_eliminate_blocks, - int* row_block_size, - int* e_block_size, - int* f_block_size); +void CERES_NO_EXPORT DetectStructure(const CompressedRowBlockStructure& bs, + const int num_eliminate_blocks, + int* row_block_size, + int* e_block_size, + int* f_block_size); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DETECT_STRUCTURE_H_ diff --git a/extern/ceres/internal/ceres/dogleg_strategy.cc b/extern/ceres/internal/ceres/dogleg_strategy.cc index 03ae22f7e57..65f7ccd8480 100644 --- a/extern/ceres/internal/ceres/dogleg_strategy.cc +++ b/extern/ceres/internal/ceres/dogleg_strategy.cc @@ -480,7 +480,7 @@ bool DoglegStrategy::FindMinimumOnTrustRegionBoundary(Vector2d* minimum) const { // Find the real parts y_i of its roots (not only the real roots). Vector roots_real; - if (!FindPolynomialRoots(polynomial, &roots_real, NULL)) { + if (!FindPolynomialRoots(polynomial, &roots_real, nullptr)) { // Failed to find the roots of the polynomial, i.e. the candidate // solutions of the constrained problem. Report this back to the caller. return false; diff --git a/extern/ceres/internal/ceres/dogleg_strategy.h b/extern/ceres/internal/ceres/dogleg_strategy.h index cc3778ea2a0..1d219afe8bc 100644 --- a/extern/ceres/internal/ceres/dogleg_strategy.h +++ b/extern/ceres/internal/ceres/dogleg_strategy.h @@ -31,7 +31,8 @@ #ifndef CERES_INTERNAL_DOGLEG_STRATEGY_H_ #define CERES_INTERNAL_DOGLEG_STRATEGY_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "ceres/trust_region_strategy.h" @@ -53,10 +54,9 @@ namespace internal { // DoglegStrategy follows the approach by Shultz, Schnabel, Byrd. // This finds the exact optimum over the two-dimensional subspace // spanned by the two Dogleg vectors. -class CERES_EXPORT_INTERNAL DoglegStrategy : public TrustRegionStrategy { +class CERES_NO_EXPORT DoglegStrategy final : public TrustRegionStrategy { public: explicit DoglegStrategy(const TrustRegionStrategy::Options& options); - virtual ~DoglegStrategy() {} // TrustRegionStrategy interface Summary ComputeStep(const PerSolveOptions& per_solve_options, @@ -65,7 +65,7 @@ class CERES_EXPORT_INTERNAL DoglegStrategy : public TrustRegionStrategy { double* step) final; void StepAccepted(double step_quality) final; void StepRejected(double step_quality) final; - void StepIsInvalid(); + void StepIsInvalid() override; double Radius() const final; // These functions are predominantly for testing. @@ -76,8 +76,8 @@ class CERES_EXPORT_INTERNAL DoglegStrategy : public TrustRegionStrategy { Matrix subspace_B() const { return subspace_B_; } private: - typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vector2d; - typedef Eigen::Matrix<double, 2, 2, Eigen::DontAlign> Matrix2d; + using Vector2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>; + using Matrix2d = Eigen::Matrix<double, 2, 2, Eigen::DontAlign>; LinearSolver::Summary ComputeGaussNewtonStep( const PerSolveOptions& per_solve_options, @@ -162,4 +162,6 @@ class CERES_EXPORT_INTERNAL DoglegStrategy : public TrustRegionStrategy { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DOGLEG_STRATEGY_H_ diff --git a/extern/ceres/internal/ceres/dynamic_compressed_row_finalizer.h b/extern/ceres/internal/ceres/dynamic_compressed_row_finalizer.h index 30c98d86b6f..fedee3b7a83 100644 --- a/extern/ceres/internal/ceres/dynamic_compressed_row_finalizer.h +++ b/extern/ceres/internal/ceres/dynamic_compressed_row_finalizer.h @@ -33,13 +33,14 @@ #include "ceres/casts.h" #include "ceres/dynamic_compressed_row_sparse_matrix.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { -struct DynamicCompressedRowJacobianFinalizer { +struct CERES_NO_EXPORT DynamicCompressedRowJacobianFinalizer { void operator()(SparseMatrix* base_jacobian, int num_parameters) { - DynamicCompressedRowSparseMatrix* jacobian = + auto* jacobian = down_cast<DynamicCompressedRowSparseMatrix*>(base_jacobian); jacobian->Finalize(num_parameters); } diff --git a/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc b/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc index 1749449043e..8c254e98f46 100644 --- a/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc +++ b/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -30,6 +30,8 @@ #include "ceres/dynamic_compressed_row_jacobian_writer.h" +#include <memory> + #include "ceres/casts.h" #include "ceres/compressed_row_jacobian_writer.h" #include "ceres/dynamic_compressed_row_sparse_matrix.h" @@ -43,25 +45,24 @@ namespace internal { using std::pair; using std::vector; -ScratchEvaluatePreparer* +std::unique_ptr<ScratchEvaluatePreparer[]> DynamicCompressedRowJacobianWriter::CreateEvaluatePreparers(int num_threads) { return ScratchEvaluatePreparer::Create(*program_, num_threads); } -SparseMatrix* DynamicCompressedRowJacobianWriter::CreateJacobian() const { - DynamicCompressedRowSparseMatrix* jacobian = - new DynamicCompressedRowSparseMatrix(program_->NumResiduals(), - program_->NumEffectiveParameters(), - 0 /* max_num_nonzeros */); - return jacobian; +std::unique_ptr<SparseMatrix> +DynamicCompressedRowJacobianWriter::CreateJacobian() const { + return std::make_unique<DynamicCompressedRowSparseMatrix>( + program_->NumResiduals(), + program_->NumEffectiveParameters(), + 0 /* max_num_nonzeros */); } void DynamicCompressedRowJacobianWriter::Write(int residual_id, int residual_offset, double** jacobians, SparseMatrix* base_jacobian) { - DynamicCompressedRowSparseMatrix* jacobian = - down_cast<DynamicCompressedRowSparseMatrix*>(base_jacobian); + auto* jacobian = down_cast<DynamicCompressedRowSparseMatrix*>(base_jacobian); // Get the `residual_block` of interest. const ResidualBlock* residual_block = @@ -77,12 +78,11 @@ void DynamicCompressedRowJacobianWriter::Write(int residual_id, jacobian->ClearRows(residual_offset, num_residuals); // Iterate over each parameter block. - for (int i = 0; i < evaluated_jacobian_blocks.size(); ++i) { + for (const auto& evaluated_jacobian_block : evaluated_jacobian_blocks) { const ParameterBlock* parameter_block = - program_->parameter_blocks()[evaluated_jacobian_blocks[i].first]; - const int parameter_block_jacobian_index = - evaluated_jacobian_blocks[i].second; - const int parameter_block_size = parameter_block->LocalSize(); + program_->parameter_blocks()[evaluated_jacobian_block.first]; + const int parameter_block_jacobian_index = evaluated_jacobian_block.second; + const int parameter_block_size = parameter_block->TangentSize(); const double* parameter_jacobian = jacobians[parameter_block_jacobian_index]; diff --git a/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.h b/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.h index ef8fa25d7d4..794a9b4c1e6 100644 --- a/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.h +++ b/extern/ceres/internal/ceres/dynamic_compressed_row_jacobian_writer.h @@ -34,7 +34,10 @@ #ifndef CERES_INTERNAL_DYNAMIC_COMPRESSED_ROW_JACOBIAN_WRITER_H_ #define CERES_INTERNAL_DYNAMIC_COMPRESSED_ROW_JACOBIAN_WRITER_H_ +#include <memory> + #include "ceres/evaluator.h" +#include "ceres/internal/export.h" #include "ceres/scratch_evaluate_preparer.h" namespace ceres { @@ -43,7 +46,7 @@ namespace internal { class Program; class SparseMatrix; -class DynamicCompressedRowJacobianWriter { +class CERES_NO_EXPORT DynamicCompressedRowJacobianWriter { public: DynamicCompressedRowJacobianWriter(Evaluator::Options /* ignored */, Program* program) @@ -55,12 +58,13 @@ class DynamicCompressedRowJacobianWriter { // the cost functions. The scratch space is therefore used to store // the jacobians (including zeros) temporarily before only the non-zero // entries are copied over to the larger jacobian in `Write`. - ScratchEvaluatePreparer* CreateEvaluatePreparers(int num_threads); + std::unique_ptr<ScratchEvaluatePreparer[]> CreateEvaluatePreparers( + int num_threads); // Return a `DynamicCompressedRowSparseMatrix` which is filled by // `Write`. Note that `Finalize` must be called to make the // `CompressedRowSparseMatrix` interface valid. - SparseMatrix* CreateJacobian() const; + std::unique_ptr<SparseMatrix> CreateJacobian() const; // Write only the non-zero jacobian entries for a residual block // (specified by `residual_id`) into `base_jacobian`, starting at the row diff --git a/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.cc b/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.cc index 936e682b763..7185e14a411 100644 --- a/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -70,8 +70,8 @@ void DynamicCompressedRowSparseMatrix::Finalize(int num_additional_elements) { // Count the number of non-zeros and resize `cols_` and `values_`. int num_jacobian_nonzeros = 0; - for (int i = 0; i < dynamic_cols_.size(); ++i) { - num_jacobian_nonzeros += dynamic_cols_[i].size(); + for (const auto& dynamic_col : dynamic_cols_) { + num_jacobian_nonzeros += dynamic_col.size(); } SetMaxNumNonZeros(num_jacobian_nonzeros + num_additional_elements); diff --git a/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.h b/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.h index d06c36ebb94..5b4c402f830 100644 --- a/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.h +++ b/extern/ceres/internal/ceres/dynamic_compressed_row_sparse_matrix.h @@ -44,12 +44,13 @@ #include <vector> #include "ceres/compressed_row_sparse_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { -class CERES_EXPORT_INTERNAL DynamicCompressedRowSparseMatrix +class CERES_NO_EXPORT DynamicCompressedRowSparseMatrix final : public CompressedRowSparseMatrix { public: // Set the number of rows and columns for the underlyig @@ -100,4 +101,6 @@ class CERES_EXPORT_INTERNAL DynamicCompressedRowSparseMatrix } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_DYNAMIC_COMPRESSED_ROW_SPARSE_MATRIX_H_ diff --git a/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.cc b/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.cc index d31c4228f05..5e907e18d51 100644 --- a/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.cc +++ b/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.cc @@ -35,10 +35,12 @@ #include <ctime> #include <memory> #include <sstream> +#include <utility> #include "Eigen/SparseCore" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/cxsparse.h" +#include "ceres/internal/config.h" #include "ceres/internal/eigen.h" #include "ceres/linear_solver.h" #include "ceres/suitesparse.h" @@ -54,8 +56,8 @@ namespace ceres { namespace internal { DynamicSparseNormalCholeskySolver::DynamicSparseNormalCholeskySolver( - const LinearSolver::Options& options) - : options_(options) {} + LinearSolver::Options options) + : options_(std::move(options)) {} LinearSolver::Summary DynamicSparseNormalCholeskySolver::SolveImpl( CompressedRowSparseMatrix* A, @@ -71,11 +73,11 @@ LinearSolver::Summary DynamicSparseNormalCholeskySolver::SolveImpl( // it before returning the matrix to the user. std::unique_ptr<CompressedRowSparseMatrix> regularizer; if (!A->col_blocks().empty()) { - regularizer.reset(CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( - per_solve_options.D, A->col_blocks())); + regularizer = CompressedRowSparseMatrix::CreateBlockDiagonalMatrix( + per_solve_options.D, A->col_blocks()); } else { - regularizer.reset( - new CompressedRowSparseMatrix(per_solve_options.D, num_cols)); + regularizer = std::make_unique<CompressedRowSparseMatrix>( + per_solve_options.D, num_cols); } A->AppendRows(*regularizer); } @@ -123,12 +125,13 @@ LinearSolver::Summary DynamicSparseNormalCholeskySolver::SolveImplUsingEigen( EventLogger event_logger("DynamicSparseNormalCholeskySolver::Eigen::Solve"); - Eigen::MappedSparseMatrix<double, Eigen::RowMajor> a(A->num_rows(), - A->num_cols(), - A->num_nonzeros(), - A->mutable_rows(), - A->mutable_cols(), - A->mutable_values()); + Eigen::Map<Eigen::SparseMatrix<double, Eigen::RowMajor>> a( + A->num_rows(), + A->num_cols(), + A->num_nonzeros(), + A->mutable_rows(), + A->mutable_cols(), + A->mutable_values()); Eigen::SparseMatrix<double> lhs = a.transpose() * a; Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver; diff --git a/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.h b/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.h index 36118bab1a5..6f73c961212 100644 --- a/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.h +++ b/extern/ceres/internal/ceres/dynamic_sparse_normal_cholesky_solver.h @@ -36,9 +36,10 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -53,12 +54,10 @@ class CompressedRowSparseMatrix; // // TODO(alex): Add support for Accelerate sparse solvers: // https://github.com/ceres-solver/ceres-solver/issues/397 -class DynamicSparseNormalCholeskySolver +class CERES_NO_EXPORT DynamicSparseNormalCholeskySolver : public CompressedRowSparseMatrixSolver { public: - explicit DynamicSparseNormalCholeskySolver( - const LinearSolver::Options& options); - virtual ~DynamicSparseNormalCholeskySolver() {} + explicit DynamicSparseNormalCholeskySolver(LinearSolver::Options options); private: LinearSolver::Summary SolveImpl(CompressedRowSparseMatrix* A, diff --git a/extern/ceres/internal/ceres/eigensparse.cc b/extern/ceres/internal/ceres/eigensparse.cc index 22ed2c43b5d..81668c82e67 100644 --- a/extern/ceres/internal/ceres/eigensparse.cc +++ b/extern/ceres/internal/ceres/eigensparse.cc @@ -30,6 +30,8 @@ #include "ceres/eigensparse.h" +#include <memory> + #ifdef CERES_USE_EIGEN_SPARSE #include <sstream> @@ -45,10 +47,9 @@ namespace internal { // TODO(sameeragarwal): Use enable_if to clean up the implementations // for when Scalar == double. template <typename Solver> -class EigenSparseCholeskyTemplate : public SparseCholesky { +class EigenSparseCholeskyTemplate final : public SparseCholesky { public: - EigenSparseCholeskyTemplate() : analyzed_(false) {} - virtual ~EigenSparseCholeskyTemplate() {} + EigenSparseCholeskyTemplate() = default; CompressedRowSparseMatrix::StorageType StorageType() const final { return CompressedRowSparseMatrix::LOWER_TRIANGULAR; } @@ -83,7 +84,7 @@ class EigenSparseCholeskyTemplate : public SparseCholesky { LinearSolverTerminationType Solve(const double* rhs_ptr, double* solution_ptr, - std::string* message) { + std::string* message) override { CHECK(analyzed_) << "Solve called without a call to Factorize first."; scalar_rhs_ = ConstVectorRef(rhs_ptr, solver_.cols()) @@ -109,7 +110,7 @@ class EigenSparseCholeskyTemplate : public SparseCholesky { std::string* message) final { CHECK_EQ(lhs->storage_type(), StorageType()); - typename Solver::Scalar* values_ptr = NULL; + typename Solver::Scalar* values_ptr = nullptr; if (std::is_same<typename Solver::Scalar, double>::value) { values_ptr = reinterpret_cast<typename Solver::Scalar*>(lhs->mutable_values()); @@ -122,7 +123,7 @@ class EigenSparseCholeskyTemplate : public SparseCholesky { values_ptr = values_.data(); } - Eigen::MappedSparseMatrix<typename Solver::Scalar, Eigen::ColMajor> + Eigen::Map<Eigen::SparseMatrix<typename Solver::Scalar, Eigen::ColMajor>> eigen_lhs(lhs->num_rows(), lhs->num_rows(), lhs->num_nonzeros(), @@ -135,54 +136,46 @@ class EigenSparseCholeskyTemplate : public SparseCholesky { private: Eigen::Matrix<typename Solver::Scalar, Eigen::Dynamic, 1> values_, scalar_rhs_, scalar_solution_; - bool analyzed_; + bool analyzed_{false}; Solver solver_; }; std::unique_ptr<SparseCholesky> EigenSparseCholesky::Create( const OrderingType ordering_type) { - std::unique_ptr<SparseCholesky> sparse_cholesky; - - typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, - Eigen::Upper, - Eigen::AMDOrdering<int>> - WithAMDOrdering; - typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, - Eigen::Upper, - Eigen::NaturalOrdering<int>> - WithNaturalOrdering; + using WithAMDOrdering = Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, + Eigen::Upper, + Eigen::AMDOrdering<int>>; + using WithNaturalOrdering = + Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>, + Eigen::Upper, + Eigen::NaturalOrdering<int>>; + if (ordering_type == AMD) { - sparse_cholesky.reset(new EigenSparseCholeskyTemplate<WithAMDOrdering>()); + return std::make_unique<EigenSparseCholeskyTemplate<WithAMDOrdering>>(); } else { - sparse_cholesky.reset( - new EigenSparseCholeskyTemplate<WithNaturalOrdering>()); + return std::make_unique<EigenSparseCholeskyTemplate<WithNaturalOrdering>>(); } - return sparse_cholesky; } -EigenSparseCholesky::~EigenSparseCholesky() {} +EigenSparseCholesky::~EigenSparseCholesky() = default; std::unique_ptr<SparseCholesky> FloatEigenSparseCholesky::Create( const OrderingType ordering_type) { - std::unique_ptr<SparseCholesky> sparse_cholesky; - typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<float>, - Eigen::Upper, - Eigen::AMDOrdering<int>> - WithAMDOrdering; - typedef Eigen::SimplicialLDLT<Eigen::SparseMatrix<float>, - Eigen::Upper, - Eigen::NaturalOrdering<int>> - WithNaturalOrdering; + using WithAMDOrdering = Eigen::SimplicialLDLT<Eigen::SparseMatrix<float>, + Eigen::Upper, + Eigen::AMDOrdering<int>>; + using WithNaturalOrdering = + Eigen::SimplicialLDLT<Eigen::SparseMatrix<float>, + Eigen::Upper, + Eigen::NaturalOrdering<int>>; if (ordering_type == AMD) { - sparse_cholesky.reset(new EigenSparseCholeskyTemplate<WithAMDOrdering>()); + return std::make_unique<EigenSparseCholeskyTemplate<WithAMDOrdering>>(); } else { - sparse_cholesky.reset( - new EigenSparseCholeskyTemplate<WithNaturalOrdering>()); + return std::make_unique<EigenSparseCholeskyTemplate<WithNaturalOrdering>>(); } - return sparse_cholesky; } -FloatEigenSparseCholesky::~FloatEigenSparseCholesky() {} +FloatEigenSparseCholesky::~FloatEigenSparseCholesky() = default; } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/eigensparse.h b/extern/ceres/internal/ceres/eigensparse.h index bb89c2c11ac..c4a4142e586 100644 --- a/extern/ceres/internal/ceres/eigensparse.h +++ b/extern/ceres/internal/ceres/eigensparse.h @@ -34,7 +34,7 @@ #define CERES_INTERNAL_EIGENSPARSE_H_ // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifdef CERES_USE_EIGEN_SPARSE @@ -42,44 +42,45 @@ #include <string> #include "Eigen/SparseCore" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "ceres/sparse_cholesky.h" namespace ceres { namespace internal { -class EigenSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT EigenSparseCholesky : public SparseCholesky { public: // Factory static std::unique_ptr<SparseCholesky> Create( const OrderingType ordering_type); // SparseCholesky interface. - virtual ~EigenSparseCholesky(); - virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, - std::string* message) = 0; - virtual CompressedRowSparseMatrix::StorageType StorageType() const = 0; - virtual LinearSolverTerminationType Solve(const double* rhs, - double* solution, - std::string* message) = 0; + ~EigenSparseCholesky() override; + LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, + std::string* message) override = 0; + CompressedRowSparseMatrix::StorageType StorageType() const override = 0; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override = 0; }; // Even though the input is double precision linear system, this class // solves it by computing a single precision Cholesky factorization. -class FloatEigenSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT FloatEigenSparseCholesky : public SparseCholesky { public: // Factory static std::unique_ptr<SparseCholesky> Create( const OrderingType ordering_type); // SparseCholesky interface. - virtual ~FloatEigenSparseCholesky(); - virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, - std::string* message) = 0; - virtual CompressedRowSparseMatrix::StorageType StorageType() const = 0; - virtual LinearSolverTerminationType Solve(const double* rhs, - double* solution, - std::string* message) = 0; + ~FloatEigenSparseCholesky() override; + LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, + std::string* message) override = 0; + CompressedRowSparseMatrix::StorageType StorageType() const override = 0; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override = 0; }; } // namespace internal diff --git a/extern/ceres/internal/ceres/evaluation_callback.cc b/extern/ceres/internal/ceres/evaluation_callback.cc new file mode 100644 index 00000000000..77591a8c621 --- /dev/null +++ b/extern/ceres/internal/ceres/evaluation_callback.cc @@ -0,0 +1,37 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2022 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: mierle@gmail.com (Keir Mierle) + +#include "ceres/evaluation_callback.h" + +namespace ceres { + +EvaluationCallback::~EvaluationCallback() = default; + +} // namespace ceres diff --git a/extern/ceres/internal/ceres/evaluator.cc b/extern/ceres/internal/ceres/evaluator.cc index 516874184d9..52d0f09e5df 100644 --- a/extern/ceres/internal/ceres/evaluator.cc +++ b/extern/ceres/internal/ceres/evaluator.cc @@ -30,6 +30,7 @@ #include "ceres/evaluator.h" +#include <memory> #include <vector> #include "ceres/block_evaluate_preparer.h" @@ -40,7 +41,7 @@ #include "ceres/dense_jacobian_writer.h" #include "ceres/dynamic_compressed_row_finalizer.h" #include "ceres/dynamic_compressed_row_jacobian_writer.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/program_evaluator.h" #include "ceres/scratch_evaluate_preparer.h" #include "glog/logging.h" @@ -48,38 +49,42 @@ namespace ceres { namespace internal { -Evaluator::~Evaluator() {} +Evaluator::~Evaluator() = default; -Evaluator* Evaluator::Create(const Evaluator::Options& options, - Program* program, - std::string* error) { - CHECK(options.context != NULL); +std::unique_ptr<Evaluator> Evaluator::Create(const Evaluator::Options& options, + Program* program, + std::string* error) { + CHECK(options.context != nullptr); switch (options.linear_solver_type) { case DENSE_QR: case DENSE_NORMAL_CHOLESKY: - return new ProgramEvaluator<ScratchEvaluatePreparer, DenseJacobianWriter>( + return std::make_unique< + ProgramEvaluator<ScratchEvaluatePreparer, DenseJacobianWriter>>( options, program); case DENSE_SCHUR: case SPARSE_SCHUR: case ITERATIVE_SCHUR: case CGNR: - return new ProgramEvaluator<BlockEvaluatePreparer, BlockJacobianWriter>( + return std::make_unique< + ProgramEvaluator<BlockEvaluatePreparer, BlockJacobianWriter>>( options, program); case SPARSE_NORMAL_CHOLESKY: if (options.dynamic_sparsity) { - return new ProgramEvaluator<ScratchEvaluatePreparer, - DynamicCompressedRowJacobianWriter, - DynamicCompressedRowJacobianFinalizer>( - options, program); + return std::make_unique< + ProgramEvaluator<ScratchEvaluatePreparer, + DynamicCompressedRowJacobianWriter, + DynamicCompressedRowJacobianFinalizer>>(options, + program); } else { - return new ProgramEvaluator<BlockEvaluatePreparer, BlockJacobianWriter>( + return std::make_unique< + ProgramEvaluator<BlockEvaluatePreparer, BlockJacobianWriter>>( options, program); } default: *error = "Invalid Linear Solver Type. Unable to create evaluator."; - return NULL; + return nullptr; } } diff --git a/extern/ceres/internal/ceres/evaluator.h b/extern/ceres/internal/ceres/evaluator.h index 9cf42593e95..68a4fb28a55 100644 --- a/extern/ceres/internal/ceres/evaluator.h +++ b/extern/ceres/internal/ceres/evaluator.h @@ -33,12 +33,14 @@ #define CERES_INTERNAL_EVALUATOR_H_ #include <map> +#include <memory> #include <string> #include <vector> #include "ceres/context_impl.h" #include "ceres/execution_summary.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/types.h" namespace ceres { @@ -54,8 +56,8 @@ class SparseMatrix; // The Evaluator interface offers a way to interact with a least squares cost // function that is useful for an optimizer that wants to minimize the least // squares objective. This insulates the optimizer from issues like Jacobian -// storage, parameterization, etc. -class CERES_EXPORT_INTERNAL Evaluator { +// storage, manifolds, etc. +class CERES_NO_EXPORT Evaluator { public: virtual ~Evaluator(); @@ -68,9 +70,9 @@ class CERES_EXPORT_INTERNAL Evaluator { EvaluationCallback* evaluation_callback = nullptr; }; - static Evaluator* Create(const Options& options, - Program* program, - std::string* error); + static std::unique_ptr<Evaluator> Create(const Options& options, + Program* program, + std::string* error); // Build and return a sparse matrix for storing and working with the Jacobian // of the objective function. The jacobian has dimensions @@ -88,7 +90,7 @@ class CERES_EXPORT_INTERNAL Evaluator { // the jacobian for use with CHOLMOD, where as BlockOptimizationProblem // creates a BlockSparseMatrix representation of the jacobian for use in the // Schur complement based methods. - virtual SparseMatrix* CreateJacobian() const = 0; + virtual std::unique_ptr<SparseMatrix> CreateJacobian() const = 0; // Options struct to control Evaluator::Evaluate; struct EvaluateOptions { @@ -102,10 +104,10 @@ class CERES_EXPORT_INTERNAL Evaluator { // Evaluate the cost function for the given state. Returns the cost, // residuals, and jacobian in the corresponding arguments. Both residuals and - // jacobian are optional; to avoid computing them, pass NULL. + // jacobian are optional; to avoid computing them, pass nullptr. // - // If non-NULL, the Jacobian must have a suitable sparsity pattern; only the - // values array of the jacobian is modified. + // If non-nullptr, the Jacobian must have a suitable sparsity pattern; only + // the values array of the jacobian is modified. // // state is an array of size NumParameters(), cost is a pointer to a single // double, and residuals is an array of doubles of size NumResiduals(). @@ -131,13 +133,13 @@ class CERES_EXPORT_INTERNAL Evaluator { // Make a change delta (of size NumEffectiveParameters()) to state (of size // NumParameters()) and store the result in state_plus_delta. // - // In the case that there are no parameterizations used, this is equivalent to + // In the case that there are no manifolds used, this is equivalent to // // state_plus_delta[i] = state[i] + delta[i] ; // - // however, the mapping is more complicated in the case of parameterizations + // however, the mapping is more complicated in the case of manifolds // like quaternions. This is the same as the "Plus()" operation in - // local_parameterization.h, but operating over the entire state vector for a + // manifold.h, but operating over the entire state vector for a // problem. virtual bool Plus(const double* state, const double* delta, @@ -147,7 +149,7 @@ class CERES_EXPORT_INTERNAL Evaluator { virtual int NumParameters() const = 0; // This is the effective number of parameters that the optimizer may adjust. - // This applies when there are parameterizations on some of the parameters. + // This applies when there are manifolds on some of the parameters. virtual int NumEffectiveParameters() const = 0; // The number of residuals in the optimization problem. @@ -158,11 +160,13 @@ class CERES_EXPORT_INTERNAL Evaluator { // life time issues. Further, these calls are not expected to be // frequent or performance sensitive. virtual std::map<std::string, CallStatistics> Statistics() const { - return std::map<std::string, CallStatistics>(); + return {}; } }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_EVALUATOR_H_ diff --git a/extern/ceres/internal/ceres/execution_summary.h b/extern/ceres/internal/ceres/execution_summary.h index 17fd882af03..fbee75fc0cb 100644 --- a/extern/ceres/internal/ceres/execution_summary.h +++ b/extern/ceres/internal/ceres/execution_summary.h @@ -34,17 +34,18 @@ #include <map> #include <mutex> #include <string> +#include <utility> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/wall_time.h" namespace ceres { namespace internal { struct CallStatistics { - CallStatistics() : time(0.), calls(0) {} - double time; - int calls; + CallStatistics() = default; + double time{0.}; + int calls{0}; }; // Struct used by various objects to report statistics about their @@ -69,8 +70,10 @@ class ExecutionSummary { class ScopedExecutionTimer { public: - ScopedExecutionTimer(const std::string& name, ExecutionSummary* summary) - : start_time_(WallTimeInSeconds()), name_(name), summary_(summary) {} + ScopedExecutionTimer(std::string name, ExecutionSummary* summary) + : start_time_(WallTimeInSeconds()), + name_(std::move(name)), + summary_(summary) {} ~ScopedExecutionTimer() { summary_->IncrementTimeBy(name_, WallTimeInSeconds() - start_time_); diff --git a/extern/ceres/internal/ceres/file.h b/extern/ceres/internal/ceres/file.h index c0015df60f0..bd13128aedf 100644 --- a/extern/ceres/internal/ceres/file.h +++ b/extern/ceres/internal/ceres/file.h @@ -35,21 +35,26 @@ #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { +CERES_NO_EXPORT void WriteStringToFileOrDie(const std::string& data, const std::string& filename); +CERES_NO_EXPORT void ReadFileToStringOrDie(const std::string& filename, std::string* data); // Join two path components, adding a slash if necessary. If basename is an // absolute path then JoinPath ignores dirname and simply returns basename. -CERES_EXPORT_INTERNAL std::string JoinPath(const std::string& dirname, - const std::string& basename); +CERES_NO_EXPORT +std::string JoinPath(const std::string& dirname, const std::string& basename); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_FILE_H_ diff --git a/extern/ceres/internal/ceres/blas.h b/extern/ceres/internal/ceres/first_order_function.cc index a43301c5d18..26f13488a1d 100644 --- a/extern/ceres/internal/ceres/blas.h +++ b/extern/ceres/internal/ceres/first_order_function.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -27,31 +27,11 @@ // POSSIBILITY OF SUCH DAMAGE. // // Author: sameeragarwal@google.com (Sameer Agarwal) -// -// Wrapper functions around BLAS functions. -#ifndef CERES_INTERNAL_BLAS_H_ -#define CERES_INTERNAL_BLAS_H_ +#include "ceres/first_order_function.h" namespace ceres { -namespace internal { -class BLAS { - public: - // transpose = true : c = alpha * a'a + beta * c; - // transpose = false : c = alpha * aa' + beta * c; - // - // Assumes column major matrices. - static void SymmetricRankKUpdate(int num_rows, - int num_cols, - const double* a, - bool transpose, - double alpha, - double beta, - double* c); -}; +FirstOrderFunction::~FirstOrderFunction() = default; -} // namespace internal } // namespace ceres - -#endif // CERES_INTERNAL_BLAS_H_ diff --git a/extern/ceres/internal/ceres/float_cxsparse.cc b/extern/ceres/internal/ceres/float_cxsparse.cc index 6c688303444..a6d5e811efd 100644 --- a/extern/ceres/internal/ceres/float_cxsparse.cc +++ b/extern/ceres/internal/ceres/float_cxsparse.cc @@ -30,6 +30,8 @@ #include "ceres/float_cxsparse.h" +#include <memory> + #if !defined(CERES_NO_CXSPARSE) namespace ceres { @@ -38,7 +40,7 @@ namespace internal { std::unique_ptr<SparseCholesky> FloatCXSparseCholesky::Create( OrderingType ordering_type) { LOG(FATAL) << "FloatCXSparseCholesky is not available."; - return std::unique_ptr<SparseCholesky>(); + return {}; } } // namespace internal diff --git a/extern/ceres/internal/ceres/float_cxsparse.h b/extern/ceres/internal/ceres/float_cxsparse.h index 9a274c23636..8b4514acb18 100644 --- a/extern/ceres/internal/ceres/float_cxsparse.h +++ b/extern/ceres/internal/ceres/float_cxsparse.h @@ -32,12 +32,13 @@ #define CERES_INTERNAL_FLOAT_CXSPARSE_H_ // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #if !defined(CERES_NO_CXSPARSE) #include <memory> +#include "ceres/internal/export.h" #include "ceres/sparse_cholesky.h" namespace ceres { @@ -45,7 +46,7 @@ namespace internal { // Fake implementation of a single precision Sparse Cholesky using // CXSparse. -class FloatCXSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT FloatCXSparseCholesky : public SparseCholesky { public: static std::unique_ptr<SparseCholesky> Create(OrderingType ordering_type); }; diff --git a/extern/ceres/internal/ceres/float_suitesparse.cc b/extern/ceres/internal/ceres/float_suitesparse.cc index 03604572b5c..dc1d0e45bdb 100644 --- a/extern/ceres/internal/ceres/float_suitesparse.cc +++ b/extern/ceres/internal/ceres/float_suitesparse.cc @@ -30,6 +30,8 @@ #include "ceres/float_suitesparse.h" +#include <memory> + #if !defined(CERES_NO_SUITESPARSE) namespace ceres { @@ -38,7 +40,7 @@ namespace internal { std::unique_ptr<SparseCholesky> FloatSuiteSparseCholesky::Create( OrderingType ordering_type) { LOG(FATAL) << "FloatSuiteSparseCholesky is not available."; - return std::unique_ptr<SparseCholesky>(); + return {}; } } // namespace internal diff --git a/extern/ceres/internal/ceres/float_suitesparse.h b/extern/ceres/internal/ceres/float_suitesparse.h index c436da43f86..7e76799e241 100644 --- a/extern/ceres/internal/ceres/float_suitesparse.h +++ b/extern/ceres/internal/ceres/float_suitesparse.h @@ -33,11 +33,12 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on #include <memory> +#include "ceres/internal/export.h" #include "ceres/sparse_cholesky.h" #if !defined(CERES_NO_SUITESPARSE) @@ -47,7 +48,7 @@ namespace internal { // Fake implementation of a single precision Sparse Cholesky using // SuiteSparse. -class FloatSuiteSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT FloatSuiteSparseCholesky : public SparseCholesky { public: static std::unique_ptr<SparseCholesky> Create(OrderingType ordering_type); }; diff --git a/extern/ceres/internal/ceres/function_sample.h b/extern/ceres/internal/ceres/function_sample.h index 3bcea1bc5ff..63ffc8ff8fc 100644 --- a/extern/ceres/internal/ceres/function_sample.h +++ b/extern/ceres/internal/ceres/function_sample.h @@ -33,8 +33,9 @@ #include <string> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -47,7 +48,7 @@ namespace internal { // line/direction. FunctionSample contains the information in two // ways. Information in the ambient space and information along the // direction of search. -struct CERES_EXPORT_INTERNAL FunctionSample { +struct CERES_NO_EXPORT FunctionSample { FunctionSample(); FunctionSample(double x, double value); FunctionSample(double x, double value, double gradient); @@ -90,4 +91,6 @@ struct CERES_EXPORT_INTERNAL FunctionSample { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_FUNCTION_SAMPLE_H_ diff --git a/extern/ceres/internal/ceres/generate_template_specializations.py b/extern/ceres/internal/ceres/generate_template_specializations.py deleted file mode 100644 index 74e46c28b78..00000000000 --- a/extern/ceres/internal/ceres/generate_template_specializations.py +++ /dev/null @@ -1,246 +0,0 @@ -# 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) -# -# Script for explicitly generating template specialization of the -# SchurEliminator class. It is a rather large class -# and the number of explicit instantiations is also large. Explicitly -# generating these instantiations in separate .cc files breaks the -# compilation into separate compilation unit rather than one large cc -# file which takes 2+GB of RAM to compile. -# -# This script creates three sets of files. -# -# 1. schur_eliminator_x_x_x.cc and partitioned_matrix_view_x_x_x.cc -# where, the x indicates the template parameters and -# -# 2. schur_eliminator.cc & partitioned_matrix_view.cc -# -# that contains a factory function for instantiating these classes -# based on runtime parameters. -# -# 3. schur_templates.cc -# -# that contains a function which can be queried to determine what -# template specializations are available. -# -# The following list of tuples, specializations indicates the set of -# specializations that is generated. -SPECIALIZATIONS = [(2, 2, 2), - (2, 2, 3), - (2, 2, 4), - (2, 2, "Eigen::Dynamic"), - (2, 3, 3), - (2, 3, 4), - (2, 3, 6), - (2, 3, 9), - (2, 3, "Eigen::Dynamic"), - (2, 4, 3), - (2, 4, 4), - (2, 4, 6), - (2, 4, 8), - (2, 4, 9), - (2, 4, "Eigen::Dynamic"), - (2, "Eigen::Dynamic", "Eigen::Dynamic"), - (3, 3, 3), - (4, 4, 2), - (4, 4, 3), - (4, 4, 4), - (4, 4, "Eigen::Dynamic")] - -import schur_eliminator_template -import partitioned_matrix_view_template -import os -import glob - -def SuffixForSize(size): - if size == "Eigen::Dynamic": - return "d" - return str(size) - -def SpecializationFilename(prefix, row_block_size, e_block_size, f_block_size): - return "_".join([prefix] + map(SuffixForSize, (row_block_size, - e_block_size, - f_block_size))) - -def GenerateFactoryConditional(row_block_size, e_block_size, f_block_size): - conditionals = [] - if (row_block_size != "Eigen::Dynamic"): - conditionals.append("(options.row_block_size == %s)" % row_block_size) - if (e_block_size != "Eigen::Dynamic"): - conditionals.append("(options.e_block_size == %s)" % e_block_size) - if (f_block_size != "Eigen::Dynamic"): - conditionals.append("(options.f_block_size == %s)" % f_block_size) - if (len(conditionals) == 0): - return "%s" - - if (len(conditionals) == 1): - return " if " + conditionals[0] + " {\n %s\n }\n" - - return " if (" + " &&\n ".join(conditionals) + ") {\n %s\n }\n" - -def Specialize(name, data): - """ - Generate specialization code and the conditionals to instantiate it. - """ - - # Specialization files - for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS: - output = SpecializationFilename("generated/" + name, - row_block_size, - e_block_size, - f_block_size) + ".cc" - - with open(output, "w") as f: - f.write(data["HEADER"]) - f.write(data["SPECIALIZATION_FILE"] % - (row_block_size, e_block_size, f_block_size)) - - # Generate the _d_d_d specialization. - output = SpecializationFilename("generated/" + name, - "Eigen::Dynamic", - "Eigen::Dynamic", - "Eigen::Dynamic") + ".cc" - with open(output, "w") as f: - f.write(data["HEADER"]) - f.write(data["DYNAMIC_FILE"] % - ("Eigen::Dynamic", "Eigen::Dynamic", "Eigen::Dynamic")) - - # Factory - with open(name + ".cc", "w") as f: - f.write(data["HEADER"]) - f.write(data["FACTORY_FILE_HEADER"]) - for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS: - factory_conditional = GenerateFactoryConditional( - row_block_size, e_block_size, f_block_size) - factory = data["FACTORY"] % (row_block_size, e_block_size, f_block_size) - f.write(factory_conditional % factory); - f.write(data["FACTORY_FOOTER"]) - -QUERY_HEADER = """// 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) -// -// What template specializations are available. -// -// ======================================== -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -//========================================= -// -// This file is generated using generate_template_specializations.py. -""" - -QUERY_FILE_HEADER = """ -#include "ceres/internal/eigen.h" -#include "ceres/schur_templates.h" - -namespace ceres { -namespace internal { - -void GetBestSchurTemplateSpecialization(int* row_block_size, - int* e_block_size, - int* f_block_size) { - LinearSolver::Options options; - options.row_block_size = *row_block_size; - options.e_block_size = *e_block_size; - options.f_block_size = *f_block_size; - *row_block_size = Eigen::Dynamic; - *e_block_size = Eigen::Dynamic; - *f_block_size = Eigen::Dynamic; -#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION -""" - -QUERY_FOOTER = """ -#endif - return; -} - -} // namespace internal -} // namespace ceres -""" - -QUERY_ACTION = """ *row_block_size = %s; - *e_block_size = %s; - *f_block_size = %s; - return;""" - -def GenerateQueryFile(): - """ - Generate file that allows querying for available template specializations. - """ - - with open("schur_templates.cc", "w") as f: - f.write(QUERY_HEADER) - f.write(QUERY_FILE_HEADER) - for row_block_size, e_block_size, f_block_size in SPECIALIZATIONS: - factory_conditional = GenerateFactoryConditional( - row_block_size, e_block_size, f_block_size) - action = QUERY_ACTION % (row_block_size, e_block_size, f_block_size) - f.write(factory_conditional % action) - f.write(QUERY_FOOTER) - - -if __name__ == "__main__": - for f in glob.glob("generated/*"): - os.remove(f) - - Specialize("schur_eliminator", - schur_eliminator_template.__dict__) - Specialize("partitioned_matrix_view", - partitioned_matrix_view_template.__dict__) - GenerateQueryFile() diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc index f5753bef544..7b4ed167d05 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_2.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc index a7a9b5231cf..0f012515a95 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc index faf6c4a754a..bdbe91c43f6 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc index 92fd4cddf43..71f293b5512 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_2_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc index 2df314f137a..a6ea7761c9a 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc index ff1ca3e7f1f..e712678a28a 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_6.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_6.cc index 5041df9152d..3aff26e657b 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_6.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_6.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc index c0b72fec8b8..6cd239bfd9a 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_9.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc index 8a3c162ab7e..68c50552d42 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_3_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc index 0e69ca6404d..88c5e29c6f8 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc index ba9bb615291..b9487834441 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_6.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_6.cc index 1acdb9b21d5..7f044ef628b 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_6.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_6.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_8.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_8.cc index 888ff99557d..7394e7998e7 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_8.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_8.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_9.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_9.cc index bd4dde3d207..263f1fb36f1 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_9.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_9.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc index 6d3516fc6d5..d47634e0f40 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_4_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc index 77d22ed6bc2..0944cdcbfda 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_2_d_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_3_3_3.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_3_3_3.cc index aeb456c6e2a..23674031bb9 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_3_3_3.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_3_3_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc index bb240b9e3f6..d5268cac481 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_2.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc index 5d47543644d..67e098fc6f3 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc index e14f980933d..5fe28caee8c 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc index 9ec50563ac8..d87c76d0aa4 100644 --- a/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc +++ b/extern/ceres/internal/ceres/generated/partitioned_matrix_view_4_4_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc index 289a809acb7..dc47a2e6d8e 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_2.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc index 20311ba843d..e2df6f63d2f 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc index 1f6a8ae4a0e..0b1ae949a09 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc index 08b18d357bd..0f7b6d78c7f 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_2_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc index 115b4c8cce1..e4ab8eb19bf 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc index c7035370424..d73d466b04c 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_6.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_6.cc index edb9afea969..800ee536bbf 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_6.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_6.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc index faa5c19f5c0..d38cd566082 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_9.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc index 81b6f975e7f..4ac4b8ac8b7 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_3_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc index 2cb2d15ac93..d5f5dbea4b4 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc index a78eff3aa02..d50a6d4002b 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_6.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_6.cc index e2534f235b6..f79fa4dd2f0 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_6.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_6.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_8.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_8.cc index 296a46273bc..972b000f1ba 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_8.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_8.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_9.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_9.cc index 0d0b04e686c..aa33e479bc5 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_9.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_9.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc index 797992660d7..a28ef15a522 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_4_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc index 189be043af8..43924279a39 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_2_d_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_3_3_3.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_3_3_3.cc index 35c14a8f4bd..7ff2a62341c 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_3_3_3.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_3_3_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc index 878500a2100..9008b816843 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_2.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc index c4b0959db6a..8e37df51bee 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_3.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc index 20df5343335..09d50813a8a 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_4.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc index 17368dca4f6..089df2d7e3e 100644 --- a/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc +++ b/extern/ceres/internal/ceres/generated/schur_eliminator_4_4_d.cc @@ -40,7 +40,7 @@ // This file is generated using generate_template_specializations.py. // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION diff --git a/extern/ceres/internal/ceres/gradient_checker.cc b/extern/ceres/internal/ceres/gradient_checker.cc index dadaaa08734..777001e013c 100644 --- a/extern/ceres/internal/ceres/gradient_checker.cc +++ b/extern/ceres/internal/ceres/gradient_checker.cc @@ -40,6 +40,7 @@ #include <vector> #include "ceres/is_close.h" +#include "ceres/manifold_adapter.h" #include "ceres/stringprintf.h" #include "ceres/types.h" @@ -53,15 +54,13 @@ using std::vector; namespace { // Evaluate the cost function and transform the returned Jacobians to -// the local space of the respective local parameterizations. -bool EvaluateCostFunction( - const ceres::CostFunction* function, - double const* const* parameters, - const std::vector<const ceres::LocalParameterization*>& - local_parameterizations, - Vector* residuals, - std::vector<Matrix>* jacobians, - std::vector<Matrix>* local_jacobians) { +// the tangent space of the respective local parameterizations. +bool EvaluateCostFunction(const CostFunction* function, + double const* const* parameters, + const std::vector<const Manifold*>& manifolds, + Vector* residuals, + std::vector<Matrix>* jacobians, + std::vector<Matrix>* local_jacobians) { CHECK(residuals != nullptr); CHECK(jacobians != nullptr); CHECK(local_jacobians != nullptr); @@ -69,20 +68,20 @@ bool EvaluateCostFunction( const vector<int32_t>& block_sizes = function->parameter_block_sizes(); const int num_parameter_blocks = block_sizes.size(); - // Allocate Jacobian matrices in local space. + // Allocate Jacobian matrices in tangent space. local_jacobians->resize(num_parameter_blocks); vector<double*> local_jacobian_data(num_parameter_blocks); for (int i = 0; i < num_parameter_blocks; ++i) { int block_size = block_sizes.at(i); - if (local_parameterizations.at(i) != NULL) { - block_size = local_parameterizations.at(i)->LocalSize(); + if (manifolds.at(i) != nullptr) { + block_size = manifolds.at(i)->TangentSize(); } local_jacobians->at(i).resize(function->num_residuals(), block_size); local_jacobians->at(i).setZero(); local_jacobian_data.at(i) = local_jacobians->at(i).data(); } - // Allocate Jacobian matrices in global space. + // Allocate Jacobian matrices in ambient space. jacobians->resize(num_parameter_blocks); vector<double*> jacobian_data(num_parameter_blocks); for (int i = 0; i < num_parameter_blocks; ++i) { @@ -100,18 +99,17 @@ bool EvaluateCostFunction( return false; } - // Convert Jacobians from global to local space. + // Convert Jacobians from ambient to local space. for (size_t i = 0; i < local_jacobians->size(); ++i) { - if (local_parameterizations.at(i) == NULL) { + if (manifolds.at(i) == nullptr) { local_jacobians->at(i) = jacobians->at(i); } else { - int global_size = local_parameterizations.at(i)->GlobalSize(); - int local_size = local_parameterizations.at(i)->LocalSize(); - CHECK_EQ(jacobians->at(i).cols(), global_size); - Matrix global_J_local(global_size, local_size); - local_parameterizations.at(i)->ComputeJacobian(parameters[i], - global_J_local.data()); - local_jacobians->at(i).noalias() = jacobians->at(i) * global_J_local; + int ambient_size = manifolds.at(i)->AmbientSize(); + int tangent_size = manifolds.at(i)->TangentSize(); + CHECK_EQ(jacobians->at(i).cols(), ambient_size); + Matrix ambient_J_tangent(ambient_size, tangent_size); + manifolds.at(i)->PlusJacobian(parameters[i], ambient_J_tangent.data()); + local_jacobians->at(i).noalias() = jacobians->at(i) * ambient_J_tangent; } } return true; @@ -122,20 +120,47 @@ GradientChecker::GradientChecker( const CostFunction* function, const vector<const LocalParameterization*>* local_parameterizations, const NumericDiffOptions& options) + : delete_manifolds_(true), function_(function) { + CHECK(function != nullptr); + manifolds_.resize(function->parameter_block_sizes().size(), nullptr); + + // Wrap the local parameterization into manifold objects using + // ManifoldAdapter. + for (int i = 0; i < manifolds_.size(); ++i) { + const LocalParameterization* local_param = local_parameterizations->at(i); + if (local_param == nullptr) { + continue; + } + manifolds_[i] = new internal::ManifoldAdapter(local_param); + } + + auto finite_diff_cost_function = + std::make_unique<DynamicNumericDiffCostFunction<CostFunction, RIDDERS>>( + function, DO_NOT_TAKE_OWNERSHIP, options); + const vector<int32_t>& parameter_block_sizes = + function->parameter_block_sizes(); + for (int32_t parameter_block_size : parameter_block_sizes) { + finite_diff_cost_function->AddParameterBlock(parameter_block_size); + } + finite_diff_cost_function->SetNumResiduals(function->num_residuals()); + + finite_diff_cost_function_ = std::move(finite_diff_cost_function); +} + +GradientChecker::GradientChecker(const CostFunction* function, + const vector<const Manifold*>* manifolds, + const NumericDiffOptions& options) : function_(function) { CHECK(function != nullptr); - if (local_parameterizations != NULL) { - local_parameterizations_ = *local_parameterizations; + if (manifolds != nullptr) { + manifolds_ = *manifolds; } else { - local_parameterizations_.resize(function->parameter_block_sizes().size(), - NULL); + manifolds_.resize(function->parameter_block_sizes().size(), nullptr); } - DynamicNumericDiffCostFunction<CostFunction, RIDDERS>* - finite_diff_cost_function = - new DynamicNumericDiffCostFunction<CostFunction, RIDDERS>( - function, DO_NOT_TAKE_OWNERSHIP, options); - finite_diff_cost_function_.reset(finite_diff_cost_function); + auto finite_diff_cost_function = + std::make_unique<DynamicNumericDiffCostFunction<CostFunction, RIDDERS>>( + function, DO_NOT_TAKE_OWNERSHIP, options); const vector<int32_t>& parameter_block_sizes = function->parameter_block_sizes(); const int num_parameter_blocks = parameter_block_sizes.size(); @@ -143,6 +168,16 @@ GradientChecker::GradientChecker( finite_diff_cost_function->AddParameterBlock(parameter_block_sizes[i]); } finite_diff_cost_function->SetNumResiduals(function->num_residuals()); + + finite_diff_cost_function_ = std::move(finite_diff_cost_function); +} + +GradientChecker::~GradientChecker() { + if (delete_manifolds_) { + for (const auto m : manifolds_) { + delete m; + } + } } bool GradientChecker::Probe(double const* const* parameters, @@ -154,7 +189,7 @@ bool GradientChecker::Probe(double const* const* parameters, // provided an output argument. ProbeResults* results; ProbeResults results_local; - if (results_param != NULL) { + if (results_param != nullptr) { results = results_param; results->residuals.resize(0); results->jacobians.clear(); @@ -173,7 +208,7 @@ bool GradientChecker::Probe(double const* const* parameters, vector<Matrix>& local_jacobians = results->local_jacobians; if (!EvaluateCostFunction(function_, parameters, - local_parameterizations_, + manifolds_, &results->residuals, &jacobians, &local_jacobians)) { @@ -187,7 +222,7 @@ bool GradientChecker::Probe(double const* const* parameters, Vector finite_diff_residuals; if (!EvaluateCostFunction(finite_diff_cost_function_.get(), parameters, - local_parameterizations_, + manifolds_, &finite_diff_residuals, &numeric_jacobians, &local_numeric_jacobians)) { @@ -205,8 +240,8 @@ bool GradientChecker::Probe(double const* const* parameters, if (!IsClose(results->residuals[i], finite_diff_residuals[i], relative_precision, - NULL, - NULL)) { + nullptr, + nullptr)) { results->error_log = "Function evaluation with and without Jacobians " "resulted in different residuals."; diff --git a/extern/ceres/internal/ceres/gradient_checking_cost_function.cc b/extern/ceres/internal/ceres/gradient_checking_cost_function.cc index 2eb6d627167..1c3b318ed04 100644 --- a/extern/ceres/internal/ceres/gradient_checking_cost_function.cc +++ b/extern/ceres/internal/ceres/gradient_checking_cost_function.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -34,8 +34,10 @@ #include <algorithm> #include <cmath> #include <cstdint> +#include <memory> #include <numeric> #include <string> +#include <utility> #include <vector> #include "ceres/dynamic_numeric_diff_cost_function.h" @@ -60,19 +62,18 @@ using std::vector; namespace { -class GradientCheckingCostFunction : public CostFunction { +class GradientCheckingCostFunction final : public CostFunction { public: - GradientCheckingCostFunction( - const CostFunction* function, - const std::vector<const LocalParameterization*>* local_parameterizations, - const NumericDiffOptions& options, - double relative_precision, - const string& extra_info, - GradientCheckingIterationCallback* callback) + GradientCheckingCostFunction(const CostFunction* function, + const std::vector<const Manifold*>* manifolds, + const NumericDiffOptions& options, + double relative_precision, + string extra_info, + GradientCheckingIterationCallback* callback) : function_(function), - gradient_checker_(function, local_parameterizations, options), + gradient_checker_(function, manifolds, options), relative_precision_(relative_precision), - extra_info_(extra_info), + extra_info_(std::move(extra_info)), callback_(callback) { CHECK(callback_ != nullptr); const vector<int32_t>& parameter_block_sizes = @@ -81,14 +82,12 @@ class GradientCheckingCostFunction : public CostFunction { set_num_residuals(function->num_residuals()); } - virtual ~GradientCheckingCostFunction() {} - bool Evaluate(double const* const* parameters, double* residuals, double** jacobians) const final { if (!jacobians) { // Nothing to check in this case; just forward. - return function_->Evaluate(parameters, residuals, NULL); + return function_->Evaluate(parameters, residuals, nullptr); } GradientChecker::ProbeResults results; @@ -108,7 +107,7 @@ class GradientCheckingCostFunction : public CostFunction { // Copy the original jacobian blocks into the jacobians array. const vector<int32_t>& block_sizes = function_->parameter_block_sizes(); for (int k = 0; k < block_sizes.size(); k++) { - if (jacobians[k] != NULL) { + if (jacobians[k] != nullptr) { MatrixRef(jacobians[k], results.jacobians[k].rows(), results.jacobians[k].cols()) = results.jacobians[k]; @@ -145,6 +144,7 @@ CallbackReturnType GradientCheckingIterationCallback::operator()( } return SOLVER_CONTINUE; } + void GradientCheckingIterationCallback::SetGradientErrorDetected( std::string& error_log) { std::lock_guard<std::mutex> l(mutex_); @@ -152,9 +152,9 @@ void GradientCheckingIterationCallback::SetGradientErrorDetected( error_log_ += "\n" + error_log; } -CostFunction* CreateGradientCheckingCostFunction( +std::unique_ptr<CostFunction> CreateGradientCheckingCostFunction( const CostFunction* cost_function, - const std::vector<const LocalParameterization*>* local_parameterizations, + const std::vector<const Manifold*>* manifolds, double relative_step_size, double relative_precision, const std::string& extra_info, @@ -162,51 +162,48 @@ CostFunction* CreateGradientCheckingCostFunction( NumericDiffOptions numeric_diff_options; numeric_diff_options.relative_step_size = relative_step_size; - return new GradientCheckingCostFunction(cost_function, - local_parameterizations, - numeric_diff_options, - relative_precision, - extra_info, - callback); + return std::make_unique<GradientCheckingCostFunction>(cost_function, + manifolds, + numeric_diff_options, + relative_precision, + extra_info, + callback); } -ProblemImpl* CreateGradientCheckingProblemImpl( +std::unique_ptr<ProblemImpl> CreateGradientCheckingProblemImpl( ProblemImpl* problem_impl, double relative_step_size, double relative_precision, GradientCheckingIterationCallback* callback) { CHECK(callback != nullptr); - // We create new CostFunctions by wrapping the original CostFunction - // in a gradient checking CostFunction. So its okay for the - // ProblemImpl to take ownership of it and destroy it. The - // LossFunctions and LocalParameterizations are reused and since - // they are owned by problem_impl, gradient_checking_problem_impl + // We create new CostFunctions by wrapping the original CostFunction in a + // gradient checking CostFunction. So its okay for the ProblemImpl to take + // ownership of it and destroy it. The LossFunctions and Manifolds are reused + // and since they are owned by problem_impl, gradient_checking_problem_impl // should not take ownership of it. Problem::Options gradient_checking_problem_options; gradient_checking_problem_options.cost_function_ownership = TAKE_OWNERSHIP; gradient_checking_problem_options.loss_function_ownership = DO_NOT_TAKE_OWNERSHIP; - gradient_checking_problem_options.local_parameterization_ownership = - DO_NOT_TAKE_OWNERSHIP; + gradient_checking_problem_options.manifold_ownership = DO_NOT_TAKE_OWNERSHIP; gradient_checking_problem_options.context = problem_impl->context(); NumericDiffOptions numeric_diff_options; numeric_diff_options.relative_step_size = relative_step_size; - ProblemImpl* gradient_checking_problem_impl = - new ProblemImpl(gradient_checking_problem_options); + auto gradient_checking_problem_impl = + std::make_unique<ProblemImpl>(gradient_checking_problem_options); Program* program = problem_impl->mutable_program(); - // For every ParameterBlock in problem_impl, create a new parameter - // block with the same local parameterization and constancy. + // For every ParameterBlock in problem_impl, create a new parameter block with + // the same manifold and constancy. const vector<ParameterBlock*>& parameter_blocks = program->parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks[i]; + for (auto* parameter_block : parameter_blocks) { gradient_checking_problem_impl->AddParameterBlock( parameter_block->mutable_user_state(), parameter_block->Size(), - parameter_block->mutable_local_parameterization()); + parameter_block->mutable_manifold()); if (parameter_block->IsConstant()) { gradient_checking_problem_impl->SetParameterBlockConstant( @@ -238,22 +235,22 @@ ProblemImpl* CreateGradientCheckingProblemImpl( string extra_info = StringPrintf("Residual block id %d; depends on parameters [", i); vector<double*> parameter_blocks; - vector<const LocalParameterization*> local_parameterizations; + vector<const Manifold*> manifolds; parameter_blocks.reserve(residual_block->NumParameterBlocks()); - local_parameterizations.reserve(residual_block->NumParameterBlocks()); + manifolds.reserve(residual_block->NumParameterBlocks()); for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; parameter_blocks.push_back(parameter_block->mutable_user_state()); StringAppendF(&extra_info, "%p", parameter_block->mutable_user_state()); extra_info += (j < residual_block->NumParameterBlocks() - 1) ? ", " : "]"; - local_parameterizations.push_back(problem_impl->GetParameterization( - parameter_block->mutable_user_state())); + manifolds.push_back( + problem_impl->GetManifold(parameter_block->mutable_user_state())); } // Wrap the original CostFunction in a GradientCheckingCostFunction. CostFunction* gradient_checking_cost_function = new GradientCheckingCostFunction(residual_block->cost_function(), - &local_parameterizations, + &manifolds, numeric_diff_options, relative_precision, extra_info, diff --git a/extern/ceres/internal/ceres/gradient_checking_cost_function.h b/extern/ceres/internal/ceres/gradient_checking_cost_function.h index ea6e9b31c8c..0caafafa8fa 100644 --- a/extern/ceres/internal/ceres/gradient_checking_cost_function.h +++ b/extern/ceres/internal/ceres/gradient_checking_cost_function.h @@ -32,13 +32,15 @@ #ifndef CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ #define CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ +#include <memory> #include <mutex> #include <string> #include "ceres/cost_function.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/iteration_callback.h" -#include "ceres/local_parameterization.h" +#include "ceres/manifold.h" namespace ceres { namespace internal { @@ -47,7 +49,7 @@ class ProblemImpl; // Callback that collects information about gradient checking errors, and // will abort the solve as soon as an error occurs. -class CERES_EXPORT_INTERNAL GradientCheckingIterationCallback +class CERES_NO_EXPORT GradientCheckingIterationCallback : public IterationCallback { public: GradientCheckingIterationCallback(); @@ -73,9 +75,10 @@ class CERES_EXPORT_INTERNAL GradientCheckingIterationCallback // with finite differences. This API is only intended for unit tests that intend // to check the functionality of the GradientCheckingCostFunction // implementation directly. -CERES_EXPORT_INTERNAL CostFunction* CreateGradientCheckingCostFunction( +CERES_NO_EXPORT std::unique_ptr<CostFunction> +CreateGradientCheckingCostFunction( const CostFunction* cost_function, - const std::vector<const LocalParameterization*>* local_parameterizations, + const std::vector<const Manifold*>* manifolds, double relative_step_size, double relative_precision, const std::string& extra_info, @@ -92,8 +95,6 @@ CERES_EXPORT_INTERNAL CostFunction* CreateGradientCheckingCostFunction( // iteration, the respective cost function will notify the // GradientCheckingIterationCallback. // -// The caller owns the returned ProblemImpl object. -// // Note: This is quite inefficient and is intended only for debugging. // // relative_step_size and relative_precision are parameters to control @@ -102,7 +103,7 @@ CERES_EXPORT_INTERNAL CostFunction* CreateGradientCheckingCostFunction( // jacobians obtained by numerically differentiating them. See the // documentation of 'numeric_derivative_relative_step_size' in solver.h for a // better explanation. -CERES_EXPORT_INTERNAL ProblemImpl* CreateGradientCheckingProblemImpl( +CERES_NO_EXPORT std::unique_ptr<ProblemImpl> CreateGradientCheckingProblemImpl( ProblemImpl* problem_impl, double relative_step_size, double relative_precision, @@ -111,4 +112,6 @@ CERES_EXPORT_INTERNAL ProblemImpl* CreateGradientCheckingProblemImpl( } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_GRADIENT_CHECKING_COST_FUNCTION_H_ diff --git a/extern/ceres/internal/ceres/gradient_problem.cc b/extern/ceres/internal/ceres/gradient_problem.cc index ba33fbc90f8..cdd472fe87f 100644 --- a/extern/ceres/internal/ceres/gradient_problem.cc +++ b/extern/ceres/internal/ceres/gradient_problem.cc @@ -30,49 +30,75 @@ #include "ceres/gradient_problem.h" +#include <memory> + #include "ceres/local_parameterization.h" +#include "ceres/manifold_adapter.h" #include "glog/logging.h" namespace ceres { GradientProblem::GradientProblem(FirstOrderFunction* function) : function_(function), - parameterization_( - new IdentityParameterization(function_->NumParameters())), - scratch_(new double[function_->NumParameters()]) {} + manifold_(std::make_unique<EuclideanManifold<DYNAMIC>>( + function_->NumParameters())), + scratch_(new double[function_->NumParameters()]) { + CHECK(function != nullptr); +} GradientProblem::GradientProblem(FirstOrderFunction* function, LocalParameterization* parameterization) : function_(function), parameterization_(parameterization), scratch_(new double[function_->NumParameters()]) { - CHECK_EQ(function_->NumParameters(), parameterization_->GlobalSize()); + CHECK(function != nullptr); + if (parameterization != nullptr) { + manifold_ = + std::make_unique<internal::ManifoldAdapter>(parameterization_.get()); + } else { + manifold_ = std::make_unique<EuclideanManifold<DYNAMIC>>( + function_->NumParameters()); + } + CHECK_EQ(function_->NumParameters(), manifold_->AmbientSize()); +} + +GradientProblem::GradientProblem(FirstOrderFunction* function, + Manifold* manifold) + : function_(function), scratch_(new double[function_->NumParameters()]) { + CHECK(function != nullptr); + if (manifold != nullptr) { + manifold_.reset(manifold); + } else { + manifold_ = std::make_unique<EuclideanManifold<DYNAMIC>>( + function_->NumParameters()); + } + CHECK_EQ(function_->NumParameters(), manifold_->AmbientSize()); } int GradientProblem::NumParameters() const { return function_->NumParameters(); } -int GradientProblem::NumLocalParameters() const { - return parameterization_->LocalSize(); +int GradientProblem::NumTangentParameters() const { + return manifold_->TangentSize(); } bool GradientProblem::Evaluate(const double* parameters, double* cost, double* gradient) const { - if (gradient == NULL) { - return function_->Evaluate(parameters, cost, NULL); + if (gradient == nullptr) { + return function_->Evaluate(parameters, cost, nullptr); } return (function_->Evaluate(parameters, cost, scratch_.get()) && - parameterization_->MultiplyByJacobian( + manifold_->RightMultiplyByPlusJacobian( parameters, 1, scratch_.get(), gradient)); } bool GradientProblem::Plus(const double* x, const double* delta, double* x_plus_delta) const { - return parameterization_->Plus(x, delta, x_plus_delta); + return manifold_->Plus(x, delta, x_plus_delta); } } // namespace ceres diff --git a/extern/ceres/internal/ceres/gradient_problem_evaluator.h b/extern/ceres/internal/ceres/gradient_problem_evaluator.h index d224dbed0ae..efbb257ec75 100644 --- a/extern/ceres/internal/ceres/gradient_problem_evaluator.h +++ b/extern/ceres/internal/ceres/gradient_problem_evaluator.h @@ -32,30 +32,34 @@ #define CERES_INTERNAL_GRADIENT_PROBLEM_EVALUATOR_H_ #include <map> +#include <memory> #include <string> #include "ceres/evaluator.h" #include "ceres/execution_summary.h" #include "ceres/gradient_problem.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" +#include "ceres/sparse_matrix.h" #include "ceres/wall_time.h" namespace ceres { namespace internal { -class GradientProblemEvaluator : public Evaluator { +class CERES_NO_EXPORT GradientProblemEvaluator final : public Evaluator { public: explicit GradientProblemEvaluator(const GradientProblem& problem) : problem_(problem) {} - virtual ~GradientProblemEvaluator() {} - SparseMatrix* CreateJacobian() const final { return nullptr; } + + std::unique_ptr<SparseMatrix> CreateJacobian() const final { return nullptr; } + bool Evaluate(const EvaluateOptions& evaluate_options, const double* state, double* cost, double* residuals, double* gradient, SparseMatrix* jacobian) final { - CHECK(jacobian == NULL); + CHECK(jacobian == nullptr); ScopedExecutionTimer total_timer("Evaluator::Total", &execution_summary_); // The reason we use Residual and Jacobian here even when we are // only computing the cost and gradient has to do with the fact @@ -65,7 +69,7 @@ class GradientProblemEvaluator : public Evaluator { // to be consistent across the code base for the time accounting // to work. ScopedExecutionTimer call_type_timer( - gradient == NULL ? "Evaluator::Residual" : "Evaluator::Jacobian", + gradient == nullptr ? "Evaluator::Residual" : "Evaluator::Jacobian", &execution_summary_); return problem_.Evaluate(state, cost, gradient); } @@ -96,4 +100,6 @@ class GradientProblemEvaluator : public Evaluator { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_GRADIENT_PROBLEM_EVALUATOR_H_ diff --git a/extern/ceres/internal/ceres/gradient_problem_solver.cc b/extern/ceres/internal/ceres/gradient_problem_solver.cc index b72fad91542..9382556d292 100644 --- a/extern/ceres/internal/ceres/gradient_problem_solver.cc +++ b/extern/ceres/internal/ceres/gradient_problem_solver.cc @@ -36,7 +36,7 @@ #include "ceres/gradient_problem.h" #include "ceres/gradient_problem_evaluator.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/map_util.h" #include "ceres/minimizer.h" #include "ceres/solver.h" @@ -92,7 +92,7 @@ bool GradientProblemSolver::Options::IsValid(std::string* error) const { return solver_options.IsValid(error); } -GradientProblemSolver::~GradientProblemSolver() {} +GradientProblemSolver::~GradientProblemSolver() = default; void GradientProblemSolver::Solve(const GradientProblemSolver::Options& options, const GradientProblem& problem, @@ -135,21 +135,22 @@ void GradientProblemSolver::Solve(const GradientProblemSolver::Options& options, // now. Minimizer::Options minimizer_options = Minimizer::Options(GradientProblemSolverOptionsToSolverOptions(options)); - minimizer_options.evaluator.reset(new GradientProblemEvaluator(problem)); + minimizer_options.evaluator = + std::make_unique<GradientProblemEvaluator>(problem); std::unique_ptr<IterationCallback> logging_callback; if (options.logging_type != SILENT) { - logging_callback.reset( - new LoggingCallback(LINE_SEARCH, options.minimizer_progress_to_stdout)); + logging_callback = std::make_unique<LoggingCallback>( + LINE_SEARCH, options.minimizer_progress_to_stdout); minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), logging_callback.get()); } std::unique_ptr<IterationCallback> state_updating_callback; if (options.update_state_every_iteration) { - state_updating_callback.reset( - new GradientProblemSolverStateUpdatingCallback( - problem.NumParameters(), solution.data(), parameters_ptr)); + state_updating_callback = + std::make_unique<GradientProblemSolverStateUpdatingCallback>( + problem.NumParameters(), solution.data(), parameters_ptr); minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), state_updating_callback.get()); } diff --git a/extern/ceres/internal/ceres/graph.h b/extern/ceres/internal/ceres/graph.h index 9b26158753f..6a6f8f01c00 100644 --- a/extern/ceres/internal/ceres/graph.h +++ b/extern/ceres/internal/ceres/graph.h @@ -36,6 +36,7 @@ #include <unordered_set> #include <utility> +#include "ceres/internal/export.h" #include "ceres/map_util.h" #include "ceres/pair_hash.h" #include "ceres/types.h" @@ -47,10 +48,8 @@ namespace internal { // A unweighted undirected graph templated over the vertex ids. Vertex // should be hashable. template <typename Vertex> -class Graph { +class CERES_NO_EXPORT Graph { public: - Graph() {} - // Add a vertex. void AddVertex(const Vertex& vertex) { if (vertices_.insert(vertex).second) { @@ -106,8 +105,6 @@ class Graph { template <typename Vertex> class WeightedGraph { public: - WeightedGraph() {} - // Add a weighted vertex. If the vertex already exists in the graph, // its weight is set to the new weight. void AddVertex(const Vertex& vertex, double weight) { diff --git a/extern/ceres/internal/ceres/graph_algorithms.h b/extern/ceres/internal/ceres/graph_algorithms.h index 7d63b337f68..5299f80d963 100644 --- a/extern/ceres/internal/ceres/graph_algorithms.h +++ b/extern/ceres/internal/ceres/graph_algorithms.h @@ -34,12 +34,14 @@ #define CERES_INTERNAL_GRAPH_ALGORITHMS_H_ #include <algorithm> +#include <memory> #include <unordered_map> #include <unordered_set> #include <utility> #include <vector> #include "ceres/graph.h" +#include "ceres/internal/export.h" #include "ceres/wall_time.h" #include "glog/logging.h" @@ -49,7 +51,7 @@ namespace internal { // Compare two vertices of a graph by their degrees, if the degrees // are equal then order them by their ids. template <typename Vertex> -class VertexTotalOrdering { +class CERES_NO_EXPORT VertexTotalOrdering { public: explicit VertexTotalOrdering(const Graph<Vertex>& graph) : graph_(graph) {} @@ -257,11 +259,11 @@ Vertex FindConnectedComponent(const Vertex& vertex, // spanning forest, or a collection of linear paths that span the // graph G. template <typename Vertex> -WeightedGraph<Vertex>* Degree2MaximumSpanningForest( +std::unique_ptr<WeightedGraph<Vertex>> Degree2MaximumSpanningForest( const WeightedGraph<Vertex>& graph) { // Array of edges sorted in decreasing order of their weights. std::vector<std::pair<double, std::pair<Vertex, Vertex>>> weighted_edges; - WeightedGraph<Vertex>* forest = new WeightedGraph<Vertex>(); + auto forest = std::make_unique<WeightedGraph<Vertex>>(); // Disjoint-set to keep track of the connected components in the // maximum spanning tree. diff --git a/extern/ceres/internal/ceres/implicit_schur_complement.cc b/extern/ceres/internal/ceres/implicit_schur_complement.cc index f2196d4ef9c..677d767fa93 100644 --- a/extern/ceres/internal/ceres/implicit_schur_complement.cc +++ b/extern/ceres/internal/ceres/implicit_schur_complement.cc @@ -43,17 +43,15 @@ namespace internal { ImplicitSchurComplement::ImplicitSchurComplement( const LinearSolver::Options& options) - : options_(options), D_(NULL), b_(NULL) {} - -ImplicitSchurComplement::~ImplicitSchurComplement() {} + : options_(options), D_(nullptr), b_(nullptr) {} void ImplicitSchurComplement::Init(const BlockSparseMatrix& A, const double* D, const double* b) { // Since initialization is reasonably heavy, perhaps we can save on // constructing a new object everytime. - if (A_ == NULL) { - A_.reset(PartitionedMatrixViewBase::Create(options_, A)); + if (A_ == nullptr) { + A_ = PartitionedMatrixViewBase::Create(options_, A); } D_ = D; @@ -61,10 +59,10 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A, // Initialize temporary storage and compute the block diagonals of // E'E and F'E. - if (block_diagonal_EtE_inverse_ == NULL) { - block_diagonal_EtE_inverse_.reset(A_->CreateBlockDiagonalEtE()); + if (block_diagonal_EtE_inverse_ == nullptr) { + block_diagonal_EtE_inverse_ = A_->CreateBlockDiagonalEtE(); if (options_.preconditioner_type == JACOBI) { - block_diagonal_FtF_inverse_.reset(A_->CreateBlockDiagonalFtF()); + block_diagonal_FtF_inverse_ = A_->CreateBlockDiagonalFtF(); } rhs_.resize(A_->num_cols_f()); rhs_.setZero(); @@ -84,7 +82,7 @@ void ImplicitSchurComplement::Init(const BlockSparseMatrix& A, // the block diagonals and invert them. AddDiagonalAndInvert(D_, block_diagonal_EtE_inverse_.get()); if (options_.preconditioner_type == JACOBI) { - AddDiagonalAndInvert((D_ == NULL) ? NULL : D_ + A_->num_cols_e(), + AddDiagonalAndInvert((D_ == nullptr) ? nullptr : D_ + A_->num_cols_e(), block_diagonal_FtF_inverse_.get()); } @@ -118,7 +116,7 @@ void ImplicitSchurComplement::RightMultiply(const double* x, double* y) const { A_->RightMultiplyE(tmp_e_cols_2_.data(), tmp_rows_.data()); // y5 = D * x - if (D_ != NULL) { + if (D_ != nullptr) { ConstVectorRef Dref(D_ + A_->num_cols_e(), num_cols()); VectorRef(y, num_cols()) = (Dref.array().square() * ConstVectorRef(x, num_cols()).array()) @@ -138,15 +136,15 @@ void ImplicitSchurComplement::AddDiagonalAndInvert( const double* D, BlockSparseMatrix* block_diagonal) { const CompressedRowBlockStructure* block_diagonal_structure = block_diagonal->block_structure(); - for (int r = 0; r < block_diagonal_structure->rows.size(); ++r) { - const int row_block_pos = block_diagonal_structure->rows[r].block.position; - const int row_block_size = block_diagonal_structure->rows[r].block.size; - const Cell& cell = block_diagonal_structure->rows[r].cells[0]; + for (const auto& row : block_diagonal_structure->rows) { + const int row_block_pos = row.block.position; + const int row_block_size = row.block.size; + const Cell& cell = row.cells[0]; MatrixRef m(block_diagonal->mutable_values() + cell.position, row_block_size, row_block_size); - if (D != NULL) { + if (D != nullptr) { ConstVectorRef d(D + row_block_pos, row_block_size); m += d.array().square().matrix().asDiagonal(); } diff --git a/extern/ceres/internal/ceres/implicit_schur_complement.h b/extern/ceres/internal/ceres/implicit_schur_complement.h index e83892af017..598d48411aa 100644 --- a/extern/ceres/internal/ceres/implicit_schur_complement.h +++ b/extern/ceres/internal/ceres/implicit_schur_complement.h @@ -36,8 +36,9 @@ #include <memory> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_operator.h" #include "ceres/linear_solver.h" #include "ceres/partitioned_matrix_view.h" @@ -88,7 +89,7 @@ class BlockSparseMatrix; // RightMultiply (and the LeftMultiply) methods are not thread safe as // they depend on mutable arrays used for the temporaries needed to // compute the product y += Sx; -class CERES_EXPORT_INTERNAL ImplicitSchurComplement : public LinearOperator { +class CERES_NO_EXPORT ImplicitSchurComplement final : public LinearOperator { public: // num_eliminate_blocks is the number of E blocks in the matrix // A. @@ -100,7 +101,6 @@ class CERES_EXPORT_INTERNAL ImplicitSchurComplement : public LinearOperator { // TODO(sameeragarwal): Get rid of the two bools below and replace // them with enums. explicit ImplicitSchurComplement(const LinearSolver::Options& options); - virtual ~ImplicitSchurComplement(); // Initialize the Schur complement for a linear least squares // problem of the form @@ -166,4 +166,6 @@ class CERES_EXPORT_INTERNAL ImplicitSchurComplement : public LinearOperator { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_IMPLICIT_SCHUR_COMPLEMENT_H_ diff --git a/extern/ceres/internal/ceres/inner_product_computer.cc b/extern/ceres/internal/ceres/inner_product_computer.cc index ef38b7b3ad4..fbc43bfed8b 100644 --- a/extern/ceres/internal/ceres/inner_product_computer.cc +++ b/extern/ceres/internal/ceres/inner_product_computer.cc @@ -31,6 +31,7 @@ #include "ceres/inner_product_computer.h" #include <algorithm> +#include <memory> #include "ceres/small_blas.h" @@ -44,11 +45,12 @@ namespace internal { // or the lower triangular part of the product. // // num_nonzeros is the number of non-zeros in the result matrix. -CompressedRowSparseMatrix* InnerProductComputer::CreateResultMatrix( +std::unique_ptr<CompressedRowSparseMatrix> +InnerProductComputer::CreateResultMatrix( const CompressedRowSparseMatrix::StorageType storage_type, const int num_nonzeros) { - CompressedRowSparseMatrix* matrix = - new CompressedRowSparseMatrix(m_.num_cols(), m_.num_cols(), num_nonzeros); + auto matrix = std::make_unique<CompressedRowSparseMatrix>( + m_.num_cols(), m_.num_cols(), num_nonzeros); matrix->set_storage_type(storage_type); const CompressedRowBlockStructure* bs = m_.block_structure(); @@ -116,14 +118,14 @@ InnerProductComputer::InnerProductComputer(const BlockSparseMatrix& m, // // product_storage_type controls the form of the output matrix. It // can be LOWER_TRIANGULAR or UPPER_TRIANGULAR. -InnerProductComputer* InnerProductComputer::Create( +std::unique_ptr<InnerProductComputer> InnerProductComputer::Create( const BlockSparseMatrix& m, CompressedRowSparseMatrix::StorageType product_storage_type) { return InnerProductComputer::Create( m, 0, m.block_structure()->rows.size(), product_storage_type); } -InnerProductComputer* InnerProductComputer::Create( +std::unique_ptr<InnerProductComputer> InnerProductComputer::Create( const BlockSparseMatrix& m, const int start_row_block, const int end_row_block, @@ -132,8 +134,8 @@ InnerProductComputer* InnerProductComputer::Create( product_storage_type == CompressedRowSparseMatrix::UPPER_TRIANGULAR); CHECK_GT(m.num_nonzeros(), 0) << "Congratulations, you found a bug in Ceres. Please report it."; - InnerProductComputer* inner_product_computer = - new InnerProductComputer(m, start_row_block, end_row_block); + std::unique_ptr<InnerProductComputer> inner_product_computer( + new InnerProductComputer(m, start_row_block, end_row_block)); inner_product_computer->Init(product_storage_type); return inner_product_computer; } @@ -165,8 +167,8 @@ void InnerProductComputer::Init( for (int c2 = c2_begin; c2 < c2_end; ++c2) { const Cell& cell2 = row.cells[c2]; - product_terms.push_back(InnerProductComputer::ProductTerm( - cell1.block_id, cell2.block_id, product_terms.size())); + product_terms.emplace_back( + cell1.block_id, cell2.block_id, product_terms.size()); } } } @@ -183,7 +185,7 @@ void InnerProductComputer::ComputeOffsetsAndCreateResultMatrix( std::vector<int> row_block_nnz; const int num_nonzeros = ComputeNonzeros(product_terms, &row_block_nnz); - result_.reset(CreateResultMatrix(product_storage_type, num_nonzeros)); + result_ = CreateResultMatrix(product_storage_type, num_nonzeros); // Populate the row non-zero counts in the result matrix. int* crsm_rows = result_->mutable_rows(); diff --git a/extern/ceres/internal/ceres/inner_product_computer.h b/extern/ceres/internal/ceres/inner_product_computer.h index 04ec1d18316..c6ed0b23e87 100644 --- a/extern/ceres/internal/ceres/inner_product_computer.h +++ b/extern/ceres/internal/ceres/inner_product_computer.h @@ -36,7 +36,8 @@ #include "ceres/block_sparse_matrix.h" #include "ceres/compressed_row_sparse_matrix.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -61,7 +62,7 @@ namespace internal { // This is not a problem as sparse linear algebra libraries can ignore // these entries with ease and the space used is minimal/linear in the // size of the matrices. -class CERES_EXPORT_INTERNAL InnerProductComputer { +class CERES_NO_EXPORT InnerProductComputer { public: // Factory // @@ -74,7 +75,7 @@ class CERES_EXPORT_INTERNAL InnerProductComputer { // // The user must ensure that the matrix m is valid for the life time // of this object. - static InnerProductComputer* Create( + static std::unique_ptr<InnerProductComputer> Create( const BlockSparseMatrix& m, CompressedRowSparseMatrix::StorageType storage_type); @@ -83,7 +84,7 @@ class CERES_EXPORT_INTERNAL InnerProductComputer { // // a = m(start_row_block : end_row_block, :); // result = a' * a; - static InnerProductComputer* Create( + static std::unique_ptr<InnerProductComputer> Create( const BlockSparseMatrix& m, int start_row_block, int end_row_block, @@ -127,7 +128,7 @@ class CERES_EXPORT_INTERNAL InnerProductComputer { void Init(CompressedRowSparseMatrix::StorageType storage_type); - CompressedRowSparseMatrix* CreateResultMatrix( + std::unique_ptr<CompressedRowSparseMatrix> CreateResultMatrix( const CompressedRowSparseMatrix::StorageType storage_type, int num_nonzeros); @@ -155,4 +156,6 @@ class CERES_EXPORT_INTERNAL InnerProductComputer { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_INNER_PRODUCT_COMPUTER_H_ diff --git a/extern/ceres/internal/ceres/is_close.h b/extern/ceres/internal/ceres/is_close.h index b781a4493ff..a1e4e2f6721 100644 --- a/extern/ceres/internal/ceres/is_close.h +++ b/extern/ceres/internal/ceres/is_close.h @@ -33,21 +33,24 @@ #ifndef CERES_INTERNAL_IS_CLOSE_H_ #define CERES_INTERNAL_IS_CLOSE_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { // Returns true if x and y have a relative (unsigned) difference less than // relative_precision and false otherwise. Stores the relative and absolute -// difference in relative/absolute_error if non-NULL. If one of the two values -// is exactly zero, the absolute difference will be compared, and relative_error -// will be set to the absolute difference. -CERES_EXPORT_INTERNAL bool IsClose(double x, - double y, - double relative_precision, - double* relative_error, - double* absolute_error); +// difference in relative/absolute_error if non-nullptr. If one of the two +// values is exactly zero, the absolute difference will be compared, and +// relative_error will be set to the absolute difference. +CERES_NO_EXPORT bool IsClose(double x, + double y, + double relative_precision, + double* relative_error, + double* absolute_error); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_IS_CLOSE_H_ diff --git a/extern/ceres/internal/ceres/blas.cc b/extern/ceres/internal/ceres/iteration_callback.cc index f8d006e3069..804811d2807 100644 --- a/extern/ceres/internal/ceres/blas.cc +++ b/extern/ceres/internal/ceres/iteration_callback.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2019 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -28,55 +28,10 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) -#include "ceres/blas.h" - -#include "ceres/internal/port.h" -#include "glog/logging.h" - -#ifndef CERES_NO_LAPACK -extern "C" void dsyrk_(char* uplo, - char* trans, - int* n, - int* k, - double* alpha, - double* a, - int* lda, - double* beta, - double* c, - int* ldc); -#endif +#include "ceres/iteration_callback.h" namespace ceres { -namespace internal { -void BLAS::SymmetricRankKUpdate(int num_rows, - int num_cols, - const double* a, - bool transpose, - double alpha, - double beta, - double* c) { -#ifdef CERES_NO_LAPACK - LOG(FATAL) << "Ceres was built without a BLAS library."; -#else - char uplo = 'L'; - char trans = transpose ? 'T' : 'N'; - int n = transpose ? num_cols : num_rows; - int k = transpose ? num_rows : num_cols; - int lda = k; - int ldc = n; - dsyrk_(&uplo, - &trans, - &n, - &k, - &alpha, - const_cast<double*>(a), - &lda, - &beta, - c, - &ldc); -#endif -} +IterationCallback::~IterationCallback() = default; -} // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/iterative_refiner.cc b/extern/ceres/internal/ceres/iterative_refiner.cc index 5f0bfdd250d..18154690597 100644 --- a/extern/ceres/internal/ceres/iterative_refiner.cc +++ b/extern/ceres/internal/ceres/iterative_refiner.cc @@ -42,7 +42,7 @@ namespace internal { IterativeRefiner::IterativeRefiner(const int max_num_iterations) : max_num_iterations_(max_num_iterations) {} -IterativeRefiner::~IterativeRefiner() {} +IterativeRefiner::~IterativeRefiner() = default; void IterativeRefiner::Allocate(int num_cols) { residual_.resize(num_cols); diff --git a/extern/ceres/internal/ceres/iterative_refiner.h b/extern/ceres/internal/ceres/iterative_refiner.h index 08f8d6762cf..837af178ab4 100644 --- a/extern/ceres/internal/ceres/iterative_refiner.h +++ b/extern/ceres/internal/ceres/iterative_refiner.h @@ -33,10 +33,11 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -57,11 +58,11 @@ class SparseMatrix; // Definite linear systems. // // The above iterative loop is run until max_num_iterations is reached. -class CERES_EXPORT_INTERNAL IterativeRefiner { +class CERES_NO_EXPORT IterativeRefiner { public: // max_num_iterations is the number of refinement iterations to // perform. - IterativeRefiner(int max_num_iterations); + explicit IterativeRefiner(int max_num_iterations); // Needed for mocking. virtual ~IterativeRefiner(); diff --git a/extern/ceres/internal/ceres/iterative_schur_complement_solver.cc b/extern/ceres/internal/ceres/iterative_schur_complement_solver.cc index 143df5e5814..bc22d68bc55 100644 --- a/extern/ceres/internal/ceres/iterative_schur_complement_solver.cc +++ b/extern/ceres/internal/ceres/iterative_schur_complement_solver.cc @@ -32,6 +32,7 @@ #include <algorithm> #include <cstring> +#include <utility> #include <vector> #include "Eigen/Dense" @@ -54,10 +55,10 @@ namespace ceres { namespace internal { IterativeSchurComplementSolver::IterativeSchurComplementSolver( - const LinearSolver::Options& options) - : options_(options) {} + LinearSolver::Options options) + : options_(std::move(options)) {} -IterativeSchurComplementSolver::~IterativeSchurComplementSolver() {} +IterativeSchurComplementSolver::~IterativeSchurComplementSolver() = default; LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( BlockSparseMatrix* A, @@ -69,13 +70,13 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( CHECK(A->block_structure() != nullptr); const int num_eliminate_blocks = options_.elimination_groups[0]; // Initialize a ImplicitSchurComplement object. - if (schur_complement_ == NULL) { + if (schur_complement_ == nullptr) { DetectStructure(*(A->block_structure()), num_eliminate_blocks, &options_.row_block_size, &options_.e_block_size, &options_.f_block_size); - schur_complement_.reset(new ImplicitSchurComplement(options_)); + schur_complement_ = std::make_unique<ImplicitSchurComplement>(options_); } schur_complement_->Init(*A, per_solve_options.D, b); @@ -86,7 +87,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( LinearSolver::Summary summary; summary.num_iterations = 0; summary.termination_type = LINEAR_SOLVER_SUCCESS; - schur_complement_->BackSubstitute(NULL, x); + schur_complement_->BackSubstitute(nullptr, x); return summary; } @@ -104,7 +105,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( cg_per_solve_options.q_tolerance = per_solve_options.q_tolerance; CreatePreconditioner(A); - if (preconditioner_.get() != NULL) { + if (preconditioner_.get() != nullptr) { if (!preconditioner_->Update(*A, per_solve_options.D)) { LinearSolver::Summary summary; summary.num_iterations = 0; @@ -134,7 +135,7 @@ LinearSolver::Summary IterativeSchurComplementSolver::SolveImpl( void IterativeSchurComplementSolver::CreatePreconditioner( BlockSparseMatrix* A) { if (options_.preconditioner_type == IDENTITY || - preconditioner_.get() != NULL) { + preconditioner_.get() != nullptr) { return; } @@ -149,22 +150,22 @@ void IterativeSchurComplementSolver::CreatePreconditioner( preconditioner_options.e_block_size = options_.e_block_size; preconditioner_options.f_block_size = options_.f_block_size; preconditioner_options.elimination_groups = options_.elimination_groups; - CHECK(options_.context != NULL); + CHECK(options_.context != nullptr); preconditioner_options.context = options_.context; switch (options_.preconditioner_type) { case JACOBI: - preconditioner_.reset(new SparseMatrixPreconditionerWrapper( - schur_complement_->block_diagonal_FtF_inverse())); + preconditioner_ = std::make_unique<SparseMatrixPreconditionerWrapper>( + schur_complement_->block_diagonal_FtF_inverse()); break; case SCHUR_JACOBI: - preconditioner_.reset(new SchurJacobiPreconditioner( - *A->block_structure(), preconditioner_options)); + preconditioner_ = std::make_unique<SchurJacobiPreconditioner>( + *A->block_structure(), preconditioner_options); break; case CLUSTER_JACOBI: case CLUSTER_TRIDIAGONAL: - preconditioner_.reset(new VisibilityBasedPreconditioner( - *A->block_structure(), preconditioner_options)); + preconditioner_ = std::make_unique<VisibilityBasedPreconditioner>( + *A->block_structure(), preconditioner_options); break; default: LOG(FATAL) << "Unknown Preconditioner Type"; diff --git a/extern/ceres/internal/ceres/iterative_schur_complement_solver.h b/extern/ceres/internal/ceres/iterative_schur_complement_solver.h index 37606b32d3a..50f469484f8 100644 --- a/extern/ceres/internal/ceres/iterative_schur_complement_solver.h +++ b/extern/ceres/internal/ceres/iterative_schur_complement_solver.h @@ -33,8 +33,9 @@ #include <memory> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "ceres/types.h" @@ -69,15 +70,15 @@ class Preconditioner; // a proof of this fact and others related to this solver please see // the section on Domain Decomposition Methods in Saad's book // "Iterative Methods for Sparse Linear Systems". -class CERES_EXPORT_INTERNAL IterativeSchurComplementSolver +class CERES_NO_EXPORT IterativeSchurComplementSolver final : public BlockSparseMatrixSolver { public: - explicit IterativeSchurComplementSolver(const LinearSolver::Options& options); + explicit IterativeSchurComplementSolver(LinearSolver::Options options); IterativeSchurComplementSolver(const IterativeSchurComplementSolver&) = delete; void operator=(const IterativeSchurComplementSolver&) = delete; - virtual ~IterativeSchurComplementSolver(); + ~IterativeSchurComplementSolver() override; private: LinearSolver::Summary SolveImpl(BlockSparseMatrix* A, @@ -96,4 +97,6 @@ class CERES_EXPORT_INTERNAL IterativeSchurComplementSolver } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_ITERATIVE_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/lapack.cc b/extern/ceres/internal/ceres/lapack.cc deleted file mode 100644 index a159ec70696..00000000000 --- a/extern/ceres/internal/ceres/lapack.cc +++ /dev/null @@ -1,190 +0,0 @@ -// 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/lapack.h" - -#include "ceres/internal/port.h" -#include "ceres/linear_solver.h" -#include "glog/logging.h" - -#ifndef CERES_NO_LAPACK -// C interface to the LAPACK Cholesky factorization and triangular solve. -extern "C" void dpotrf_(char* uplo, int* n, double* a, int* lda, int* info); - -extern "C" void dpotrs_(char* uplo, - int* n, - int* nrhs, - double* a, - int* lda, - double* b, - int* ldb, - int* info); - -extern "C" void dgels_(char* uplo, - int* m, - int* n, - int* nrhs, - double* a, - int* lda, - double* b, - int* ldb, - double* work, - int* lwork, - int* info); -#endif - -namespace ceres { -namespace internal { - -LinearSolverTerminationType LAPACK::SolveInPlaceUsingCholesky( - int num_rows, - const double* in_lhs, - double* rhs_and_solution, - std::string* message) { -#ifdef CERES_NO_LAPACK - LOG(FATAL) << "Ceres was built without a BLAS library."; - return LINEAR_SOLVER_FATAL_ERROR; -#else - char uplo = 'L'; - int n = num_rows; - int info = 0; - int nrhs = 1; - double* lhs = const_cast<double*>(in_lhs); - - dpotrf_(&uplo, &n, lhs, &n, &info); - if (info < 0) { - LOG(FATAL) << "Congratulations, you found a bug in Ceres." - << "Please report it." - << "LAPACK::dpotrf fatal error." - << "Argument: " << -info << " is invalid."; - return LINEAR_SOLVER_FATAL_ERROR; - } - - if (info > 0) { - *message = StringPrintf( - "LAPACK::dpotrf numerical failure. " - "The leading minor of order %d is not positive definite.", - info); - return LINEAR_SOLVER_FAILURE; - } - - dpotrs_(&uplo, &n, &nrhs, lhs, &n, rhs_and_solution, &n, &info); - if (info < 0) { - LOG(FATAL) << "Congratulations, you found a bug in Ceres." - << "Please report it." - << "LAPACK::dpotrs fatal error." - << "Argument: " << -info << " is invalid."; - return LINEAR_SOLVER_FATAL_ERROR; - } - - *message = "Success"; - return LINEAR_SOLVER_SUCCESS; -#endif -} - -int LAPACK::EstimateWorkSizeForQR(int num_rows, int num_cols) { -#ifdef CERES_NO_LAPACK - LOG(FATAL) << "Ceres was built without a LAPACK library."; - return -1; -#else - char trans = 'N'; - int nrhs = 1; - int lwork = -1; - double work; - int info = 0; - dgels_(&trans, - &num_rows, - &num_cols, - &nrhs, - NULL, - &num_rows, - NULL, - &num_rows, - &work, - &lwork, - &info); - - if (info < 0) { - LOG(FATAL) << "Congratulations, you found a bug in Ceres." - << "Please report it." - << "LAPACK::dgels fatal error." - << "Argument: " << -info << " is invalid."; - } - return static_cast<int>(work); -#endif -} - -LinearSolverTerminationType LAPACK::SolveInPlaceUsingQR( - int num_rows, - int num_cols, - const double* in_lhs, - int work_size, - double* work, - double* rhs_and_solution, - std::string* message) { -#ifdef CERES_NO_LAPACK - LOG(FATAL) << "Ceres was built without a LAPACK library."; - return LINEAR_SOLVER_FATAL_ERROR; -#else - char trans = 'N'; - int m = num_rows; - int n = num_cols; - int nrhs = 1; - int lda = num_rows; - int ldb = num_rows; - int info = 0; - double* lhs = const_cast<double*>(in_lhs); - - dgels_(&trans, - &m, - &n, - &nrhs, - lhs, - &lda, - rhs_and_solution, - &ldb, - work, - &work_size, - &info); - - if (info < 0) { - LOG(FATAL) << "Congratulations, you found a bug in Ceres." - << "Please report it." - << "LAPACK::dgels fatal error." - << "Argument: " << -info << " is invalid."; - } - - *message = "Success."; - return LINEAR_SOLVER_SUCCESS; -#endif -} - -} // namespace internal -} // namespace ceres diff --git a/extern/ceres/internal/ceres/lapack.h b/extern/ceres/internal/ceres/lapack.h deleted file mode 100644 index 5c5bf8bf8b8..00000000000 --- a/extern/ceres/internal/ceres/lapack.h +++ /dev/null @@ -1,101 +0,0 @@ -// 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) - -#ifndef CERES_INTERNAL_LAPACK_H_ -#define CERES_INTERNAL_LAPACK_H_ - -#include <string> - -#include "ceres/internal/port.h" -#include "ceres/linear_solver.h" - -namespace ceres { -namespace internal { - -class LAPACK { - public: - // Solve - // - // lhs * solution = rhs - // - // using a Cholesky factorization. Here - // lhs is a symmetric positive definite matrix. It is assumed to be - // column major and only the lower triangular part of the matrix is - // referenced. - // - // This function uses the LAPACK dpotrf and dpotrs routines. - // - // The return value and the message string together describe whether - // the solver terminated successfully or not and if so, what was the - // reason for failure. - static LinearSolverTerminationType SolveInPlaceUsingCholesky( - int num_rows, - const double* lhs, - double* rhs_and_solution, - std::string* message); - - // The SolveUsingQR function requires a buffer for its temporary - // computation. This function given the size of the lhs matrix will - // return the size of the buffer needed. - static int EstimateWorkSizeForQR(int num_rows, int num_cols); - - // Solve - // - // lhs * solution = rhs - // - // using a dense QR factorization. lhs is an arbitrary (possibly - // rectangular) matrix with full column rank. - // - // work is an array of size work_size that this routine uses for its - // temporary storage. The optimal size of this array can be obtained - // by calling EstimateWorkSizeForQR. - // - // When calling, rhs_and_solution contains the rhs, and upon return - // the first num_col entries are the solution. - // - // This function uses the LAPACK dgels routine. - // - // The return value and the message string together describe whether - // the solver terminated successfully or not and if so, what was the - // reason for failure. - static LinearSolverTerminationType SolveInPlaceUsingQR( - int num_rows, - int num_cols, - const double* lhs, - int work_size, - double* work, - double* rhs_and_solution, - std::string* message); -}; - -} // namespace internal -} // namespace ceres - -#endif // CERES_INTERNAL_LAPACK_H_ diff --git a/extern/ceres/internal/ceres/levenberg_marquardt_strategy.cc b/extern/ceres/internal/ceres/levenberg_marquardt_strategy.cc index cb0e9371b75..2445f5bb99a 100644 --- a/extern/ceres/internal/ceres/levenberg_marquardt_strategy.cc +++ b/extern/ceres/internal/ceres/levenberg_marquardt_strategy.cc @@ -61,7 +61,7 @@ LevenbergMarquardtStrategy::LevenbergMarquardtStrategy( CHECK_GT(max_radius_, 0.0); } -LevenbergMarquardtStrategy::~LevenbergMarquardtStrategy() {} +LevenbergMarquardtStrategy::~LevenbergMarquardtStrategy() = default; TrustRegionStrategy::Summary LevenbergMarquardtStrategy::ComputeStep( const TrustRegionStrategy::PerSolveOptions& per_solve_options, diff --git a/extern/ceres/internal/ceres/levenberg_marquardt_strategy.h b/extern/ceres/internal/ceres/levenberg_marquardt_strategy.h index 12cd463c152..4383a493cde 100644 --- a/extern/ceres/internal/ceres/levenberg_marquardt_strategy.h +++ b/extern/ceres/internal/ceres/levenberg_marquardt_strategy.h @@ -31,8 +31,9 @@ #ifndef CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ #define CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/trust_region_strategy.h" namespace ceres { @@ -43,12 +44,12 @@ namespace internal { // K. Madsen, H.B. Nielsen and O. Tingleff. Available to download from // // http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf -class CERES_EXPORT_INTERNAL LevenbergMarquardtStrategy +class CERES_NO_EXPORT LevenbergMarquardtStrategy final : public TrustRegionStrategy { public: explicit LevenbergMarquardtStrategy( const TrustRegionStrategy::Options& options); - virtual ~LevenbergMarquardtStrategy(); + ~LevenbergMarquardtStrategy() override; // TrustRegionStrategy interface TrustRegionStrategy::Summary ComputeStep( @@ -86,4 +87,6 @@ class CERES_EXPORT_INTERNAL LevenbergMarquardtStrategy } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_LEVENBERG_MARQUARDT_STRATEGY_H_ diff --git a/extern/ceres/internal/ceres/line_search.cc b/extern/ceres/internal/ceres/line_search.cc index 7e871a20a53..7e7d97f6d93 100644 --- a/extern/ceres/internal/ceres/line_search.cc +++ b/extern/ceres/internal/ceres/line_search.cc @@ -34,6 +34,7 @@ #include <cmath> #include <iomanip> #include <iostream> // NOLINT +#include <memory> #include "ceres/evaluator.h" #include "ceres/function_sample.h" @@ -65,27 +66,26 @@ ostream& operator<<(ostream& os, const FunctionSample& sample) { return os; } +LineSearch::~LineSearch() = default; + LineSearch::LineSearch(const LineSearch::Options& options) : options_(options) {} -LineSearch* LineSearch::Create(const LineSearchType line_search_type, - const LineSearch::Options& options, - string* error) { - LineSearch* line_search = NULL; +std::unique_ptr<LineSearch> LineSearch::Create( + const LineSearchType line_search_type, + const LineSearch::Options& options, + string* error) { switch (line_search_type) { case ceres::ARMIJO: - line_search = new ArmijoLineSearch(options); - break; + return std::make_unique<ArmijoLineSearch>(options); case ceres::WOLFE: - line_search = new WolfeLineSearch(options); - break; + return std::make_unique<WolfeLineSearch>(options); default: *error = string("Invalid line search algorithm type: ") + LineSearchTypeToString(line_search_type) + string(", unable to create line search."); - return NULL; } - return line_search; + return nullptr; } LineSearchFunction::LineSearchFunction(Evaluator* evaluator) @@ -119,13 +119,13 @@ void LineSearchFunction::Evaluate(const double x, } output->vector_x_is_valid = true; - double* gradient = NULL; + double* gradient = nullptr; if (evaluate_gradient) { output->vector_gradient.resize(direction_.rows(), 1); gradient = output->vector_gradient.data(); } const bool eval_status = evaluator_->Evaluate( - output->vector_x.data(), &(output->value), NULL, gradient, NULL); + output->vector_x.data(), &(output->value), nullptr, gradient, nullptr); if (!eval_status || !std::isfinite(output->value)) { return; @@ -249,12 +249,12 @@ double LineSearch::InterpolatingPolynomialMinimizingStepSize( if (interpolation_type == QUADRATIC) { // Two point interpolation using function values and the // gradient at the lower bound. - samples.push_back(FunctionSample(current.x, current.value)); + samples.emplace_back(current.x, current.value); if (previous.value_is_valid) { // Three point interpolation, using function values and the // gradient at the lower bound. - samples.push_back(FunctionSample(previous.x, previous.value)); + samples.emplace_back(previous.x, previous.value); } } else if (interpolation_type == CUBIC) { // Two point interpolation using the function values and the gradients. diff --git a/extern/ceres/internal/ceres/line_search.h b/extern/ceres/internal/ceres/line_search.h index 634c9717532..c2c744afe00 100644 --- a/extern/ceres/internal/ceres/line_search.h +++ b/extern/ceres/internal/ceres/line_search.h @@ -33,12 +33,13 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_H_ #define CERES_INTERNAL_LINE_SEARCH_H_ +#include <memory> #include <string> #include <vector> #include "ceres/function_sample.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/types.h" namespace ceres { @@ -57,11 +58,11 @@ class LineSearchFunction; // sufficient decrease condition. Depending on the particular // condition used, we get a variety of different line search // algorithms, e.g., Armijo, Wolfe etc. -class LineSearch { +class CERES_NO_EXPORT LineSearch { public: struct Summary; - struct Options { + struct CERES_NO_EXPORT Options { // Degree of the polynomial used to approximate the objective // function. LineSearchInterpolationType interpolation_type = CUBIC; @@ -161,11 +162,12 @@ class LineSearch { }; explicit LineSearch(const LineSearch::Options& options); - virtual ~LineSearch() {} + virtual ~LineSearch(); - static LineSearch* Create(const LineSearchType line_search_type, - const LineSearch::Options& options, - std::string* error); + static std::unique_ptr<LineSearch> Create( + const LineSearchType line_search_type, + const LineSearch::Options& options, + std::string* error); // Perform the line search. // @@ -208,7 +210,7 @@ class LineSearch { // In practice, this object provides access to the objective // function value and the directional derivative of the underlying // optimization problem along a specific search direction. -class LineSearchFunction { +class CERES_NO_EXPORT LineSearchFunction { public: explicit LineSearchFunction(Evaluator* evaluator); void Init(const Vector& position, const Vector& direction); @@ -257,10 +259,9 @@ class LineSearchFunction { // minFunc package by Mark Schmidt. // // For more details: http://www.di.ens.fr/~mschmidt/Software/minFunc.html -class ArmijoLineSearch : public LineSearch { +class CERES_NO_EXPORT ArmijoLineSearch final : public LineSearch { public: explicit ArmijoLineSearch(const LineSearch::Options& options); - virtual ~ArmijoLineSearch() {} private: void DoSearch(double step_size_estimate, @@ -276,10 +277,9 @@ class ArmijoLineSearch : public LineSearch { // // [1] Nocedal J., Wright S., Numerical Optimization, 2nd Ed., Springer, 1999. // [2] http://www.di.ens.fr/~mschmidt/Software/minFunc.html. -class WolfeLineSearch : public LineSearch { +class CERES_NO_EXPORT WolfeLineSearch final : public LineSearch { public: explicit WolfeLineSearch(const LineSearch::Options& options); - virtual ~WolfeLineSearch() {} // Returns true iff either a valid point, or valid bracket are found. bool BracketingPhase(const FunctionSample& initial_position, diff --git a/extern/ceres/internal/ceres/line_search_direction.cc b/extern/ceres/internal/ceres/line_search_direction.cc index 48e6c9812e9..98e335a8029 100644 --- a/extern/ceres/internal/ceres/line_search_direction.cc +++ b/extern/ceres/internal/ceres/line_search_direction.cc @@ -30,7 +30,10 @@ #include "ceres/line_search_direction.h" +#include <memory> + #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/line_search_minimizer.h" #include "ceres/low_rank_inverse_hessian.h" #include "glog/logging.h" @@ -38,18 +41,18 @@ namespace ceres { namespace internal { -class SteepestDescent : public LineSearchDirection { +class CERES_NO_EXPORT SteepestDescent final : public LineSearchDirection { public: - virtual ~SteepestDescent() {} bool NextDirection(const LineSearchMinimizer::State& previous, const LineSearchMinimizer::State& current, - Vector* search_direction) { + Vector* search_direction) override { *search_direction = -current.gradient; return true; } }; -class NonlinearConjugateGradient : public LineSearchDirection { +class CERES_NO_EXPORT NonlinearConjugateGradient final + : public LineSearchDirection { public: NonlinearConjugateGradient(const NonlinearConjugateGradientType type, const double function_tolerance) @@ -57,7 +60,7 @@ class NonlinearConjugateGradient : public LineSearchDirection { bool NextDirection(const LineSearchMinimizer::State& previous, const LineSearchMinimizer::State& current, - Vector* search_direction) { + Vector* search_direction) override { double beta = 0.0; Vector gradient_change; switch (type_) { @@ -95,7 +98,7 @@ class NonlinearConjugateGradient : public LineSearchDirection { const double function_tolerance_; }; -class LBFGS : public LineSearchDirection { +class CERES_NO_EXPORT LBFGS final : public LineSearchDirection { public: LBFGS(const int num_parameters, const int max_lbfgs_rank, @@ -105,11 +108,9 @@ class LBFGS : public LineSearchDirection { use_approximate_eigenvalue_bfgs_scaling), is_positive_definite_(true) {} - virtual ~LBFGS() {} - bool NextDirection(const LineSearchMinimizer::State& previous, const LineSearchMinimizer::State& current, - Vector* search_direction) { + Vector* search_direction) override { CHECK(is_positive_definite_) << "Ceres bug: NextDirection() called on L-BFGS after inverse Hessian " << "approximation has become indefinite, please contact the " @@ -141,7 +142,7 @@ class LBFGS : public LineSearchDirection { bool is_positive_definite_; }; -class BFGS : public LineSearchDirection { +class CERES_NO_EXPORT BFGS final : public LineSearchDirection { public: BFGS(const int num_parameters, const bool use_approximate_eigenvalue_scaling) : num_parameters_(num_parameters), @@ -161,11 +162,9 @@ class BFGS : public LineSearchDirection { inverse_hessian_ = Matrix::Identity(num_parameters, num_parameters); } - virtual ~BFGS() {} - bool NextDirection(const LineSearchMinimizer::State& previous, const LineSearchMinimizer::State& current, - Vector* search_direction) { + Vector* search_direction) override { CHECK(is_positive_definite_) << "Ceres bug: NextDirection() called on BFGS after inverse Hessian " << "approximation has become indefinite, please contact the " @@ -338,32 +337,34 @@ class BFGS : public LineSearchDirection { bool is_positive_definite_; }; -LineSearchDirection* LineSearchDirection::Create( +LineSearchDirection::~LineSearchDirection() = default; + +std::unique_ptr<LineSearchDirection> LineSearchDirection::Create( const LineSearchDirection::Options& options) { if (options.type == STEEPEST_DESCENT) { - return new SteepestDescent; + return std::make_unique<SteepestDescent>(); } if (options.type == NONLINEAR_CONJUGATE_GRADIENT) { - return new NonlinearConjugateGradient( + return std::make_unique<NonlinearConjugateGradient>( options.nonlinear_conjugate_gradient_type, options.function_tolerance); } if (options.type == ceres::LBFGS) { - return new ceres::internal::LBFGS( + return std::make_unique<ceres::internal::LBFGS>( options.num_parameters, options.max_lbfgs_rank, options.use_approximate_eigenvalue_bfgs_scaling); } if (options.type == ceres::BFGS) { - return new ceres::internal::BFGS( + return std::make_unique<ceres::internal::BFGS>( options.num_parameters, options.use_approximate_eigenvalue_bfgs_scaling); } LOG(ERROR) << "Unknown line search direction type: " << options.type; - return NULL; + return nullptr; } } // namespace internal diff --git a/extern/ceres/internal/ceres/line_search_direction.h b/extern/ceres/internal/ceres/line_search_direction.h index 2fcf4729ca5..47b256d7133 100644 --- a/extern/ceres/internal/ceres/line_search_direction.h +++ b/extern/ceres/internal/ceres/line_search_direction.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -31,35 +31,31 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_ #define CERES_INTERNAL_LINE_SEARCH_DIRECTION_H_ +#include <memory> + #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/line_search_minimizer.h" #include "ceres/types.h" namespace ceres { namespace internal { -class LineSearchDirection { +class CERES_NO_EXPORT LineSearchDirection { public: struct Options { - Options() - : num_parameters(0), - type(LBFGS), - nonlinear_conjugate_gradient_type(FLETCHER_REEVES), - function_tolerance(1e-12), - max_lbfgs_rank(20), - use_approximate_eigenvalue_bfgs_scaling(true) {} - - int num_parameters; - LineSearchDirectionType type; - NonlinearConjugateGradientType nonlinear_conjugate_gradient_type; - double function_tolerance; - int max_lbfgs_rank; - bool use_approximate_eigenvalue_bfgs_scaling; + int num_parameters{0}; + LineSearchDirectionType type{LBFGS}; + NonlinearConjugateGradientType nonlinear_conjugate_gradient_type{ + FLETCHER_REEVES}; + double function_tolerance{1e-12}; + int max_lbfgs_rank{20}; + bool use_approximate_eigenvalue_bfgs_scaling{true}; }; - static LineSearchDirection* Create(const Options& options); + static std::unique_ptr<LineSearchDirection> Create(const Options& options); - virtual ~LineSearchDirection() {} + virtual ~LineSearchDirection(); virtual bool NextDirection(const LineSearchMinimizer::State& previous, const LineSearchMinimizer::State& current, Vector* search_direction) = 0; diff --git a/extern/ceres/internal/ceres/line_search_minimizer.cc b/extern/ceres/internal/ceres/line_search_minimizer.cc index ea1c5072a14..ad1e1852386 100644 --- a/extern/ceres/internal/ceres/line_search_minimizer.cc +++ b/extern/ceres/internal/ceres/line_search_minimizer.cc @@ -51,7 +51,7 @@ #include "ceres/array_utils.h" #include "ceres/evaluator.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/line_search.h" #include "ceres/line_search_direction.h" #include "ceres/stringprintf.h" @@ -171,8 +171,8 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options, line_search_direction_options.max_lbfgs_rank = options.max_lbfgs_rank; line_search_direction_options.use_approximate_eigenvalue_bfgs_scaling = options.use_approximate_eigenvalue_bfgs_scaling; - std::unique_ptr<LineSearchDirection> line_search_direction( - LineSearchDirection::Create(line_search_direction_options)); + std::unique_ptr<LineSearchDirection> line_search_direction = + LineSearchDirection::Create(line_search_direction_options); LineSearchFunction line_search_function(evaluator); @@ -280,8 +280,8 @@ void LineSearchMinimizer::Minimize(const Minimizer::Options& options, << options.max_num_line_search_direction_restarts << " [max]."; } - line_search_direction.reset( - LineSearchDirection::Create(line_search_direction_options)); + line_search_direction = + LineSearchDirection::Create(line_search_direction_options); current_state.search_direction = -current_state.gradient; } diff --git a/extern/ceres/internal/ceres/line_search_minimizer.h b/extern/ceres/internal/ceres/line_search_minimizer.h index 79e8dc9e49a..9a0e994dcfc 100644 --- a/extern/ceres/internal/ceres/line_search_minimizer.h +++ b/extern/ceres/internal/ceres/line_search_minimizer.h @@ -32,6 +32,7 @@ #define CERES_INTERNAL_LINE_SEARCH_MINIMIZER_H_ #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/minimizer.h" #include "ceres/solver.h" #include "ceres/types.h" @@ -43,7 +44,7 @@ namespace internal { // Generic line search minimization algorithm. // // For example usage, see SolverImpl::Minimize. -class LineSearchMinimizer : public Minimizer { +class CERES_NO_EXPORT LineSearchMinimizer final : public Minimizer { public: struct State { State(int num_parameters, int num_effective_parameters) @@ -63,7 +64,6 @@ class LineSearchMinimizer : public Minimizer { double step_size; }; - ~LineSearchMinimizer() {} void Minimize(const Minimizer::Options& options, double* parameters, Solver::Summary* summary) final; diff --git a/extern/ceres/internal/ceres/line_search_preprocessor.cc b/extern/ceres/internal/ceres/line_search_preprocessor.cc index 6a69425e764..26b8d99a4c7 100644 --- a/extern/ceres/internal/ceres/line_search_preprocessor.cc +++ b/extern/ceres/internal/ceres/line_search_preprocessor.cc @@ -63,15 +63,13 @@ bool SetupEvaluator(PreprocessedProblem* pp) { pp->evaluator_options.context = pp->problem->context(); pp->evaluator_options.evaluation_callback = pp->reduced_program->mutable_evaluation_callback(); - pp->evaluator.reset(Evaluator::Create( - pp->evaluator_options, pp->reduced_program.get(), &pp->error)); - return (pp->evaluator.get() != NULL); + pp->evaluator = Evaluator::Create( + pp->evaluator_options, pp->reduced_program.get(), &pp->error); + return (pp->evaluator.get() != nullptr); } } // namespace -LineSearchPreprocessor::~LineSearchPreprocessor() {} - bool LineSearchPreprocessor::Preprocess(const Solver::Options& options, ProblemImpl* problem, PreprocessedProblem* pp) { @@ -85,10 +83,10 @@ bool LineSearchPreprocessor::Preprocess(const Solver::Options& options, return false; } - pp->reduced_program.reset(program->CreateReducedProgram( - &pp->removed_parameter_blocks, &pp->fixed_cost, &pp->error)); + pp->reduced_program = program->CreateReducedProgram( + &pp->removed_parameter_blocks, &pp->fixed_cost, &pp->error); - if (pp->reduced_program.get() == NULL) { + if (pp->reduced_program.get() == nullptr) { return false; } diff --git a/extern/ceres/internal/ceres/line_search_preprocessor.h b/extern/ceres/internal/ceres/line_search_preprocessor.h index bd426c7f2f6..27e9c2db9b9 100644 --- a/extern/ceres/internal/ceres/line_search_preprocessor.h +++ b/extern/ceres/internal/ceres/line_search_preprocessor.h @@ -31,15 +31,15 @@ #ifndef CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ #define CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/preprocessor.h" namespace ceres { namespace internal { -class CERES_EXPORT_INTERNAL LineSearchPreprocessor : public Preprocessor { +class CERES_NO_EXPORT LineSearchPreprocessor final : public Preprocessor { public: - virtual ~LineSearchPreprocessor(); bool Preprocess(const Solver::Options& options, ProblemImpl* problem, PreprocessedProblem* preprocessed_problem) final; @@ -48,4 +48,6 @@ class CERES_EXPORT_INTERNAL LineSearchPreprocessor : public Preprocessor { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_LINE_SEARCH_PREPROCESSOR_H_ diff --git a/extern/ceres/internal/ceres/linear_least_squares_problems.cc b/extern/ceres/internal/ceres/linear_least_squares_problems.cc index 299051c5bcf..2d415af338f 100644 --- a/extern/ceres/internal/ceres/linear_least_squares_problems.cc +++ b/extern/ceres/internal/ceres/linear_least_squares_problems.cc @@ -49,7 +49,8 @@ namespace internal { using std::string; -LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) { +std::unique_ptr<LinearLeastSquaresProblem> +CreateLinearLeastSquaresProblemFromId(int id) { switch (id) { case 0: return LinearLeastSquaresProblem0(); @@ -64,7 +65,7 @@ LinearLeastSquaresProblem* CreateLinearLeastSquaresProblemFromId(int id) { default: LOG(FATAL) << "Unknown problem id requested " << id; } - return NULL; + return nullptr; } /* @@ -85,15 +86,16 @@ D = [1 x_D = [1.78448275; 2.82327586;] */ -LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { - LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem0() { + std::unique_ptr<LinearLeastSquaresProblem> problem = + std::make_unique<LinearLeastSquaresProblem>(); - TripletSparseMatrix* A = new TripletSparseMatrix(3, 2, 6); - problem->b.reset(new double[3]); - problem->D.reset(new double[2]); + auto A = std::make_unique<TripletSparseMatrix>(3, 2, 6); + problem->b = std::make_unique<double[]>(3); + problem->D = std::make_unique<double[]>(2); - problem->x.reset(new double[2]); - problem->x_D.reset(new double[2]); + problem->x = std::make_unique<double[]>(2); + problem->x_D = std::make_unique<double[]>(2); int* Ai = A->mutable_rows(); int* Aj = A->mutable_cols(); @@ -115,7 +117,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { Ax[4] = 6; Ax[5] = -10; A->set_num_nonzeros(6); - problem->A.reset(A); + problem->A = std::move(A); problem->b[0] = 8; problem->b[1] = 18; @@ -161,7 +163,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { S = [ 42.3419 -1.4000 -11.5806 -1.4000 2.6000 1.0000 - 11.5806 1.0000 31.1935] + -11.5806 1.0000 31.1935] r = [ 4.3032 5.4000 @@ -181,15 +183,16 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem0() { // BlockSparseMatrix version of this problem. // TripletSparseMatrix version. -LinearLeastSquaresProblem* LinearLeastSquaresProblem1() { +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem1() { int num_rows = 6; int num_cols = 5; - LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; - TripletSparseMatrix* A = - new TripletSparseMatrix(num_rows, num_cols, num_rows * num_cols); - problem->b.reset(new double[num_rows]); - problem->D.reset(new double[num_cols]); + std::unique_ptr<LinearLeastSquaresProblem> problem = + std::make_unique<LinearLeastSquaresProblem>(); + auto A = std::make_unique<TripletSparseMatrix>( + num_rows, num_cols, num_rows * num_cols); + problem->b = std::make_unique<double[]>(num_rows); + problem->D = std::make_unique<double[]>(num_cols); problem->num_eliminate_blocks = 2; int* rows = A->mutable_rows(); @@ -271,7 +274,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem1() { A->set_num_nonzeros(nnz); CHECK(A->IsValid()); - problem->A.reset(A); + problem->A = std::move(A); for (int i = 0; i < num_cols; ++i) { problem->D.get()[i] = 1; @@ -285,21 +288,23 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem1() { } // BlockSparseMatrix version -LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem2() { int num_rows = 6; int num_cols = 5; - LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + std::unique_ptr<LinearLeastSquaresProblem> problem = + std::make_unique<LinearLeastSquaresProblem>(); - problem->b.reset(new double[num_rows]); - problem->D.reset(new double[num_cols]); + problem->b = std::make_unique<double[]>(num_rows); + problem->D = std::make_unique<double[]>(num_cols); problem->num_eliminate_blocks = 2; - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; - std::unique_ptr<double[]> values(new double[num_rows * num_cols]); + auto* bs = new CompressedRowBlockStructure; + std::unique_ptr<double[]> values = + std::make_unique<double[]>(num_rows * num_cols); for (int c = 0; c < num_cols; ++c) { - bs->cols.push_back(Block()); + bs->cols.emplace_back(); bs->cols.back().size = 1; bs->cols.back().position = c; } @@ -311,12 +316,12 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 1; values[nnz++] = 2; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 0; - row.cells.push_back(Cell(0, 0)); - row.cells.push_back(Cell(2, 1)); + row.cells.emplace_back(0, 0); + row.cells.emplace_back(2, 1); } // Row 2 @@ -324,12 +329,12 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 3; values[nnz++] = 4; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 1; - row.cells.push_back(Cell(0, 2)); - row.cells.push_back(Cell(3, 3)); + row.cells.emplace_back(0, 2); + row.cells.emplace_back(3, 3); } // Row 3 @@ -337,12 +342,12 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 5; values[nnz++] = 6; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 2; - row.cells.push_back(Cell(1, 4)); - row.cells.push_back(Cell(4, 5)); + row.cells.emplace_back(1, 4); + row.cells.emplace_back(4, 5); } // Row 4 @@ -350,12 +355,12 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 7; values[nnz++] = 8; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 3; - row.cells.push_back(Cell(1, 6)); - row.cells.push_back(Cell(2, 7)); + row.cells.emplace_back(1, 6); + row.cells.emplace_back(2, 7); } // Row 5 @@ -363,12 +368,12 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 9; values[nnz++] = 1; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 4; - row.cells.push_back(Cell(1, 8)); - row.cells.push_back(Cell(2, 9)); + row.cells.emplace_back(1, 8); + row.cells.emplace_back(2, 9); } // Row 6 @@ -377,16 +382,16 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { values[nnz++] = 1; values[nnz++] = 1; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 5; - row.cells.push_back(Cell(2, 10)); - row.cells.push_back(Cell(3, 11)); - row.cells.push_back(Cell(4, 12)); + row.cells.emplace_back(2, 10); + row.cells.emplace_back(3, 11); + row.cells.emplace_back(4, 12); } - BlockSparseMatrix* A = new BlockSparseMatrix(bs); + auto A = std::make_unique<BlockSparseMatrix>(bs); memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); for (int i = 0; i < num_cols; ++i) { @@ -397,7 +402,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { problem->b.get()[i] = i; } - problem->A.reset(A); + problem->A = std::move(A); return problem; } @@ -418,21 +423,23 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem2() { 5] */ // BlockSparseMatrix version -LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem3() { int num_rows = 5; int num_cols = 2; - LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + std::unique_ptr<LinearLeastSquaresProblem> problem = + std::make_unique<LinearLeastSquaresProblem>(); - problem->b.reset(new double[num_rows]); - problem->D.reset(new double[num_cols]); + problem->b = std::make_unique<double[]>(num_rows); + problem->D = std::make_unique<double[]>(num_cols); problem->num_eliminate_blocks = 2; - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; - std::unique_ptr<double[]> values(new double[num_rows * num_cols]); + auto* bs = new CompressedRowBlockStructure; + std::unique_ptr<double[]> values = + std::make_unique<double[]>(num_rows * num_cols); for (int c = 0; c < num_cols; ++c) { - bs->cols.push_back(Block()); + bs->cols.emplace_back(); bs->cols.back().size = 1; bs->cols.back().position = c; } @@ -442,54 +449,54 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { // Row 1 { values[nnz++] = 1; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 0; - row.cells.push_back(Cell(0, 0)); + row.cells.emplace_back(0, 0); } // Row 2 { values[nnz++] = 3; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 1; - row.cells.push_back(Cell(0, 1)); + row.cells.emplace_back(0, 1); } // Row 3 { values[nnz++] = 5; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 2; - row.cells.push_back(Cell(1, 2)); + row.cells.emplace_back(1, 2); } // Row 4 { values[nnz++] = 7; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 3; - row.cells.push_back(Cell(1, 3)); + row.cells.emplace_back(1, 3); } // Row 5 { values[nnz++] = 9; - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 4; - row.cells.push_back(Cell(1, 4)); + row.cells.emplace_back(1, 4); } - BlockSparseMatrix* A = new BlockSparseMatrix(bs); + auto A = std::make_unique<BlockSparseMatrix>(bs); memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); for (int i = 0; i < num_cols; ++i) { @@ -500,7 +507,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { problem->b.get()[i] = i; } - problem->A.reset(A); + problem->A = std::move(A); return problem; } @@ -525,29 +532,31 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem3() { // // NOTE: This problem is too small and rank deficient to be solved without // the diagonal regularization. -LinearLeastSquaresProblem* LinearLeastSquaresProblem4() { +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem4() { int num_rows = 3; int num_cols = 7; - LinearLeastSquaresProblem* problem = new LinearLeastSquaresProblem; + std::unique_ptr<LinearLeastSquaresProblem> problem = + std::make_unique<LinearLeastSquaresProblem>(); - problem->b.reset(new double[num_rows]); - problem->D.reset(new double[num_cols]); + problem->b = std::make_unique<double[]>(num_rows); + problem->D = std::make_unique<double[]>(num_cols); problem->num_eliminate_blocks = 1; - CompressedRowBlockStructure* bs = new CompressedRowBlockStructure; - std::unique_ptr<double[]> values(new double[num_rows * num_cols]); + auto* bs = new CompressedRowBlockStructure; + std::unique_ptr<double[]> values = + std::make_unique<double[]>(num_rows * num_cols); // Column block structure - bs->cols.push_back(Block()); + bs->cols.emplace_back(); bs->cols.back().size = 2; bs->cols.back().position = 0; - bs->cols.push_back(Block()); + bs->cols.emplace_back(); bs->cols.back().size = 3; bs->cols.back().position = 2; - bs->cols.push_back(Block()); + bs->cols.emplace_back(); bs->cols.back().size = 2; bs->cols.back().position = 5; @@ -555,18 +564,18 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem4() { // Row 1 & 2 { - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 2; row.block.position = 0; - row.cells.push_back(Cell(0, nnz)); + row.cells.emplace_back(0, nnz); values[nnz++] = 1; values[nnz++] = 2; values[nnz++] = 1; values[nnz++] = 4; - row.cells.push_back(Cell(2, nnz)); + row.cells.emplace_back(2, nnz); values[nnz++] = 1; values[nnz++] = 1; values[nnz++] = 5; @@ -575,22 +584,22 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem4() { // Row 3 { - bs->rows.push_back(CompressedRow()); + bs->rows.emplace_back(); CompressedRow& row = bs->rows.back(); row.block.size = 1; row.block.position = 2; - row.cells.push_back(Cell(1, nnz)); + row.cells.emplace_back(1, nnz); values[nnz++] = 9; values[nnz++] = 0; values[nnz++] = 0; - row.cells.push_back(Cell(2, nnz)); + row.cells.emplace_back(2, nnz); values[nnz++] = 3; values[nnz++] = 1; } - BlockSparseMatrix* A = new BlockSparseMatrix(bs); + auto A = std::make_unique<BlockSparseMatrix>(bs); memcpy(A->mutable_values(), values.get(), nnz * sizeof(*A->values())); for (int i = 0; i < num_cols; ++i) { @@ -601,7 +610,7 @@ LinearLeastSquaresProblem* LinearLeastSquaresProblem4() { problem->b.get()[i] = i; } - problem->A.reset(A); + problem->A = std::move(A); return problem; } @@ -616,15 +625,15 @@ bool DumpLinearLeastSquaresProblemToConsole(const SparseMatrix* A, A->ToDenseMatrix(&AA); LOG(INFO) << "A^T: \n" << AA.transpose(); - if (D != NULL) { + if (D != nullptr) { LOG(INFO) << "A's appended diagonal:\n" << ConstVectorRef(D, A->num_cols()); } - if (b != NULL) { + if (b != nullptr) { LOG(INFO) << "b: \n" << ConstVectorRef(b, A->num_rows()); } - if (x != NULL) { + if (x != nullptr) { LOG(INFO) << "x: \n" << ConstVectorRef(x, A->num_cols()); } return true; @@ -673,21 +682,21 @@ bool DumpLinearLeastSquaresProblemToTextFile(const string& filename_base, A->num_cols()); } - if (D != NULL) { + if (D != nullptr) { string filename = filename_base + "_D.txt"; WriteArrayToFileOrDie(filename, D, A->num_cols()); StringAppendF( &matlab_script, "lsqp.D = load('%s', '-ascii');\n", filename.c_str()); } - if (b != NULL) { + if (b != nullptr) { string filename = filename_base + "_b.txt"; WriteArrayToFileOrDie(filename, b, A->num_rows()); StringAppendF( &matlab_script, "lsqp.b = load('%s', '-ascii');\n", filename.c_str()); } - if (x != NULL) { + if (x != nullptr) { string filename = filename_base + "_x.txt"; WriteArrayToFileOrDie(filename, x, A->num_cols()); StringAppendF( diff --git a/extern/ceres/internal/ceres/linear_least_squares_problems.h b/extern/ceres/internal/ceres/linear_least_squares_problems.h index cddaa9fd4d7..a1f67eb306e 100644 --- a/extern/ceres/internal/ceres/linear_least_squares_problems.h +++ b/extern/ceres/internal/ceres/linear_least_squares_problems.h @@ -35,7 +35,8 @@ #include <string> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/sparse_matrix.h" namespace ceres { @@ -43,15 +44,15 @@ namespace internal { // Structure defining a linear least squares problem and if possible // ground truth solutions. To be used by various LinearSolver tests. -struct CERES_EXPORT_INTERNAL LinearLeastSquaresProblem { - LinearLeastSquaresProblem() : num_eliminate_blocks(0) {} +struct CERES_NO_EXPORT LinearLeastSquaresProblem { + LinearLeastSquaresProblem() = default; std::unique_ptr<SparseMatrix> A; std::unique_ptr<double[]> b; std::unique_ptr<double[]> D; // If using the schur eliminator then how many of the variable // blocks are e_type blocks. - int num_eliminate_blocks; + int num_eliminate_blocks{0}; // Solution to min_x |Ax - b|^2 std::unique_ptr<double[]> x; @@ -60,17 +61,23 @@ struct CERES_EXPORT_INTERNAL LinearLeastSquaresProblem { }; // Factories for linear least squares problem. -CERES_EXPORT_INTERNAL LinearLeastSquaresProblem* +CERES_NO_EXPORT std::unique_ptr<LinearLeastSquaresProblem> CreateLinearLeastSquaresProblemFromId(int id); -LinearLeastSquaresProblem* LinearLeastSquaresProblem0(); -LinearLeastSquaresProblem* LinearLeastSquaresProblem1(); -LinearLeastSquaresProblem* LinearLeastSquaresProblem2(); -LinearLeastSquaresProblem* LinearLeastSquaresProblem3(); -LinearLeastSquaresProblem* LinearLeastSquaresProblem4(); +CERES_NO_EXPORT +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem0(); +CERES_NO_EXPORT +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem1(); +CERES_NO_EXPORT +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem2(); +CERES_NO_EXPORT +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem3(); +CERES_NO_EXPORT +std::unique_ptr<LinearLeastSquaresProblem> LinearLeastSquaresProblem4(); // Write the linear least squares problem to disk. The exact format // depends on dump_format_type. +CERES_NO_EXPORT bool DumpLinearLeastSquaresProblem(const std::string& filename_base, DumpFormatType dump_format_type, const SparseMatrix* A, @@ -81,4 +88,6 @@ bool DumpLinearLeastSquaresProblem(const std::string& filename_base, } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_LINEAR_LEAST_SQUARES_PROBLEMS_H_ diff --git a/extern/ceres/internal/ceres/linear_operator.cc b/extern/ceres/internal/ceres/linear_operator.cc index 548c724267e..88b7cc752d4 100644 --- a/extern/ceres/internal/ceres/linear_operator.cc +++ b/extern/ceres/internal/ceres/linear_operator.cc @@ -33,7 +33,7 @@ namespace ceres { namespace internal { -LinearOperator::~LinearOperator() {} +LinearOperator::~LinearOperator() = default; } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/linear_operator.h b/extern/ceres/internal/ceres/linear_operator.h index 9c59fc39c13..c9e6188e2e8 100644 --- a/extern/ceres/internal/ceres/linear_operator.h +++ b/extern/ceres/internal/ceres/linear_operator.h @@ -33,7 +33,7 @@ #ifndef CERES_INTERNAL_LINEAR_OPERATOR_H_ #define CERES_INTERNAL_LINEAR_OPERATOR_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/types.h" namespace ceres { @@ -41,7 +41,7 @@ namespace internal { // This is an abstract base class for linear operators. It supports // access to size information and left and right multiply operators. -class CERES_EXPORT_INTERNAL LinearOperator { +class CERES_NO_EXPORT LinearOperator { public: virtual ~LinearOperator(); diff --git a/extern/ceres/internal/ceres/linear_solver.cc b/extern/ceres/internal/ceres/linear_solver.cc index 6cae2488f07..fe324f81301 100644 --- a/extern/ceres/internal/ceres/linear_solver.cc +++ b/extern/ceres/internal/ceres/linear_solver.cc @@ -30,10 +30,13 @@ #include "ceres/linear_solver.h" +#include <memory> + #include "ceres/cgnr_solver.h" #include "ceres/dense_normal_cholesky_solver.h" #include "ceres/dense_qr_solver.h" #include "ceres/dynamic_sparse_normal_cholesky_solver.h" +#include "ceres/internal/config.h" #include "ceres/iterative_schur_complement_solver.h" #include "ceres/schur_complement_solver.h" #include "ceres/sparse_normal_cholesky_solver.h" @@ -43,7 +46,7 @@ namespace ceres { namespace internal { -LinearSolver::~LinearSolver() {} +LinearSolver::~LinearSolver() = default; LinearSolverType LinearSolver::LinearSolverForZeroEBlocks( LinearSolverType linear_solver_type) { @@ -69,50 +72,51 @@ LinearSolverType LinearSolver::LinearSolverForZeroEBlocks( return linear_solver_type; } -LinearSolver* LinearSolver::Create(const LinearSolver::Options& options) { - CHECK(options.context != NULL); +std::unique_ptr<LinearSolver> LinearSolver::Create( + const LinearSolver::Options& options) { + CHECK(options.context != nullptr); switch (options.type) { case CGNR: - return new CgnrSolver(options); + return std::make_unique<CgnrSolver>(options); case SPARSE_NORMAL_CHOLESKY: #if defined(CERES_NO_SPARSE) - return NULL; + return nullptr; #else if (options.dynamic_sparsity) { - return new DynamicSparseNormalCholeskySolver(options); + return std::make_unique<DynamicSparseNormalCholeskySolver>(options); } - return new SparseNormalCholeskySolver(options); + return std::make_unique<SparseNormalCholeskySolver>(options); #endif case SPARSE_SCHUR: #if defined(CERES_NO_SPARSE) - return NULL; + return nullptr; #else - return new SparseSchurComplementSolver(options); + return std::make_unique<SparseSchurComplementSolver>(options); #endif case DENSE_SCHUR: - return new DenseSchurComplementSolver(options); + return std::make_unique<DenseSchurComplementSolver>(options); case ITERATIVE_SCHUR: if (options.use_explicit_schur_complement) { - return new SparseSchurComplementSolver(options); + return std::make_unique<SparseSchurComplementSolver>(options); } else { - return new IterativeSchurComplementSolver(options); + return std::make_unique<IterativeSchurComplementSolver>(options); } case DENSE_QR: - return new DenseQRSolver(options); + return std::make_unique<DenseQRSolver>(options); case DENSE_NORMAL_CHOLESKY: - return new DenseNormalCholeskySolver(options); + return std::make_unique<DenseNormalCholeskySolver>(options); default: LOG(FATAL) << "Unknown linear solver type :" << options.type; - return NULL; // MSVC doesn't understand that LOG(FATAL) never returns. + return nullptr; // MSVC doesn't understand that LOG(FATAL) never returns. } } diff --git a/extern/ceres/internal/ceres/linear_solver.h b/extern/ceres/internal/ceres/linear_solver.h index 49c6527acc9..2f709c297e5 100644 --- a/extern/ceres/internal/ceres/linear_solver.h +++ b/extern/ceres/internal/ceres/linear_solver.h @@ -36,6 +36,7 @@ #include <cstddef> #include <map> +#include <memory> #include <string> #include <vector> @@ -45,7 +46,8 @@ #include "ceres/context_impl.h" #include "ceres/dense_sparse_matrix.h" #include "ceres/execution_summary.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/triplet_sparse_matrix.h" #include "ceres/types.h" #include "glog/logging.h" @@ -101,7 +103,7 @@ class LinearOperator; // The Options struct configures the LinearSolver object for its // lifetime. The PerSolveOptions struct is used to specify options for // a particular Solve call. -class CERES_EXPORT_INTERNAL LinearSolver { +class CERES_NO_EXPORT LinearSolver { public: struct Options { LinearSolverType type = SPARSE_NORMAL_CHOLESKY; @@ -284,11 +286,11 @@ class CERES_EXPORT_INTERNAL LinearSolver { // issues. Further, this calls are not expected to be frequent or // performance sensitive. virtual std::map<std::string, CallStatistics> Statistics() const { - return std::map<std::string, CallStatistics>(); + return {}; } // Factory - static LinearSolver* Create(const Options& options); + static std::unique_ptr<LinearSolver> Create(const Options& options); }; // This templated subclass of LinearSolver serves as a base class for @@ -301,12 +303,11 @@ class CERES_EXPORT_INTERNAL LinearSolver { template <typename MatrixType> class TypedLinearSolver : public LinearSolver { public: - virtual ~TypedLinearSolver() {} - virtual LinearSolver::Summary Solve( + LinearSolver::Summary Solve( LinearOperator* A, const double* b, const LinearSolver::PerSolveOptions& per_solve_options, - double* x) { + double* x) override { ScopedExecutionTimer total_time("LinearSolver::Solve", &execution_summary_); CHECK(A != nullptr); CHECK(b != nullptr); @@ -314,7 +315,7 @@ class TypedLinearSolver : public LinearSolver { return SolveImpl(down_cast<MatrixType*>(A), b, per_solve_options, x); } - virtual std::map<std::string, CallStatistics> Statistics() const { + std::map<std::string, CallStatistics> Statistics() const override { return execution_summary_.statistics(); } @@ -340,4 +341,6 @@ typedef TypedLinearSolver<TripletSparseMatrix> TripletSparseMatrixSolver; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_LINEAR_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/local_parameterization.cc b/extern/ceres/internal/ceres/local_parameterization.cc index 62947f06fcc..db6f95a1984 100644 --- a/extern/ceres/internal/ceres/local_parameterization.cc +++ b/extern/ceres/internal/ceres/local_parameterization.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ namespace ceres { using std::vector; -LocalParameterization::~LocalParameterization() {} +LocalParameterization::~LocalParameterization() = default; bool LocalParameterization::MultiplyByJacobian(const double* x, const int num_rows, @@ -107,8 +107,8 @@ SubsetParameterization::SubsetParameterization( << "of the parameter block."; CHECK(std::adjacent_find(constant.begin(), constant.end()) == constant.end()) << "The set of constant parameters cannot contain duplicates"; - for (int i = 0; i < constant_parameters.size(); ++i) { - constancy_mask_[constant_parameters[i]] = 1; + for (int parameter : constant_parameters) { + constancy_mask_[parameter] = 1; } } diff --git a/extern/ceres/internal/ceres/loss_function.cc b/extern/ceres/internal/ceres/loss_function.cc index 353f29a5bf5..3392b3b7f81 100644 --- a/extern/ceres/internal/ceres/loss_function.cc +++ b/extern/ceres/internal/ceres/loss_function.cc @@ -39,6 +39,8 @@ namespace ceres { +LossFunction::~LossFunction() = default; + void TrivialLoss::Evaluate(double s, double rho[3]) const { rho[0] = s; rho[1] = 1.0; @@ -161,7 +163,7 @@ void ComposedLoss::Evaluate(double s, double rho[3]) const { } void ScaledLoss::Evaluate(double s, double rho[3]) const { - if (rho_.get() == NULL) { + if (rho_.get() == nullptr) { rho[0] = a_ * s; rho[1] = a_; rho[2] = 0.0; diff --git a/extern/ceres/internal/ceres/low_rank_inverse_hessian.cc b/extern/ceres/internal/ceres/low_rank_inverse_hessian.cc index c73e5dbf88d..2fd1ac83f00 100644 --- a/extern/ceres/internal/ceres/low_rank_inverse_hessian.cc +++ b/extern/ceres/internal/ceres/low_rank_inverse_hessian.cc @@ -127,9 +127,7 @@ void LowRankInverseHessian::RightMultiply(const double* x_ptr, const int num_corrections = indices_.size(); Vector alpha(num_corrections); - for (list<int>::const_reverse_iterator it = indices_.rbegin(); - it != indices_.rend(); - ++it) { + for (auto it = indices_.rbegin(); it != indices_.rend(); ++it) { const double alpha_i = delta_x_history_.col(*it).dot(search_direction) / delta_x_dot_delta_gradient_(*it); search_direction -= alpha_i * delta_gradient_history_.col(*it); diff --git a/extern/ceres/internal/ceres/low_rank_inverse_hessian.h b/extern/ceres/internal/ceres/low_rank_inverse_hessian.h index 0028a988923..36519360262 100644 --- a/extern/ceres/internal/ceres/low_rank_inverse_hessian.h +++ b/extern/ceres/internal/ceres/low_rank_inverse_hessian.h @@ -37,6 +37,7 @@ #include <list> #include "ceres/internal/eigen.h" +#include "ceres/internal/export.h" #include "ceres/linear_operator.h" namespace ceres { @@ -59,7 +60,7 @@ namespace internal { // Byrd, R. H.; Nocedal, J.; Schnabel, R. B. (1994). // "Representations of Quasi-Newton Matrices and their use in // Limited Memory Methods". Mathematical Programming 63 (4): -class LowRankInverseHessian : public LinearOperator { +class CERES_NO_EXPORT LowRankInverseHessian final : public LinearOperator { public: // num_parameters is the row/column size of the Hessian. // max_num_corrections is the rank of the Hessian approximation. @@ -73,7 +74,6 @@ class LowRankInverseHessian : public LinearOperator { LowRankInverseHessian(int num_parameters, int max_num_corrections, bool use_approximate_eigenvalue_scaling); - virtual ~LowRankInverseHessian() {} // Update the low rank approximation. delta_x is the change in the // domain of Hessian, and delta_gradient is the change in the diff --git a/extern/ceres/internal/ceres/manifold.cc b/extern/ceres/internal/ceres/manifold.cc new file mode 100644 index 00000000000..f412a793f93 --- /dev/null +++ b/extern/ceres/internal/ceres/manifold.cc @@ -0,0 +1,321 @@ +#include "ceres/manifold.h" + +#include <algorithm> +#include <cmath> + +#include "ceres/internal/eigen.h" +#include "ceres/internal/fixed_array.h" +#include "glog/logging.h" + +namespace ceres { +namespace { + +struct CeresQuaternionOrder { + static constexpr int kW = 0; + static constexpr int kX = 1; + static constexpr int kY = 2; + static constexpr int kZ = 3; +}; + +struct EigenQuaternionOrder { + static constexpr int kW = 3; + static constexpr int kX = 0; + static constexpr int kY = 1; + static constexpr int kZ = 2; +}; + +template <typename Order> +inline void QuaternionPlusImpl(const double* x, + const double* delta, + double* x_plus_delta) { + // x_plus_delta = QuaternionProduct(q_delta, x), where q_delta is the + // quaternion constructed from delta. + const double norm_delta = std::sqrt( + delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]); + + if (norm_delta == 0.0) { + for (int i = 0; i < 4; ++i) { + x_plus_delta[i] = x[i]; + } + return; + } + + const double sin_delta_by_delta = (std::sin(norm_delta) / norm_delta); + double q_delta[4]; + q_delta[Order::kW] = std::cos(norm_delta); + q_delta[Order::kX] = sin_delta_by_delta * delta[0]; + q_delta[Order::kY] = sin_delta_by_delta * delta[1]; + q_delta[Order::kZ] = sin_delta_by_delta * delta[2]; + + x_plus_delta[Order::kW] = + q_delta[Order::kW] * x[Order::kW] - q_delta[Order::kX] * x[Order::kX] - + q_delta[Order::kY] * x[Order::kY] - q_delta[Order::kZ] * x[Order::kZ]; + x_plus_delta[Order::kX] = + q_delta[Order::kW] * x[Order::kX] + q_delta[Order::kX] * x[Order::kW] + + q_delta[Order::kY] * x[Order::kZ] - q_delta[Order::kZ] * x[Order::kY]; + x_plus_delta[Order::kY] = + q_delta[Order::kW] * x[Order::kY] - q_delta[Order::kX] * x[Order::kZ] + + q_delta[Order::kY] * x[Order::kW] + q_delta[Order::kZ] * x[Order::kX]; + x_plus_delta[Order::kZ] = + q_delta[Order::kW] * x[Order::kZ] + q_delta[Order::kX] * x[Order::kY] - + q_delta[Order::kY] * x[Order::kX] + q_delta[Order::kZ] * x[Order::kW]; +} + +template <typename Order> +inline void QuaternionPlusJacobianImpl(const double* x, double* jacobian_ptr) { + Eigen::Map<Eigen::Matrix<double, 4, 3, Eigen::RowMajor>> jacobian( + jacobian_ptr); + + jacobian(Order::kW, 0) = -x[Order::kX]; + jacobian(Order::kW, 1) = -x[Order::kY]; + jacobian(Order::kW, 2) = -x[Order::kZ]; + jacobian(Order::kX, 0) = x[Order::kW]; + jacobian(Order::kX, 1) = x[Order::kZ]; + jacobian(Order::kX, 2) = -x[Order::kY]; + jacobian(Order::kY, 0) = -x[Order::kZ]; + jacobian(Order::kY, 1) = x[Order::kW]; + jacobian(Order::kY, 2) = x[Order::kX]; + jacobian(Order::kZ, 0) = x[Order::kY]; + jacobian(Order::kZ, 1) = -x[Order::kX]; + jacobian(Order::kZ, 2) = x[Order::kW]; +} + +template <typename Order> +inline void QuaternionMinusImpl(const double* y, + const double* x, + double* y_minus_x) { + // ambient_y_minus_x = QuaternionProduct(y, -x) where -x is the conjugate of + // x. + double ambient_y_minus_x[4]; + ambient_y_minus_x[Order::kW] = + y[Order::kW] * x[Order::kW] + y[Order::kX] * x[Order::kX] + + y[Order::kY] * x[Order::kY] + y[Order::kZ] * x[Order::kZ]; + ambient_y_minus_x[Order::kX] = + -y[Order::kW] * x[Order::kX] + y[Order::kX] * x[Order::kW] - + y[Order::kY] * x[Order::kZ] + y[Order::kZ] * x[Order::kY]; + ambient_y_minus_x[Order::kY] = + -y[Order::kW] * x[Order::kY] + y[Order::kX] * x[Order::kZ] + + y[Order::kY] * x[Order::kW] - y[Order::kZ] * x[Order::kX]; + ambient_y_minus_x[Order::kZ] = + -y[Order::kW] * x[Order::kZ] - y[Order::kX] * x[Order::kY] + + y[Order::kY] * x[Order::kX] + y[Order::kZ] * x[Order::kW]; + + const double u_norm = + std::sqrt(ambient_y_minus_x[Order::kX] * ambient_y_minus_x[Order::kX] + + ambient_y_minus_x[Order::kY] * ambient_y_minus_x[Order::kY] + + ambient_y_minus_x[Order::kZ] * ambient_y_minus_x[Order::kZ]); + if (u_norm > 0.0) { + const double theta = std::atan2(u_norm, ambient_y_minus_x[Order::kW]); + y_minus_x[0] = theta * ambient_y_minus_x[Order::kX] / u_norm; + y_minus_x[1] = theta * ambient_y_minus_x[Order::kY] / u_norm; + y_minus_x[2] = theta * ambient_y_minus_x[Order::kZ] / u_norm; + } else { + y_minus_x[0] = 0.0; + y_minus_x[1] = 0.0; + y_minus_x[2] = 0.0; + } +} + +template <typename Order> +inline void QuaternionMinusJacobianImpl(const double* x, double* jacobian_ptr) { + Eigen::Map<Eigen::Matrix<double, 3, 4, Eigen::RowMajor>> jacobian( + jacobian_ptr); + + jacobian(0, Order::kW) = -x[Order::kX]; + jacobian(0, Order::kX) = x[Order::kW]; + jacobian(0, Order::kY) = -x[Order::kZ]; + jacobian(0, Order::kZ) = x[Order::kY]; + jacobian(1, Order::kW) = -x[Order::kY]; + jacobian(1, Order::kX) = x[Order::kZ]; + jacobian(1, Order::kY) = x[Order::kW]; + jacobian(1, Order::kZ) = -x[Order::kX]; + jacobian(2, Order::kW) = -x[Order::kZ]; + jacobian(2, Order::kX) = -x[Order::kY]; + jacobian(2, Order::kY) = x[Order::kX]; + jacobian(2, Order::kZ) = x[Order::kW]; +} + +} // namespace + +Manifold::~Manifold() = default; + +bool Manifold::RightMultiplyByPlusJacobian(const double* x, + const int num_rows, + const double* ambient_matrix, + double* tangent_matrix) const { + const int tangent_size = TangentSize(); + if (tangent_size == 0) { + return true; + } + + const int ambient_size = AmbientSize(); + Matrix plus_jacobian(ambient_size, tangent_size); + if (!PlusJacobian(x, plus_jacobian.data())) { + return false; + } + + MatrixRef(tangent_matrix, num_rows, tangent_size) = + ConstMatrixRef(ambient_matrix, num_rows, ambient_size) * plus_jacobian; + return true; +} + +SubsetManifold::SubsetManifold(const int size, + const std::vector<int>& constant_parameters) + + : tangent_size_(size - constant_parameters.size()), + constancy_mask_(size, false) { + if (constant_parameters.empty()) { + return; + } + + std::vector<int> constant = constant_parameters; + std::sort(constant.begin(), constant.end()); + CHECK_GE(constant.front(), 0) << "Indices indicating constant parameter must " + "be greater than equal to zero."; + CHECK_LT(constant.back(), size) + << "Indices indicating constant parameter must be less than the size " + << "of the parameter block."; + CHECK(std::adjacent_find(constant.begin(), constant.end()) == constant.end()) + << "The set of constant parameters cannot contain duplicates"; + + for (auto index : constant_parameters) { + constancy_mask_[index] = true; + } +} + +int SubsetManifold::AmbientSize() const { return constancy_mask_.size(); } + +int SubsetManifold::TangentSize() const { return tangent_size_; } + +bool SubsetManifold::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + const int ambient_size = AmbientSize(); + for (int i = 0, j = 0; i < ambient_size; ++i) { + if (constancy_mask_[i]) { + x_plus_delta[i] = x[i]; + } else { + x_plus_delta[i] = x[i] + delta[j++]; + } + } + return true; +} + +bool SubsetManifold::PlusJacobian(const double* x, + double* plus_jacobian) const { + if (tangent_size_ == 0) { + return true; + } + + const int ambient_size = AmbientSize(); + MatrixRef m(plus_jacobian, ambient_size, tangent_size_); + m.setZero(); + for (int r = 0, c = 0; r < ambient_size; ++r) { + if (!constancy_mask_[r]) { + m(r, c++) = 1.0; + } + } + return true; +} + +bool SubsetManifold::RightMultiplyByPlusJacobian(const double* x, + const int num_rows, + const double* ambient_matrix, + double* tangent_matrix) const { + if (tangent_size_ == 0) { + return true; + } + + const int ambient_size = AmbientSize(); + for (int r = 0; r < num_rows; ++r) { + for (int idx = 0, c = 0; idx < ambient_size; ++idx) { + if (!constancy_mask_[idx]) { + tangent_matrix[r * tangent_size_ + c++] = + ambient_matrix[r * ambient_size + idx]; + } + } + } + return true; +} + +bool SubsetManifold::Minus(const double* y, + const double* x, + double* y_minus_x) const { + if (tangent_size_ == 0) { + return true; + } + + const int ambient_size = AmbientSize(); + for (int i = 0, j = 0; i < ambient_size; ++i) { + if (!constancy_mask_[i]) { + y_minus_x[j++] = y[i] - x[i]; + } + } + return true; +} + +bool SubsetManifold::MinusJacobian(const double* x, + double* minus_jacobian) const { + const int ambient_size = AmbientSize(); + MatrixRef m(minus_jacobian, tangent_size_, ambient_size); + m.setZero(); + for (int c = 0, r = 0; c < ambient_size; ++c) { + if (!constancy_mask_[c]) { + m(r++, c) = 1.0; + } + } + return true; +} + +bool QuaternionManifold::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + QuaternionPlusImpl<CeresQuaternionOrder>(x, delta, x_plus_delta); + return true; +} + +bool QuaternionManifold::PlusJacobian(const double* x, double* jacobian) const { + QuaternionPlusJacobianImpl<CeresQuaternionOrder>(x, jacobian); + return true; +} + +bool QuaternionManifold::Minus(const double* y, + const double* x, + double* y_minus_x) const { + QuaternionMinusImpl<CeresQuaternionOrder>(y, x, y_minus_x); + return true; +} + +bool QuaternionManifold::MinusJacobian(const double* x, + double* jacobian) const { + QuaternionMinusJacobianImpl<CeresQuaternionOrder>(x, jacobian); + return true; +} + +bool EigenQuaternionManifold::Plus(const double* x, + const double* delta, + double* x_plus_delta) const { + QuaternionPlusImpl<EigenQuaternionOrder>(x, delta, x_plus_delta); + return true; +} + +bool EigenQuaternionManifold::PlusJacobian(const double* x, + double* jacobian) const { + QuaternionPlusJacobianImpl<EigenQuaternionOrder>(x, jacobian); + return true; +} + +bool EigenQuaternionManifold::Minus(const double* y, + const double* x, + double* y_minus_x) const { + QuaternionMinusImpl<EigenQuaternionOrder>(y, x, y_minus_x); + return true; +} + +bool EigenQuaternionManifold::MinusJacobian(const double* x, + double* jacobian) const { + QuaternionMinusJacobianImpl<EigenQuaternionOrder>(x, jacobian); + return true; +} + +} // namespace ceres diff --git a/extern/ceres/internal/ceres/manifold_adapter.h b/extern/ceres/internal/ceres/manifold_adapter.h new file mode 100644 index 00000000000..9a21456a731 --- /dev/null +++ b/extern/ceres/internal/ceres/manifold_adapter.h @@ -0,0 +1,60 @@ +#include "ceres/internal/export.h" +#include "ceres/local_parameterization.h" +#include "ceres/manifold.h" +#include "glog/logging.h" + +namespace ceres { +namespace internal { + +// Adapter to wrap LocalParameterization and make them look like Manifolds. +// +// ManifoldAdapter NEVER takes ownership of local_parameterization. +class CERES_NO_EXPORT ManifoldAdapter final : public Manifold { + public: + explicit ManifoldAdapter(const LocalParameterization* local_parameterization) + : local_parameterization_(local_parameterization) { + CHECK(local_parameterization != nullptr); + } + + bool Plus(const double* x, + const double* delta, + double* x_plus_delta) const override { + return local_parameterization_->Plus(x, delta, x_plus_delta); + } + + bool PlusJacobian(const double* x, double* jacobian) const override { + return local_parameterization_->ComputeJacobian(x, jacobian); + } + + bool RightMultiplyByPlusJacobian(const double* x, + const int num_rows, + const double* ambient_matrix, + double* tangent_matrix) const override { + return local_parameterization_->MultiplyByJacobian( + x, num_rows, ambient_matrix, tangent_matrix); + } + + bool Minus(const double* y, const double* x, double* delta) const override { + LOG(FATAL) << "This should never be called."; + return false; + } + + bool MinusJacobian(const double* x, double* jacobian) const override { + LOG(FATAL) << "This should never be called."; + return false; + } + + int AmbientSize() const override { + return local_parameterization_->GlobalSize(); + } + + int TangentSize() const override { + return local_parameterization_->LocalSize(); + } + + private: + const LocalParameterization* local_parameterization_; +}; + +} // namespace internal +} // namespace ceres diff --git a/extern/ceres/internal/ceres/map_util.h b/extern/ceres/internal/ceres/map_util.h index 6e310f8db2d..5632c22e916 100644 --- a/extern/ceres/internal/ceres/map_util.h +++ b/extern/ceres/internal/ceres/map_util.h @@ -35,7 +35,7 @@ #include <utility> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "glog/logging.h" namespace ceres { @@ -121,7 +121,7 @@ template <class Collection> void InsertOrDie(Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; + using value_type = typename Collection::value_type; CHECK(collection->insert(value_type(key, data)).second) << "duplicate key: " << key; } diff --git a/extern/ceres/internal/ceres/minimizer.cc b/extern/ceres/internal/ceres/minimizer.cc index b96e0c9de44..449c728774d 100644 --- a/extern/ceres/internal/ceres/minimizer.cc +++ b/extern/ceres/internal/ceres/minimizer.cc @@ -30,6 +30,8 @@ #include "ceres/minimizer.h" +#include <memory> + #include "ceres/line_search_minimizer.h" #include "ceres/trust_region_minimizer.h" #include "ceres/types.h" @@ -38,20 +40,20 @@ namespace ceres { namespace internal { -Minimizer* Minimizer::Create(MinimizerType minimizer_type) { +std::unique_ptr<Minimizer> Minimizer::Create(MinimizerType minimizer_type) { if (minimizer_type == TRUST_REGION) { - return new TrustRegionMinimizer; + return std::make_unique<TrustRegionMinimizer>(); } if (minimizer_type == LINE_SEARCH) { - return new LineSearchMinimizer; + return std::make_unique<LineSearchMinimizer>(); } LOG(FATAL) << "Unknown minimizer_type: " << minimizer_type; - return NULL; + return nullptr; } -Minimizer::~Minimizer() {} +Minimizer::~Minimizer() = default; bool Minimizer::RunCallbacks(const Minimizer::Options& options, const IterationSummary& iteration_summary, diff --git a/extern/ceres/internal/ceres/minimizer.h b/extern/ceres/internal/ceres/minimizer.h index 246550de7cd..c2c1f71df9f 100644 --- a/extern/ceres/internal/ceres/minimizer.h +++ b/extern/ceres/internal/ceres/minimizer.h @@ -35,7 +35,8 @@ #include <string> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/iteration_callback.h" #include "ceres/solver.h" @@ -49,7 +50,7 @@ class CoordinateDescentMinimizer; class LinearSolver; // Interface for non-linear least squares solvers. -class CERES_EXPORT_INTERNAL Minimizer { +class CERES_NO_EXPORT Minimizer { public: // Options struct to control the behaviour of the Minimizer. Please // see solver.h for detailed information about the meaning and @@ -178,7 +179,7 @@ class CERES_EXPORT_INTERNAL Minimizer { std::shared_ptr<CoordinateDescentMinimizer> inner_iteration_minimizer; }; - static Minimizer* Create(MinimizerType minimizer_type); + static std::unique_ptr<Minimizer> Create(MinimizerType minimizer_type); static bool RunCallbacks(const Options& options, const IterationSummary& iteration_summary, Solver::Summary* summary); @@ -195,4 +196,6 @@ class CERES_EXPORT_INTERNAL Minimizer { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_MINIMIZER_H_ diff --git a/extern/ceres/internal/ceres/normal_prior.cc b/extern/ceres/internal/ceres/normal_prior.cc index 4a62132dbda..17de40f2e77 100644 --- a/extern/ceres/internal/ceres/normal_prior.cc +++ b/extern/ceres/internal/ceres/normal_prior.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -56,7 +56,7 @@ bool NormalPrior::Evaluate(double const* const* parameters, // r = A_ * (p - b_); // The extra eval is to get around a bug in the eigen library. r = A_ * (p - b_).eval(); - if ((jacobians != NULL) && (jacobians[0] != NULL)) { + if ((jacobians != nullptr) && (jacobians[0] != nullptr)) { MatrixRef(jacobians[0], num_residuals(), parameter_block_sizes()[0]) = A_; } return true; diff --git a/extern/ceres/internal/ceres/pair_hash.h b/extern/ceres/internal/ceres/pair_hash.h index abbedccf961..83ff2b46401 100644 --- a/extern/ceres/internal/ceres/pair_hash.h +++ b/extern/ceres/internal/ceres/pair_hash.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2018 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -33,10 +33,12 @@ #ifndef CERES_INTERNAL_PAIR_HASH_H_ #define CERES_INTERNAL_PAIR_HASH_H_ +#include <cstddef> #include <cstdint> +#include <functional> #include <utility> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { diff --git a/extern/ceres/internal/ceres/parallel_for.h b/extern/ceres/internal/ceres/parallel_for.h index b64bd310650..9528c267d49 100644 --- a/extern/ceres/internal/ceres/parallel_for.h +++ b/extern/ceres/internal/ceres/parallel_for.h @@ -28,37 +28,38 @@ // // Author: vitus@google.com (Michael Vitus) -#ifndef CERES_INTERNAL_PARALLEL_FOR_ -#define CERES_INTERNAL_PARALLEL_FOR_ +#ifndef CERES_INTERNAL_PARALLEL_FOR_H_ +#define CERES_INTERNAL_PARALLEL_FOR_H_ #include <functional> #include "ceres/context_impl.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { // Returns the maximum number of threads supported by the threading backend // Ceres was compiled with. +CERES_NO_EXPORT int MaxNumThreadsAvailable(); // Execute the function for every element in the range [start, end) with at most // num_threads. It will execute all the work on the calling thread if // num_threads is 1. -CERES_EXPORT_INTERNAL void ParallelFor( - ContextImpl* context, - int start, - int end, - int num_threads, - const std::function<void(int)>& function); +CERES_NO_EXPORT void ParallelFor(ContextImpl* context, + int start, + int end, + int num_threads, + const std::function<void(int)>& function); // Execute the function for every element in the range [start, end) with at most // num_threads. It will execute all the work on the calling thread if // num_threads is 1. Each invocation of function() will be passed a thread_id // in [0, num_threads) that is guaranteed to be distinct from the value passed // to any concurrent execution of function(). -CERES_EXPORT_INTERNAL void ParallelFor( +CERES_NO_EXPORT void ParallelFor( ContextImpl* context, int start, int end, @@ -67,4 +68,6 @@ CERES_EXPORT_INTERNAL void ParallelFor( } // namespace internal } // namespace ceres +#include "ceres/internal/disable_warnings.h" + #endif // CERES_INTERNAL_PARALLEL_FOR_H_ diff --git a/extern/ceres/internal/ceres/parallel_for_cxx.cc b/extern/ceres/internal/ceres/parallel_for_cxx.cc index 4da40c01eb6..5b78db19a44 100644 --- a/extern/ceres/internal/ceres/parallel_for_cxx.cc +++ b/extern/ceres/internal/ceres/parallel_for_cxx.cc @@ -29,7 +29,7 @@ // Author: vitus@google.com (Michael Vitus) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifdef CERES_USE_CXX_THREADS @@ -125,7 +125,7 @@ void ParallelFor(ContextImpl* context, int num_threads, const std::function<void(int)>& function) { CHECK_GT(num_threads, 0); - CHECK(context != NULL); + CHECK(context != nullptr); if (end <= start) { return; } @@ -167,7 +167,7 @@ void ParallelFor(ContextImpl* context, int num_threads, const std::function<void(int thread_id, int i)>& function) { CHECK_GT(num_threads, 0); - CHECK(context != NULL); + CHECK(context != nullptr); if (end <= start) { return; } diff --git a/extern/ceres/internal/ceres/parallel_for_nothreads.cc b/extern/ceres/internal/ceres/parallel_for_nothreads.cc index d036569fcd7..1c1871662c8 100644 --- a/extern/ceres/internal/ceres/parallel_for_nothreads.cc +++ b/extern/ceres/internal/ceres/parallel_for_nothreads.cc @@ -29,7 +29,7 @@ // Author: alexs.mac@gmail.com (Alex Stewart) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifdef CERES_NO_THREADS @@ -47,7 +47,7 @@ void ParallelFor(ContextImpl* context, int num_threads, const std::function<void(int)>& function) { CHECK_GT(num_threads, 0); - CHECK(context != NULL); + CHECK(context != nullptr); if (end <= start) { return; } @@ -62,7 +62,7 @@ void ParallelFor(ContextImpl* context, int num_threads, const std::function<void(int thread_id, int i)>& function) { CHECK_GT(num_threads, 0); - CHECK(context != NULL); + CHECK(context != nullptr); if (end <= start) { return; } diff --git a/extern/ceres/internal/ceres/parallel_for_openmp.cc b/extern/ceres/internal/ceres/parallel_for_openmp.cc index eb9d90581ae..1d44bf9977a 100644 --- a/extern/ceres/internal/ceres/parallel_for_openmp.cc +++ b/extern/ceres/internal/ceres/parallel_for_openmp.cc @@ -29,7 +29,7 @@ // Author: vitus@google.com (Michael Vitus) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #if defined(CERES_USE_OPENMP) @@ -50,7 +50,7 @@ void ParallelFor(ContextImpl* context, int num_threads, const std::function<void(int)>& function) { CHECK_GT(num_threads, 0); - CHECK(context != NULL); + CHECK(context != nullptr); if (end <= start) { return; } @@ -69,7 +69,7 @@ void ParallelFor(ContextImpl* context, int end, int num_threads, const std::function<void(int thread_id, int i)>& function) { - CHECK(context != NULL); + CHECK(context != nullptr); ThreadTokenProvider thread_token_provider(num_threads); ParallelFor(context, start, end, num_threads, [&](int i) { diff --git a/extern/ceres/internal/ceres/parallel_utils.h b/extern/ceres/internal/ceres/parallel_utils.h index 89d21106d74..b2d9e0da765 100644 --- a/extern/ceres/internal/ceres/parallel_utils.h +++ b/extern/ceres/internal/ceres/parallel_utils.h @@ -31,7 +31,7 @@ #ifndef CERES_INTERNAL_PARALLEL_UTILS_H_ #define CERES_INTERNAL_PARALLEL_UTILS_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -61,10 +61,10 @@ namespace internal { // }); // which in each iteration will produce i and j satisfying // 0 <= i <= j < n -CERES_EXPORT_INTERNAL void LinearIndexToUpperTriangularIndex(int k, - int n, - int* i, - int* j); +CERES_NO_EXPORT void LinearIndexToUpperTriangularIndex(int k, + int n, + int* i, + int* j); } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/parameter_block.h b/extern/ceres/internal/ceres/parameter_block.h index 88943dfbcff..a9845a3a9e3 100644 --- a/extern/ceres/internal/ceres/parameter_block.h +++ b/extern/ceres/internal/ceres/parameter_block.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 Google Inc. All rights reserved. +// Copyright 2021 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -40,9 +40,10 @@ #include <unordered_set> #include "ceres/array_utils.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" -#include "ceres/local_parameterization.h" +#include "ceres/internal/export.h" +#include "ceres/manifold.h" #include "ceres/stringprintf.h" #include "glog/logging.h" @@ -58,12 +59,12 @@ class ResidualBlock; // methods are performance sensitive. // // The class is not thread-safe, unless only const methods are called. The -// parameter block may also hold a pointer to a local parameterization; the -// parameter block does not take ownership of this pointer, so the user is -// responsible for the proper disposal of the local parameterization. -class ParameterBlock { +// parameter block may also hold a pointer to a manifold; the parameter block +// does not take ownership of this pointer, so the user is responsible for the +// proper disposal of the manifold. +class CERES_NO_EXPORT ParameterBlock { public: - typedef std::unordered_set<ResidualBlock*> ResidualBlockSet; + using ResidualBlockSet = std::unordered_set<ResidualBlock*>; // Create a parameter block with the user state, size, and index specified. // The size is the size of the parameter block and the index is the position @@ -74,16 +75,13 @@ class ParameterBlock { state_(user_state), index_(index) {} - ParameterBlock(double* user_state, - int size, - int index, - LocalParameterization* local_parameterization) + ParameterBlock(double* user_state, int size, int index, Manifold* manifold) : user_state_(user_state), size_(size), state_(user_state), index_(index) { - if (local_parameterization != nullptr) { - SetParameterization(local_parameterization); + if (manifold != nullptr) { + SetManifold(manifold); } } @@ -98,7 +96,7 @@ class ParameterBlock { << "with user location " << user_state_; state_ = x; - return UpdateLocalParameterizationJacobian(); + return UpdatePlusJacobian(); } // Copy the current parameter state out to x. This is "GetState()" rather than @@ -114,17 +112,13 @@ class ParameterBlock { const double* state() const { return state_; } const double* user_state() const { return user_state_; } double* mutable_user_state() { return user_state_; } - const LocalParameterization* local_parameterization() const { - return local_parameterization_; - } - LocalParameterization* mutable_local_parameterization() { - return local_parameterization_; - } + const Manifold* manifold() const { return manifold_; } + Manifold* mutable_manifold() { return manifold_; } // Set this parameter block to vary or not. void SetConstant() { is_set_constant_ = true; } void SetVarying() { is_set_constant_ = false; } - bool IsConstant() const { return (is_set_constant_ || LocalSize() == 0); } + bool IsConstant() const { return (is_set_constant_ || TangentSize() == 0); } double UpperBound(int index) const { return (upper_bounds_ ? upper_bounds_[index] @@ -151,51 +145,46 @@ class ParameterBlock { int delta_offset() const { return delta_offset_; } void set_delta_offset(int delta_offset) { delta_offset_ = delta_offset; } - // Methods relating to the parameter block's parameterization. + // Methods relating to the parameter block's manifold. - // The local to global jacobian. Returns nullptr if there is no local - // parameterization for this parameter block. The returned matrix is row-major - // and has Size() rows and LocalSize() columns. - const double* LocalParameterizationJacobian() const { - return local_parameterization_jacobian_.get(); - } + // The local to global jacobian. Returns nullptr if there is no manifold for + // this parameter block. The returned matrix is row-major and has Size() rows + // and TangentSize() columns. + const double* PlusJacobian() const { return plus_jacobian_.get(); } - int LocalSize() const { - return (local_parameterization_ == nullptr) - ? size_ - : local_parameterization_->LocalSize(); + int TangentSize() const { + return (manifold_ == nullptr) ? size_ : manifold_->TangentSize(); } - // Set the parameterization. The parameter block does not take - // ownership of the parameterization. - void SetParameterization(LocalParameterization* new_parameterization) { - // Nothing to do if the new parameterization is the same as the - // old parameterization. - if (new_parameterization == local_parameterization_) { + // Set the manifold. The parameter block does not take ownership of + // the manifold. + void SetManifold(Manifold* new_manifold) { + // Nothing to do if the new manifold is the same as the old + // manifold. + if (new_manifold == manifold_) { return; } - if (new_parameterization == nullptr) { - local_parameterization_ = nullptr; + if (new_manifold == nullptr) { + manifold_ = nullptr; + plus_jacobian_ = nullptr; return; } - CHECK(new_parameterization->GlobalSize() == size_) - << "Invalid parameterization for parameter block. The parameter block " - << "has size " << size_ << " while the parameterization has a global " - << "size of " << new_parameterization->GlobalSize() << ". Did you " - << "accidentally use the wrong parameter block or parameterization?"; + CHECK_EQ(new_manifold->AmbientSize(), size_) + << "The parameter block has size = " << size_ + << " while the manifold has ambient size = " + << new_manifold->AmbientSize(); - CHECK_GE(new_parameterization->LocalSize(), 0) - << "Invalid parameterization. Parameterizations must have a " + CHECK_GE(new_manifold->TangentSize(), 0) + << "Invalid Manifold. Manifolds must have a " << "non-negative dimensional tangent space."; - local_parameterization_ = new_parameterization; - local_parameterization_jacobian_.reset( - new double[local_parameterization_->GlobalSize() * - local_parameterization_->LocalSize()]); - CHECK(UpdateLocalParameterizationJacobian()) - << "Local parameterization Jacobian computation failed for x: " + manifold_ = new_manifold; + plus_jacobian_ = std::make_unique<double[]>(manifold_->AmbientSize() * + manifold_->TangentSize()); + CHECK(UpdatePlusJacobian()) + << "Manifold::PlusJacobian computation failed for x: " << ConstVectorRef(state_, Size()).transpose(); } @@ -207,7 +196,7 @@ class ParameterBlock { } if (!upper_bounds_) { - upper_bounds_.reset(new double[size_]); + upper_bounds_ = std::make_unique<double[]>(size_); std::fill(upper_bounds_.get(), upper_bounds_.get() + size_, std::numeric_limits<double>::max()); @@ -224,7 +213,7 @@ class ParameterBlock { } if (!lower_bounds_) { - lower_bounds_.reset(new double[size_]); + lower_bounds_ = std::make_unique<double[]>(size_); std::fill(lower_bounds_.get(), lower_bounds_.get() + size_, -std::numeric_limits<double>::max()); @@ -234,11 +223,11 @@ class ParameterBlock { } // Generalization of the addition operation. This is the same as - // LocalParameterization::Plus() followed by projection onto the + // Manifold::Plus() followed by projection onto the // hyper cube implied by the bounds constraints. bool Plus(const double* x, const double* delta, double* x_plus_delta) { - if (local_parameterization_ != nullptr) { - if (!local_parameterization_->Plus(x, delta, x_plus_delta)) { + if (manifold_ != nullptr) { + if (!manifold_->Plus(x, delta, x_plus_delta)) { return false; } } else { @@ -281,7 +270,7 @@ class ParameterBlock { CHECK(residual_blocks_.get() == nullptr) << "Ceres bug: There is already a residual block collection " << "for parameter block: " << ToString(); - residual_blocks_.reset(new ResidualBlockSet); + residual_blocks_ = std::make_unique<ResidualBlockSet>(); } void AddResidualBlock(ResidualBlock* residual_block) { @@ -321,33 +310,30 @@ class ParameterBlock { } private: - bool UpdateLocalParameterizationJacobian() { - if (local_parameterization_ == nullptr) { + bool UpdatePlusJacobian() { + if (manifold_ == nullptr) { return true; } - // Update the local to global Jacobian. In some cases this is + // Update the Plus Jacobian. In some cases this is // wasted effort; if this is a bottleneck, we will find a solution // at that time. - - const int jacobian_size = Size() * LocalSize(); - InvalidateArray(jacobian_size, local_parameterization_jacobian_.get()); - if (!local_parameterization_->ComputeJacobian( - state_, local_parameterization_jacobian_.get())) { - LOG(WARNING) << "Local parameterization Jacobian computation failed" + const int jacobian_size = Size() * TangentSize(); + InvalidateArray(jacobian_size, plus_jacobian_.get()); + if (!manifold_->PlusJacobian(state_, plus_jacobian_.get())) { + LOG(WARNING) << "Manifold::PlusJacobian computation failed" "for x: " << ConstVectorRef(state_, Size()).transpose(); return false; } - if (!IsArrayValid(jacobian_size, local_parameterization_jacobian_.get())) { - LOG(WARNING) << "Local parameterization Jacobian computation returned" + if (!IsArrayValid(jacobian_size, plus_jacobian_.get())) { + LOG(WARNING) << "Manifold::PlusJacobian computation returned " << "an invalid matrix for x: " << ConstVectorRef(state_, Size()).transpose() << "\n Jacobian matrix : " - << ConstMatrixRef(local_parameterization_jacobian_.get(), - Size(), - LocalSize()); + << ConstMatrixRef( + plus_jacobian_.get(), Size(), TangentSize()); return false; } return true; @@ -356,14 +342,14 @@ class ParameterBlock { double* user_state_ = nullptr; int size_ = -1; bool is_set_constant_ = false; - LocalParameterization* local_parameterization_ = nullptr; + Manifold* manifold_ = nullptr; // The "state" of the parameter. These fields are only needed while the // solver is running. While at first glance using mutable is a bad idea, this // ends up simplifying the internals of Ceres enough to justify the potential // pitfalls of using "mutable." mutable const double* state_ = nullptr; - mutable std::unique_ptr<double[]> local_parameterization_jacobian_; + mutable std::unique_ptr<double[]> plus_jacobian_; // The index of the parameter. This is used by various other parts of Ceres to // permit switching from a ParameterBlock* to an index in another array. @@ -392,11 +378,13 @@ class ParameterBlock { std::unique_ptr<double[]> upper_bounds_; std::unique_ptr<double[]> lower_bounds_; - // Necessary so ProblemImpl can clean up the parameterizations. + // Necessary so ProblemImpl can clean up the manifolds. friend class ProblemImpl; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PARAMETER_BLOCK_H_ diff --git a/extern/ceres/internal/ceres/parameter_block_ordering.cc b/extern/ceres/internal/ceres/parameter_block_ordering.cc index 9899c243899..570a09c60ba 100644 --- a/extern/ceres/internal/ceres/parameter_block_ordering.cc +++ b/extern/ceres/internal/ceres/parameter_block_ordering.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -54,14 +54,14 @@ int ComputeStableSchurOrdering(const Program& program, CHECK(ordering != nullptr); ordering->clear(); EventLogger event_logger("ComputeStableSchurOrdering"); - std::unique_ptr<Graph<ParameterBlock*>> graph(CreateHessianGraph(program)); + auto graph = CreateHessianGraph(program); event_logger.AddEvent("CreateHessianGraph"); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); const std::unordered_set<ParameterBlock*>& vertices = graph->vertices(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - if (vertices.count(parameter_blocks[i]) > 0) { - ordering->push_back(parameter_blocks[i]); + for (auto* parameter_block : parameter_blocks) { + if (vertices.count(parameter_block) > 0) { + ordering->push_back(parameter_block); } } event_logger.AddEvent("Preordering"); @@ -70,8 +70,7 @@ int ComputeStableSchurOrdering(const Program& program, event_logger.AddEvent("StableIndependentSet"); // Add the excluded blocks to back of the ordering vector. - for (int i = 0; i < parameter_blocks.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks[i]; + for (auto* parameter_block : parameter_blocks) { if (parameter_block->IsConstant()) { ordering->push_back(parameter_block); } @@ -86,13 +85,12 @@ int ComputeSchurOrdering(const Program& program, CHECK(ordering != nullptr); ordering->clear(); - std::unique_ptr<Graph<ParameterBlock*>> graph(CreateHessianGraph(program)); + auto graph = CreateHessianGraph(program); int independent_set_size = IndependentSetOrdering(*graph, ordering); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); // Add the excluded blocks to back of the ordering vector. - for (int i = 0; i < parameter_blocks.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks[i]; + for (auto* parameter_block : parameter_blocks) { if (parameter_block->IsConstant()) { ordering->push_back(parameter_block); } @@ -106,7 +104,7 @@ void ComputeRecursiveIndependentSetOrdering(const Program& program, CHECK(ordering != nullptr); ordering->Clear(); const vector<ParameterBlock*> parameter_blocks = program.parameter_blocks(); - std::unique_ptr<Graph<ParameterBlock*>> graph(CreateHessianGraph(program)); + auto graph = CreateHessianGraph(program); int num_covered = 0; int round = 0; @@ -124,20 +122,19 @@ void ComputeRecursiveIndependentSetOrdering(const Program& program, } } -Graph<ParameterBlock*>* CreateHessianGraph(const Program& program) { - Graph<ParameterBlock*>* graph = new Graph<ParameterBlock*>; +std::unique_ptr<Graph<ParameterBlock*>> CreateHessianGraph( + const Program& program) { + auto graph = std::make_unique<Graph<ParameterBlock*>>(); CHECK(graph != nullptr); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks[i]; + for (auto* parameter_block : parameter_blocks) { if (!parameter_block->IsConstant()) { graph->AddVertex(parameter_block); } } const vector<ResidualBlock*>& residual_blocks = program.residual_blocks(); - for (int i = 0; i < residual_blocks.size(); ++i) { - const ResidualBlock* residual_block = residual_blocks[i]; + for (auto* residual_block : residual_blocks) { const int num_parameter_blocks = residual_block->NumParameterBlocks(); ParameterBlock* const* parameter_blocks = residual_block->parameter_blocks(); @@ -163,7 +160,7 @@ void OrderingToGroupSizes(const ParameterBlockOrdering* ordering, vector<int>* group_sizes) { CHECK(group_sizes != nullptr); group_sizes->clear(); - if (ordering == NULL) { + if (ordering == nullptr) { return; } diff --git a/extern/ceres/internal/ceres/parameter_block_ordering.h b/extern/ceres/internal/ceres/parameter_block_ordering.h index 82ab75dc6dc..f9a447adf87 100644 --- a/extern/ceres/internal/ceres/parameter_block_ordering.h +++ b/extern/ceres/internal/ceres/parameter_block_ordering.h @@ -31,10 +31,12 @@ #ifndef CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_ #define CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_ +#include <memory> #include <vector> #include "ceres/graph.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/ordered_groups.h" #include "ceres/types.h" @@ -57,20 +59,20 @@ class ParameterBlock; // ordering = [independent set, // complement of the independent set, // fixed blocks] -CERES_EXPORT_INTERNAL int ComputeSchurOrdering( +CERES_NO_EXPORT int ComputeSchurOrdering( const Program& program, std::vector<ParameterBlock*>* ordering); // Same as above, except that ties while computing the independent set // ordering are resolved in favour of the order in which the parameter // blocks occur in the program. -CERES_EXPORT_INTERNAL int ComputeStableSchurOrdering( +CERES_NO_EXPORT int ComputeStableSchurOrdering( const Program& program, std::vector<ParameterBlock*>* ordering); // Use an approximate independent set ordering to decompose the // parameter blocks of a problem in a sequence of independent // sets. The ordering covers all the non-constant parameter blocks in // the program. -CERES_EXPORT_INTERNAL void ComputeRecursiveIndependentSetOrdering( +CERES_NO_EXPORT void ComputeRecursiveIndependentSetOrdering( const Program& program, ParameterBlockOrdering* ordering); // Builds a graph on the parameter blocks of a Problem, whose @@ -78,15 +80,17 @@ CERES_EXPORT_INTERNAL void ComputeRecursiveIndependentSetOrdering( // vertex corresponds to a parameter block in the Problem except for // parameter blocks that are marked constant. An edge connects two // parameter blocks, if they co-occur in a residual block. -CERES_EXPORT_INTERNAL Graph<ParameterBlock*>* CreateHessianGraph( +CERES_NO_EXPORT std::unique_ptr<Graph<ParameterBlock*>> CreateHessianGraph( const Program& program); // Iterate over each of the groups in order of their priority and fill // summary with their sizes. -CERES_EXPORT_INTERNAL void OrderingToGroupSizes( +CERES_NO_EXPORT void OrderingToGroupSizes( const ParameterBlockOrdering* ordering, std::vector<int>* group_sizes); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PARAMETER_BLOCK_ORDERING_H_ diff --git a/extern/ceres/internal/ceres/partitioned_matrix_view.cc b/extern/ceres/internal/ceres/partitioned_matrix_view.cc index b67bc905d15..d38f30a09d7 100644 --- a/extern/ceres/internal/ceres/partitioned_matrix_view.cc +++ b/extern/ceres/internal/ceres/partitioned_matrix_view.cc @@ -39,143 +39,147 @@ // // This file is generated using generate_template_specializations.py. +#include <memory> + #include "ceres/linear_solver.h" #include "ceres/partitioned_matrix_view.h" namespace ceres { namespace internal { -PartitionedMatrixViewBase* PartitionedMatrixViewBase::Create( +PartitionedMatrixViewBase::~PartitionedMatrixViewBase() = default; + +std::unique_ptr<PartitionedMatrixViewBase> PartitionedMatrixViewBase::Create( const LinearSolver::Options& options, const BlockSparseMatrix& matrix) { #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 2)) { - return new PartitionedMatrixView<2, 2, 2>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,2, 2>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 3)) { - return new PartitionedMatrixView<2, 2, 3>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,2, 3>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 4)) { - return new PartitionedMatrixView<2, 2, 4>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,2, 4>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 2)) { - return new PartitionedMatrixView<2, 2, Eigen::Dynamic>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,2, Eigen::Dynamic>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 3)) { - return new PartitionedMatrixView<2, 3, 3>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,3, 3>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 4)) { - return new PartitionedMatrixView<2, 3, 4>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,3, 4>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 6)) { - return new PartitionedMatrixView<2, 3, 6>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,3, 6>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 9)) { - return new PartitionedMatrixView<2, 3, 9>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,3, 9>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 3)) { - return new PartitionedMatrixView<2, 3, Eigen::Dynamic>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,3, Eigen::Dynamic>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 3)) { - return new PartitionedMatrixView<2, 4, 3>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, 3>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 4)) { - return new PartitionedMatrixView<2, 4, 4>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, 4>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 6)) { - return new PartitionedMatrixView<2, 4, 6>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, 6>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 8)) { - return new PartitionedMatrixView<2, 4, 8>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, 8>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 9)) { - return new PartitionedMatrixView<2, 4, 9>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, 9>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 2) && (options.e_block_size == 4)) { - return new PartitionedMatrixView<2, 4, Eigen::Dynamic>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,4, Eigen::Dynamic>>( + matrix, options.elimination_groups[0]); } if (options.row_block_size == 2) { - return new PartitionedMatrixView<2, Eigen::Dynamic, Eigen::Dynamic>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<2,Eigen::Dynamic, Eigen::Dynamic>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 3) && (options.e_block_size == 3) && (options.f_block_size == 3)) { - return new PartitionedMatrixView<3, 3, 3>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<3,3, 3>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 2)) { - return new PartitionedMatrixView<4, 4, 2>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<4,4, 2>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 3)) { - return new PartitionedMatrixView<4, 4, 3>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<4,4, 3>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 4)) { - return new PartitionedMatrixView<4, 4, 4>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<4,4, 4>>( + matrix, options.elimination_groups[0]); } if ((options.row_block_size == 4) && (options.e_block_size == 4)) { - return new PartitionedMatrixView<4, 4, Eigen::Dynamic>(matrix, - options.elimination_groups[0]); + return std::make_unique<PartitionedMatrixView<4,4, Eigen::Dynamic>>( + matrix, options.elimination_groups[0]); } #endif VLOG(1) << "Template specializations not found for <" << options.row_block_size << "," << options.e_block_size << "," << options.f_block_size << ">"; - return new PartitionedMatrixView<Eigen::Dynamic, - Eigen::Dynamic, - Eigen::Dynamic>( + return std::make_unique<PartitionedMatrixView<Eigen::Dynamic, + Eigen::Dynamic, + Eigen::Dynamic>>( matrix, options.elimination_groups[0]); }; diff --git a/extern/ceres/internal/ceres/partitioned_matrix_view.h b/extern/ceres/internal/ceres/partitioned_matrix_view.h index 9f204ee1fdd..5623d3b6bca 100644 --- a/extern/ceres/internal/ceres/partitioned_matrix_view.h +++ b/extern/ceres/internal/ceres/partitioned_matrix_view.h @@ -38,11 +38,14 @@ #include <algorithm> #include <cstring> +#include <memory> #include <vector> #include "ceres/block_structure.h" +#include "ceres/internal/config.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "ceres/small_blas.h" #include "glog/logging.h" @@ -60,9 +63,9 @@ namespace internal { // block structure of the matrix does not satisfy the requirements of // the Schur complement solver it will result in unpredictable and // wrong output. -class CERES_EXPORT_INTERNAL PartitionedMatrixViewBase { +class CERES_NO_EXPORT PartitionedMatrixViewBase { public: - virtual ~PartitionedMatrixViewBase() {} + virtual ~PartitionedMatrixViewBase(); // y += E'x virtual void LeftMultiplyE(const double* x, double* y) const = 0; @@ -77,11 +80,11 @@ class CERES_EXPORT_INTERNAL PartitionedMatrixViewBase { virtual void RightMultiplyF(const double* x, double* y) const = 0; // Create and return the block diagonal of the matrix E'E. - virtual BlockSparseMatrix* CreateBlockDiagonalEtE() const = 0; + virtual std::unique_ptr<BlockSparseMatrix> CreateBlockDiagonalEtE() const = 0; // Create and return the block diagonal of the matrix F'F. Caller // owns the result. - virtual BlockSparseMatrix* CreateBlockDiagonalFtF() const = 0; + virtual std::unique_ptr<BlockSparseMatrix> CreateBlockDiagonalFtF() const = 0; // Compute the block diagonal of the matrix E'E and store it in // block_diagonal. The matrix block_diagonal is expected to have a @@ -108,26 +111,26 @@ class CERES_EXPORT_INTERNAL PartitionedMatrixViewBase { virtual int num_cols() const = 0; // clang-format on - static PartitionedMatrixViewBase* Create(const LinearSolver::Options& options, - const BlockSparseMatrix& matrix); + static std::unique_ptr<PartitionedMatrixViewBase> Create( + const LinearSolver::Options& options, const BlockSparseMatrix& matrix); }; template <int kRowBlockSize = Eigen::Dynamic, int kEBlockSize = Eigen::Dynamic, int kFBlockSize = Eigen::Dynamic> -class PartitionedMatrixView : public PartitionedMatrixViewBase { +class CERES_NO_EXPORT PartitionedMatrixView final + : public PartitionedMatrixViewBase { public: // matrix = [E F], where the matrix E contains the first // num_col_blocks_a column blocks. PartitionedMatrixView(const BlockSparseMatrix& matrix, int num_col_blocks_e); - virtual ~PartitionedMatrixView(); void LeftMultiplyE(const double* x, double* y) const final; void LeftMultiplyF(const double* x, double* y) const final; void RightMultiplyE(const double* x, double* y) const final; void RightMultiplyF(const double* x, double* y) const final; - BlockSparseMatrix* CreateBlockDiagonalEtE() const final; - BlockSparseMatrix* CreateBlockDiagonalFtF() const final; + std::unique_ptr<BlockSparseMatrix> CreateBlockDiagonalEtE() const final; + std::unique_ptr<BlockSparseMatrix> CreateBlockDiagonalFtF() const final; void UpdateBlockDiagonalEtE(BlockSparseMatrix* block_diagonal) const final; void UpdateBlockDiagonalFtF(BlockSparseMatrix* block_diagonal) const final; // clang-format off @@ -140,8 +143,8 @@ class PartitionedMatrixView : public PartitionedMatrixViewBase { // clang-format on private: - BlockSparseMatrix* CreateBlockDiagonalMatrixLayout(int start_col_block, - int end_col_block) const; + std::unique_ptr<BlockSparseMatrix> CreateBlockDiagonalMatrixLayout( + int start_col_block, int end_col_block) const; const BlockSparseMatrix& matrix_; int num_row_blocks_e_; @@ -154,4 +157,6 @@ class PartitionedMatrixView : public PartitionedMatrixViewBase { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PARTITIONED_MATRIX_VIEW_H_ diff --git a/extern/ceres/internal/ceres/partitioned_matrix_view_impl.h b/extern/ceres/internal/ceres/partitioned_matrix_view_impl.h index 0b6a57fb9f2..2e818caa6ef 100644 --- a/extern/ceres/internal/ceres/partitioned_matrix_view_impl.h +++ b/extern/ceres/internal/ceres/partitioned_matrix_view_impl.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -30,6 +30,7 @@ #include <algorithm> #include <cstring> +#include <memory> #include <vector> #include "ceres/block_sparse_matrix.h" @@ -57,8 +58,8 @@ PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: // e_blocks. For a definition of what an e_block is, please see // explicit_schur_complement_solver.h num_row_blocks_e_ = 0; - for (int r = 0; r < bs->rows.size(); ++r) { - const std::vector<Cell>& cells = bs->rows[r].cells; + for (const auto& row : bs->rows) { + const std::vector<Cell>& cells = row.cells; if (cells[0].block_id < num_col_blocks_e_) { ++num_row_blocks_e_; } @@ -80,10 +81,6 @@ PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: CHECK_EQ(num_cols_e_ + num_cols_f_, matrix_.num_cols()); } -template <int kRowBlockSize, int kEBlockSize, int kFBlockSize> -PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: - ~PartitionedMatrixView() {} - // The next four methods don't seem to be particularly cache // friendly. This is an artifact of how the BlockStructure of the // input matrix is constructed. These methods will benefit from @@ -145,13 +142,13 @@ void PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: const int row_block_pos = bs->rows[r].block.position; const int row_block_size = bs->rows[r].block.size; const std::vector<Cell>& cells = bs->rows[r].cells; - for (int c = 0; c < cells.size(); ++c) { - const int col_block_id = cells[c].block_id; + for (const auto& cell : cells) { + const int col_block_id = cell.block_id; const int col_block_pos = bs->cols[col_block_id].position; const int col_block_size = bs->cols[col_block_id].size; // clang-format off MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - values + cells[c].position, row_block_size, col_block_size, + values + cell.position, row_block_size, col_block_size, x + col_block_pos - num_cols_e_, y + row_block_pos); // clang-format on @@ -215,13 +212,13 @@ void PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: const int row_block_pos = bs->rows[r].block.position; const int row_block_size = bs->rows[r].block.size; const std::vector<Cell>& cells = bs->rows[r].cells; - for (int c = 0; c < cells.size(); ++c) { - const int col_block_id = cells[c].block_id; + for (const auto& cell : cells) { + const int col_block_id = cell.block_id; const int col_block_pos = bs->cols[col_block_id].position; const int col_block_size = bs->cols[col_block_id].size; // clang-format off MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( - values + cells[c].position, row_block_size, col_block_size, + values + cell.position, row_block_size, col_block_size, x + row_block_pos, y + col_block_pos - num_cols_e_); // clang-format on @@ -235,13 +232,12 @@ void PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: // and return a BlockSparseMatrix with the this block structure. The // caller owns the result. template <int kRowBlockSize, int kEBlockSize, int kFBlockSize> -BlockSparseMatrix* +std::unique_ptr<BlockSparseMatrix> PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: CreateBlockDiagonalMatrixLayout(int start_col_block, int end_col_block) const { const CompressedRowBlockStructure* bs = matrix_.block_structure(); - CompressedRowBlockStructure* block_diagonal_structure = - new CompressedRowBlockStructure; + auto* block_diagonal_structure = new CompressedRowBlockStructure; int block_position = 0; int diagonal_cell_position = 0; @@ -250,16 +246,16 @@ PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: // each column block. for (int c = start_col_block; c < end_col_block; ++c) { const Block& block = bs->cols[c]; - block_diagonal_structure->cols.push_back(Block()); + block_diagonal_structure->cols.emplace_back(); Block& diagonal_block = block_diagonal_structure->cols.back(); diagonal_block.size = block.size; diagonal_block.position = block_position; - block_diagonal_structure->rows.push_back(CompressedRow()); + block_diagonal_structure->rows.emplace_back(); CompressedRow& row = block_diagonal_structure->rows.back(); row.block = diagonal_block; - row.cells.push_back(Cell()); + row.cells.emplace_back(); Cell& cell = row.cells.back(); cell.block_id = c - start_col_block; cell.position = diagonal_cell_position; @@ -270,28 +266,27 @@ PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: // Build a BlockSparseMatrix with the just computed block // structure. - return new BlockSparseMatrix(block_diagonal_structure); + return std::make_unique<BlockSparseMatrix>(block_diagonal_structure); } template <int kRowBlockSize, int kEBlockSize, int kFBlockSize> -BlockSparseMatrix* PartitionedMatrixView<kRowBlockSize, - kEBlockSize, - kFBlockSize>::CreateBlockDiagonalEtE() - const { - BlockSparseMatrix* block_diagonal = +std::unique_ptr<BlockSparseMatrix> +PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: + CreateBlockDiagonalEtE() const { + std::unique_ptr<BlockSparseMatrix> block_diagonal = CreateBlockDiagonalMatrixLayout(0, num_col_blocks_e_); - UpdateBlockDiagonalEtE(block_diagonal); + UpdateBlockDiagonalEtE(block_diagonal.get()); return block_diagonal; } template <int kRowBlockSize, int kEBlockSize, int kFBlockSize> -BlockSparseMatrix* PartitionedMatrixView<kRowBlockSize, - kEBlockSize, - kFBlockSize>::CreateBlockDiagonalFtF() - const { - BlockSparseMatrix* block_diagonal = CreateBlockDiagonalMatrixLayout( - num_col_blocks_e_, num_col_blocks_e_ + num_col_blocks_f_); - UpdateBlockDiagonalFtF(block_diagonal); +std::unique_ptr<BlockSparseMatrix> +PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: + CreateBlockDiagonalFtF() const { + std::unique_ptr<BlockSparseMatrix> block_diagonal = + CreateBlockDiagonalMatrixLayout(num_col_blocks_e_, + num_col_blocks_e_ + num_col_blocks_f_); + UpdateBlockDiagonalFtF(block_diagonal.get()); return block_diagonal; } @@ -366,8 +361,8 @@ void PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: for (int r = num_row_blocks_e_; r < bs->rows.size(); ++r) { const int row_block_size = bs->rows[r].block.size; const std::vector<Cell>& cells = bs->rows[r].cells; - for (int c = 0; c < cells.size(); ++c) { - const int col_block_id = cells[c].block_id; + for (const auto& cell : cells) { + const int col_block_id = cell.block_id; const int col_block_size = bs->cols[col_block_id].size; const int diagonal_block_id = col_block_id - num_col_blocks_e_; const int cell_position = @@ -376,8 +371,8 @@ void PartitionedMatrixView<kRowBlockSize, kEBlockSize, kFBlockSize>:: // clang-format off MatrixTransposeMatrixMultiply <Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic, 1>( - values + cells[c].position, row_block_size, col_block_size, - values + cells[c].position, row_block_size, col_block_size, + values + cell.position, row_block_size, col_block_size, + values + cell.position, row_block_size, col_block_size, block_diagonal->mutable_values() + cell_position, 0, 0, col_block_size, col_block_size); // clang-format on diff --git a/extern/ceres/internal/ceres/partitioned_matrix_view_template.py b/extern/ceres/internal/ceres/partitioned_matrix_view_template.py deleted file mode 100644 index 05a25bf8335..00000000000 --- a/extern/ceres/internal/ceres/partitioned_matrix_view_template.py +++ /dev/null @@ -1,151 +0,0 @@ -# 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) -# -# Script for explicitly generating template specialization of the -# PartitionedMatrixView class. Explicitly generating these -# instantiations in separate .cc files breaks the compilation into -# separate compilation unit rather than one large cc file. -# -# This script creates two sets of files. -# -# 1. partitioned_matrix_view_x_x_x.cc -# where the x indicates the template parameters and -# -# 2. partitioned_matrix_view.cc -# -# that contains a factory function for instantiating these classes -# based on runtime parameters. -# -# The list of tuples, specializations indicates the set of -# specializations that is generated. - -HEADER = """// 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) -// -// Template specialization of PartitionedMatrixView. -// -// ======================================== -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -//========================================= -// -// This file is generated using generate_template_specializations.py. -""" - -DYNAMIC_FILE = """ -#include "ceres/partitioned_matrix_view_impl.h" - -namespace ceres { -namespace internal { - -template class PartitionedMatrixView<%s, - %s, - %s>; - -} // namespace internal -} // namespace ceres -""" - -SPECIALIZATION_FILE = """ -// This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" - -#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION - -#include "ceres/partitioned_matrix_view_impl.h" - -namespace ceres { -namespace internal { - -template class PartitionedMatrixView<%s, %s, %s>; - -} // namespace internal -} // namespace ceres - -#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION -""" - -FACTORY_FILE_HEADER = """ -#include "ceres/linear_solver.h" -#include "ceres/partitioned_matrix_view.h" - -namespace ceres { -namespace internal { - -PartitionedMatrixViewBase* PartitionedMatrixViewBase::Create( - const LinearSolver::Options& options, const BlockSparseMatrix& matrix) { -#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION -""" -FACTORY = """ return new PartitionedMatrixView<%s, %s, %s>(matrix, - options.elimination_groups[0]);""" - -FACTORY_FOOTER = """ -#endif - VLOG(1) << "Template specializations not found for <" - << options.row_block_size << "," << options.e_block_size << "," - << options.f_block_size << ">"; - return new PartitionedMatrixView<Eigen::Dynamic, - Eigen::Dynamic, - Eigen::Dynamic>( - matrix, options.elimination_groups[0]); -}; - -} // namespace internal -} // namespace ceres -""" diff --git a/extern/ceres/internal/ceres/polynomial.cc b/extern/ceres/internal/ceres/polynomial.cc index 20812f4de81..96267aae97f 100644 --- a/extern/ceres/internal/ceres/polynomial.cc +++ b/extern/ceres/internal/ceres/polynomial.cc @@ -37,7 +37,7 @@ #include "Eigen/Dense" #include "ceres/function_sample.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "glog/logging.h" namespace ceres { @@ -128,12 +128,12 @@ void FindLinearPolynomialRoots(const Vector& polynomial, Vector* real, Vector* imaginary) { CHECK_EQ(polynomial.size(), 2); - if (real != NULL) { + if (real != nullptr) { real->resize(1); (*real)(0) = -polynomial(1) / polynomial(0); } - if (imaginary != NULL) { + if (imaginary != nullptr) { imaginary->setZero(1); } } @@ -147,16 +147,16 @@ void FindQuadraticPolynomialRoots(const Vector& polynomial, const double c = polynomial(2); const double D = b * b - 4 * a * c; const double sqrt_D = sqrt(fabs(D)); - if (real != NULL) { + if (real != nullptr) { real->setZero(2); } - if (imaginary != NULL) { + if (imaginary != nullptr) { imaginary->setZero(2); } // Real roots. if (D >= 0) { - if (real != NULL) { + if (real != nullptr) { // Stable quadratic roots according to BKP Horn. // http://people.csail.mit.edu/bkph/articles/Quadratics.pdf if (b >= 0) { @@ -171,11 +171,11 @@ void FindQuadraticPolynomialRoots(const Vector& polynomial, } // Use the normal quadratic formula for the complex case. - if (real != NULL) { + if (real != nullptr) { (*real)(0) = -b / (2.0 * a); (*real)(1) = -b / (2.0 * a); } - if (imaginary != NULL) { + if (imaginary != nullptr) { (*imaginary)(0) = sqrt_D / (2.0 * a); (*imaginary)(1) = -sqrt_D / (2.0 * a); } @@ -240,14 +240,14 @@ bool FindPolynomialRoots(const Vector& polynomial_in, } // Output roots - if (real != NULL) { + if (real != nullptr) { *real = solver.eigenvalues().real(); } else { - LOG(WARNING) << "NULL pointer passed as real argument to " + LOG(WARNING) << "nullptr pointer passed as real argument to " << "FindPolynomialRoots. Real parts of the roots will not " << "be returned."; } - if (imaginary != NULL) { + if (imaginary != nullptr) { *imaginary = solver.eigenvalues().imag(); } return true; @@ -304,7 +304,7 @@ void MinimizePolynomial(const Vector& polynomial, const Vector derivative = DifferentiatePolynomial(polynomial); Vector roots_real; - if (!FindPolynomialRoots(derivative, &roots_real, NULL)) { + if (!FindPolynomialRoots(derivative, &roots_real, nullptr)) { LOG(WARNING) << "Unable to find the critical points of " << "the interpolating polynomial."; return; @@ -376,8 +376,7 @@ void MinimizeInterpolatingPolynomial(const vector<FunctionSample>& samples, double* optimal_value) { const Vector polynomial = FindInterpolatingPolynomial(samples); MinimizePolynomial(polynomial, x_min, x_max, optimal_x, optimal_value); - for (int i = 0; i < samples.size(); ++i) { - const FunctionSample& sample = samples[i]; + for (const auto& sample : samples) { if ((sample.x < x_min) || (sample.x > x_max)) { continue; } diff --git a/extern/ceres/internal/ceres/polynomial.h b/extern/ceres/internal/ceres/polynomial.h index 20071f2c693..3ca753c4618 100644 --- a/extern/ceres/internal/ceres/polynomial.h +++ b/extern/ceres/internal/ceres/polynomial.h @@ -34,8 +34,9 @@ #include <vector> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -49,6 +50,7 @@ struct FunctionSample; // and are given by a vector of coefficients of size N + 1. // Evaluate the polynomial at x using the Horner scheme. +CERES_NO_EXPORT inline double EvaluatePolynomial(const Vector& polynomial, double x) { double v = 0.0; for (int i = 0; i < polynomial.size(); ++i) { @@ -64,15 +66,16 @@ inline double EvaluatePolynomial(const Vector& polynomial, double x) { // Failure indicates that the polynomial is invalid (of size 0) or // that the eigenvalues of the companion matrix could not be computed. // On failure, a more detailed message will be written to LOG(ERROR). -// If real is not NULL, the real parts of the roots will be returned in it. -// Likewise, if imaginary is not NULL, imaginary parts will be returned in it. -CERES_EXPORT_INTERNAL bool FindPolynomialRoots(const Vector& polynomial, - Vector* real, - Vector* imaginary); +// If real is not nullptr, the real parts of the roots will be returned in it. +// Likewise, if imaginary is not nullptr, imaginary parts will be returned in +// it. +CERES_NO_EXPORT bool FindPolynomialRoots(const Vector& polynomial, + Vector* real, + Vector* imaginary); // Return the derivative of the given polynomial. It is assumed that // the input polynomial is at least of degree zero. -CERES_EXPORT_INTERNAL Vector DifferentiatePolynomial(const Vector& polynomial); +CERES_NO_EXPORT Vector DifferentiatePolynomial(const Vector& polynomial); // Find the minimum value of the polynomial in the interval [x_min, // x_max]. The minimum is obtained by computing all the roots of the @@ -80,11 +83,11 @@ CERES_EXPORT_INTERNAL Vector DifferentiatePolynomial(const Vector& polynomial); // interval [x_min, x_max] are considered as well as the end points // x_min and x_max. Since polynomials are differentiable functions, // this ensures that the true minimum is found. -CERES_EXPORT_INTERNAL void MinimizePolynomial(const Vector& polynomial, - double x_min, - double x_max, - double* optimal_x, - double* optimal_value); +CERES_NO_EXPORT void MinimizePolynomial(const Vector& polynomial, + double x_min, + double x_max, + double* optimal_x, + double* optimal_value); // Given a set of function value and/or gradient samples, find a // polynomial whose value and gradients are exactly equal to the ones @@ -97,7 +100,7 @@ CERES_EXPORT_INTERNAL void MinimizePolynomial(const Vector& polynomial, // Of course its possible to sample a polynomial any number of times, // in which case, generally speaking the spurious higher order // coefficients will be zero. -CERES_EXPORT_INTERNAL Vector +CERES_NO_EXPORT Vector FindInterpolatingPolynomial(const std::vector<FunctionSample>& samples); // Interpolate the function described by samples with a polynomial, @@ -106,7 +109,7 @@ FindInterpolatingPolynomial(const std::vector<FunctionSample>& samples); // finding algorithms may fail due to numerical difficulties. But the // function is guaranteed to return its best guess of an answer, by // considering the samples and the end points as possible solutions. -CERES_EXPORT_INTERNAL void MinimizeInterpolatingPolynomial( +CERES_NO_EXPORT void MinimizeInterpolatingPolynomial( const std::vector<FunctionSample>& samples, double x_min, double x_max, @@ -116,4 +119,6 @@ CERES_EXPORT_INTERNAL void MinimizeInterpolatingPolynomial( } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_POLYNOMIAL_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/preconditioner.cc b/extern/ceres/internal/ceres/preconditioner.cc index 69ba04db8f5..17b9629cf94 100644 --- a/extern/ceres/internal/ceres/preconditioner.cc +++ b/extern/ceres/internal/ceres/preconditioner.cc @@ -35,7 +35,7 @@ namespace ceres { namespace internal { -Preconditioner::~Preconditioner() {} +Preconditioner::~Preconditioner() = default; PreconditionerType Preconditioner::PreconditionerForZeroEBlocks( PreconditionerType preconditioner_type) { @@ -53,7 +53,8 @@ SparseMatrixPreconditionerWrapper::SparseMatrixPreconditionerWrapper( CHECK(matrix != nullptr); } -SparseMatrixPreconditionerWrapper::~SparseMatrixPreconditionerWrapper() {} +SparseMatrixPreconditionerWrapper::~SparseMatrixPreconditionerWrapper() = + default; bool SparseMatrixPreconditionerWrapper::UpdateImpl(const SparseMatrix& A, const double* D) { diff --git a/extern/ceres/internal/ceres/preconditioner.h b/extern/ceres/internal/ceres/preconditioner.h index dd843b01ce3..6433cc7dd38 100644 --- a/extern/ceres/internal/ceres/preconditioner.h +++ b/extern/ceres/internal/ceres/preconditioner.h @@ -36,7 +36,8 @@ #include "ceres/casts.h" #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/context_impl.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_operator.h" #include "ceres/sparse_matrix.h" #include "ceres/types.h" @@ -47,7 +48,7 @@ namespace internal { class BlockSparseMatrix; class SparseMatrix; -class CERES_EXPORT_INTERNAL Preconditioner : public LinearOperator { +class CERES_NO_EXPORT Preconditioner : public LinearOperator { public: struct Options { PreconditionerType type = JACOBI; @@ -115,7 +116,7 @@ class CERES_EXPORT_INTERNAL Preconditioner : public LinearOperator { static PreconditionerType PreconditionerForZeroEBlocks( PreconditionerType preconditioner_type); - virtual ~Preconditioner(); + ~Preconditioner() override; // Update the numerical value of the preconditioner for the linear // system: @@ -126,7 +127,7 @@ class CERES_EXPORT_INTERNAL Preconditioner : public LinearOperator { // for some vector b. It is important that the matrix A have the // same block structure as the one used to construct this object. // - // D can be NULL, in which case its interpreted as a diagonal matrix + // D can be nullptr, in which case its interpreted as a diagonal matrix // of size zero. virtual bool Update(const LinearOperator& A, const double* D) = 0; @@ -147,9 +148,8 @@ class CERES_EXPORT_INTERNAL Preconditioner : public LinearOperator { // other preconditioners that depend on the particular matrix layout of // the underlying linear operator. template <typename MatrixType> -class TypedPreconditioner : public Preconditioner { +class CERES_NO_EXPORT TypedPreconditioner : public Preconditioner { public: - virtual ~TypedPreconditioner() {} bool Update(const LinearOperator& A, const double* D) final { return UpdateImpl(*down_cast<const MatrixType*>(&A), D); } @@ -161,28 +161,31 @@ class TypedPreconditioner : public Preconditioner { // Preconditioners that depend on access to the low level structure // of a SparseMatrix. // clang-format off -typedef TypedPreconditioner<SparseMatrix> SparseMatrixPreconditioner; -typedef TypedPreconditioner<BlockSparseMatrix> BlockSparseMatrixPreconditioner; -typedef TypedPreconditioner<CompressedRowSparseMatrix> CompressedRowSparseMatrixPreconditioner; +using SparseMatrixPreconditioner = TypedPreconditioner<SparseMatrix>; +using BlockSparseMatrixPreconditioner = TypedPreconditioner<BlockSparseMatrix>; +using CompressedRowSparseMatrixPreconditioner = TypedPreconditioner<CompressedRowSparseMatrix>; // clang-format on // Wrap a SparseMatrix object as a preconditioner. -class SparseMatrixPreconditionerWrapper : public SparseMatrixPreconditioner { +class CERES_NO_EXPORT SparseMatrixPreconditionerWrapper final + : public SparseMatrixPreconditioner { public: // Wrapper does NOT take ownership of the matrix pointer. explicit SparseMatrixPreconditionerWrapper(const SparseMatrix* matrix); - virtual ~SparseMatrixPreconditionerWrapper(); + ~SparseMatrixPreconditionerWrapper() override; // Preconditioner interface - virtual void RightMultiply(const double* x, double* y) const; - virtual int num_rows() const; + void RightMultiply(const double* x, double* y) const override; + int num_rows() const override; private: - virtual bool UpdateImpl(const SparseMatrix& A, const double* D); + bool UpdateImpl(const SparseMatrix& A, const double* D) override; const SparseMatrix* matrix_; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PRECONDITIONER_H_ diff --git a/extern/ceres/internal/ceres/preprocessor.cc b/extern/ceres/internal/ceres/preprocessor.cc index 6a67d385645..44f0974dc5a 100644 --- a/extern/ceres/internal/ceres/preprocessor.cc +++ b/extern/ceres/internal/ceres/preprocessor.cc @@ -30,6 +30,8 @@ #include "ceres/preprocessor.h" +#include <memory> + #include "ceres/callbacks.h" #include "ceres/gradient_checking_cost_function.h" #include "ceres/line_search_preprocessor.h" @@ -41,22 +43,26 @@ namespace ceres { namespace internal { -Preprocessor* Preprocessor::Create(MinimizerType minimizer_type) { +std::unique_ptr<Preprocessor> Preprocessor::Create( + MinimizerType minimizer_type) { if (minimizer_type == TRUST_REGION) { - return new TrustRegionPreprocessor; + return std::make_unique<TrustRegionPreprocessor>(); } if (minimizer_type == LINE_SEARCH) { - return new LineSearchPreprocessor; + return std::make_unique<LineSearchPreprocessor>(); } LOG(FATAL) << "Unknown minimizer_type: " << minimizer_type; - return NULL; + return nullptr; } -Preprocessor::~Preprocessor() {} +Preprocessor::~Preprocessor() = default; void ChangeNumThreadsIfNeeded(Solver::Options* options) { + if (options->num_threads == 1) { + return; + } const int num_threads_available = MaxNumThreadsAvailable(); if (options->num_threads > num_threads_available) { LOG(WARNING) << "Specified options.num_threads: " << options->num_threads @@ -82,15 +88,15 @@ void SetupCommonMinimizerOptions(PreprocessedProblem* pp) { minimizer_options.evaluator = pp->evaluator; if (options.logging_type != SILENT) { - pp->logging_callback.reset(new LoggingCallback( - options.minimizer_type, options.minimizer_progress_to_stdout)); + pp->logging_callback = std::make_unique<LoggingCallback>( + options.minimizer_type, options.minimizer_progress_to_stdout); minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), pp->logging_callback.get()); } if (options.update_state_every_iteration) { - pp->state_updating_callback.reset( - new StateUpdatingCallback(program, reduced_parameters)); + pp->state_updating_callback = + std::make_unique<StateUpdatingCallback>(program, reduced_parameters); // This must get pushed to the front of the callbacks so that it // is run before any of the user callbacks. minimizer_options.callbacks.insert(minimizer_options.callbacks.begin(), diff --git a/extern/ceres/internal/ceres/preprocessor.h b/extern/ceres/internal/ceres/preprocessor.h index ec56c6e430a..b5db80af7e6 100644 --- a/extern/ceres/internal/ceres/preprocessor.h +++ b/extern/ceres/internal/ceres/preprocessor.h @@ -37,8 +37,9 @@ #include "ceres/coordinate_descent_minimizer.h" #include "ceres/evaluator.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/iteration_callback.h" #include "ceres/linear_solver.h" #include "ceres/minimizer.h" @@ -67,10 +68,10 @@ struct PreprocessedProblem; // // The output of the Preprocessor is stored in a PreprocessedProblem // object. -class CERES_EXPORT_INTERNAL Preprocessor { +class CERES_NO_EXPORT Preprocessor { public: // Factory. - static Preprocessor* Create(MinimizerType minimizer_type); + static std::unique_ptr<Preprocessor> Create(MinimizerType minimizer_type); virtual ~Preprocessor(); virtual bool Preprocess(const Solver::Options& options, ProblemImpl* problem, @@ -79,8 +80,8 @@ class CERES_EXPORT_INTERNAL Preprocessor { // A PreprocessedProblem is the result of running the Preprocessor on // a Problem and Solver::Options object. -struct PreprocessedProblem { - PreprocessedProblem() : fixed_cost(0.0) {} +struct CERES_NO_EXPORT PreprocessedProblem { + PreprocessedProblem() = default; std::string error; Solver::Options options; @@ -100,7 +101,7 @@ struct PreprocessedProblem { std::vector<double*> removed_parameter_blocks; Vector reduced_parameters; - double fixed_cost; + double fixed_cost{0.0}; }; // Common functions used by various preprocessors. @@ -108,14 +109,18 @@ struct PreprocessedProblem { // If the user has specified a num_threads > the maximum number of threads // available from the compiled threading model, bound the number of threads // to the maximum. +CERES_NO_EXPORT void ChangeNumThreadsIfNeeded(Solver::Options* options); // Extract the effective parameter vector from the preprocessed // problem and setup bits of the Minimizer::Options object that are // common to all Preprocessors. +CERES_NO_EXPORT void SetupCommonMinimizerOptions(PreprocessedProblem* pp); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PREPROCESSOR_H_ diff --git a/extern/ceres/internal/ceres/problem.cc b/extern/ceres/internal/ceres/problem.cc index f3ffd546ef7..4269ca3ebc3 100644 --- a/extern/ceres/internal/ceres/problem.cc +++ b/extern/ceres/internal/ceres/problem.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2021 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ #include "ceres/problem.h" +#include <memory> #include <vector> #include "ceres/crs_matrix.h" @@ -46,7 +47,7 @@ Problem::Problem(const Problem::Options& options) // Not inline defaulted in declaration due to use of std::unique_ptr. Problem::Problem(Problem&&) = default; Problem& Problem::operator=(Problem&&) = default; -Problem::~Problem() {} +Problem::~Problem() = default; ResidualBlockId Problem::AddResidualBlock( CostFunction* cost_function, @@ -76,6 +77,10 @@ void Problem::AddParameterBlock(double* values, impl_->AddParameterBlock(values, size, local_parameterization); } +void Problem::AddParameterBlock(double* values, int size, Manifold* manifold) { + impl_->AddParameterBlock(values, size, manifold); +} + void Problem::RemoveResidualBlock(ResidualBlockId residual_block) { impl_->RemoveResidualBlock(residual_block); } @@ -106,6 +111,22 @@ const LocalParameterization* Problem::GetParameterization( return impl_->GetParameterization(values); } +bool Problem::HasParameterization(const double* values) const { + return impl_->HasParameterization(values); +} + +void Problem::SetManifold(double* values, Manifold* manifold) { + impl_->SetManifold(values, manifold); +} + +const Manifold* Problem::GetManifold(const double* values) const { + return impl_->GetManifold(values); +} + +bool Problem::HasManifold(const double* values) const { + return impl_->HasManifold(values); +} + void Problem::SetParameterLowerBound(double* values, int index, double lower_bound) { @@ -169,12 +190,16 @@ int Problem::NumResidualBlocks() const { return impl_->NumResidualBlocks(); } int Problem::NumResiduals() const { return impl_->NumResiduals(); } -int Problem::ParameterBlockSize(const double* parameter_block) const { - return impl_->ParameterBlockSize(parameter_block); +int Problem::ParameterBlockSize(const double* values) const { + return impl_->ParameterBlockSize(values); +} + +int Problem::ParameterBlockLocalSize(const double* values) const { + return impl_->ParameterBlockTangentSize(values); } -int Problem::ParameterBlockLocalSize(const double* parameter_block) const { - return impl_->ParameterBlockLocalSize(parameter_block); +int Problem::ParameterBlockTangentSize(const double* values) const { + return impl_->ParameterBlockTangentSize(values); } bool Problem::HasParameterBlock(const double* values) const { diff --git a/extern/ceres/internal/ceres/problem_impl.cc b/extern/ceres/internal/ceres/problem_impl.cc index 3155bc3569e..01a22c128be 100644 --- a/extern/ceres/internal/ceres/problem_impl.cc +++ b/extern/ceres/internal/ceres/problem_impl.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -49,9 +49,11 @@ #include "ceres/crs_matrix.h" #include "ceres/evaluation_callback.h" #include "ceres/evaluator.h" +#include "ceres/internal/export.h" #include "ceres/internal/fixed_array.h" -#include "ceres/internal/port.h" #include "ceres/loss_function.h" +#include "ceres/manifold.h" +#include "ceres/manifold_adapter.h" #include "ceres/map_util.h" #include "ceres/parameter_block.h" #include "ceres/program.h" @@ -64,11 +66,6 @@ namespace ceres { namespace internal { - -using std::map; -using std::string; -using std::vector; - namespace { // Returns true if two regions of memory, a and b, with sizes size_a and size_b // respectively, overlap. @@ -130,7 +127,7 @@ ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values, << "for a parameter with size " << size; // Ignore the request if there is a block for the given pointer already. - ParameterMap::iterator it = parameter_block_map_.find(values); + auto it = parameter_block_map_.find(values); if (it != parameter_block_map_.end()) { if (!options_.disable_all_safety_checks) { int existing_size = it->second->Size(); @@ -146,11 +143,11 @@ ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values, // Before adding the parameter block, also check that it doesn't alias any // other parameter blocks. if (!parameter_block_map_.empty()) { - ParameterMap::iterator lb = parameter_block_map_.lower_bound(values); + auto lb = parameter_block_map_.lower_bound(values); // If lb is not the first block, check the previous block for aliasing. if (lb != parameter_block_map_.begin()) { - ParameterMap::iterator previous = lb; + auto previous = lb; --previous; CheckForNoAliasing( previous->first, previous->second->Size(), values, size); @@ -165,7 +162,7 @@ ParameterBlock* ProblemImpl::InternalAddParameterBlock(double* values, // Pass the index of the new parameter block as well to keep the index in // sync with the position of the parameter in the program's parameter vector. - ParameterBlock* new_parameter_block = + auto* new_parameter_block = new ParameterBlock(values, size, program_->parameter_blocks_.size()); // For dynamic problems, add the list of dependent residual blocks, which is @@ -192,7 +189,7 @@ void ProblemImpl::InternalRemoveResidualBlock(ResidualBlock* residual_block) { residual_block); } - ResidualBlockSet::iterator it = residual_block_set_.find(residual_block); + auto it = residual_block_set_.find(residual_block); residual_block_set_.erase(it); } DeleteBlockInVector(program_->mutable_residual_blocks(), residual_block); @@ -207,13 +204,13 @@ void ProblemImpl::DeleteBlock(ResidualBlock* residual_block) { // The const casts here are legit, since ResidualBlock holds these // pointers as const pointers but we have ownership of them and // have the right to destroy them when the destructor is called. - CostFunction* cost_function = + auto* cost_function = const_cast<CostFunction*>(residual_block->cost_function()); if (options_.cost_function_ownership == TAKE_OWNERSHIP) { DecrementValueOrDeleteKey(cost_function, &cost_function_ref_count_); } - LossFunction* loss_function = + auto* loss_function = const_cast<LossFunction*>(residual_block->loss_function()); if (options_.loss_function_ownership == TAKE_OWNERSHIP && loss_function != nullptr) { @@ -225,15 +222,7 @@ void ProblemImpl::DeleteBlock(ResidualBlock* residual_block) { // Deletes the parameter block in question, assuming there are no other // references to it inside the problem (e.g. by any residual blocks). -// Referenced parameterizations are tucked away for future deletion, since it -// is not possible to know whether other parts of the problem depend on them -// without doing a full scan. void ProblemImpl::DeleteBlock(ParameterBlock* parameter_block) { - if (options_.local_parameterization_ownership == TAKE_OWNERSHIP && - parameter_block->local_parameterization() != nullptr) { - local_parameterizations_to_delete_.push_back( - parameter_block->mutable_local_parameterization()); - } parameter_block_map_.erase(parameter_block->mutable_user_state()); delete parameter_block; } @@ -264,14 +253,18 @@ ProblemImpl::~ProblemImpl() { } // Collect the unique parameterizations and delete the parameters. - for (int i = 0; i < program_->parameter_blocks_.size(); ++i) { - DeleteBlock(program_->parameter_blocks_[i]); + for (auto* parameter_block : program_->parameter_blocks_) { + DeleteBlock(parameter_block); } // Delete the owned parameterizations. STLDeleteUniqueContainerPointers(local_parameterizations_to_delete_.begin(), local_parameterizations_to_delete_.end()); + // Delete the owned manifolds. + STLDeleteUniqueContainerPointers(manifolds_to_delete_.begin(), + manifolds_to_delete_.end()); + if (context_impl_owned_) { delete context_impl_; } @@ -286,7 +279,7 @@ ResidualBlockId ProblemImpl::AddResidualBlock( CHECK_EQ(num_parameter_blocks, cost_function->parameter_block_sizes().size()); // Check the sizes match. - const vector<int32_t>& parameter_block_sizes = + const std::vector<int32_t>& parameter_block_sizes = cost_function->parameter_block_sizes(); if (!options_.disable_all_safety_checks) { @@ -295,7 +288,7 @@ ResidualBlockId ProblemImpl::AddResidualBlock( << "that the cost function expects."; // Check for duplicate parameter blocks. - vector<double*> sorted_parameter_blocks( + std::vector<double*> sorted_parameter_blocks( parameter_blocks, parameter_blocks + num_parameter_blocks); sort(sorted_parameter_blocks.begin(), sorted_parameter_blocks.end()); const bool has_duplicate_items = @@ -303,7 +296,7 @@ ResidualBlockId ProblemImpl::AddResidualBlock( sorted_parameter_blocks.end()) != sorted_parameter_blocks.end()); if (has_duplicate_items) { - string blocks; + std::string blocks; for (int i = 0; i < num_parameter_blocks; ++i) { blocks += StringPrintf(" %p ", parameter_blocks[i]); } @@ -315,7 +308,7 @@ ResidualBlockId ProblemImpl::AddResidualBlock( } // Add parameter blocks and convert the double*'s to parameter blocks. - vector<ParameterBlock*> parameter_block_ptrs(num_parameter_blocks); + std::vector<ParameterBlock*> parameter_block_ptrs(num_parameter_blocks); for (int i = 0; i < num_parameter_blocks; ++i) { parameter_block_ptrs[i] = InternalAddParameterBlock( parameter_blocks[i], parameter_block_sizes[i]); @@ -334,7 +327,7 @@ ResidualBlockId ProblemImpl::AddResidualBlock( } } - ResidualBlock* new_residual_block = + auto* new_residual_block = new ResidualBlock(cost_function, loss_function, parameter_block_ptrs, @@ -372,12 +365,50 @@ void ProblemImpl::AddParameterBlock(double* values, int size) { InternalAddParameterBlock(values, size); } +void ProblemImpl::InternalSetParameterization( + double* values, + ParameterBlock* parameter_block, + LocalParameterization* local_parameterization) { + parameter_block_to_local_param_[values] = local_parameterization; + Manifold* manifold = nullptr; + if (local_parameterization != nullptr) { + if (options_.local_parameterization_ownership == TAKE_OWNERSHIP) { + local_parameterizations_to_delete_.push_back(local_parameterization); + } + + manifold = new ManifoldAdapter(local_parameterization); + // Add the manifold to manifolds_to_delete_ unconditionally since + // we own it and it will need to be deleted. + manifolds_to_delete_.push_back(manifold); + } + + parameter_block->SetManifold(manifold); +} + +void ProblemImpl::InternalSetManifold(double* values, + ParameterBlock* parameter_block, + Manifold* manifold) { + // Reset any association between this parameter block and a local + // parameterization. This only needs done while we are in the transition from + // LocalParameterization to Manifold. + parameter_block_to_local_param_[values] = nullptr; + if (manifold != nullptr && options_.manifold_ownership == TAKE_OWNERSHIP) { + manifolds_to_delete_.push_back(manifold); + } + parameter_block->SetManifold(manifold); +} + void ProblemImpl::AddParameterBlock( double* values, int size, LocalParameterization* local_parameterization) { ParameterBlock* parameter_block = InternalAddParameterBlock(values, size); - if (local_parameterization != nullptr) { - parameter_block->SetParameterization(local_parameterization); - } + InternalSetParameterization(values, parameter_block, local_parameterization); +} + +void ProblemImpl::AddParameterBlock(double* values, + int size, + Manifold* manifold) { + ParameterBlock* parameter_block = InternalAddParameterBlock(values, size); + InternalSetManifold(values, parameter_block, manifold); } // Delete a block from a vector of blocks, maintaining the indexing invariant. @@ -385,7 +416,7 @@ void ProblemImpl::AddParameterBlock( // vector over the element to remove, then popping the last element. It // destroys the ordering in the interest of speed. template <typename Block> -void ProblemImpl::DeleteBlockInVector(vector<Block*>* mutable_blocks, +void ProblemImpl::DeleteBlockInVector(std::vector<Block*>* mutable_blocks, Block* block_to_remove) { CHECK_EQ((*mutable_blocks)[block_to_remove->index()], block_to_remove) << "You found a Ceres bug! \n" @@ -411,7 +442,7 @@ void ProblemImpl::RemoveResidualBlock(ResidualBlock* residual_block) { CHECK(residual_block != nullptr); // Verify that residual_block identifies a residual in the current problem. - const string residual_not_found_message = StringPrintf( + const std::string residual_not_found_message = StringPrintf( "Residual block to remove: %p not found. This usually means " "one of three things have happened:\n" " 1) residual_block is uninitialised and points to a random " @@ -449,11 +480,11 @@ void ProblemImpl::RemoveParameterBlock(const double* values) { if (options_.enable_fast_removal) { // Copy the dependent residuals from the parameter block because the set of // dependents will change after each call to RemoveResidualBlock(). - vector<ResidualBlock*> residual_blocks_to_remove( + std::vector<ResidualBlock*> residual_blocks_to_remove( parameter_block->mutable_residual_blocks()->begin(), parameter_block->mutable_residual_blocks()->end()); - for (int i = 0; i < residual_blocks_to_remove.size(); ++i) { - InternalRemoveResidualBlock(residual_blocks_to_remove[i]); + for (auto* residual_block : residual_blocks_to_remove) { + InternalRemoveResidualBlock(residual_block); } } else { // Scan all the residual blocks to remove ones that depend on the parameter @@ -518,20 +549,31 @@ void ProblemImpl::SetParameterization( << "you can set its local parameterization."; } - // If the parameter block already has a local parameterization and - // we are to take ownership of local parameterizations, then add it - // to local_parameterizations_to_delete_ for eventual deletion. - if (parameter_block->local_parameterization_ && - options_.local_parameterization_ownership == TAKE_OWNERSHIP) { - local_parameterizations_to_delete_.push_back( - parameter_block->local_parameterization_); + InternalSetParameterization(values, parameter_block, local_parameterization); +} + +void ProblemImpl::SetManifold(double* values, Manifold* manifold) { + ParameterBlock* parameter_block = + FindWithDefault(parameter_block_map_, values, nullptr); + if (parameter_block == nullptr) { + LOG(FATAL) << "Parameter block not found: " << values + << ". You must add the parameter block to the problem before " + << "you can set its manifold."; } - parameter_block->SetParameterization(local_parameterization); + InternalSetManifold(values, parameter_block, manifold); } const LocalParameterization* ProblemImpl::GetParameterization( const double* values) const { + return FindWithDefault(parameter_block_to_local_param_, values, nullptr); +} + +bool ProblemImpl::HasParameterization(const double* values) const { + return GetParameterization(values) != nullptr; +} + +const Manifold* ProblemImpl::GetManifold(const double* values) const { ParameterBlock* parameter_block = FindWithDefault( parameter_block_map_, const_cast<double*>(values), nullptr); if (parameter_block == nullptr) { @@ -540,7 +582,11 @@ const LocalParameterization* ProblemImpl::GetParameterization( << "you can get its local parameterization."; } - return parameter_block->local_parameterization(); + return parameter_block->manifold(); +} + +bool ProblemImpl::HasManifold(const double* values) const { + return GetManifold(values) != nullptr; } void ProblemImpl::SetParameterLowerBound(double* values, @@ -596,8 +642,8 @@ double ProblemImpl::GetParameterUpperBound(const double* values, bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, double* cost, - vector<double>* residuals, - vector<double>* gradient, + std::vector<double>* residuals, + std::vector<double>* gradient, CRSMatrix* jacobian) { if (cost == nullptr && residuals == nullptr && gradient == nullptr && jacobian == nullptr) { @@ -612,11 +658,11 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, ? evaluate_options.residual_blocks : program_->residual_blocks()); - const vector<double*>& parameter_block_ptrs = + const std::vector<double*>& parameter_block_ptrs = evaluate_options.parameter_blocks; - vector<ParameterBlock*> variable_parameter_blocks; - vector<ParameterBlock*>& parameter_blocks = + std::vector<ParameterBlock*> variable_parameter_blocks; + std::vector<ParameterBlock*>& parameter_blocks = *program.mutable_parameter_blocks(); if (parameter_block_ptrs.size() == 0) { @@ -649,11 +695,12 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, // columns of the jacobian, we need to make sure that they are // constant during evaluation and then make them variable again // after we are done. - vector<ParameterBlock*> all_parameter_blocks(program_->parameter_blocks()); - vector<ParameterBlock*> included_parameter_blocks( + std::vector<ParameterBlock*> all_parameter_blocks( + program_->parameter_blocks()); + std::vector<ParameterBlock*> included_parameter_blocks( program.parameter_blocks()); - vector<ParameterBlock*> excluded_parameter_blocks; + std::vector<ParameterBlock*> excluded_parameter_blocks; sort(all_parameter_blocks.begin(), all_parameter_blocks.end()); sort(included_parameter_blocks.begin(), included_parameter_blocks.end()); set_difference(all_parameter_blocks.begin(), @@ -663,8 +710,7 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, back_inserter(excluded_parameter_blocks)); variable_parameter_blocks.reserve(excluded_parameter_blocks.size()); - for (int i = 0; i < excluded_parameter_blocks.size(); ++i) { - ParameterBlock* parameter_block = excluded_parameter_blocks[i]; + for (auto* parameter_block : excluded_parameter_blocks) { if (!parameter_block->IsConstant()) { variable_parameter_blocks.push_back(parameter_block); parameter_block->SetConstant(); @@ -716,8 +762,8 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, std::unique_ptr<CompressedRowSparseMatrix> tmp_jacobian; if (jacobian != nullptr) { - tmp_jacobian.reset( - down_cast<CompressedRowSparseMatrix*>(evaluator->CreateJacobian())); + tmp_jacobian.reset(down_cast<CompressedRowSparseMatrix*>( + evaluator->CreateJacobian().release())); } // Point the state pointers to the user state pointers. This is @@ -749,8 +795,8 @@ bool ProblemImpl::Evaluate(const Problem::EvaluateOptions& evaluate_options, // Make the parameter blocks that were temporarily marked constant, // variable again. - for (int i = 0; i < variable_parameter_blocks.size(); ++i) { - variable_parameter_blocks[i]->SetVarying(); + for (auto* parameter_block : variable_parameter_blocks) { + parameter_block->SetVarying(); } if (status) { @@ -829,24 +875,25 @@ int ProblemImpl::ParameterBlockSize(const double* values) const { return parameter_block->Size(); } -int ProblemImpl::ParameterBlockLocalSize(const double* values) const { +int ProblemImpl::ParameterBlockTangentSize(const double* values) const { ParameterBlock* parameter_block = FindWithDefault( parameter_block_map_, const_cast<double*>(values), nullptr); if (parameter_block == nullptr) { LOG(FATAL) << "Parameter block not found: " << values << ". You must add the parameter block to the problem before " - << "you can get its local size."; + << "you can get its tangent size."; } - return parameter_block->LocalSize(); + return parameter_block->TangentSize(); } -bool ProblemImpl::HasParameterBlock(const double* parameter_block) const { - return (parameter_block_map_.find(const_cast<double*>(parameter_block)) != +bool ProblemImpl::HasParameterBlock(const double* values) const { + return (parameter_block_map_.find(const_cast<double*>(values)) != parameter_block_map_.end()); } -void ProblemImpl::GetParameterBlocks(vector<double*>* parameter_blocks) const { +void ProblemImpl::GetParameterBlocks( + std::vector<double*>* parameter_blocks) const { CHECK(parameter_blocks != nullptr); parameter_blocks->resize(0); parameter_blocks->reserve(parameter_block_map_.size()); @@ -856,14 +903,14 @@ void ProblemImpl::GetParameterBlocks(vector<double*>* parameter_blocks) const { } void ProblemImpl::GetResidualBlocks( - vector<ResidualBlockId>* residual_blocks) const { + std::vector<ResidualBlockId>* residual_blocks) const { CHECK(residual_blocks != nullptr); *residual_blocks = program().residual_blocks(); } void ProblemImpl::GetParameterBlocksForResidualBlock( const ResidualBlockId residual_block, - vector<double*>* parameter_blocks) const { + std::vector<double*>* parameter_blocks) const { int num_parameter_blocks = residual_block->NumParameterBlocks(); CHECK(parameter_blocks != nullptr); parameter_blocks->resize(num_parameter_blocks); @@ -884,7 +931,7 @@ const LossFunction* ProblemImpl::GetLossFunctionForResidualBlock( } void ProblemImpl::GetResidualBlocksForParameterBlock( - const double* values, vector<ResidualBlockId>* residual_blocks) const { + const double* values, std::vector<ResidualBlockId>* residual_blocks) const { ParameterBlock* parameter_block = FindWithDefault( parameter_block_map_, const_cast<double*>(values), nullptr); if (parameter_block == nullptr) { diff --git a/extern/ceres/internal/ceres/problem_impl.h b/extern/ceres/internal/ceres/problem_impl.h index 9abff3f19ae..22073b674f1 100644 --- a/extern/ceres/internal/ceres/problem_impl.h +++ b/extern/ceres/internal/ceres/problem_impl.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2019 Google Inc. All rights reserved. +// Copyright 2021 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -42,11 +42,15 @@ #include <array> #include <map> #include <memory> +#include <unordered_map> #include <unordered_set> #include <vector> #include "ceres/context_impl.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/internal/port.h" +#include "ceres/manifold.h" #include "ceres/problem.h" #include "ceres/types.h" @@ -63,12 +67,12 @@ namespace internal { class Program; class ResidualBlock; -class CERES_EXPORT_INTERNAL ProblemImpl { +class CERES_NO_EXPORT ProblemImpl { public: - typedef std::map<double*, ParameterBlock*> ParameterMap; - typedef std::unordered_set<ResidualBlock*> ResidualBlockSet; - typedef std::map<CostFunction*, int> CostFunctionRefCount; - typedef std::map<LossFunction*, int> LossFunctionRefCount; + using ParameterMap = std::map<double*, ParameterBlock*>; + using ResidualBlockSet = std::unordered_set<ResidualBlock*>; + using CostFunctionRefCount = std::map<CostFunction*, int>; + using LossFunctionRefCount = std::map<LossFunction*, int>; ProblemImpl(); explicit ProblemImpl(const Problem::Options& options); @@ -100,6 +104,8 @@ class CERES_EXPORT_INTERNAL ProblemImpl { int size, LocalParameterization* local_parameterization); + void AddParameterBlock(double* values, int size, Manifold* manifold); + void RemoveResidualBlock(ResidualBlock* residual_block); void RemoveParameterBlock(const double* values); @@ -110,6 +116,11 @@ class CERES_EXPORT_INTERNAL ProblemImpl { void SetParameterization(double* values, LocalParameterization* local_parameterization); const LocalParameterization* GetParameterization(const double* values) const; + bool HasParameterization(const double* values) const; + + void SetManifold(double* values, Manifold* manifold); + const Manifold* GetManifold(const double* values) const; + bool HasManifold(const double* values) const; void SetParameterLowerBound(double* values, int index, double lower_bound); void SetParameterUpperBound(double* values, int index, double upper_bound); @@ -134,10 +145,10 @@ class CERES_EXPORT_INTERNAL ProblemImpl { int NumResidualBlocks() const; int NumResiduals() const; - int ParameterBlockSize(const double* parameter_block) const; - int ParameterBlockLocalSize(const double* parameter_block) const; + int ParameterBlockSize(const double* values) const; + int ParameterBlockTangentSize(const double* values) const; - bool HasParameterBlock(const double* parameter_block) const; + bool HasParameterBlock(const double* values) const; void GetParameterBlocks(std::vector<double*>* parameter_blocks) const; void GetResidualBlocks(std::vector<ResidualBlockId>* residual_blocks) const; @@ -169,6 +180,14 @@ class CERES_EXPORT_INTERNAL ProblemImpl { private: ParameterBlock* InternalAddParameterBlock(double* values, int size); + void InternalSetParameterization( + double* values, + ParameterBlock* parameter_block, + LocalParameterization* local_parameterization); + void InternalSetManifold(double* values, + ParameterBlock* parameter_block, + Manifold* manifold); + void InternalRemoveResidualBlock(ResidualBlock* residual_block); // Delete the arguments in question. These differ from the Remove* functions @@ -194,23 +213,45 @@ class CERES_EXPORT_INTERNAL ProblemImpl { // The actual parameter and residual blocks. std::unique_ptr<internal::Program> program_; + // TODO(sameeragarwal): Unify the shared object handling across object types. + // Right now we are using vectors for LocalParameterization and Manifold + // objects and reference counting for CostFunctions and LossFunctions. Ideally + // this should be done uniformly. + // When removing parameter blocks, parameterizations have ambiguous // ownership. Instead of scanning the entire problem to see if the // parameterization is shared with other parameter blocks, buffer // them until destruction. - // - // TODO(keir): See if it makes sense to use sets instead. std::vector<LocalParameterization*> local_parameterizations_to_delete_; + // When removing parameter blocks, manifolds have ambiguous + // ownership. Instead of scanning the entire problem to see if the + // manifold is shared with other parameter blocks, buffer + // them until destruction. + std::vector<Manifold*> manifolds_to_delete_; + // For each cost function and loss function in the problem, a count // of the number of residual blocks that refer to them. When the // count goes to zero and the problem owns these objects, they are // destroyed. CostFunctionRefCount cost_function_ref_count_; LossFunctionRefCount loss_function_ref_count_; + + // Because we wrap LocalParameterization objects using a ManifoldAdapter, when + // the user calls GetParameterization we cannot use the same logic as + // GetManifold as the ParameterBlock object only returns a Manifold object. So + // this map stores the association between parameter blocks and local + // parameterizations. + // + // This is a temporary object which will be removed once the + // LocalParameterization to Manifold transition is complete. + std::unordered_map<const double*, LocalParameterization*> + parameter_block_to_local_param_; }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_PUBLIC_PROBLEM_IMPL_H_ diff --git a/extern/ceres/internal/ceres/program.cc b/extern/ceres/internal/ceres/program.cc index f1ded2e5d5a..1cb9ebcbe73 100644 --- a/extern/ceres/internal/ceres/program.cc +++ b/extern/ceres/internal/ceres/program.cc @@ -33,6 +33,7 @@ #include <algorithm> #include <map> #include <memory> +#include <string> #include <vector> #include "ceres/array_utils.h" @@ -40,9 +41,9 @@ #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/cost_function.h" #include "ceres/evaluator.h" -#include "ceres/internal/port.h" -#include "ceres/local_parameterization.h" +#include "ceres/internal/export.h" #include "ceres/loss_function.h" +#include "ceres/manifold.h" #include "ceres/map_util.h" #include "ceres/parameter_block.h" #include "ceres/problem.h" @@ -53,31 +54,19 @@ namespace ceres { namespace internal { -using std::max; -using std::set; -using std::string; -using std::vector; - -Program::Program() {} - -Program::Program(const Program& program) - : parameter_blocks_(program.parameter_blocks_), - residual_blocks_(program.residual_blocks_), - evaluation_callback_(program.evaluation_callback_) {} - -const vector<ParameterBlock*>& Program::parameter_blocks() const { +const std::vector<ParameterBlock*>& Program::parameter_blocks() const { return parameter_blocks_; } -const vector<ResidualBlock*>& Program::residual_blocks() const { +const std::vector<ResidualBlock*>& Program::residual_blocks() const { return residual_blocks_; } -vector<ParameterBlock*>* Program::mutable_parameter_blocks() { +std::vector<ParameterBlock*>* Program::mutable_parameter_blocks() { return ¶meter_blocks_; } -vector<ResidualBlock*>* Program::mutable_residual_blocks() { +std::vector<ResidualBlock*>* Program::mutable_residual_blocks() { return &residual_blocks_; } @@ -86,33 +75,32 @@ EvaluationCallback* Program::mutable_evaluation_callback() { } bool Program::StateVectorToParameterBlocks(const double* state) { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - if (!parameter_blocks_[i]->IsConstant() && - !parameter_blocks_[i]->SetState(state)) { + for (auto* parameter_block : parameter_blocks_) { + if (!parameter_block->IsConstant() && !parameter_block->SetState(state)) { return false; } - state += parameter_blocks_[i]->Size(); + state += parameter_block->Size(); } return true; } void Program::ParameterBlocksToStateVector(double* state) const { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - parameter_blocks_[i]->GetState(state); - state += parameter_blocks_[i]->Size(); + for (auto* parameter_block : parameter_blocks_) { + parameter_block->GetState(state); + state += parameter_block->Size(); } } void Program::CopyParameterBlockStateToUserState() { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - parameter_blocks_[i]->GetState(parameter_blocks_[i]->mutable_user_state()); + for (auto* parameter_block : parameter_blocks_) { + parameter_block->GetState(parameter_block->mutable_user_state()); } } bool Program::SetParameterBlockStatePtrsToUserStatePtrs() { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - if (!parameter_blocks_[i]->IsConstant() && - !parameter_blocks_[i]->SetState(parameter_blocks_[i]->user_state())) { + for (auto* parameter_block : parameter_blocks_) { + if (!parameter_block->IsConstant() && + !parameter_block->SetState(parameter_block->user_state())) { return false; } } @@ -122,13 +110,13 @@ bool Program::SetParameterBlockStatePtrsToUserStatePtrs() { bool Program::Plus(const double* state, const double* delta, double* state_plus_delta) const { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - if (!parameter_blocks_[i]->Plus(state, delta, state_plus_delta)) { + for (auto* parameter_block : parameter_blocks_) { + if (!parameter_block->Plus(state, delta, state_plus_delta)) { return false; } - state += parameter_blocks_[i]->Size(); - delta += parameter_blocks_[i]->LocalSize(); - state_plus_delta += parameter_blocks_[i]->Size(); + state += parameter_block->Size(); + delta += parameter_block->TangentSize(); + state_plus_delta += parameter_block->Size(); } return true; } @@ -136,8 +124,7 @@ bool Program::Plus(const double* state, void Program::SetParameterOffsetsAndIndex() { // Set positions for all parameters appearing as arguments to residuals to one // past the end of the parameter block array. - for (int i = 0; i < residual_blocks_.size(); ++i) { - ResidualBlock* residual_block = residual_blocks_[i]; + for (auto* residual_block : residual_blocks_) { for (int j = 0; j < residual_block->NumParameterBlocks(); ++j) { residual_block->parameter_blocks()[j]->set_index(-1); } @@ -150,7 +137,7 @@ void Program::SetParameterOffsetsAndIndex() { parameter_blocks_[i]->set_state_offset(state_offset); parameter_blocks_[i]->set_delta_offset(delta_offset); state_offset += parameter_blocks_[i]->Size(); - delta_offset += parameter_blocks_[i]->LocalSize(); + delta_offset += parameter_blocks_[i]->TangentSize(); } } @@ -178,16 +165,15 @@ bool Program::IsValid() const { } state_offset += parameter_blocks_[i]->Size(); - delta_offset += parameter_blocks_[i]->LocalSize(); + delta_offset += parameter_blocks_[i]->TangentSize(); } return true; } -bool Program::ParameterBlocksAreFinite(string* message) const { +bool Program::ParameterBlocksAreFinite(std::string* message) const { CHECK(message != nullptr); - for (int i = 0; i < parameter_blocks_.size(); ++i) { - const ParameterBlock* parameter_block = parameter_blocks_[i]; + for (auto* parameter_block : parameter_blocks_) { const double* array = parameter_block->user_state(); const int size = parameter_block->Size(); const int invalid_index = FindInvalidValue(size, array); @@ -207,8 +193,7 @@ bool Program::ParameterBlocksAreFinite(string* message) const { } bool Program::IsBoundsConstrained() const { - for (int i = 0; i < parameter_blocks_.size(); ++i) { - const ParameterBlock* parameter_block = parameter_blocks_[i]; + for (auto* parameter_block : parameter_blocks_) { if (parameter_block->IsConstant()) { continue; } @@ -225,10 +210,9 @@ bool Program::IsBoundsConstrained() const { return false; } -bool Program::IsFeasible(string* message) const { +bool Program::IsFeasible(std::string* message) const { CHECK(message != nullptr); - for (int i = 0; i < parameter_blocks_.size(); ++i) { - const ParameterBlock* parameter_block = parameter_blocks_[i]; + for (auto* parameter_block : parameter_blocks_) { const double* parameters = parameter_block->user_state(); const int size = parameter_block->Size(); if (parameter_block->IsConstant()) { @@ -284,42 +268,42 @@ bool Program::IsFeasible(string* message) const { return true; } -Program* Program::CreateReducedProgram( - vector<double*>* removed_parameter_blocks, +std::unique_ptr<Program> Program::CreateReducedProgram( + std::vector<double*>* removed_parameter_blocks, double* fixed_cost, - string* error) const { + std::string* error) const { CHECK(removed_parameter_blocks != nullptr); CHECK(fixed_cost != nullptr); CHECK(error != nullptr); - std::unique_ptr<Program> reduced_program(new Program(*this)); + std::unique_ptr<Program> reduced_program = std::make_unique<Program>(*this); if (!reduced_program->RemoveFixedBlocks( removed_parameter_blocks, fixed_cost, error)) { return nullptr; } reduced_program->SetParameterOffsetsAndIndex(); - return reduced_program.release(); + return reduced_program; } -bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks, +bool Program::RemoveFixedBlocks(std::vector<double*>* removed_parameter_blocks, double* fixed_cost, - string* error) { + std::string* error) { CHECK(removed_parameter_blocks != nullptr); CHECK(fixed_cost != nullptr); CHECK(error != nullptr); std::unique_ptr<double[]> residual_block_evaluate_scratch; - residual_block_evaluate_scratch.reset( - new double[MaxScratchDoublesNeededForEvaluate()]); + residual_block_evaluate_scratch = + std::make_unique<double[]>(MaxScratchDoublesNeededForEvaluate()); *fixed_cost = 0.0; bool need_to_call_prepare_for_evaluation = evaluation_callback_ != nullptr; // Mark all the parameters as unused. Abuse the index member of the // parameter blocks for the marking. - for (int i = 0; i < parameter_blocks_.size(); ++i) { - parameter_blocks_[i]->set_index(-1); + for (auto* parameter_block : parameter_blocks_) { + parameter_block->set_index(-1); } // Filter out residual that have all-constant parameters, and mark @@ -391,8 +375,7 @@ bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks, // Filter out unused or fixed parameter blocks. int num_active_parameter_blocks = 0; removed_parameter_blocks->clear(); - for (int i = 0; i < parameter_blocks_.size(); ++i) { - ParameterBlock* parameter_block = parameter_blocks_[i]; + for (auto* parameter_block : parameter_blocks_) { if (parameter_block->index() == -1) { removed_parameter_blocks->push_back( parameter_block->mutable_user_state()); @@ -412,7 +395,7 @@ bool Program::RemoveFixedBlocks(vector<double*>* removed_parameter_blocks, } bool Program::IsParameterBlockSetIndependent( - const set<double*>& independent_set) const { + const std::set<double*>& independent_set) const { // Loop over each residual block and ensure that no two parameter // blocks in the same residual block are part of // parameter_block_ptrs as that would violate the assumption that it @@ -483,24 +466,24 @@ int Program::NumParameterBlocks() const { return parameter_blocks_.size(); } int Program::NumResiduals() const { int num_residuals = 0; - for (int i = 0; i < residual_blocks_.size(); ++i) { - num_residuals += residual_blocks_[i]->NumResiduals(); + for (auto* residual_block : residual_blocks_) { + num_residuals += residual_block->NumResiduals(); } return num_residuals; } int Program::NumParameters() const { int num_parameters = 0; - for (int i = 0; i < parameter_blocks_.size(); ++i) { - num_parameters += parameter_blocks_[i]->Size(); + for (auto* parameter_block : parameter_blocks_) { + num_parameters += parameter_block->Size(); } return num_parameters; } int Program::NumEffectiveParameters() const { int num_parameters = 0; - for (int i = 0; i < parameter_blocks_.size(); ++i) { - num_parameters += parameter_blocks_[i]->LocalSize(); + for (auto* parameter_block : parameter_blocks_) { + num_parameters += parameter_block->TangentSize(); } return num_parameters; } @@ -511,48 +494,47 @@ int Program::NumEffectiveParameters() const { int Program::MaxScratchDoublesNeededForEvaluate() const { // Compute the scratch space needed for evaluate. int max_scratch_bytes_for_evaluate = 0; - for (int i = 0; i < residual_blocks_.size(); ++i) { + for (auto* residual_block : residual_blocks_) { max_scratch_bytes_for_evaluate = - max(max_scratch_bytes_for_evaluate, - residual_blocks_[i]->NumScratchDoublesForEvaluate()); + std::max(max_scratch_bytes_for_evaluate, + residual_block->NumScratchDoublesForEvaluate()); } return max_scratch_bytes_for_evaluate; } int Program::MaxDerivativesPerResidualBlock() const { int max_derivatives = 0; - for (int i = 0; i < residual_blocks_.size(); ++i) { + for (auto* residual_block : residual_blocks_) { int derivatives = 0; - ResidualBlock* residual_block = residual_blocks_[i]; int num_parameters = residual_block->NumParameterBlocks(); for (int j = 0; j < num_parameters; ++j) { derivatives += residual_block->NumResiduals() * - residual_block->parameter_blocks()[j]->LocalSize(); + residual_block->parameter_blocks()[j]->TangentSize(); } - max_derivatives = max(max_derivatives, derivatives); + max_derivatives = std::max(max_derivatives, derivatives); } return max_derivatives; } int Program::MaxParametersPerResidualBlock() const { int max_parameters = 0; - for (int i = 0; i < residual_blocks_.size(); ++i) { + for (auto* residual_block : residual_blocks_) { max_parameters = - max(max_parameters, residual_blocks_[i]->NumParameterBlocks()); + std::max(max_parameters, residual_block->NumParameterBlocks()); } return max_parameters; } int Program::MaxResidualsPerResidualBlock() const { int max_residuals = 0; - for (int i = 0; i < residual_blocks_.size(); ++i) { - max_residuals = max(max_residuals, residual_blocks_[i]->NumResiduals()); + for (auto* residual_block : residual_blocks_) { + max_residuals = std::max(max_residuals, residual_block->NumResiduals()); } return max_residuals; } -string Program::ToString() const { - string ret = "Program dump\n"; +std::string Program::ToString() const { + std::string ret = "Program dump\n"; ret += StringPrintf("Number of parameter blocks: %d\n", NumParameterBlocks()); ret += StringPrintf("Number of parameters: %d\n", NumParameters()); ret += "Parameters:\n"; diff --git a/extern/ceres/internal/ceres/program.h b/extern/ceres/internal/ceres/program.h index ca29d316284..4dbd1ba5ff1 100644 --- a/extern/ceres/internal/ceres/program.h +++ b/extern/ceres/internal/ceres/program.h @@ -37,7 +37,8 @@ #include <vector> #include "ceres/evaluation_callback.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -57,11 +58,8 @@ class TripletSparseMatrix; // another; for example, the first stage of solving involves stripping all // constant parameters and residuals. This is in contrast with Problem, which is // not built for transformation. -class CERES_EXPORT_INTERNAL Program { +class CERES_NO_EXPORT Program { public: - Program(); - explicit Program(const Program& program); - // The ordered parameter and residual blocks for the program. const std::vector<ParameterBlock*>& parameter_blocks() const; const std::vector<ResidualBlock*>& residual_blocks() const; @@ -72,9 +70,9 @@ class CERES_EXPORT_INTERNAL Program { // Serialize to/from the program and update states. // // NOTE: Setting the state of a parameter block can trigger the - // computation of the Jacobian of its local parameterization. If - // this computation fails for some reason, then this method returns - // false and the state of the parameter blocks cannot be trusted. + // computation of the Jacobian of its manifold. If this computation fails for + // some reason, then this method returns false and the state of the parameter + // blocks cannot be trusted. bool StateVectorToParameterBlocks(const double* state); void ParameterBlocksToStateVector(double* state) const; @@ -82,8 +80,8 @@ class CERES_EXPORT_INTERNAL Program { void CopyParameterBlockStateToUserState(); // Set the parameter block pointers to the user pointers. Since this - // runs parameter block set state internally, which may call local - // parameterizations, this can fail. False is returned on failure. + // runs parameter block set state internally, which may call manifold, this + // can fail. False is returned on failure. bool SetParameterBlockStatePtrsToUserStatePtrs(); // Update a state vector for the program given a delta. @@ -146,12 +144,13 @@ class CERES_EXPORT_INTERNAL Program { // fixed_cost will be equal to the sum of the costs of the residual // blocks that were removed. // - // If there was a problem, then the function will return a NULL + // If there was a problem, then the function will return a nullptr // pointer and error will contain a human readable description of // the problem. - Program* CreateReducedProgram(std::vector<double*>* removed_parameter_blocks, - double* fixed_cost, - std::string* error) const; + std::unique_ptr<Program> CreateReducedProgram( + std::vector<double*>* removed_parameter_blocks, + double* fixed_cost, + std::string* error) const; // See problem.h for what these do. int NumParameterBlocks() const; @@ -196,4 +195,6 @@ class CERES_EXPORT_INTERNAL Program { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_PROGRAM_H_ diff --git a/extern/ceres/internal/ceres/program_evaluator.h b/extern/ceres/internal/ceres/program_evaluator.h index 36c9c64baf6..826a73a9af1 100644 --- a/extern/ceres/internal/ceres/program_evaluator.h +++ b/extern/ceres/internal/ceres/program_evaluator.h @@ -59,11 +59,13 @@ // class JacobianWriter { // // Create a jacobian that this writer can write. Same as // // Evaluator::CreateJacobian. -// SparseMatrix* CreateJacobian() const; +// std::unique_ptr<SparseMatrix> CreateJacobian() const; // -// // Create num_threads evaluate preparers. Caller owns result which must -// // be freed with delete[]. Resulting preparers are valid while *this is. -// EvaluatePreparer* CreateEvaluatePreparers(int num_threads); +// // Create num_threads evaluate preparers.Resulting preparers are valid +// // while *this is. +// +// std::unique_ptr<EvaluatePreparer[]> CreateEvaluatePreparers( +// int num_threads); // // // Write the block jacobians from a residual block evaluation to the // // larger sparse jacobian. @@ -81,7 +83,7 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on #include <atomic> @@ -109,14 +111,14 @@ struct NullJacobianFinalizer { template <typename EvaluatePreparer, typename JacobianWriter, typename JacobianFinalizer = NullJacobianFinalizer> -class ProgramEvaluator : public Evaluator { +class ProgramEvaluator final : public Evaluator { public: ProgramEvaluator(const Evaluator::Options& options, Program* program) : options_(options), program_(program), jacobian_writer_(options, program), - evaluate_preparers_( - jacobian_writer_.CreateEvaluatePreparers(options.num_threads)) { + evaluate_preparers_(std::move( + jacobian_writer_.CreateEvaluatePreparers(options.num_threads))) { #ifdef CERES_NO_THREADS if (options_.num_threads > 1) { LOG(WARNING) << "No threading support is compiled into this binary; " @@ -127,12 +129,12 @@ class ProgramEvaluator : public Evaluator { #endif // CERES_NO_THREADS BuildResidualLayout(*program, &residual_layout_); - evaluate_scratch_.reset( - CreateEvaluatorScratch(*program, options.num_threads)); + evaluate_scratch_ = + std::move(CreateEvaluatorScratch(*program, options.num_threads)); } // Implementation of Evaluator interface. - SparseMatrix* CreateJacobian() const final { + std::unique_ptr<SparseMatrix> CreateJacobian() const final { return jacobian_writer_.CreateJacobian(); } @@ -250,7 +252,7 @@ class ProgramEvaluator : public Evaluator { MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>( block_jacobians[j], num_residuals, - parameter_block->LocalSize(), + parameter_block->TangentSize(), block_residuals, scratch->gradient.get() + parameter_block->delta_offset()); } @@ -309,18 +311,19 @@ class ProgramEvaluator : public Evaluator { int max_scratch_doubles_needed_for_evaluate, int max_residuals_per_residual_block, int num_parameters) { - residual_block_evaluate_scratch.reset( - new double[max_scratch_doubles_needed_for_evaluate]); - gradient.reset(new double[num_parameters]); + residual_block_evaluate_scratch = + std::make_unique<double[]>(max_scratch_doubles_needed_for_evaluate); + gradient = std::make_unique<double[]>(num_parameters); VectorRef(gradient.get(), num_parameters).setZero(); - residual_block_residuals.reset( - new double[max_residuals_per_residual_block]); - jacobian_block_ptrs.reset(new double*[max_parameters_per_residual_block]); + residual_block_residuals = + std::make_unique<double[]>(max_residuals_per_residual_block); + jacobian_block_ptrs = + std::make_unique<double*[]>(max_parameters_per_residual_block); } double cost; std::unique_ptr<double[]> residual_block_evaluate_scratch; - // The gradient in the local parameterization. + // The gradient on the manifold. std::unique_ptr<double[]> gradient; // Enough space to store the residual for the largest residual block. std::unique_ptr<double[]> residual_block_residuals; @@ -341,8 +344,8 @@ class ProgramEvaluator : public Evaluator { } // Create scratch space for each thread evaluating the program. - static EvaluateScratch* CreateEvaluatorScratch(const Program& program, - int num_threads) { + static std::unique_ptr<EvaluateScratch[]> CreateEvaluatorScratch( + const Program& program, int num_threads) { int max_parameters_per_residual_block = program.MaxParametersPerResidualBlock(); int max_scratch_doubles_needed_for_evaluate = @@ -351,7 +354,7 @@ class ProgramEvaluator : public Evaluator { program.MaxResidualsPerResidualBlock(); int num_parameters = program.NumEffectiveParameters(); - EvaluateScratch* evaluate_scratch = new EvaluateScratch[num_threads]; + auto evaluate_scratch = std::make_unique<EvaluateScratch[]>(num_threads); for (int i = 0; i < num_threads; i++) { evaluate_scratch[i].Init(max_parameters_per_residual_block, max_scratch_doubles_needed_for_evaluate, diff --git a/extern/ceres/internal/ceres/random.h b/extern/ceres/internal/ceres/random.h index 6b280f9ee64..0495d67581d 100644 --- a/extern/ceres/internal/ceres/random.h +++ b/extern/ceres/internal/ceres/random.h @@ -35,7 +35,7 @@ #include <cmath> #include <cstdlib> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { @@ -50,7 +50,7 @@ inline int Uniform(int n) { } inline double RandDouble() { - double r = static_cast<double>(rand()); + auto r = static_cast<double>(rand()); return r / RAND_MAX; } diff --git a/extern/ceres/internal/ceres/reorder_program.cc b/extern/ceres/internal/ceres/reorder_program.cc index 5d802365f33..d552ebf3de3 100644 --- a/extern/ceres/internal/ceres/reorder_program.cc +++ b/extern/ceres/internal/ceres/reorder_program.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -37,7 +37,8 @@ #include "Eigen/SparseCore" #include "ceres/cxsparse.h" -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" +#include "ceres/internal/export.h" #include "ceres/ordered_groups.h" #include "ceres/parameter_block.h" #include "ceres/parameter_block_ordering.h" @@ -88,8 +89,8 @@ static int MinParameterBlock(const ResidualBlock* residual_block, #if defined(CERES_USE_EIGEN_SPARSE) Eigen::SparseMatrix<int> CreateBlockJacobian( const TripletSparseMatrix& block_jacobian_transpose) { - typedef Eigen::SparseMatrix<int> SparseMatrix; - typedef Eigen::Triplet<int> Triplet; + using SparseMatrix = Eigen::SparseMatrix<int>; + using Triplet = Eigen::Triplet<int>; const int* rows = block_jacobian_transpose.rows(); const int* cols = block_jacobian_transpose.cols(); @@ -97,7 +98,7 @@ Eigen::SparseMatrix<int> CreateBlockJacobian( vector<Triplet> triplets; triplets.reserve(num_nonzeros); for (int i = 0; i < num_nonzeros; ++i) { - triplets.push_back(Triplet(cols[i], rows[i], 1)); + triplets.emplace_back(cols[i], rows[i], 1); } SparseMatrix block_jacobian(block_jacobian_transpose.num_cols(), @@ -127,9 +128,9 @@ void OrderingForSparseNormalCholeskyUsingSuiteSparse( ss.ApproximateMinimumDegreeOrdering(block_jacobian_transpose, &ordering[0]); } else { vector<int> constraints; - for (int i = 0; i < parameter_blocks.size(); ++i) { + for (auto* parameter_block : parameter_blocks) { constraints.push_back(parameter_block_ordering.GroupId( - parameter_blocks[i]->mutable_user_state())); + parameter_block->mutable_user_state())); } // Renumber the entries of constraints to be contiguous integers @@ -188,7 +189,7 @@ void OrderingForSparseNormalCholeskyUsingEigenSparse( // things. The right thing to do here would be to get a compressed // row sparse matrix representation of the jacobian and go from // there. But that is a project for another day. - typedef Eigen::SparseMatrix<int> SparseMatrix; + using SparseMatrix = Eigen::SparseMatrix<int>; const SparseMatrix block_jacobian = CreateBlockJacobian(tsm_block_jacobian_transpose); @@ -279,7 +280,7 @@ bool LexicographicallyOrderResidualBlocks( CHECK(find(residual_blocks_per_e_block.begin(), residual_blocks_per_e_block.end() - 1, - 0) != residual_blocks_per_e_block.end()) + 0) == residual_blocks_per_e_block.end() - 1) << "Congratulations, you found a Ceres bug! Please report this error " << "to the developers."; @@ -291,7 +292,7 @@ bool LexicographicallyOrderResidualBlocks( // filling is finished, the offset pointerts should have shifted down one // entry (this is verified below). vector<ResidualBlock*> reordered_residual_blocks( - (*residual_blocks).size(), static_cast<ResidualBlock*>(NULL)); + (*residual_blocks).size(), static_cast<ResidualBlock*>(nullptr)); for (int i = 0; i < residual_blocks->size(); ++i) { int bucket = min_position_per_residual[i]; @@ -299,7 +300,7 @@ bool LexicographicallyOrderResidualBlocks( offsets[bucket]--; // Sanity. - CHECK(reordered_residual_blocks[offsets[bucket]] == NULL) + CHECK(reordered_residual_blocks[offsets[bucket]] == nullptr) << "Congratulations, you found a Ceres bug! Please report this error " << "to the developers."; @@ -313,9 +314,9 @@ bool LexicographicallyOrderResidualBlocks( << "Congratulations, you found a Ceres bug! Please report this error " << "to the developers."; } - // Sanity check #2: No NULL's left behind. - for (int i = 0; i < reordered_residual_blocks.size(); ++i) { - CHECK(reordered_residual_blocks[i] != NULL) + // Sanity check #2: No nullptr's left behind. + for (auto* residual_block : reordered_residual_blocks) { + CHECK(residual_block != nullptr) << "Congratulations, you found a Ceres bug! Please report this error " << "to the developers."; } @@ -339,9 +340,9 @@ static void MaybeReorderSchurComplementColumnsUsingSuiteSparse( vector<ParameterBlock*>& parameter_blocks = *(program->mutable_parameter_blocks()); - for (int i = 0; i < parameter_blocks.size(); ++i) { + for (auto* parameter_block : parameter_blocks) { constraints.push_back(parameter_block_ordering.GroupId( - parameter_blocks[i]->mutable_user_state())); + parameter_block->mutable_user_state())); } // Renumber the entries of constraints to be contiguous integers as @@ -378,7 +379,7 @@ static void MaybeReorderSchurComplementColumnsUsingEigen( std::unique_ptr<TripletSparseMatrix> tsm_block_jacobian_transpose( program->CreateJacobianBlockSparsityTranspose()); - typedef Eigen::SparseMatrix<int> SparseMatrix; + using SparseMatrix = Eigen::SparseMatrix<int>; const SparseMatrix block_jacobian = CreateBlockJacobian(*tsm_block_jacobian_transpose); const int num_rows = block_jacobian.rows(); @@ -441,7 +442,7 @@ bool ReorderProgramForSchurTypeLinearSolver( if (parameter_block_ordering->NumGroups() == 1) { // If the user supplied an parameter_block_ordering with just one - // group, it is equivalent to the user supplying NULL as an + // group, it is equivalent to the user supplying nullptr as an // parameter_block_ordering. Ceres is completely free to choose the // parameter block ordering as it sees fit. For Schur type solvers, // this means that the user wishes for Ceres to identify the diff --git a/extern/ceres/internal/ceres/reorder_program.h b/extern/ceres/internal/ceres/reorder_program.h index 2e0c3264377..fbc49231c33 100644 --- a/extern/ceres/internal/ceres/reorder_program.h +++ b/extern/ceres/internal/ceres/reorder_program.h @@ -33,7 +33,8 @@ #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/parameter_block_ordering.h" #include "ceres/problem_impl.h" #include "ceres/types.h" @@ -44,7 +45,7 @@ namespace internal { class Program; // Reorder the parameter blocks in program using the ordering -CERES_EXPORT_INTERNAL bool ApplyOrdering( +CERES_NO_EXPORT bool ApplyOrdering( const ProblemImpl::ParameterMap& parameter_map, const ParameterBlockOrdering& ordering, Program* program, @@ -53,7 +54,7 @@ CERES_EXPORT_INTERNAL bool ApplyOrdering( // Reorder the residuals for program, if necessary, so that the residuals // involving each E block occur together. This is a necessary condition for the // Schur eliminator, which works on these "row blocks" in the jacobian. -CERES_EXPORT_INTERNAL bool LexicographicallyOrderResidualBlocks( +CERES_NO_EXPORT bool LexicographicallyOrderResidualBlocks( int size_of_first_elimination_group, Program* program, std::string* error); // Schur type solvers require that all parameter blocks eliminated @@ -72,7 +73,7 @@ CERES_EXPORT_INTERNAL bool LexicographicallyOrderResidualBlocks( // // Upon return, ordering contains the parameter block ordering that // was used to order the program. -CERES_EXPORT_INTERNAL bool ReorderProgramForSchurTypeLinearSolver( +CERES_NO_EXPORT bool ReorderProgramForSchurTypeLinearSolver( LinearSolverType linear_solver_type, SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, const ProblemImpl::ParameterMap& parameter_map, @@ -90,7 +91,7 @@ CERES_EXPORT_INTERNAL bool ReorderProgramForSchurTypeLinearSolver( // fill-reducing ordering is available in the sparse linear algebra // library (SuiteSparse version >= 4.2.0) then the fill reducing // ordering will take it into account, otherwise it will be ignored. -CERES_EXPORT_INTERNAL bool ReorderProgramForSparseCholesky( +CERES_NO_EXPORT bool ReorderProgramForSparseCholesky( SparseLinearAlgebraLibraryType sparse_linear_algebra_library_type, const ParameterBlockOrdering& parameter_block_ordering, int start_row_block, @@ -107,11 +108,13 @@ CERES_EXPORT_INTERNAL bool ReorderProgramForSparseCholesky( // bottom_residual_blocks.size() because we allow // bottom_residual_blocks to contain residual blocks not present in // the Program. -CERES_EXPORT_INTERNAL int ReorderResidualBlocksByPartition( +CERES_NO_EXPORT int ReorderResidualBlocksByPartition( const std::unordered_set<ResidualBlockId>& bottom_residual_blocks, Program* program); } // namespace internal } // namespace ceres -#endif // CERES_INTERNAL_REORDER_PROGRAM_ +#include "ceres/internal/reenable_warnings.h" + +#endif // CERES_INTERNAL_REORDER_PROGRAM_H_ diff --git a/extern/ceres/internal/ceres/residual_block.cc b/extern/ceres/internal/ceres/residual_block.cc index 067c9efe83d..cd408f2f98e 100644 --- a/extern/ceres/internal/ceres/residual_block.cc +++ b/extern/ceres/internal/ceres/residual_block.cc @@ -39,8 +39,8 @@ #include "ceres/cost_function.h" #include "ceres/internal/eigen.h" #include "ceres/internal/fixed_array.h" -#include "ceres/local_parameterization.h" #include "ceres/loss_function.h" +#include "ceres/manifold.h" #include "ceres/parameter_block.h" #include "ceres/residual_block_utils.h" #include "ceres/small_blas.h" @@ -87,7 +87,7 @@ bool ResidualBlock::Evaluate(const bool apply_loss_function, for (int i = 0; i < num_parameter_blocks; ++i) { const ParameterBlock* parameter_block = parameter_blocks_[i]; if (jacobians[i] != nullptr && - parameter_block->LocalParameterizationJacobian() != nullptr) { + parameter_block->PlusJacobian() != nullptr) { global_jacobians[i] = scratch; scratch += num_residuals * parameter_block->Size(); } else { @@ -132,27 +132,27 @@ bool ResidualBlock::Evaluate(const bool apply_loss_function, double squared_norm = VectorRef(residuals, num_residuals).squaredNorm(); - // Update the jacobians with the local parameterizations. + // Update the plus_jacobian for the manifolds. if (jacobians != nullptr) { for (int i = 0; i < num_parameter_blocks; ++i) { if (jacobians[i] != nullptr) { const ParameterBlock* parameter_block = parameter_blocks_[i]; - // Apply local reparameterization to the jacobians. - if (parameter_block->LocalParameterizationJacobian() != nullptr) { + // Apply the Manifold::PlusJacobian to the ambient jacobians. + if (parameter_block->PlusJacobian() != nullptr) { // jacobians[i] = global_jacobians[i] * global_to_local_jacobian. MatrixMatrixMultiply<Dynamic, Dynamic, Dynamic, Dynamic, 0>( global_jacobians[i], num_residuals, parameter_block->Size(), - parameter_block->LocalParameterizationJacobian(), + parameter_block->PlusJacobian(), parameter_block->Size(), - parameter_block->LocalSize(), + parameter_block->TangentSize(), jacobians[i], 0, 0, num_residuals, - parameter_block->LocalSize()); + parameter_block->TangentSize()); } } } @@ -183,7 +183,7 @@ bool ResidualBlock::Evaluate(const bool apply_loss_function, // Correct the jacobians for the loss function. correct.CorrectJacobian(num_residuals, - parameter_block->LocalSize(), + parameter_block->TangentSize(), residuals, jacobians[i]); } @@ -199,16 +199,16 @@ bool ResidualBlock::Evaluate(const bool apply_loss_function, int ResidualBlock::NumScratchDoublesForEvaluate() const { // Compute the amount of scratch space needed to store the full-sized - // jacobians. For parameters that have no local parameterization no storage - // is needed and the passed-in jacobian array is used directly. Also include - // space to store the residuals, which is needed for cost-only evaluations. - // This is slightly pessimistic, since both won't be needed all the time, but - // the amount of excess should not cause problems for the caller. + // jacobians. For parameters that have no manifold no storage is needed and + // the passed-in jacobian array is used directly. Also include space to store + // the residuals, which is needed for cost-only evaluations. This is slightly + // pessimistic, since both won't be needed all the time, but the amount of + // excess should not cause problems for the caller. int num_parameters = NumParameterBlocks(); int scratch_doubles = 1; for (int i = 0; i < num_parameters; ++i) { const ParameterBlock* parameter_block = parameter_blocks_[i]; - if (parameter_block->LocalParameterizationJacobian() != nullptr) { + if (parameter_block->PlusJacobian() != nullptr) { scratch_doubles += parameter_block->Size(); } } diff --git a/extern/ceres/internal/ceres/residual_block.h b/extern/ceres/internal/ceres/residual_block.h index f28fd42857c..978b94640fe 100644 --- a/extern/ceres/internal/ceres/residual_block.h +++ b/extern/ceres/internal/ceres/residual_block.h @@ -40,7 +40,8 @@ #include <vector> #include "ceres/cost_function.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/stringprintf.h" #include "ceres/types.h" @@ -65,7 +66,7 @@ class ParameterBlock; // // The residual block stores pointers to but does not own the cost functions, // loss functions, and parameter blocks. -class CERES_EXPORT_INTERNAL ResidualBlock { +class CERES_NO_EXPORT ResidualBlock { public: // Construct the residual block with the given cost/loss functions. Loss may // be null. The index is the index of the residual block in the Program's @@ -77,10 +78,10 @@ class CERES_EXPORT_INTERNAL ResidualBlock { // Evaluates the residual term, storing the scalar cost in *cost, the residual // components in *residuals, and the jacobians between the parameters and - // residuals in jacobians[i], in row-major order. If residuals is NULL, the - // residuals are not computed. If jacobians is NULL, no jacobians are - // computed. If jacobians[i] is NULL, then the jacobian for that parameter is - // not computed. + // residuals in jacobians[i], in row-major order. If residuals is nullptr, the + // residuals are not computed. If jacobians is nullptr, no jacobians are + // computed. If jacobians[i] is nullptr, then the jacobian for that parameter + // is not computed. // // cost must not be null. // @@ -92,10 +93,10 @@ class CERES_EXPORT_INTERNAL ResidualBlock { // false, the caller should expect the output memory locations to have // been modified. // - // The returned cost and jacobians have had robustification and local - // parameterizations applied already; for example, the jacobian for a - // 4-dimensional quaternion parameter using the "QuaternionParameterization" - // is num_residuals by 3 instead of num_residuals by 4. + // The returned cost and jacobians have had robustification and manifold + // projection applied already; for example, the jacobian for a 4-dimensional + // quaternion parameter using the "Quaternion" manifold is num_residuals by 3 + // instead of num_residuals by 4. // // apply_loss_function as the name implies allows the user to switch // the application of the loss function on and off. @@ -147,4 +148,6 @@ class CERES_EXPORT_INTERNAL ResidualBlock { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_RESIDUAL_BLOCK_H_ diff --git a/extern/ceres/internal/ceres/residual_block_utils.cc b/extern/ceres/internal/ceres/residual_block_utils.cc index d5b3fa1fa37..11c7623ce22 100644 --- a/extern/ceres/internal/ceres/residual_block_utils.cc +++ b/extern/ceres/internal/ceres/residual_block_utils.cc @@ -36,7 +36,7 @@ #include "ceres/array_utils.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/parameter_block.h" #include "ceres/residual_block.h" #include "ceres/stringprintf.h" @@ -56,7 +56,7 @@ void InvalidateEvaluation(const ResidualBlock& block, InvalidateArray(1, cost); InvalidateArray(num_residuals, residuals); - if (jacobians != NULL) { + if (jacobians != nullptr) { for (int i = 0; i < num_parameter_blocks; ++i) { const int parameter_block_size = block.parameter_blocks()[i]->Size(); InvalidateArray(num_residuals * parameter_block_size, jacobians[i]); @@ -104,9 +104,9 @@ string EvaluationToString(const ResidualBlock& block, StringAppendF(&result, "| "); for (int k = 0; k < num_residuals; ++k) { AppendArrayToString(1, - (jacobians != NULL && jacobians[i] != NULL) + (jacobians != nullptr && jacobians[i] != nullptr) ? jacobians[i] + k * parameter_block_size + j - : NULL, + : nullptr, &result); } StringAppendF(&result, "\n"); @@ -129,7 +129,7 @@ bool IsEvaluationValid(const ResidualBlock& block, return false; } - if (jacobians != NULL) { + if (jacobians != nullptr) { for (int i = 0; i < num_parameter_blocks; ++i) { const int parameter_block_size = block.parameter_blocks()[i]->Size(); if (!IsArrayValid(num_residuals * parameter_block_size, jacobians[i])) { diff --git a/extern/ceres/internal/ceres/residual_block_utils.h b/extern/ceres/internal/ceres/residual_block_utils.h index 41ae81abc99..f75b6aecce9 100644 --- a/extern/ceres/internal/ceres/residual_block_utils.h +++ b/extern/ceres/internal/ceres/residual_block_utils.h @@ -45,14 +45,15 @@ #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { class ResidualBlock; -// Invalidate cost, resdual and jacobian arrays (if not NULL). +// Invalidate cost, resdual and jacobian arrays (if not nullptr). +CERES_NO_EXPORT void InvalidateEvaluation(const ResidualBlock& block, double* cost, double* residuals, @@ -60,6 +61,7 @@ void InvalidateEvaluation(const ResidualBlock& block, // Check if any of the arrays cost, residuals or jacobians contains an // NaN, return true if it does. +CERES_NO_EXPORT bool IsEvaluationValid(const ResidualBlock& block, double const* const* parameters, double* cost, @@ -69,6 +71,7 @@ bool IsEvaluationValid(const ResidualBlock& block, // Create a string representation of the Residual block containing the // value of the parameters, residuals and jacobians if present. // Useful for debugging output. +CERES_NO_EXPORT std::string EvaluationToString(const ResidualBlock& block, double const* const* parameters, double* cost, diff --git a/extern/ceres/internal/ceres/schur_complement_solver.cc b/extern/ceres/internal/ceres/schur_complement_solver.cc index 65e7854f9e5..bb442b4280b 100644 --- a/extern/ceres/internal/ceres/schur_complement_solver.cc +++ b/extern/ceres/internal/ceres/schur_complement_solver.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -46,7 +46,6 @@ #include "ceres/conjugate_gradients_solver.h" #include "ceres/detect_structure.h" #include "ceres/internal/eigen.h" -#include "ceres/lapack.h" #include "ceres/linear_solver.h" #include "ceres/sparse_cholesky.h" #include "ceres/triplet_sparse_matrix.h" @@ -63,14 +62,12 @@ using std::vector; namespace { -class BlockRandomAccessSparseMatrixAdapter : public LinearOperator { +class BlockRandomAccessSparseMatrixAdapter final : public LinearOperator { public: explicit BlockRandomAccessSparseMatrixAdapter( const BlockRandomAccessSparseMatrix& m) : m_(m) {} - virtual ~BlockRandomAccessSparseMatrixAdapter() {} - // y = y + Ax; void RightMultiply(const double* x, double* y) const final { m_.SymmetricRightMultiply(x, y); @@ -88,14 +85,12 @@ class BlockRandomAccessSparseMatrixAdapter : public LinearOperator { const BlockRandomAccessSparseMatrix& m_; }; -class BlockRandomAccessDiagonalMatrixAdapter : public LinearOperator { +class BlockRandomAccessDiagonalMatrixAdapter final : public LinearOperator { public: explicit BlockRandomAccessDiagonalMatrixAdapter( const BlockRandomAccessDiagonalMatrix& m) : m_(m) {} - virtual ~BlockRandomAccessDiagonalMatrixAdapter() {} - // y = y + Ax; void RightMultiply(const double* x, double* y) const final { m_.RightMultiply(x, y); @@ -115,6 +110,14 @@ class BlockRandomAccessDiagonalMatrixAdapter : public LinearOperator { } // namespace +SchurComplementSolver::SchurComplementSolver( + const LinearSolver::Options& options) + : options_(options) { + CHECK_GT(options.elimination_groups.size(), 1); + CHECK_GT(options.elimination_groups[0], 0); + CHECK(options.context != nullptr); +} + LinearSolver::Summary SchurComplementSolver::SolveImpl( BlockSparseMatrix* A, const double* b, @@ -123,7 +126,7 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( EventLogger event_logger("SchurComplementSolver::Solve"); const CompressedRowBlockStructure* bs = A->block_structure(); - if (eliminator_.get() == NULL) { + if (eliminator_.get() == nullptr) { const int num_eliminate_blocks = options_.elimination_groups[0]; const int num_f_blocks = bs->cols.size() - num_eliminate_blocks; @@ -141,9 +144,9 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( // mechanism that does not cause binary bloat. if (options_.row_block_size == 2 && options_.e_block_size == 3 && options_.f_block_size == 6 && num_f_blocks == 1) { - eliminator_.reset(new SchurEliminatorForOneFBlock<2, 3, 6>); + eliminator_ = std::make_unique<SchurEliminatorForOneFBlock<2, 3, 6>>(); } else { - eliminator_.reset(SchurEliminatorBase::Create(options_)); + eliminator_ = SchurEliminatorBase::Create(options_); } CHECK(eliminator_); @@ -174,6 +177,12 @@ LinearSolver::Summary SchurComplementSolver::SolveImpl( return summary; } +DenseSchurComplementSolver::DenseSchurComplementSolver( + const LinearSolver::Options& options) + : SchurComplementSolver(options), + cholesky_(DenseCholesky::Create(options)) {} + +DenseSchurComplementSolver::~DenseSchurComplementSolver() = default; // Initialize a BlockRandomAccessDenseMatrix to store the Schur // complement. @@ -187,8 +196,8 @@ void DenseSchurComplementSolver::InitStorage( blocks[j] = bs->cols[i].size; } - set_lhs(new BlockRandomAccessDenseMatrix(blocks)); - set_rhs(new double[lhs()->num_rows()]); + set_lhs(std::make_unique<BlockRandomAccessDenseMatrix>(blocks)); + set_rhs(std::make_unique<double[]>(lhs()->num_rows())); } // Solve the system Sx = r, assuming that the matrix S is stored in a @@ -201,8 +210,7 @@ LinearSolver::Summary DenseSchurComplementSolver::SolveReducedLinearSystem( summary.termination_type = LINEAR_SOLVER_SUCCESS; summary.message = "Success."; - const BlockRandomAccessDenseMatrix* m = - down_cast<const BlockRandomAccessDenseMatrix*>(lhs()); + auto* m = down_cast<BlockRandomAccessDenseMatrix*>(mutable_lhs()); const int num_rows = m->num_rows(); // The case where there are no f blocks, and the system is block @@ -212,26 +220,8 @@ LinearSolver::Summary DenseSchurComplementSolver::SolveReducedLinearSystem( } summary.num_iterations = 1; - - if (options().dense_linear_algebra_library_type == EIGEN) { - Eigen::LLT<Matrix, Eigen::Upper> llt = - ConstMatrixRef(m->values(), num_rows, num_rows) - .selfadjointView<Eigen::Upper>() - .llt(); - if (llt.info() != Eigen::Success) { - summary.termination_type = LINEAR_SOLVER_FAILURE; - summary.message = - "Eigen failure. Unable to perform dense Cholesky factorization."; - return summary; - } - - VectorRef(solution, num_rows) = llt.solve(ConstVectorRef(rhs(), num_rows)); - } else { - VectorRef(solution, num_rows) = ConstVectorRef(rhs(), num_rows); - summary.termination_type = LAPACK::SolveInPlaceUsingCholesky( - num_rows, m->values(), solution, &summary.message); - } - + summary.termination_type = cholesky_->FactorAndSolve( + num_rows, m->mutable_values(), rhs(), solution, &summary.message); return summary; } @@ -243,7 +233,7 @@ SparseSchurComplementSolver::SparseSchurComplementSolver( } } -SparseSchurComplementSolver::~SparseSchurComplementSolver() {} +SparseSchurComplementSolver::~SparseSchurComplementSolver() = default; // Determine the non-zero blocks in the Schur Complement matrix, and // initialize a BlockRandomAccessSparseMatrix object. @@ -303,8 +293,8 @@ void SparseSchurComplementSolver::InitStorage( CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); for (int i = 0; i < row.cells.size(); ++i) { int r_block1_id = row.cells[i].block_id - num_eliminate_blocks; - for (int j = 0; j < row.cells.size(); ++j) { - int r_block2_id = row.cells[j].block_id - num_eliminate_blocks; + for (const auto& cell : row.cells) { + int r_block2_id = cell.block_id - num_eliminate_blocks; if (r_block1_id <= r_block2_id) { block_pairs.insert(make_pair(r_block1_id, r_block2_id)); } @@ -312,8 +302,9 @@ void SparseSchurComplementSolver::InitStorage( } } - set_lhs(new BlockRandomAccessSparseMatrix(blocks_, block_pairs)); - set_rhs(new double[lhs()->num_rows()]); + set_lhs( + std::make_unique<BlockRandomAccessSparseMatrix>(blocks_, block_pairs)); + set_rhs(std::make_unique<double[]>(lhs()->num_rows())); } LinearSolver::Summary SparseSchurComplementSolver::SolveReducedLinearSystem( @@ -338,11 +329,10 @@ LinearSolver::Summary SparseSchurComplementSolver::SolveReducedLinearSystem( const CompressedRowSparseMatrix::StorageType storage_type = sparse_cholesky_->StorageType(); if (storage_type == CompressedRowSparseMatrix::UPPER_TRIANGULAR) { - lhs.reset(CompressedRowSparseMatrix::FromTripletSparseMatrix(*tsm)); + lhs = CompressedRowSparseMatrix::FromTripletSparseMatrix(*tsm); lhs->set_storage_type(CompressedRowSparseMatrix::UPPER_TRIANGULAR); } else { - lhs.reset( - CompressedRowSparseMatrix::FromTripletSparseMatrixTransposed(*tsm)); + lhs = CompressedRowSparseMatrix::FromTripletSparseMatrixTransposed(*tsm); lhs->set_storage_type(CompressedRowSparseMatrix::LOWER_TRIANGULAR); } @@ -373,12 +363,12 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingConjugateGradients( // Only SCHUR_JACOBI is supported over here right now. CHECK_EQ(options().preconditioner_type, SCHUR_JACOBI); - if (preconditioner_.get() == NULL) { - preconditioner_.reset(new BlockRandomAccessDiagonalMatrix(blocks_)); + if (preconditioner_.get() == nullptr) { + preconditioner_ = + std::make_unique<BlockRandomAccessDiagonalMatrix>(blocks_); } - BlockRandomAccessSparseMatrix* sc = down_cast<BlockRandomAccessSparseMatrix*>( - const_cast<BlockRandomAccessMatrix*>(lhs())); + auto* sc = down_cast<BlockRandomAccessSparseMatrix*>(mutable_lhs()); // Extract block diagonal from the Schur complement to construct the // schur_jacobi preconditioner. @@ -404,10 +394,11 @@ SparseSchurComplementSolver::SolveReducedLinearSystemUsingConjugateGradients( VectorRef(solution, num_rows).setZero(); - std::unique_ptr<LinearOperator> lhs_adapter( - new BlockRandomAccessSparseMatrixAdapter(*sc)); - std::unique_ptr<LinearOperator> preconditioner_adapter( - new BlockRandomAccessDiagonalMatrixAdapter(*preconditioner_)); + std::unique_ptr<LinearOperator> lhs_adapter = + std::make_unique<BlockRandomAccessSparseMatrixAdapter>(*sc); + std::unique_ptr<LinearOperator> preconditioner_adapter = + std::make_unique<BlockRandomAccessDiagonalMatrixAdapter>( + *preconditioner_); LinearSolver::Options cg_options; cg_options.min_num_iterations = options().min_num_iterations; diff --git a/extern/ceres/internal/ceres/schur_complement_solver.h b/extern/ceres/internal/ceres/schur_complement_solver.h index 3bfa22f22e4..859a086cdf4 100644 --- a/extern/ceres/internal/ceres/schur_complement_solver.h +++ b/extern/ceres/internal/ceres/schur_complement_solver.h @@ -40,7 +40,9 @@ #include "ceres/block_random_access_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" -#include "ceres/internal/port.h" +#include "ceres/dense_cholesky.h" +#include "ceres/internal/config.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h" #include "ceres/types.h" @@ -50,6 +52,8 @@ #include "Eigen/SparseCholesky" #endif +#include "ceres/internal/disable_warnings.h" + namespace ceres { namespace internal { @@ -107,20 +111,12 @@ class SparseCholesky; // set to DENSE_SCHUR and SPARSE_SCHUR // respectively. LinearSolver::Options::elimination_groups[0] should // be at least 1. -class CERES_EXPORT_INTERNAL SchurComplementSolver - : public BlockSparseMatrixSolver { +class CERES_NO_EXPORT SchurComplementSolver : public BlockSparseMatrixSolver { public: - explicit SchurComplementSolver(const LinearSolver::Options& options) - : options_(options) { - CHECK_GT(options.elimination_groups.size(), 1); - CHECK_GT(options.elimination_groups[0], 0); - CHECK(options.context != NULL); - } + explicit SchurComplementSolver(const LinearSolver::Options& options); SchurComplementSolver(const SchurComplementSolver&) = delete; void operator=(const SchurComplementSolver&) = delete; - // LinearSolver methods - virtual ~SchurComplementSolver() {} LinearSolver::Summary SolveImpl( BlockSparseMatrix* A, const double* b, @@ -130,10 +126,14 @@ class CERES_EXPORT_INTERNAL SchurComplementSolver protected: const LinearSolver::Options& options() const { return options_; } + void set_lhs(std::unique_ptr<BlockRandomAccessMatrix> lhs) { + lhs_ = std::move(lhs); + } const BlockRandomAccessMatrix* lhs() const { return lhs_.get(); } - void set_lhs(BlockRandomAccessMatrix* lhs) { lhs_.reset(lhs); } + BlockRandomAccessMatrix* mutable_lhs() { return lhs_.get(); } + + void set_rhs(std::unique_ptr<double[]> rhs) { rhs_ = std::move(rhs); } const double* rhs() const { return rhs_.get(); } - void set_rhs(double* rhs) { rhs_.reset(rhs); } private: virtual void InitStorage(const CompressedRowBlockStructure* bs) = 0; @@ -149,30 +149,33 @@ class CERES_EXPORT_INTERNAL SchurComplementSolver }; // Dense Cholesky factorization based solver. -class DenseSchurComplementSolver : public SchurComplementSolver { +class CERES_NO_EXPORT DenseSchurComplementSolver final + : public SchurComplementSolver { public: - explicit DenseSchurComplementSolver(const LinearSolver::Options& options) - : SchurComplementSolver(options) {} + explicit DenseSchurComplementSolver(const LinearSolver::Options& options); DenseSchurComplementSolver(const DenseSchurComplementSolver&) = delete; void operator=(const DenseSchurComplementSolver&) = delete; - virtual ~DenseSchurComplementSolver() {} + ~DenseSchurComplementSolver() override; private: void InitStorage(const CompressedRowBlockStructure* bs) final; LinearSolver::Summary SolveReducedLinearSystem( const LinearSolver::PerSolveOptions& per_solve_options, double* solution) final; + + std::unique_ptr<DenseCholesky> cholesky_; }; // Sparse Cholesky factorization based solver. -class SparseSchurComplementSolver : public SchurComplementSolver { +class CERES_NO_EXPORT SparseSchurComplementSolver final + : public SchurComplementSolver { public: explicit SparseSchurComplementSolver(const LinearSolver::Options& options); SparseSchurComplementSolver(const SparseSchurComplementSolver&) = delete; void operator=(const SparseSchurComplementSolver&) = delete; - virtual ~SparseSchurComplementSolver(); + ~SparseSchurComplementSolver() override; private: void InitStorage(const CompressedRowBlockStructure* bs) final; @@ -191,4 +194,6 @@ class SparseSchurComplementSolver : public SchurComplementSolver { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SCHUR_COMPLEMENT_SOLVER_H_ diff --git a/extern/ceres/internal/ceres/schur_eliminator.cc b/extern/ceres/internal/ceres/schur_eliminator.cc index 613ae9558e9..22e7358070f 100644 --- a/extern/ceres/internal/ceres/schur_eliminator.cc +++ b/extern/ceres/internal/ceres/schur_eliminator.cc @@ -39,121 +39,126 @@ // // This file is generated using generate_template_specializations.py. +#include <memory> + #include "ceres/linear_solver.h" #include "ceres/schur_eliminator.h" namespace ceres { namespace internal { -SchurEliminatorBase* SchurEliminatorBase::Create( +SchurEliminatorBase::~SchurEliminatorBase() = default; + +std::unique_ptr<SchurEliminatorBase> SchurEliminatorBase::Create( const LinearSolver::Options& options) { #ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 2)) { - return new SchurEliminator<2, 2, 2>(options); + return std::make_unique<SchurEliminator<2, 2, 2>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 3)) { - return new SchurEliminator<2, 2, 3>(options); + return std::make_unique<SchurEliminator<2, 2, 3>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 2) && (options.f_block_size == 4)) { - return new SchurEliminator<2, 2, 4>(options); + return std::make_unique<SchurEliminator<2, 2, 4>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 2)) { - return new SchurEliminator<2, 2, Eigen::Dynamic>(options); + return std::make_unique<SchurEliminator<2, 2, Eigen::Dynamic>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 3)) { - return new SchurEliminator<2, 3, 3>(options); + return std::make_unique<SchurEliminator<2, 3, 3>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 4)) { - return new SchurEliminator<2, 3, 4>(options); + return std::make_unique<SchurEliminator<2, 3, 4>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 6)) { - return new SchurEliminator<2, 3, 6>(options); + return std::make_unique<SchurEliminator<2, 3, 6>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 3) && (options.f_block_size == 9)) { - return new SchurEliminator<2, 3, 9>(options); + return std::make_unique<SchurEliminator<2, 3, 9>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 3)) { - return new SchurEliminator<2, 3, Eigen::Dynamic>(options); + return std::make_unique<SchurEliminator<2, 3, Eigen::Dynamic>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 3)) { - return new SchurEliminator<2, 4, 3>(options); + return std::make_unique<SchurEliminator<2, 4, 3>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 4)) { - return new SchurEliminator<2, 4, 4>(options); + return std::make_unique<SchurEliminator<2, 4, 4>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 6)) { - return new SchurEliminator<2, 4, 6>(options); + return std::make_unique<SchurEliminator<2, 4, 6>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 8)) { - return new SchurEliminator<2, 4, 8>(options); + return std::make_unique<SchurEliminator<2, 4, 8>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4) && (options.f_block_size == 9)) { - return new SchurEliminator<2, 4, 9>(options); + return std::make_unique<SchurEliminator<2, 4, 9>>(options); } if ((options.row_block_size == 2) && (options.e_block_size == 4)) { - return new SchurEliminator<2, 4, Eigen::Dynamic>(options); + return std::make_unique<SchurEliminator<2, 4, Eigen::Dynamic>>(options); } if (options.row_block_size == 2) { - return new SchurEliminator<2, Eigen::Dynamic, Eigen::Dynamic>(options); + return std::make_unique<SchurEliminator<2, Eigen::Dynamic, Eigen::Dynamic>>(options); } if ((options.row_block_size == 3) && (options.e_block_size == 3) && (options.f_block_size == 3)) { - return new SchurEliminator<3, 3, 3>(options); + return std::make_unique<SchurEliminator<3, 3, 3>>(options); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 2)) { - return new SchurEliminator<4, 4, 2>(options); + return std::make_unique<SchurEliminator<4, 4, 2>>(options); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 3)) { - return new SchurEliminator<4, 4, 3>(options); + return std::make_unique<SchurEliminator<4, 4, 3>>(options); } if ((options.row_block_size == 4) && (options.e_block_size == 4) && (options.f_block_size == 4)) { - return new SchurEliminator<4, 4, 4>(options); + return std::make_unique<SchurEliminator<4, 4, 4>>(options); } if ((options.row_block_size == 4) && (options.e_block_size == 4)) { - return new SchurEliminator<4, 4, Eigen::Dynamic>(options); + return std::make_unique<SchurEliminator<4, 4, Eigen::Dynamic>>(options); } #endif VLOG(1) << "Template specializations not found for <" << options.row_block_size << "," << options.e_block_size << "," << options.f_block_size << ">"; - return new SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>( - options); + return std::make_unique<SchurEliminator<Eigen::Dynamic, + Eigen::Dynamic, + Eigen::Dynamic>>(options); } } // namespace internal diff --git a/extern/ceres/internal/ceres/schur_eliminator.h b/extern/ceres/internal/ceres/schur_eliminator.h index 42c016ee9b0..91831dceb5a 100644 --- a/extern/ceres/internal/ceres/schur_eliminator.h +++ b/extern/ceres/internal/ceres/schur_eliminator.h @@ -40,8 +40,10 @@ #include "ceres/block_random_access_matrix.h" #include "ceres/block_sparse_matrix.h" #include "ceres/block_structure.h" +#include "ceres/internal/config.h" +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -56,9 +58,8 @@ namespace internal { // Where x = [y;z] is a partition of the variables. The partitioning // of the variables is such that, E'E is a block diagonal matrix. Or // in other words, the parameter blocks in E form an independent set -// of the of the graph implied by the block matrix A'A. Then, this -// class provides the functionality to compute the Schur complement -// system +// of the graph implied by the block matrix A'A. Then, this class +// provides the functionality to compute the Schur complement system // // S z = r // @@ -164,9 +165,9 @@ namespace internal { // 2008 for an example of such use]. // // Example usage: Please see schur_complement_solver.cc -class CERES_EXPORT_INTERNAL SchurEliminatorBase { +class CERES_NO_EXPORT SchurEliminatorBase { public: - virtual ~SchurEliminatorBase() {} + virtual ~SchurEliminatorBase(); // Initialize the eliminator. It is the user's responsibilty to call // this function before calling Eliminate or BackSubstitute. It is @@ -210,7 +211,8 @@ class CERES_EXPORT_INTERNAL SchurEliminatorBase { const double* z, double* y) = 0; // Factory - static SchurEliminatorBase* Create(const LinearSolver::Options& options); + static std::unique_ptr<SchurEliminatorBase> Create( + const LinearSolver::Options& options); }; // Templated implementation of the SchurEliminatorBase interface. The @@ -223,7 +225,7 @@ class CERES_EXPORT_INTERNAL SchurEliminatorBase { template <int kRowBlockSize = Eigen::Dynamic, int kEBlockSize = Eigen::Dynamic, int kFBlockSize = Eigen::Dynamic> -class SchurEliminator : public SchurEliminatorBase { +class CERES_NO_EXPORT SchurEliminator final : public SchurEliminatorBase { public: explicit SchurEliminator(const LinearSolver::Options& options) : num_threads_(options.num_threads), context_(options.context) { @@ -231,7 +233,7 @@ class SchurEliminator : public SchurEliminatorBase { } // SchurEliminatorBase Interface - virtual ~SchurEliminator(); + ~SchurEliminator() override; void Init(int num_eliminate_blocks, bool assume_full_rank_ete, const CompressedRowBlockStructure* bs) final; @@ -272,9 +274,9 @@ class SchurEliminator : public SchurEliminatorBase { // buffer_layout[z1] = 0 // buffer_layout[z5] = y1 * z1 // buffer_layout[z2] = y1 * z1 + y1 * z5 - typedef std::map<int, int> BufferLayoutType; + using BufferLayoutType = std::map<int, int>; struct Chunk { - Chunk() : size(0) {} + explicit Chunk(int start) : size(0), start(start) {} int size; int start; BufferLayoutType buffer_layout; @@ -378,9 +380,9 @@ class SchurEliminator : public SchurEliminatorBase { template <int kRowBlockSize = Eigen::Dynamic, int kEBlockSize = Eigen::Dynamic, int kFBlockSize = Eigen::Dynamic> -class SchurEliminatorForOneFBlock : public SchurEliminatorBase { +class CERES_NO_EXPORT SchurEliminatorForOneFBlock final + : public SchurEliminatorBase { public: - virtual ~SchurEliminatorForOneFBlock() {} void Init(int num_eliminate_blocks, bool assume_full_rank_ete, const CompressedRowBlockStructure* bs) override { @@ -484,7 +486,7 @@ class SchurEliminatorForOneFBlock : public SchurEliminatorBase { Eigen::Matrix<double, kFBlockSize, 1> f_t_b; // Add the square of the diagonal to e_t_e. - if (D != NULL) { + if (D != nullptr) { const typename EigenTypes<kEBlockSize>::ConstVectorRef diag( D + bs->cols[e_block_id].position, kEBlockSize); e_t_e = diag.array().square().matrix().asDiagonal(); @@ -624,4 +626,6 @@ class SchurEliminatorForOneFBlock : public SchurEliminatorBase { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SCHUR_ELIMINATOR_H_ diff --git a/extern/ceres/internal/ceres/schur_eliminator_impl.h b/extern/ceres/internal/ceres/schur_eliminator_impl.h index 1f0b4fa481d..de3ba3e5dcb 100644 --- a/extern/ceres/internal/ceres/schur_eliminator_impl.h +++ b/extern/ceres/internal/ceres/schur_eliminator_impl.h @@ -47,7 +47,7 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on #include <algorithm> @@ -125,10 +125,8 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::Init( break; } - chunks_.push_back(Chunk()); + chunks_.push_back(Chunk(r)); Chunk& chunk = chunks_.back(); - chunk.size = 0; - chunk.start = r; int buffer_size = 0; const int e_block_size = bs->cols[chunk_block_id].size; @@ -161,12 +159,13 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::Init( uneliminated_row_begins_ = chunk.start + chunk.size; - buffer_.reset(new double[buffer_size_ * num_threads_]); + buffer_ = std::make_unique<double[]>(buffer_size_ * num_threads_); // chunk_outer_product_buffer_ only needs to store e_block_size * // f_block_size, which is always less than buffer_size_, so we just // allocate buffer_size_ per thread. - chunk_outer_product_buffer_.reset(new double[buffer_size_ * num_threads_]); + chunk_outer_product_buffer_ = + std::make_unique<double[]>(buffer_size_ * num_threads_); STLDeleteElements(&rhs_locks_); rhs_locks_.resize(num_col_blocks - num_eliminate_blocks_); @@ -193,7 +192,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::Eliminate( const int num_col_blocks = bs->cols.size(); // Add the diagonal to the schur complement. - if (D != NULL) { + if (D != nullptr) { ParallelFor(context_, num_eliminate_blocks_, num_col_blocks, @@ -203,7 +202,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::Eliminate( int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell( block_id, block_id, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { const int block_size = bs->cols[i].size; typename EigenTypes<Eigen::Dynamic>::ConstVectorRef diag( D + bs->cols[i].position, block_size); @@ -245,7 +244,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::Eliminate( typename EigenTypes<kEBlockSize, kEBlockSize>::Matrix ete(e_block_size, e_block_size); - if (D != NULL) { + if (D != nullptr) { const typename EigenTypes<kEBlockSize>::ConstVectorRef diag( D + bs->cols[e_block_id].position, e_block_size); ete = diag.array().square().matrix().asDiagonal(); @@ -327,7 +326,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>::BackSubstitute( typename EigenTypes<kEBlockSize, kEBlockSize>::Matrix ete(e_block_size, e_block_size); - if (D != NULL) { + if (D != nullptr) { const typename EigenTypes<kEBlockSize>::ConstVectorRef diag( D + bs->cols[e_block_id].position, e_block_size); ete = diag.array().square().matrix().asDiagonal(); @@ -525,7 +524,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: // computation of the right-hand matrix product, but memory // references to the left hand side. const int e_block_size = inverse_ete.rows(); - BufferLayoutType::const_iterator it1 = buffer_layout.begin(); + auto it1 = buffer_layout.begin(); double* b1_transpose_inverse_ete = chunk_outer_product_buffer_.get() + thread_id * buffer_size_; @@ -542,14 +541,14 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: b1_transpose_inverse_ete, 0, 0, block1_size, e_block_size); // clang-format on - BufferLayoutType::const_iterator it2 = it1; + auto it2 = it1; for (; it2 != buffer_layout.end(); ++it2) { const int block2 = it2->first - num_eliminate_blocks_; int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell(block1, block2, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { const int block2_size = bs->cols[it2->first].size; std::lock_guard<std::mutex> l(cell_info->m); // clang-format off @@ -627,7 +626,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell(block1, block1, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { std::lock_guard<std::mutex> l(cell_info->m); // This multiply currently ignores the fact that this is a // symmetric outer product. @@ -647,7 +646,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell(block1, block2, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { const int block2_size = bs->cols[row.cells[j].block_id].size; std::lock_guard<std::mutex> l(cell_info->m); // clang-format off @@ -682,7 +681,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell(block1, block1, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { std::lock_guard<std::mutex> l(cell_info->m); // block += b1.transpose() * b1; // clang-format off @@ -702,7 +701,7 @@ void SchurEliminator<kRowBlockSize, kEBlockSize, kFBlockSize>:: int r, c, row_stride, col_stride; CellInfo* cell_info = lhs->GetCell(block1, block2, &r, &c, &row_stride, &col_stride); - if (cell_info != NULL) { + if (cell_info != nullptr) { // block += b1.transpose() * b2; std::lock_guard<std::mutex> l(cell_info->m); // clang-format off diff --git a/extern/ceres/internal/ceres/schur_eliminator_template.py b/extern/ceres/internal/ceres/schur_eliminator_template.py deleted file mode 100644 index 50515956e89..00000000000 --- a/extern/ceres/internal/ceres/schur_eliminator_template.py +++ /dev/null @@ -1,151 +0,0 @@ -# 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) -# -# Script for explicitly generating template specialization of the -# SchurEliminator class. It is a rather large class -# and the number of explicit instantiations is also large. Explicitly -# generating these instantiations in separate .cc files breaks the -# compilation into separate compilation unit rather than one large cc -# file which takes 2+GB of RAM to compile. -# -# This script creates two sets of files. -# -# 1. schur_eliminator_x_x_x.cc -# where, the x indicates the template parameters and -# -# 2. schur_eliminator.cc -# -# that contains a factory function for instantiating these classes -# based on runtime parameters. -# -# The list of tuples, specializations indicates the set of -# specializations that is generated. - -# Set of template specializations to generate - -HEADER = """// 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) -// -// Template specialization of SchurEliminator. -// -// ======================================== -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -// THIS FILE IS AUTOGENERATED. DO NOT EDIT. -//========================================= -// -// This file is generated using generate_template_specializations.py. -""" - -DYNAMIC_FILE = """ -#include "ceres/schur_eliminator_impl.h" - -namespace ceres { -namespace internal { - -template class SchurEliminator<%s, %s, %s>; - -} // namespace internal -} // namespace ceres -""" - -SPECIALIZATION_FILE = """ -// This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" - -#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION - -#include "ceres/schur_eliminator_impl.h" - -namespace ceres { -namespace internal { - -template class SchurEliminator<%s, %s, %s>; - -} // namespace internal -} // namespace ceres - -#endif // CERES_RESTRICT_SCHUR_SPECIALIZATION -""" - -FACTORY_FILE_HEADER = """ -#include "ceres/linear_solver.h" -#include "ceres/schur_eliminator.h" - -namespace ceres { -namespace internal { - -SchurEliminatorBase* SchurEliminatorBase::Create( - const LinearSolver::Options& options) { -#ifndef CERES_RESTRICT_SCHUR_SPECIALIZATION -""" - -FACTORY = """ return new SchurEliminator<%s, %s, %s>(options);""" - -FACTORY_FOOTER = """ -#endif - VLOG(1) << "Template specializations not found for <" - << options.row_block_size << "," << options.e_block_size << "," - << options.f_block_size << ">"; - return new SchurEliminator<Eigen::Dynamic, Eigen::Dynamic, Eigen::Dynamic>( - options); -} - -} // namespace internal -} // namespace ceres -""" diff --git a/extern/ceres/internal/ceres/schur_jacobi_preconditioner.cc b/extern/ceres/internal/ceres/schur_jacobi_preconditioner.cc index 89d770b405a..3ecec728262 100644 --- a/extern/ceres/internal/ceres/schur_jacobi_preconditioner.cc +++ b/extern/ceres/internal/ceres/schur_jacobi_preconditioner.cc @@ -43,26 +43,25 @@ namespace ceres { namespace internal { SchurJacobiPreconditioner::SchurJacobiPreconditioner( - const CompressedRowBlockStructure& bs, - const Preconditioner::Options& options) - : options_(options) { + const CompressedRowBlockStructure& bs, Preconditioner::Options options) + : options_(std::move(options)) { CHECK_GT(options_.elimination_groups.size(), 1); CHECK_GT(options_.elimination_groups[0], 0); const int num_blocks = bs.cols.size() - options_.elimination_groups[0]; CHECK_GT(num_blocks, 0) << "Jacobian should have at least 1 f_block for " << "SCHUR_JACOBI preconditioner."; - CHECK(options_.context != NULL); + CHECK(options_.context != nullptr); std::vector<int> blocks(num_blocks); for (int i = 0; i < num_blocks; ++i) { blocks[i] = bs.cols[i + options_.elimination_groups[0]].size; } - m_.reset(new BlockRandomAccessDiagonalMatrix(blocks)); + m_ = std::make_unique<BlockRandomAccessDiagonalMatrix>(blocks); InitEliminator(bs); } -SchurJacobiPreconditioner::~SchurJacobiPreconditioner() {} +SchurJacobiPreconditioner::~SchurJacobiPreconditioner() = default; // Initialize the SchurEliminator. void SchurJacobiPreconditioner::InitEliminator( @@ -74,7 +73,7 @@ void SchurJacobiPreconditioner::InitEliminator( eliminator_options.f_block_size = options_.f_block_size; eliminator_options.row_block_size = options_.row_block_size; eliminator_options.context = options_.context; - eliminator_.reset(SchurEliminatorBase::Create(eliminator_options)); + eliminator_ = SchurEliminatorBase::Create(eliminator_options); const bool kFullRankETE = true; eliminator_->Init( eliminator_options.elimination_groups[0], kFullRankETE, &bs); diff --git a/extern/ceres/internal/ceres/schur_jacobi_preconditioner.h b/extern/ceres/internal/ceres/schur_jacobi_preconditioner.h index 372b790b82f..a43bc3388a1 100644 --- a/extern/ceres/internal/ceres/schur_jacobi_preconditioner.h +++ b/extern/ceres/internal/ceres/schur_jacobi_preconditioner.h @@ -43,6 +43,8 @@ #include <utility> #include <vector> +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/preconditioner.h" namespace ceres { @@ -69,10 +71,11 @@ class SchurEliminatorBase; // options.elimination_groups.push_back(num_cameras); // SchurJacobiPreconditioner preconditioner( // *A.block_structure(), options); -// preconditioner.Update(A, NULL); +// preconditioner.Update(A, nullptr); // preconditioner.RightMultiply(x, y); // -class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner { +class CERES_NO_EXPORT SchurJacobiPreconditioner + : public BlockSparseMatrixPreconditioner { public: // Initialize the symbolic structure of the preconditioner. bs is // the block structure of the linear system to be solved. It is used @@ -81,11 +84,11 @@ class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner { // It has the same structural requirement as other Schur complement // based solvers. Please see schur_eliminator.h for more details. SchurJacobiPreconditioner(const CompressedRowBlockStructure& bs, - const Preconditioner::Options& options); + Preconditioner::Options options); SchurJacobiPreconditioner(const SchurJacobiPreconditioner&) = delete; void operator=(const SchurJacobiPreconditioner&) = delete; - virtual ~SchurJacobiPreconditioner(); + ~SchurJacobiPreconditioner() override; // Preconditioner interface. void RightMultiply(const double* x, double* y) const final; @@ -104,4 +107,6 @@ class SchurJacobiPreconditioner : public BlockSparseMatrixPreconditioner { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SCHUR_JACOBI_PRECONDITIONER_H_ diff --git a/extern/ceres/internal/ceres/schur_templates.h b/extern/ceres/internal/ceres/schur_templates.h index 90aee0a1afc..cacee20c412 100644 --- a/extern/ceres/internal/ceres/schur_templates.h +++ b/extern/ceres/internal/ceres/schur_templates.h @@ -32,11 +32,14 @@ #ifndef CERES_INTERNAL_SCHUR_TEMPLATES_H_ #define CERES_INTERNAL_SCHUR_TEMPLATES_H_ +#include "ceres/internal/config.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { namespace internal { +CERES_NO_EXPORT void GetBestSchurTemplateSpecialization(int* row_block_size, int* e_block_size, int* f_block_size); diff --git a/extern/ceres/internal/ceres/scoped_thread_token.h b/extern/ceres/internal/ceres/scoped_thread_token.h index c167397cce9..533bfd5a387 100644 --- a/extern/ceres/internal/ceres/scoped_thread_token.h +++ b/extern/ceres/internal/ceres/scoped_thread_token.h @@ -31,6 +31,7 @@ #ifndef CERES_INTERNAL_SCOPED_THREAD_TOKEN_H_ #define CERES_INTERNAL_SCOPED_THREAD_TOKEN_H_ +#include "ceres/internal/export.h" #include "ceres/thread_token_provider.h" namespace ceres { @@ -38,21 +39,20 @@ namespace internal { // Helper class for ThreadTokenProvider. This object acquires a token in its // constructor and puts that token back with destruction. -class ScopedThreadToken { +class CERES_NO_EXPORT ScopedThreadToken { public: - ScopedThreadToken(ThreadTokenProvider* provider) + explicit ScopedThreadToken(ThreadTokenProvider* provider) : provider_(provider), token_(provider->Acquire()) {} ~ScopedThreadToken() { provider_->Release(token_); } + ScopedThreadToken(ScopedThreadToken&) = delete; + ScopedThreadToken& operator=(ScopedThreadToken&) = delete; int token() const { return token_; } private: ThreadTokenProvider* provider_; int token_; - - ScopedThreadToken(ScopedThreadToken&); - ScopedThreadToken& operator=(ScopedThreadToken&); }; } // namespace internal diff --git a/extern/ceres/internal/ceres/scratch_evaluate_preparer.cc b/extern/ceres/internal/ceres/scratch_evaluate_preparer.cc index 9905b220fbf..0a1b0f3e7d1 100644 --- a/extern/ceres/internal/ceres/scratch_evaluate_preparer.cc +++ b/extern/ceres/internal/ceres/scratch_evaluate_preparer.cc @@ -30,6 +30,8 @@ #include "ceres/scratch_evaluate_preparer.h" +#include <memory> + #include "ceres/parameter_block.h" #include "ceres/program.h" #include "ceres/residual_block.h" @@ -37,9 +39,9 @@ namespace ceres { namespace internal { -ScratchEvaluatePreparer* ScratchEvaluatePreparer::Create(const Program& program, - int num_threads) { - ScratchEvaluatePreparer* preparers = new ScratchEvaluatePreparer[num_threads]; +std::unique_ptr<ScratchEvaluatePreparer[]> ScratchEvaluatePreparer::Create( + const Program& program, int num_threads) { + auto preparers = std::make_unique<ScratchEvaluatePreparer[]>(num_threads); int max_derivatives_per_residual_block = program.MaxDerivativesPerResidualBlock(); for (int i = 0; i < num_threads; i++) { @@ -49,7 +51,8 @@ ScratchEvaluatePreparer* ScratchEvaluatePreparer::Create(const Program& program, } void ScratchEvaluatePreparer::Init(int max_derivatives_per_residual_block) { - jacobian_scratch_.reset(new double[max_derivatives_per_residual_block]); + jacobian_scratch_ = + std::make_unique<double[]>(max_derivatives_per_residual_block); } // Point the jacobian blocks into the scratch area of this evaluate preparer. @@ -64,10 +67,10 @@ void ScratchEvaluatePreparer::Prepare(const ResidualBlock* residual_block, const ParameterBlock* parameter_block = residual_block->parameter_blocks()[j]; if (parameter_block->IsConstant()) { - jacobians[j] = NULL; + jacobians[j] = nullptr; } else { jacobians[j] = jacobian_block_cursor; - jacobian_block_cursor += num_residuals * parameter_block->LocalSize(); + jacobian_block_cursor += num_residuals * parameter_block->TangentSize(); } } } diff --git a/extern/ceres/internal/ceres/scratch_evaluate_preparer.h b/extern/ceres/internal/ceres/scratch_evaluate_preparer.h index 2d2745d6269..3f4e7df8de0 100644 --- a/extern/ceres/internal/ceres/scratch_evaluate_preparer.h +++ b/extern/ceres/internal/ceres/scratch_evaluate_preparer.h @@ -37,6 +37,9 @@ #include <memory> +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" + namespace ceres { namespace internal { @@ -44,11 +47,11 @@ class Program; class ResidualBlock; class SparseMatrix; -class ScratchEvaluatePreparer { +class CERES_NO_EXPORT ScratchEvaluatePreparer { public: // Create num_threads ScratchEvaluatePreparers. - static ScratchEvaluatePreparer* Create(const Program& program, - int num_threads); + static std::unique_ptr<ScratchEvaluatePreparer[]> Create( + const Program& program, int num_threads); // EvaluatePreparer interface void Init(int max_derivatives_per_residual_block); @@ -66,4 +69,6 @@ class ScratchEvaluatePreparer { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SCRATCH_EVALUATE_PREPARER_H_ diff --git a/extern/ceres/internal/ceres/single_linkage_clustering.h b/extern/ceres/internal/ceres/single_linkage_clustering.h index e891a9eec0a..b4a7e077619 100644 --- a/extern/ceres/internal/ceres/single_linkage_clustering.h +++ b/extern/ceres/internal/ceres/single_linkage_clustering.h @@ -34,7 +34,8 @@ #include <unordered_map> #include "ceres/graph.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -55,12 +56,14 @@ struct SingleLinkageClusteringOptions { // // The return value of this function is the number of clusters // identified by the algorithm. -int CERES_EXPORT_INTERNAL -ComputeSingleLinkageClustering(const SingleLinkageClusteringOptions& options, - const WeightedGraph<int>& graph, - std::unordered_map<int, int>* membership); +CERES_NO_EXPORT int ComputeSingleLinkageClustering( + const SingleLinkageClusteringOptions& options, + const WeightedGraph<int>& graph, + std::unordered_map<int, int>* membership); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SINGLE_LINKAGE_CLUSTERING_H_ diff --git a/extern/ceres/internal/ceres/small_blas.h b/extern/ceres/internal/ceres/small_blas.h index 4ee9229f35f..1cf41a5f1c2 100644 --- a/extern/ceres/internal/ceres/small_blas.h +++ b/extern/ceres/internal/ceres/small_blas.h @@ -36,7 +36,7 @@ #define CERES_INTERNAL_SMALL_BLAS_H_ #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "glog/logging.h" #include "small_blas_generic.h" @@ -210,7 +210,7 @@ CERES_GEMM_BEGIN(MatrixMatrixMultiplyNaive) { // Process the couple columns in remainder if present. if (NUM_COL_C & 2) { - int col = NUM_COL_C & (int)(~(span - 1)); + int col = NUM_COL_C & (~(span - 1)); const double* pa = &A[0]; for (int row = 0; row < NUM_ROW_C; ++row, pa += NUM_COL_A) { const double* pb = &B[col]; @@ -232,7 +232,7 @@ CERES_GEMM_BEGIN(MatrixMatrixMultiplyNaive) { } // Calculate the main part with multiples of 4. - int col_m = NUM_COL_C & (int)(~(span - 1)); + int col_m = NUM_COL_C & (~(span - 1)); for (int col = 0; col < col_m; col += span) { for (int row = 0; row < NUM_ROW_C; ++row) { const int index = (row + start_row_c) * col_stride_c + start_col_c + col; @@ -315,7 +315,7 @@ CERES_GEMM_BEGIN(MatrixTransposeMatrixMultiplyNaive) { // Process the couple columns in remainder if present. if (NUM_COL_C & 2) { - int col = NUM_COL_C & (int)(~(span - 1)); + int col = NUM_COL_C & (~(span - 1)); for (int row = 0; row < NUM_ROW_C; ++row) { const double* pa = &A[row]; const double* pb = &B[col]; @@ -339,7 +339,7 @@ CERES_GEMM_BEGIN(MatrixTransposeMatrixMultiplyNaive) { } // Process the main part with multiples of 4. - int col_m = NUM_COL_C & (int)(~(span - 1)); + int col_m = NUM_COL_C & (~(span - 1)); for (int col = 0; col < col_m; col += span) { for (int row = 0; row < NUM_ROW_C; ++row) { const int index = (row + start_row_c) * col_stride_c + start_col_c + col; @@ -435,7 +435,7 @@ inline void MatrixVectorMultiply(const double* A, // Process the couple rows in remainder if present. if (NUM_ROW_A & 2) { - int row = NUM_ROW_A & (int)(~(span - 1)); + int row = NUM_ROW_A & (~(span - 1)); const double* pa1 = &A[row * NUM_COL_A]; const double* pa2 = pa1 + NUM_COL_A; const double* pb = &b[0]; @@ -454,7 +454,7 @@ inline void MatrixVectorMultiply(const double* A, } // Calculate the main part with multiples of 4. - int row_m = NUM_ROW_A & (int)(~(span - 1)); + int row_m = NUM_ROW_A & (~(span - 1)); for (int row = 0; row < row_m; row += span) { // clang-format off MVM_mat4x1(NUM_COL_A, &A[row * NUM_COL_A], NUM_COL_A, @@ -522,7 +522,7 @@ inline void MatrixTransposeVectorMultiply(const double* A, // Process the couple columns in remainder if present. if (NUM_COL_A & 2) { - int row = NUM_COL_A & (int)(~(span - 1)); + int row = NUM_COL_A & (~(span - 1)); const double* pa = &A[row]; const double* pb = &b[0]; double tmp1 = 0.0, tmp2 = 0.0; @@ -543,7 +543,7 @@ inline void MatrixTransposeVectorMultiply(const double* A, } // Calculate the main part with multiples of 4. - int row_m = NUM_COL_A & (int)(~(span - 1)); + int row_m = NUM_COL_A & (~(span - 1)); for (int row = 0; row < row_m; row += span) { // clang-format off MTV_mat4x1(NUM_ROW_A, &A[row], NUM_COL_A, diff --git a/extern/ceres/internal/ceres/small_blas_generic.h b/extern/ceres/internal/ceres/small_blas_generic.h index 3f3ea424c80..f5aa909a8a3 100644 --- a/extern/ceres/internal/ceres/small_blas_generic.h +++ b/extern/ceres/internal/ceres/small_blas_generic.h @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2018 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -100,10 +100,11 @@ static inline void MMM_mat1x4(const int col_a, #define CERES_GEMM_OPT_MMM_MAT1X4_MUL \ av = pa[k]; \ pb = b + bi; \ - c0 += av * *pb++; \ - c1 += av * *pb++; \ - c2 += av * *pb++; \ - c3 += av * *pb++; \ + c0 += av * pb[0]; \ + c1 += av * pb[1]; \ + c2 += av * pb[2]; \ + c3 += av * pb[3]; \ + pb += 4; \ bi += col_stride_b; \ k++; @@ -167,10 +168,11 @@ static inline void MTM_mat1x4(const int col_a, #define CERES_GEMM_OPT_MTM_MAT1X4_MUL \ av = pa[ai]; \ pb = b + bi; \ - c0 += av * *pb++; \ - c1 += av * *pb++; \ - c2 += av * *pb++; \ - c3 += av * *pb++; \ + c0 += av * pb[0]; \ + c1 += av * pb[1]; \ + c2 += av * pb[2]; \ + c3 += av * pb[3]; \ + pb += 4; \ ai += col_stride_a; \ bi += col_stride_b; diff --git a/extern/ceres/internal/ceres/solver.cc b/extern/ceres/internal/ceres/solver.cc index dfde1221b61..150c5550fc9 100644 --- a/extern/ceres/internal/ceres/solver.cc +++ b/extern/ceres/internal/ceres/solver.cc @@ -41,7 +41,7 @@ #include "ceres/context_impl.h" #include "ceres/detect_structure.h" #include "ceres/gradient_checking_cost_function.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/parameter_block_ordering.h" #include "ceres/preprocessor.h" #include "ceres/problem.h" @@ -141,16 +141,20 @@ bool TrustRegionOptionsAreValid(const Solver::Options& options, string* error) { return false; } - if (options.dense_linear_algebra_library_type == LAPACK && - !IsDenseLinearAlgebraLibraryTypeAvailable(LAPACK) && + if (!IsDenseLinearAlgebraLibraryTypeAvailable( + options.dense_linear_algebra_library_type) && (options.linear_solver_type == DENSE_NORMAL_CHOLESKY || options.linear_solver_type == DENSE_QR || options.linear_solver_type == DENSE_SCHUR)) { *error = StringPrintf( "Can't use %s with " - "Solver::Options::dense_linear_algebra_library_type = LAPACK " - "because LAPACK was not enabled when Ceres was built.", - LinearSolverTypeToString(options.linear_solver_type)); + "Solver::Options::dense_linear_algebra_library_type = %s " + "because %s was not enabled when Ceres was built.", + LinearSolverTypeToString(options.linear_solver_type), + DenseLinearAlgebraLibraryTypeToString( + options.dense_linear_algebra_library_type), + DenseLinearAlgebraLibraryTypeToString( + options.dense_linear_algebra_library_type)); return false; } @@ -367,7 +371,7 @@ void PostSolveSummarize(const internal::PreprocessedProblem& pp, &(summary->inner_iteration_ordering_used)); // clang-format off - summary->inner_iterations_used = pp.inner_iteration_minimizer.get() != NULL; // NOLINT + summary->inner_iterations_used = pp.inner_iteration_minimizer.get() != nullptr; // NOLINT summary->linear_solver_type_used = pp.linear_solver_options.type; summary->num_threads_used = pp.options.num_threads; summary->preconditioner_type_used = pp.options.preconditioner_type; @@ -375,7 +379,7 @@ void PostSolveSummarize(const internal::PreprocessedProblem& pp, internal::SetSummaryFinalCost(summary); - if (pp.reduced_program.get() != NULL) { + if (pp.reduced_program.get() != nullptr) { SummarizeReducedProgram(*pp.reduced_program, summary); } @@ -385,7 +389,7 @@ void PostSolveSummarize(const internal::PreprocessedProblem& pp, // case if the preprocessor failed, or if the reduced problem did // not contain any parameter blocks. Thus, only extract the // evaluator statistics if one exists. - if (pp.evaluator.get() != NULL) { + if (pp.evaluator.get() != nullptr) { const map<string, CallStatistics>& evaluator_statistics = pp.evaluator->Statistics(); { @@ -407,7 +411,7 @@ void PostSolveSummarize(const internal::PreprocessedProblem& pp, // Again, like the evaluator, there may or may not be a linear // solver from which we can extract run time statistics. In // particular the line search solver does not use a linear solver. - if (pp.linear_solver.get() != NULL) { + if (pp.linear_solver.get() != nullptr) { const map<string, CallStatistics>& linear_solver_statistics = pp.linear_solver->Statistics(); const CallStatistics& call_stats = FindWithDefault( @@ -436,8 +440,7 @@ void Minimize(internal::PreprocessedProblem* pp, Solver::Summary* summary) { } const Vector original_reduced_parameters = pp->reduced_parameters; - std::unique_ptr<Minimizer> minimizer( - Minimizer::Create(pp->options.minimizer_type)); + auto minimizer = Minimizer::Create(pp->options.minimizer_type); minimizer->Minimize( pp->minimizer_options, pp->reduced_parameters.data(), summary); @@ -485,7 +488,7 @@ bool Solver::Options::IsValid(string* error) const { return LineSearchOptionsAreValid(*this, error); } -Solver::~Solver() {} +Solver::~Solver() = default; void Solver::Solve(const Solver::Options& options, Problem* problem, @@ -518,11 +521,11 @@ void Solver::Solve(const Solver::Options& options, Solver::Options modified_options = options; if (options.check_gradients) { modified_options.callbacks.push_back(&gradient_checking_callback); - gradient_checking_problem.reset(CreateGradientCheckingProblemImpl( + gradient_checking_problem = CreateGradientCheckingProblemImpl( problem_impl, options.gradient_check_numeric_derivative_relative_step_size, options.gradient_check_relative_precision, - &gradient_checking_callback)); + &gradient_checking_callback); problem_impl = gradient_checking_problem.get(); program = problem_impl->mutable_program(); } @@ -534,8 +537,7 @@ void Solver::Solve(const Solver::Options& options, // The main thread also does work so we only need to launch num_threads - 1. problem_impl->context()->EnsureMinimumThreads(options.num_threads - 1); - std::unique_ptr<Preprocessor> preprocessor( - Preprocessor::Create(modified_options.minimizer_type)); + auto preprocessor = Preprocessor::Create(modified_options.minimizer_type); PreprocessedProblem pp; const bool status = diff --git a/extern/ceres/internal/ceres/solver_utils.cc b/extern/ceres/internal/ceres/solver_utils.cc index eb5aafa061c..22fa137055d 100644 --- a/extern/ceres/internal/ceres/solver_utils.cc +++ b/extern/ceres/internal/ceres/solver_utils.cc @@ -34,8 +34,11 @@ #include "Eigen/Core" #include "ceres/internal/config.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/version.h" +#ifndef CERES_NO_CUDA +#include "cuda_runtime.h" +#endif // CERES_NO_CUDA namespace ceres { namespace internal { @@ -87,6 +90,10 @@ std::string VersionString() { value += "-no_custom_blas"; #endif +#ifndef CERES_NO_CUDA + value += "-cuda-(" + std::to_string(CUDART_VERSION) + ")"; +#endif + return value; } diff --git a/extern/ceres/internal/ceres/solver_utils.h b/extern/ceres/internal/ceres/solver_utils.h index 85fbf3776ab..298564a897d 100644 --- a/extern/ceres/internal/ceres/solver_utils.h +++ b/extern/ceres/internal/ceres/solver_utils.h @@ -28,9 +28,14 @@ // // Author: sameeragarwal@google.com (Sameer Agarwal) +#ifndef CERES_INTERNAL_SOLVER_UTILS_H_ +#define CERES_INTERNAL_SOLVER_UTILS_H_ + #include <algorithm> #include <string> +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/iteration_callback.h" #include "ceres/types.h" @@ -55,7 +60,12 @@ void SetSummaryFinalCost(SummaryType* summary) { } } +CERES_NO_EXPORT std::string VersionString(); } // namespace internal } // namespace ceres + +#include "ceres/internal/reenable_warnings.h" + +#endif // CERES_INTERNAL_SOLVER_UTILS_H_ diff --git a/extern/ceres/internal/ceres/sparse_cholesky.cc b/extern/ceres/internal/ceres/sparse_cholesky.cc index 91cdf671b1a..4a80470ffb7 100644 --- a/extern/ceres/internal/ceres/sparse_cholesky.cc +++ b/extern/ceres/internal/ceres/sparse_cholesky.cc @@ -30,6 +30,8 @@ #include "ceres/sparse_cholesky.h" +#include <memory> + #include "ceres/accelerate_sparse.h" #include "ceres/cxsparse.h" #include "ceres/eigensparse.h" @@ -113,7 +115,7 @@ std::unique_ptr<SparseCholesky> SparseCholesky::Create( return sparse_cholesky; } -SparseCholesky::~SparseCholesky() {} +SparseCholesky::~SparseCholesky() = default; LinearSolverTerminationType SparseCholesky::FactorAndSolve( CompressedRowSparseMatrix* lhs, @@ -133,7 +135,7 @@ RefinedSparseCholesky::RefinedSparseCholesky( : sparse_cholesky_(std::move(sparse_cholesky)), iterative_refiner_(std::move(iterative_refiner)) {} -RefinedSparseCholesky::~RefinedSparseCholesky() {} +RefinedSparseCholesky::~RefinedSparseCholesky() = default; CompressedRowSparseMatrix::StorageType RefinedSparseCholesky::StorageType() const { diff --git a/extern/ceres/internal/ceres/sparse_cholesky.h b/extern/ceres/internal/ceres/sparse_cholesky.h index a6af6b2c207..80c5cb2b83b 100644 --- a/extern/ceres/internal/ceres/sparse_cholesky.h +++ b/extern/ceres/internal/ceres/sparse_cholesky.h @@ -33,11 +33,13 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on #include <memory> +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" #include "glog/logging.h" @@ -67,7 +69,7 @@ namespace internal { // CHECK_EQ(sparse_cholesky->Solve(rhs.data(), solution.data(), &message), // LINEAR_SOLVER_SUCCESS); -class CERES_EXPORT_INTERNAL SparseCholesky { +class CERES_NO_EXPORT SparseCholesky { public: static std::unique_ptr<SparseCholesky> Create( const LinearSolver::Options& options); @@ -104,29 +106,28 @@ class CERES_EXPORT_INTERNAL SparseCholesky { // Convenience method which combines a call to Factorize and // Solve. Solve is only called if Factorize returns // LINEAR_SOLVER_SUCCESS. - virtual LinearSolverTerminationType FactorAndSolve( - CompressedRowSparseMatrix* lhs, - const double* rhs, - double* solution, - std::string* message); + LinearSolverTerminationType FactorAndSolve(CompressedRowSparseMatrix* lhs, + const double* rhs, + double* solution, + std::string* message); }; class IterativeRefiner; // Computes an initial solution using the given instance of // SparseCholesky, and then refines it using the IterativeRefiner. -class CERES_EXPORT_INTERNAL RefinedSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT RefinedSparseCholesky final : public SparseCholesky { public: RefinedSparseCholesky(std::unique_ptr<SparseCholesky> sparse_cholesky, std::unique_ptr<IterativeRefiner> iterative_refiner); - virtual ~RefinedSparseCholesky(); + ~RefinedSparseCholesky() override; - virtual CompressedRowSparseMatrix::StorageType StorageType() const; - virtual LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, - std::string* message); - virtual LinearSolverTerminationType Solve(const double* rhs, - double* solution, - std::string* message); + CompressedRowSparseMatrix::StorageType StorageType() const override; + LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, + std::string* message) override; + LinearSolverTerminationType Solve(const double* rhs, + double* solution, + std::string* message) override; private: std::unique_ptr<SparseCholesky> sparse_cholesky_; @@ -137,4 +138,6 @@ class CERES_EXPORT_INTERNAL RefinedSparseCholesky : public SparseCholesky { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SPARSE_CHOLESKY_H_ diff --git a/extern/ceres/internal/ceres/sparse_matrix.cc b/extern/ceres/internal/ceres/sparse_matrix.cc index 32388f58fc3..bc757ead361 100644 --- a/extern/ceres/internal/ceres/sparse_matrix.cc +++ b/extern/ceres/internal/ceres/sparse_matrix.cc @@ -33,7 +33,7 @@ namespace ceres { namespace internal { -SparseMatrix::~SparseMatrix() {} +SparseMatrix::~SparseMatrix() = default; } // namespace internal } // namespace ceres diff --git a/extern/ceres/internal/ceres/sparse_matrix.h b/extern/ceres/internal/ceres/sparse_matrix.h index b57f10890fc..1dbb96e6070 100644 --- a/extern/ceres/internal/ceres/sparse_matrix.h +++ b/extern/ceres/internal/ceres/sparse_matrix.h @@ -36,7 +36,7 @@ #include <cstdio> #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/linear_operator.h" #include "ceres/types.h" @@ -64,14 +64,14 @@ namespace internal { // matrix type dependent and we are at this stage unable to come up // with an efficient high level interface that spans multiple sparse // matrix types. -class CERES_EXPORT_INTERNAL SparseMatrix : public LinearOperator { +class CERES_NO_EXPORT SparseMatrix : public LinearOperator { public: - virtual ~SparseMatrix(); + ~SparseMatrix() override; // y += Ax; - virtual void RightMultiply(const double* x, double* y) const = 0; + void RightMultiply(const double* x, double* y) const override = 0; // y += A'x; - virtual void LeftMultiply(const double* x, double* y) const = 0; + void LeftMultiply(const double* x, double* y) const override = 0; // In MATLAB notation sum(A.*A, 1) virtual void SquaredColumnNorm(double* x) const = 0; @@ -98,8 +98,8 @@ class CERES_EXPORT_INTERNAL SparseMatrix : public LinearOperator { virtual double* mutable_values() = 0; virtual const double* values() const = 0; - virtual int num_rows() const = 0; - virtual int num_cols() const = 0; + int num_rows() const override = 0; + int num_cols() const override = 0; virtual int num_nonzeros() const = 0; }; diff --git a/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.cc b/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.cc index 0f2e589d041..2e52ae6d908 100644 --- a/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.cc +++ b/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.cc @@ -54,7 +54,7 @@ SparseNormalCholeskySolver::SparseNormalCholeskySolver( sparse_cholesky_ = SparseCholesky::Create(options); } -SparseNormalCholeskySolver::~SparseNormalCholeskySolver() {} +SparseNormalCholeskySolver::~SparseNormalCholeskySolver() = default; LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( BlockSparseMatrix* A, @@ -75,21 +75,21 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( A->LeftMultiply(b, rhs_.data()); event_logger.AddEvent("Compute RHS"); - if (per_solve_options.D != NULL) { + if (per_solve_options.D != nullptr) { // Temporarily append a diagonal block to the A matrix, but undo // it before returning the matrix to the user. - std::unique_ptr<BlockSparseMatrix> regularizer; - regularizer.reset(BlockSparseMatrix::CreateDiagonalMatrix( - per_solve_options.D, A->block_structure()->cols)); + std::unique_ptr<BlockSparseMatrix> regularizer = + BlockSparseMatrix::CreateDiagonalMatrix(per_solve_options.D, + A->block_structure()->cols); event_logger.AddEvent("Diagonal"); A->AppendRows(*regularizer); event_logger.AddEvent("Append"); } event_logger.AddEvent("Append Rows"); - if (inner_product_computer_.get() == NULL) { - inner_product_computer_.reset( - InnerProductComputer::Create(*A, sparse_cholesky_->StorageType())); + if (inner_product_computer_.get() == nullptr) { + inner_product_computer_ = + InnerProductComputer::Create(*A, sparse_cholesky_->StorageType()); event_logger.AddEvent("InnerProductComputer::Create"); } @@ -97,7 +97,7 @@ LinearSolver::Summary SparseNormalCholeskySolver::SolveImpl( inner_product_computer_->Compute(); event_logger.AddEvent("InnerProductComputer::Compute"); - if (per_solve_options.D != NULL) { + if (per_solve_options.D != nullptr) { A->DeleteRowBlocks(A->block_structure()->cols.size()); } diff --git a/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.h b/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.h index ef3274323f5..caec566612e 100644 --- a/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.h +++ b/extern/ceres/internal/ceres/sparse_normal_cholesky_solver.h @@ -36,11 +36,13 @@ // This include must come before any #ifndef check on Ceres compile options. // clang-format off -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" // clang-format on +#include <memory> #include <vector> +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -52,13 +54,14 @@ class SparseCholesky; // Solves the normal equations (A'A + D'D) x = A'b, using the sparse // linear algebra library of the user's choice. -class SparseNormalCholeskySolver : public BlockSparseMatrixSolver { +class CERES_NO_EXPORT SparseNormalCholeskySolver + : public BlockSparseMatrixSolver { public: explicit SparseNormalCholeskySolver(const LinearSolver::Options& options); SparseNormalCholeskySolver(const SparseNormalCholeskySolver&) = delete; void operator=(const SparseNormalCholeskySolver&) = delete; - virtual ~SparseNormalCholeskySolver(); + ~SparseNormalCholeskySolver() override; private: LinearSolver::Summary SolveImpl(BlockSparseMatrix* A, diff --git a/extern/ceres/internal/ceres/split.cc b/extern/ceres/internal/ceres/split.cc deleted file mode 100644 index 804f4412deb..00000000000 --- a/extern/ceres/internal/ceres/split.cc +++ /dev/null @@ -1,122 +0,0 @@ -// 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: keir@google.com (Keir Mierle) - -#include "ceres/split.h" - -#include <iterator> -#include <string> -#include <vector> - -#include "ceres/internal/port.h" - -namespace ceres { -namespace internal { - -using std::string; -using std::vector; - -// If we know how much to allocate for a vector of strings, we can allocate the -// vector<string> only once and directly to the right size. This saves in -// between 33-66 % of memory space needed for the result, and runs faster in the -// microbenchmarks. -// -// The reserve is only implemented for the single character delim. -// -// The implementation for counting is cut-and-pasted from -// SplitStringToIteratorUsing. I could have written my own counting iterator, -// and use the existing template function, but probably this is more clear and -// more sure to get optimized to reasonable code. -static int CalculateReserveForVector(const string& full, const char* delim) { - int count = 0; - if (delim[0] != '\0' && delim[1] == '\0') { - // Optimize the common case where delim is a single character. - char c = delim[0]; - const char* p = full.data(); - const char* end = p + full.size(); - while (p != end) { - if (*p == c) { // This could be optimized with hasless(v,1) trick. - ++p; - } else { - while (++p != end && *p != c) { - // Skip to the next occurence of the delimiter. - } - ++count; - } - } - } - return count; -} - -template <typename StringType, typename ITR> -static inline void SplitStringToIteratorUsing(const StringType& full, - const char* delim, - ITR& result) { - // Optimize the common case where delim is a single character. - if (delim[0] != '\0' && delim[1] == '\0') { - char c = delim[0]; - const char* p = full.data(); - const char* end = p + full.size(); - while (p != end) { - if (*p == c) { - ++p; - } else { - const char* start = p; - while (++p != end && *p != c) { - // Skip to the next occurence of the delimiter. - } - *result++ = StringType(start, p - start); - } - } - return; - } - - string::size_type begin_index, end_index; - begin_index = full.find_first_not_of(delim); - while (begin_index != string::npos) { - end_index = full.find_first_of(delim, begin_index); - if (end_index == string::npos) { - *result++ = full.substr(begin_index); - return; - } - *result++ = full.substr(begin_index, (end_index - begin_index)); - begin_index = full.find_first_not_of(delim, end_index); - } -} - -void SplitStringUsing(const string& full, - const char* delim, - vector<string>* result) { - result->reserve(result->size() + CalculateReserveForVector(full, delim)); - std::back_insert_iterator<vector<string>> it(*result); - SplitStringToIteratorUsing(full, delim, it); -} - -} // namespace internal -} // namespace ceres diff --git a/extern/ceres/internal/ceres/stl_util.h b/extern/ceres/internal/ceres/stl_util.h index d3411b73376..2af2518f837 100644 --- a/extern/ceres/internal/ceres/stl_util.h +++ b/extern/ceres/internal/ceres/stl_util.h @@ -73,7 +73,7 @@ void STLDeleteUniqueContainerPointers(ForwardIterator begin, // hash_set, or any other STL container which defines sensible begin(), end(), // and clear() methods. // -// If container is NULL, this function is a no-op. +// If container is nullptr, this function is a no-op. // // As an alternative to calling STLDeleteElements() directly, consider // ElementDeleter (defined below), which ensures that your container's elements diff --git a/extern/ceres/internal/ceres/stringprintf.cc b/extern/ceres/internal/ceres/stringprintf.cc index b0e2acce8f9..e45b4301eef 100644 --- a/extern/ceres/internal/ceres/stringprintf.cc +++ b/extern/ceres/internal/ceres/stringprintf.cc @@ -36,7 +36,7 @@ #include <string> #include <vector> -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -66,7 +66,7 @@ void StringAppendV(string* dst, const char* format, va_list ap) { // Error or MSVC running out of space. MSVC 8.0 and higher // can be asked about space needed with the special idiom below: va_copy(backup_ap, ap); - result = vsnprintf(NULL, 0, format, backup_ap); + result = vsnprintf(nullptr, 0, format, backup_ap); va_end(backup_ap); #endif diff --git a/extern/ceres/internal/ceres/stringprintf.h b/extern/ceres/internal/ceres/stringprintf.h index 4d512784905..e24325fbd35 100644 --- a/extern/ceres/internal/ceres/stringprintf.h +++ b/extern/ceres/internal/ceres/stringprintf.h @@ -41,7 +41,8 @@ #include <cstdarg> #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -63,32 +64,35 @@ namespace internal { #endif // Return a C++ string. -CERES_EXPORT_INTERNAL extern std::string StringPrintf(const char* format, ...) +CERES_NO_EXPORT extern std::string StringPrintf(const char* format, ...) // Tell the compiler to do printf format string checking. CERES_PRINTF_ATTRIBUTE(1, 2); // Store result into a supplied string and return it. -CERES_EXPORT_INTERNAL extern const std::string& SStringPrintf( - std::string* dst, const char* format, ...) +CERES_NO_EXPORT extern const std::string& SStringPrintf(std::string* dst, + const char* format, + ...) // Tell the compiler to do printf format string checking. CERES_PRINTF_ATTRIBUTE(2, 3); // Append result to a supplied string. -CERES_EXPORT_INTERNAL extern void StringAppendF(std::string* dst, - const char* format, - ...) +CERES_NO_EXPORT extern void StringAppendF(std::string* dst, + const char* format, + ...) // Tell the compiler to do printf format string checking. CERES_PRINTF_ATTRIBUTE(2, 3); // Lower-level routine that takes a va_list and appends to a specified string. // All other routines are just convenience wrappers around it. -CERES_EXPORT_INTERNAL extern void StringAppendV(std::string* dst, - const char* format, - va_list ap); +CERES_NO_EXPORT extern void StringAppendV(std::string* dst, + const char* format, + va_list ap); #undef CERES_PRINTF_ATTRIBUTE } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_STRINGPRINTF_H_ diff --git a/extern/ceres/internal/ceres/subset_preconditioner.cc b/extern/ceres/internal/ceres/subset_preconditioner.cc index 779a34ae741..221530c0dd5 100644 --- a/extern/ceres/internal/ceres/subset_preconditioner.cc +++ b/extern/ceres/internal/ceres/subset_preconditioner.cc @@ -32,6 +32,7 @@ #include <memory> #include <string> +#include <utility> #include "ceres/compressed_row_sparse_matrix.h" #include "ceres/inner_product_computer.h" @@ -42,9 +43,9 @@ namespace ceres { namespace internal { -SubsetPreconditioner::SubsetPreconditioner( - const Preconditioner::Options& options, const BlockSparseMatrix& A) - : options_(options), num_cols_(A.num_cols()) { +SubsetPreconditioner::SubsetPreconditioner(Preconditioner::Options options, + const BlockSparseMatrix& A) + : options_(std::move(options)), num_cols_(A.num_cols()) { CHECK_GE(options_.subset_preconditioner_start_row_block, 0) << "Congratulations, you found a bug in Ceres. Please report it."; @@ -55,7 +56,7 @@ SubsetPreconditioner::SubsetPreconditioner( sparse_cholesky_ = SparseCholesky::Create(sparse_cholesky_options); } -SubsetPreconditioner::~SubsetPreconditioner() {} +SubsetPreconditioner::~SubsetPreconditioner() = default; void SubsetPreconditioner::RightMultiply(const double* x, double* y) const { CHECK(x != nullptr); @@ -66,14 +67,14 @@ void SubsetPreconditioner::RightMultiply(const double* x, double* y) const { bool SubsetPreconditioner::UpdateImpl(const BlockSparseMatrix& A, const double* D) { - BlockSparseMatrix* m = const_cast<BlockSparseMatrix*>(&A); + auto* m = const_cast<BlockSparseMatrix*>(&A); const CompressedRowBlockStructure* bs = m->block_structure(); // A = [P] // [Q] // Now add D to A if needed. - if (D != NULL) { + if (D != nullptr) { // A = [P] // [Q] // [D] @@ -82,19 +83,19 @@ bool SubsetPreconditioner::UpdateImpl(const BlockSparseMatrix& A, m->AppendRows(*regularizer); } - if (inner_product_computer_.get() == NULL) { - inner_product_computer_.reset(InnerProductComputer::Create( + if (inner_product_computer_ == nullptr) { + inner_product_computer_ = InnerProductComputer::Create( *m, options_.subset_preconditioner_start_row_block, bs->rows.size(), - sparse_cholesky_->StorageType())); + sparse_cholesky_->StorageType()); } // Compute inner_product = [Q'*Q + D'*D] inner_product_computer_->Compute(); // Unappend D if needed. - if (D != NULL) { + if (D != nullptr) { // A = [P] // [Q] m->DeleteRowBlocks(bs->cols.size()); diff --git a/extern/ceres/internal/ceres/subset_preconditioner.h b/extern/ceres/internal/ceres/subset_preconditioner.h index 9844a669f45..6d07995a136 100644 --- a/extern/ceres/internal/ceres/subset_preconditioner.h +++ b/extern/ceres/internal/ceres/subset_preconditioner.h @@ -33,7 +33,8 @@ #include <memory> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/preconditioner.h" namespace ceres { @@ -67,12 +68,12 @@ class InnerProductComputer; // computationally expensive this preconditioner will be. // // See the tests for example usage. -class CERES_EXPORT_INTERNAL SubsetPreconditioner +class CERES_NO_EXPORT SubsetPreconditioner : public BlockSparseMatrixPreconditioner { public: - SubsetPreconditioner(const Preconditioner::Options& options, + SubsetPreconditioner(Preconditioner::Options options, const BlockSparseMatrix& A); - virtual ~SubsetPreconditioner(); + ~SubsetPreconditioner() override; // Preconditioner interface void RightMultiply(const double* x, double* y) const final; @@ -91,4 +92,6 @@ class CERES_EXPORT_INTERNAL SubsetPreconditioner } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_SUBSET_PRECONDITIONER_H_ diff --git a/extern/ceres/internal/ceres/suitesparse.cc b/extern/ceres/internal/ceres/suitesparse.cc index 0d6f6bdfb88..883dcc8f63e 100644 --- a/extern/ceres/internal/ceres/suitesparse.cc +++ b/extern/ceres/internal/ceres/suitesparse.cc @@ -29,9 +29,10 @@ // Author: sameeragarwal@google.com (Sameer Agarwal) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_SUITESPARSE +#include <memory> #include <vector> #include "ceres/compressed_col_sparse_matrix_utils.h" @@ -368,7 +369,7 @@ SuiteSparseCholesky::~SuiteSparseCholesky() { LinearSolverTerminationType SuiteSparseCholesky::Factorize( CompressedRowSparseMatrix* lhs, string* message) { if (lhs == nullptr) { - *message = "Failure: Input lhs is NULL."; + *message = "Failure: Input lhs is nullptr."; return LINEAR_SOLVER_FATAL_ERROR; } diff --git a/extern/ceres/internal/ceres/suitesparse.h b/extern/ceres/internal/ceres/suitesparse.h index 5dcc53f0167..3f62e7c7b7d 100644 --- a/extern/ceres/internal/ceres/suitesparse.h +++ b/extern/ceres/internal/ceres/suitesparse.h @@ -34,11 +34,12 @@ #define CERES_INTERNAL_SUITESPARSE_H_ // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifndef CERES_NO_SUITESPARSE #include <cstring> +#include <memory> #include <string> #include <vector> @@ -70,6 +71,8 @@ #define SuiteSparse_long UF_long #endif +#include "ceres/internal/disable_warnings.h" + namespace ceres { namespace internal { @@ -81,7 +84,7 @@ class TripletSparseMatrix; // provides the user with a simpler interface. The methods here cannot // be static as a cholmod_common object serves as a global variable // for all cholmod function calls. -class SuiteSparse { +class CERES_NO_EXPORT SuiteSparse { public: SuiteSparse(); ~SuiteSparse(); @@ -106,7 +109,7 @@ class SuiteSparse { cholmod_dense CreateDenseVectorView(const double* x, int size); // Given a vector x, build a cholmod_dense vector of size out_size - // with the first in_size entries copied from x. If x is NULL, then + // with the first in_size entries copied from x. If x is nullptr, then // an all zeros vector is returned. Caller owns the result. cholmod_dense* CreateDenseVector(const double* x, int in_size, int out_size); @@ -123,7 +126,7 @@ class SuiteSparse { // Create and return a matrix m = A * A'. Caller owns the // result. The matrix A is not modified. cholmod_sparse* AATranspose(cholmod_sparse* A) { - cholmod_sparse* m = cholmod_aat(A, NULL, A->nrow, 1, &cc_); + cholmod_sparse* m = cholmod_aat(A, nullptr, A->nrow, 1, &cc_); m->stype = 1; // Pay attention to the upper triangular part. return m; } @@ -196,7 +199,7 @@ class SuiteSparse { // Given a Cholesky factorization of a matrix A = LL^T, solve the // linear system Ax = b, and return the result. If the Solve fails - // NULL is returned. Caller owns the result. + // nullptr is returned. Caller owns the result. // // message contains an explanation of the failures if any. cholmod_dense* Solve(cholmod_factor* L, @@ -288,12 +291,12 @@ class SuiteSparse { cholmod_common cc_; }; -class SuiteSparseCholesky : public SparseCholesky { +class CERES_NO_EXPORT SuiteSparseCholesky final : public SparseCholesky { public: static std::unique_ptr<SparseCholesky> Create(OrderingType ordering_type); // SparseCholesky interface. - virtual ~SuiteSparseCholesky(); + ~SuiteSparseCholesky() override; CompressedRowSparseMatrix::StorageType StorageType() const final; LinearSolverTerminationType Factorize(CompressedRowSparseMatrix* lhs, std::string* message) final; @@ -302,7 +305,7 @@ class SuiteSparseCholesky : public SparseCholesky { std::string* message) final; private: - SuiteSparseCholesky(const OrderingType ordering_type); + explicit SuiteSparseCholesky(const OrderingType ordering_type); const OrderingType ordering_type_; SuiteSparse ss_; @@ -312,14 +315,18 @@ class SuiteSparseCholesky : public SparseCholesky { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #else // CERES_NO_SUITESPARSE typedef void cholmod_factor; +#include "ceres/internal/disable_warnings.h" + namespace ceres { namespace internal { -class SuiteSparse { +class CERES_NO_EXPORT SuiteSparse { public: // Defining this static function even when SuiteSparse is not // available, allows client code to check for the presence of CAMD @@ -332,12 +339,14 @@ class SuiteSparse { return false; } - void Free(void* arg) {} + void Free(void* /*arg*/) {} }; } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_NO_SUITESPARSE #endif // CERES_INTERNAL_SUITESPARSE_H_ diff --git a/extern/ceres/internal/ceres/thread_pool.cc b/extern/ceres/internal/ceres/thread_pool.cc index 821431cedb4..57f01af5476 100644 --- a/extern/ceres/internal/ceres/thread_pool.cc +++ b/extern/ceres/internal/ceres/thread_pool.cc @@ -29,7 +29,7 @@ // Author: vitus@google.com (Michael Vitus) // This include must come before any #ifndef check on Ceres compile options. -#include "ceres/internal/port.h" +#include "ceres/internal/config.h" #ifdef CERES_USE_CXX_THREADS @@ -57,7 +57,7 @@ int ThreadPool::MaxNumThreadsAvailable() { : num_hardware_threads; } -ThreadPool::ThreadPool() {} +ThreadPool::ThreadPool() = default; ThreadPool::ThreadPool(int num_threads) { Resize(num_threads); } @@ -83,7 +83,7 @@ void ThreadPool::Resize(int num_threads) { GetNumAllowedThreads(num_threads) - num_current_threads; for (int i = 0; i < create_num_threads; ++i) { - thread_pool_.push_back(std::thread(&ThreadPool::ThreadMainLoop, this)); + thread_pool_.emplace_back(&ThreadPool::ThreadMainLoop, this); } } diff --git a/extern/ceres/internal/ceres/thread_pool.h b/extern/ceres/internal/ceres/thread_pool.h index cdf6625e196..94ab1e66bd4 100644 --- a/extern/ceres/internal/ceres/thread_pool.h +++ b/extern/ceres/internal/ceres/thread_pool.h @@ -37,7 +37,7 @@ #include <vector> #include "ceres/concurrent_queue.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -58,7 +58,7 @@ namespace internal { // workers to stop. The workers will finish all of the tasks that have already // been added to the thread pool. // -class CERES_EXPORT_INTERNAL ThreadPool { +class CERES_NO_EXPORT ThreadPool { public: // Returns the maximum number of hardware threads. static int MaxNumThreadsAvailable(); diff --git a/extern/ceres/internal/ceres/thread_token_provider.h b/extern/ceres/internal/ceres/thread_token_provider.h index 06dc0438572..918c687eb24 100644 --- a/extern/ceres/internal/ceres/thread_token_provider.h +++ b/extern/ceres/internal/ceres/thread_token_provider.h @@ -32,7 +32,7 @@ #define CERES_INTERNAL_THREAD_TOKEN_PROVIDER_H_ #include "ceres/internal/config.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #ifdef CERES_USE_CXX_THREADS #include "ceres/concurrent_queue.h" @@ -66,9 +66,9 @@ namespace internal { // ttp.Release(token); // return token to the pool // } // -class ThreadTokenProvider { +class CERES_NO_EXPORT ThreadTokenProvider { public: - ThreadTokenProvider(int num_threads); + explicit ThreadTokenProvider(int num_threads); // Returns the first token from the queue. The acquired value must be // given back by Release(). @@ -87,8 +87,8 @@ class ThreadTokenProvider { ConcurrentQueue<int> pool_; #endif - ThreadTokenProvider(ThreadTokenProvider&); - ThreadTokenProvider& operator=(ThreadTokenProvider&); + ThreadTokenProvider(ThreadTokenProvider&) = delete; + ThreadTokenProvider& operator=(ThreadTokenProvider&) = delete; }; } // namespace internal diff --git a/extern/ceres/internal/ceres/triplet_sparse_matrix.cc b/extern/ceres/internal/ceres/triplet_sparse_matrix.cc index 5dbf0e7cd3a..bbb5f676a5d 100644 --- a/extern/ceres/internal/ceres/triplet_sparse_matrix.cc +++ b/extern/ceres/internal/ceres/triplet_sparse_matrix.cc @@ -31,10 +31,10 @@ #include "ceres/triplet_sparse_matrix.h" #include <algorithm> -#include <cstddef> +#include <memory> #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/random.h" #include "ceres/types.h" #include "glog/logging.h" @@ -45,7 +45,7 @@ namespace internal { TripletSparseMatrix::TripletSparseMatrix() : num_rows_(0), num_cols_(0), max_num_nonzeros_(0), num_nonzeros_(0) {} -TripletSparseMatrix::~TripletSparseMatrix() {} +TripletSparseMatrix::~TripletSparseMatrix() = default; TripletSparseMatrix::TripletSparseMatrix(int num_rows, int num_cols, @@ -109,8 +109,9 @@ bool TripletSparseMatrix::AllTripletsWithinBounds() const { for (int i = 0; i < num_nonzeros_; ++i) { // clang-format off if ((rows_[i] < 0) || (rows_[i] >= num_rows_) || - (cols_[i] < 0) || (cols_[i] >= num_cols_)) + (cols_[i] < 0) || (cols_[i] >= num_cols_)) { return false; + } // clang-format on } return true; @@ -123,9 +124,12 @@ void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) { // Nothing to do if we have enough space already. if (new_max_num_nonzeros <= max_num_nonzeros_) return; - int* new_rows = new int[new_max_num_nonzeros]; - int* new_cols = new int[new_max_num_nonzeros]; - double* new_values = new double[new_max_num_nonzeros]; + std::unique_ptr<int[]> new_rows = + std::make_unique<int[]>(new_max_num_nonzeros); + std::unique_ptr<int[]> new_cols = + std::make_unique<int[]>(new_max_num_nonzeros); + std::unique_ptr<double[]> new_values = + std::make_unique<double[]>(new_max_num_nonzeros); for (int i = 0; i < num_nonzeros_; ++i) { new_rows[i] = rows_[i]; @@ -133,10 +137,9 @@ void TripletSparseMatrix::Reserve(int new_max_num_nonzeros) { new_values[i] = values_[i]; } - rows_.reset(new_rows); - cols_.reset(new_cols); - values_.reset(new_values); - + rows_ = std::move(new_rows); + cols_ = std::move(new_cols); + values_ = std::move(new_values); max_num_nonzeros_ = new_max_num_nonzeros; } @@ -152,9 +155,9 @@ void TripletSparseMatrix::set_num_nonzeros(int num_nonzeros) { } void TripletSparseMatrix::AllocateMemory() { - rows_.reset(new int[max_num_nonzeros_]); - cols_.reset(new int[max_num_nonzeros_]); - values_.reset(new double[max_num_nonzeros_]); + rows_ = std::make_unique<int[]>(max_num_nonzeros_); + cols_ = std::make_unique<int[]>(max_num_nonzeros_); + values_ = std::make_unique<double[]>(max_num_nonzeros_); } void TripletSparseMatrix::CopyData(const TripletSparseMatrix& orig) { @@ -252,10 +255,11 @@ void TripletSparseMatrix::Resize(int new_num_rows, int new_num_cols) { num_nonzeros_ -= dropped_terms; } -TripletSparseMatrix* TripletSparseMatrix::CreateSparseDiagonalMatrix( - const double* values, int num_rows) { - TripletSparseMatrix* m = - new TripletSparseMatrix(num_rows, num_rows, num_rows); +std::unique_ptr<TripletSparseMatrix> +TripletSparseMatrix::CreateSparseDiagonalMatrix(const double* values, + int num_rows) { + std::unique_ptr<TripletSparseMatrix> m = + std::make_unique<TripletSparseMatrix>(num_rows, num_rows, num_rows); for (int i = 0; i < num_rows; ++i) { m->mutable_rows()[i] = i; m->mutable_cols()[i] = i; @@ -272,7 +276,7 @@ void TripletSparseMatrix::ToTextFile(FILE* file) const { } } -TripletSparseMatrix* TripletSparseMatrix::CreateRandomMatrix( +std::unique_ptr<TripletSparseMatrix> TripletSparseMatrix::CreateRandomMatrix( const TripletSparseMatrix::RandomMatrixOptions& options) { CHECK_GT(options.num_rows, 0); CHECK_GT(options.num_cols, 0); @@ -297,7 +301,7 @@ TripletSparseMatrix* TripletSparseMatrix::CreateRandomMatrix( } } - return new TripletSparseMatrix( + return std::make_unique<TripletSparseMatrix>( options.num_rows, options.num_cols, rows, cols, values); } diff --git a/extern/ceres/internal/ceres/triplet_sparse_matrix.h b/extern/ceres/internal/ceres/triplet_sparse_matrix.h index cc9fee572a2..065c690dba3 100644 --- a/extern/ceres/internal/ceres/triplet_sparse_matrix.h +++ b/extern/ceres/internal/ceres/triplet_sparse_matrix.h @@ -34,8 +34,9 @@ #include <memory> #include <vector> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/sparse_matrix.h" #include "ceres/types.h" @@ -46,7 +47,7 @@ namespace internal { // manipulate sparse matrices in triplet (i,j,s) form. This object is // inspired by the design of the cholmod_triplet struct used in the // SuiteSparse package and is memory layout compatible with it. -class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix { +class CERES_NO_EXPORT TripletSparseMatrix final : public SparseMatrix { public: TripletSparseMatrix(); TripletSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros); @@ -56,11 +57,11 @@ class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix { const std::vector<int>& cols, const std::vector<double>& values); - explicit TripletSparseMatrix(const TripletSparseMatrix& orig); + TripletSparseMatrix(const TripletSparseMatrix& orig); TripletSparseMatrix& operator=(const TripletSparseMatrix& rhs); - virtual ~TripletSparseMatrix(); + ~TripletSparseMatrix() override; // Implementation of the SparseMatrix interface. void SetZero() final; @@ -115,8 +116,8 @@ class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix { // Build a sparse diagonal matrix of size num_rows x num_rows from // the array values. Entries of the values array are copied into the // sparse matrix. - static TripletSparseMatrix* CreateSparseDiagonalMatrix(const double* values, - int num_rows); + static std::unique_ptr<TripletSparseMatrix> CreateSparseDiagonalMatrix( + const double* values, int num_rows); // Options struct to control the generation of random // TripletSparseMatrix objects. @@ -132,9 +133,7 @@ class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix { // Create a random CompressedRowSparseMatrix whose entries are // normally distributed and whose structure is determined by // RandomMatrixOptions. - // - // Caller owns the result. - static TripletSparseMatrix* CreateRandomMatrix( + static std::unique_ptr<TripletSparseMatrix> CreateRandomMatrix( const TripletSparseMatrix::RandomMatrixOptions& options); private: @@ -158,4 +157,6 @@ class CERES_EXPORT_INTERNAL TripletSparseMatrix : public SparseMatrix { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_TRIPLET_SPARSE_MATRIX_H__ diff --git a/extern/ceres/internal/ceres/trust_region_minimizer.cc b/extern/ceres/internal/ceres/trust_region_minimizer.cc index bcf05b3ddfb..9ef5167ba6c 100644 --- a/extern/ceres/internal/ceres/trust_region_minimizer.cc +++ b/extern/ceres/internal/ceres/trust_region_minimizer.cc @@ -62,8 +62,6 @@ namespace ceres { namespace internal { -TrustRegionMinimizer::~TrustRegionMinimizer() {} - void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, double* parameters, Solver::Summary* solver_summary) { @@ -75,11 +73,11 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, // Create the TrustRegionStepEvaluator. The construction needs to be // delayed to this point because we need the cost for the starting // point to initialize the step evaluator. - step_evaluator_.reset(new TrustRegionStepEvaluator( + step_evaluator_ = std::make_unique<TrustRegionStepEvaluator>( x_cost_, options_.use_nonmonotonic_steps ? options_.max_consecutive_nonmonotonic_steps - : 0)); + : 0); while (FinalizeIterationAndCheckIfMinimizerCanContinue()) { iteration_start_time_in_secs_ = WallTimeInSeconds(); @@ -750,14 +748,12 @@ bool TrustRegionMinimizer::FunctionToleranceReached() { // Compute candidate_x_ = Plus(x_, delta_) // Evaluate the cost of candidate_x_ as candidate_cost_. // -// Failure to compute the step or the cost mean that candidate_cost_ -// is set to std::numeric_limits<double>::max(). Unlike -// EvaluateGradientAndJacobian, failure in this function is not fatal -// as we are only computing and evaluating a candidate point, and if -// for some reason we are unable to evaluate it, we consider it to be -// a point with very high cost. This allows the user to deal with edge -// cases/constraints as part of the LocalParameterization and -// CostFunction objects. +// Failure to compute the step or the cost mean that candidate_cost_ is set to +// std::numeric_limits<double>::max(). Unlike EvaluateGradientAndJacobian, +// failure in this function is not fatal as we are only computing and evaluating +// a candidate point, and if for some reason we are unable to evaluate it, we +// consider it to be a point with very high cost. This allows the user to deal +// with edge cases/constraints as part of the Manifold and CostFunction objects. void TrustRegionMinimizer::ComputeCandidatePointAndEvaluateCost() { if (!evaluator_->Plus(x_.data(), delta_.data(), candidate_x_.data())) { if (is_not_silent_) { diff --git a/extern/ceres/internal/ceres/trust_region_minimizer.h b/extern/ceres/internal/ceres/trust_region_minimizer.h index be4d40653c4..c6fc542a063 100644 --- a/extern/ceres/internal/ceres/trust_region_minimizer.h +++ b/extern/ceres/internal/ceres/trust_region_minimizer.h @@ -33,8 +33,9 @@ #include <memory> +#include "ceres/internal/disable_warnings.h" #include "ceres/internal/eigen.h" -#include "ceres/internal/port.h" +#include "ceres/internal/export.h" #include "ceres/minimizer.h" #include "ceres/solver.h" #include "ceres/sparse_matrix.h" @@ -48,10 +49,8 @@ namespace internal { // Generic trust region minimization algorithm. // // For example usage, see SolverImpl::Minimize. -class CERES_EXPORT_INTERNAL TrustRegionMinimizer : public Minimizer { +class CERES_NO_EXPORT TrustRegionMinimizer final : public Minimizer { public: - ~TrustRegionMinimizer(); - // This method is not thread safe. void Minimize(const Minimizer::Options& options, double* parameters, @@ -164,4 +163,6 @@ class CERES_EXPORT_INTERNAL TrustRegionMinimizer : public Minimizer { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_TRUST_REGION_MINIMIZER_H_ diff --git a/extern/ceres/internal/ceres/trust_region_preprocessor.cc b/extern/ceres/internal/ceres/trust_region_preprocessor.cc index 0943edbba85..edba47d88a5 100644 --- a/extern/ceres/internal/ceres/trust_region_preprocessor.cc +++ b/extern/ceres/internal/ceres/trust_region_preprocessor.cc @@ -55,13 +55,14 @@ using std::vector; namespace { -ParameterBlockOrdering* CreateDefaultLinearSolverOrdering( +std::shared_ptr<ParameterBlockOrdering> CreateDefaultLinearSolverOrdering( const Program& program) { - ParameterBlockOrdering* ordering = new ParameterBlockOrdering; + std::shared_ptr<ParameterBlockOrdering> ordering = + std::make_shared<ParameterBlockOrdering>(); const vector<ParameterBlock*>& parameter_blocks = program.parameter_blocks(); - for (int i = 0; i < parameter_blocks.size(); ++i) { + for (auto* parameter_block : parameter_blocks) { ordering->AddElementToGroup( - const_cast<double*>(parameter_blocks[i]->user_state()), 0); + const_cast<double*>(parameter_block->user_state()), 0); } return ordering; } @@ -160,8 +161,8 @@ bool SetupLinearSolver(PreprocessedProblem* pp) { // assume that they are giving all the freedom to us in choosing // the best possible ordering. This intent can be indicated by // putting all the parameter blocks in the same elimination group. - options.linear_solver_ordering.reset( - CreateDefaultLinearSolverOrdering(*pp->reduced_program)); + options.linear_solver_ordering = + CreateDefaultLinearSolverOrdering(*pp->reduced_program); } else { // If the user supplied an ordering, then check if the first // elimination group is still non-empty after the reduced problem @@ -247,7 +248,7 @@ bool SetupLinearSolver(PreprocessedProblem* pp) { } } - pp->linear_solver.reset(LinearSolver::Create(pp->linear_solver_options)); + pp->linear_solver = LinearSolver::Create(pp->linear_solver_options); return (pp->linear_solver != nullptr); } @@ -269,8 +270,8 @@ bool SetupEvaluator(PreprocessedProblem* pp) { pp->evaluator_options.context = pp->problem->context(); pp->evaluator_options.evaluation_callback = pp->reduced_program->mutable_evaluation_callback(); - pp->evaluator.reset(Evaluator::Create( - pp->evaluator_options, pp->reduced_program.get(), &pp->error)); + pp->evaluator = Evaluator::Create( + pp->evaluator_options, pp->reduced_program.get(), &pp->error); return (pp->evaluator != nullptr); } @@ -316,12 +317,12 @@ bool SetupInnerIterationMinimizer(PreprocessedProblem* pp) { } } else { // The user did not supply an ordering, so create one. - options.inner_iteration_ordering.reset( - CoordinateDescentMinimizer::CreateOrdering(*pp->reduced_program)); + options.inner_iteration_ordering = + CoordinateDescentMinimizer::CreateOrdering(*pp->reduced_program); } - pp->inner_iteration_minimizer.reset( - new CoordinateDescentMinimizer(pp->problem->context())); + pp->inner_iteration_minimizer = + std::make_unique<CoordinateDescentMinimizer>(pp->problem->context()); return pp->inner_iteration_minimizer->Init(*pp->reduced_program, pp->problem->parameter_map(), *options.inner_iteration_ordering, @@ -335,7 +336,7 @@ void SetupMinimizerOptions(PreprocessedProblem* pp) { SetupCommonMinimizerOptions(pp); pp->minimizer_options.is_constrained = pp->reduced_program->IsBoundsConstrained(); - pp->minimizer_options.jacobian.reset(pp->evaluator->CreateJacobian()); + pp->minimizer_options.jacobian = pp->evaluator->CreateJacobian(); pp->minimizer_options.inner_iteration_minimizer = pp->inner_iteration_minimizer; @@ -348,15 +349,13 @@ void SetupMinimizerOptions(PreprocessedProblem* pp) { strategy_options.trust_region_strategy_type = options.trust_region_strategy_type; strategy_options.dogleg_type = options.dogleg_type; - pp->minimizer_options.trust_region_strategy.reset( - TrustRegionStrategy::Create(strategy_options)); + pp->minimizer_options.trust_region_strategy = + TrustRegionStrategy::Create(strategy_options); CHECK(pp->minimizer_options.trust_region_strategy != nullptr); } } // namespace -TrustRegionPreprocessor::~TrustRegionPreprocessor() {} - bool TrustRegionPreprocessor::Preprocess(const Solver::Options& options, ProblemImpl* problem, PreprocessedProblem* pp) { @@ -370,10 +369,10 @@ bool TrustRegionPreprocessor::Preprocess(const Solver::Options& options, return false; } - pp->reduced_program.reset(program->CreateReducedProgram( - &pp->removed_parameter_blocks, &pp->fixed_cost, &pp->error)); + pp->reduced_program = program->CreateReducedProgram( + &pp->removed_parameter_blocks, &pp->fixed_cost, &pp->error); - if (pp->reduced_program.get() == NULL) { + if (pp->reduced_program.get() == nullptr) { return false; } diff --git a/extern/ceres/internal/ceres/trust_region_preprocessor.h b/extern/ceres/internal/ceres/trust_region_preprocessor.h index 2655abe4b2e..26ef8fad37d 100644 --- a/extern/ceres/internal/ceres/trust_region_preprocessor.h +++ b/extern/ceres/internal/ceres/trust_region_preprocessor.h @@ -31,15 +31,15 @@ #ifndef CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ #define CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/preprocessor.h" namespace ceres { namespace internal { -class CERES_EXPORT_INTERNAL TrustRegionPreprocessor : public Preprocessor { +class CERES_NO_EXPORT TrustRegionPreprocessor final : public Preprocessor { public: - virtual ~TrustRegionPreprocessor(); bool Preprocess(const Solver::Options& options, ProblemImpl* problem, PreprocessedProblem* preprocessed_problem) override; @@ -48,4 +48,6 @@ class CERES_EXPORT_INTERNAL TrustRegionPreprocessor : public Preprocessor { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_TRUST_REGION_PREPROCESSOR_H_ diff --git a/extern/ceres/internal/ceres/trust_region_step_evaluator.h b/extern/ceres/internal/ceres/trust_region_step_evaluator.h index 03c00362dac..8e0c4e91f49 100644 --- a/extern/ceres/internal/ceres/trust_region_step_evaluator.h +++ b/extern/ceres/internal/ceres/trust_region_step_evaluator.h @@ -31,6 +31,8 @@ #ifndef CERES_INTERNAL_TRUST_REGION_STEP_EVALUATOR_H_ #define CERES_INTERNAL_TRUST_REGION_STEP_EVALUATOR_H_ +#include "ceres/internal/export.h" + namespace ceres { namespace internal { @@ -74,7 +76,7 @@ namespace internal { // x = x + delta; // step_evaluator->StepAccepted(cost, model_cost_change); // } -class TrustRegionStepEvaluator { +class CERES_NO_EXPORT TrustRegionStepEvaluator { public: // initial_cost is as the name implies the cost of the starting // state of the trust region minimizer. diff --git a/extern/ceres/internal/ceres/trust_region_strategy.cc b/extern/ceres/internal/ceres/trust_region_strategy.cc index 7e429d5e557..1096cd3c8aa 100644 --- a/extern/ceres/internal/ceres/trust_region_strategy.cc +++ b/extern/ceres/internal/ceres/trust_region_strategy.cc @@ -32,20 +32,23 @@ #include "ceres/trust_region_strategy.h" +#include <memory> + #include "ceres/dogleg_strategy.h" #include "ceres/levenberg_marquardt_strategy.h" namespace ceres { namespace internal { -TrustRegionStrategy::~TrustRegionStrategy() {} +TrustRegionStrategy::~TrustRegionStrategy() = default; -TrustRegionStrategy* TrustRegionStrategy::Create(const Options& options) { +std::unique_ptr<TrustRegionStrategy> TrustRegionStrategy::Create( + const Options& options) { switch (options.trust_region_strategy_type) { case LEVENBERG_MARQUARDT: - return new LevenbergMarquardtStrategy(options); + return std::make_unique<LevenbergMarquardtStrategy>(options); case DOGLEG: - return new DoglegStrategy(options); + return std::make_unique<DoglegStrategy>(options); default: LOG(FATAL) << "Unknown trust region strategy: " << options.trust_region_strategy_type; @@ -53,7 +56,7 @@ TrustRegionStrategy* TrustRegionStrategy::Create(const Options& options) { LOG(FATAL) << "Unknown trust region strategy: " << options.trust_region_strategy_type; - return NULL; + return nullptr; } } // namespace internal diff --git a/extern/ceres/internal/ceres/trust_region_strategy.h b/extern/ceres/internal/ceres/trust_region_strategy.h index 176f73a4876..33086cafb52 100644 --- a/extern/ceres/internal/ceres/trust_region_strategy.h +++ b/extern/ceres/internal/ceres/trust_region_strategy.h @@ -31,9 +31,11 @@ #ifndef CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ #define CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ +#include <memory> #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/linear_solver.h" namespace ceres { @@ -54,7 +56,7 @@ class SparseMatrix; // the LevenbergMarquardtStrategy uses the inverse of the trust region // radius to scale the damping term, which controls the step size, but // does not set a hard limit on its size. -class CERES_EXPORT_INTERNAL TrustRegionStrategy { +class CERES_NO_EXPORT TrustRegionStrategy { public: struct Options { TrustRegionStrategyType trust_region_strategy_type = LEVENBERG_MARQUARDT; @@ -75,7 +77,7 @@ class CERES_EXPORT_INTERNAL TrustRegionStrategy { }; // Factory. - static TrustRegionStrategy* Create(const Options& options); + static std::unique_ptr<TrustRegionStrategy> Create(const Options& options); virtual ~TrustRegionStrategy(); @@ -142,4 +144,6 @@ class CERES_EXPORT_INTERNAL TrustRegionStrategy { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_TRUST_REGION_STRATEGY_H_ diff --git a/extern/ceres/internal/ceres/types.cc b/extern/ceres/internal/ceres/types.cc index 39bb2d8cc4d..48242678b46 100644 --- a/extern/ceres/internal/ceres/types.cc +++ b/extern/ceres/internal/ceres/types.cc @@ -34,6 +34,7 @@ #include <cctype> #include <string> +#include "ceres/internal/config.h" #include "glog/logging.h" namespace ceres { @@ -128,6 +129,7 @@ const char* DenseLinearAlgebraLibraryTypeToString( switch (type) { CASESTR(EIGEN); CASESTR(LAPACK); + CASESTR(CUDA); default: return "UNKNOWN"; } @@ -138,6 +140,7 @@ bool StringToDenseLinearAlgebraLibraryType( UpperCase(&value); STRENUM(EIGEN); STRENUM(LAPACK); + STRENUM(CUDA); return false; } @@ -417,6 +420,7 @@ bool IsDenseLinearAlgebraLibraryTypeAvailable( if (type == EIGEN) { return true; } + if (type == LAPACK) { #ifdef CERES_NO_LAPACK return false; @@ -425,6 +429,14 @@ bool IsDenseLinearAlgebraLibraryTypeAvailable( #endif } + if (type == CUDA) { +#ifdef CERES_NO_CUDA + return false; +#else + return true; +#endif + } + LOG(WARNING) << "Unknown dense linear algebra library " << type; return false; } diff --git a/extern/ceres/internal/ceres/visibility.cc b/extern/ceres/internal/ceres/visibility.cc index 82bf6f170b8..f666ce0c4bb 100644 --- a/extern/ceres/internal/ceres/visibility.cc +++ b/extern/ceres/internal/ceres/visibility.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ #include <algorithm> #include <cmath> #include <ctime> +#include <memory> #include <set> #include <unordered_map> #include <utility> @@ -62,8 +63,8 @@ void ComputeVisibility(const CompressedRowBlockStructure& block_structure, visibility->resize(0); visibility->resize(block_structure.cols.size() - num_eliminate_blocks); - for (int i = 0; i < block_structure.rows.size(); ++i) { - const vector<Cell>& cells = block_structure.rows[i].cells; + for (const auto& row : block_structure.rows) { + const vector<Cell>& cells = row.cells; int block_id = cells[0].block_id; // If the first block is not an e_block, then skip this row block. if (block_id >= num_eliminate_blocks) { @@ -79,16 +80,16 @@ void ComputeVisibility(const CompressedRowBlockStructure& block_structure, } } -WeightedGraph<int>* CreateSchurComplementGraph( +std::unique_ptr<WeightedGraph<int>> CreateSchurComplementGraph( const vector<set<int>>& visibility) { - const time_t start_time = time(NULL); + const time_t start_time = time(nullptr); // Compute the number of e_blocks/point blocks. Since the visibility // set for each e_block/camera contains the set of e_blocks/points // visible to it, we find the maximum across all visibility sets. int num_points = 0; - for (int i = 0; i < visibility.size(); i++) { - if (visibility[i].size() > 0) { - num_points = max(num_points, (*visibility[i].rbegin()) + 1); + for (const auto& visible : visibility) { + if (!visible.empty()) { + num_points = max(num_points, (*visible.rbegin()) + 1); } } @@ -100,7 +101,7 @@ WeightedGraph<int>* CreateSchurComplementGraph( vector<set<int>> inverse_visibility(num_points); for (int i = 0; i < visibility.size(); i++) { const set<int>& visibility_set = visibility[i]; - for (const int v : visibility_set) { + for (int v : visibility_set) { inverse_visibility[v].insert(i); } } @@ -111,17 +112,17 @@ WeightedGraph<int>* CreateSchurComplementGraph( // Count the number of points visible to each camera/f_block pair. for (const auto& inverse_visibility_set : inverse_visibility) { - for (set<int>::const_iterator camera1 = inverse_visibility_set.begin(); + for (auto camera1 = inverse_visibility_set.begin(); camera1 != inverse_visibility_set.end(); ++camera1) { - set<int>::const_iterator camera2 = camera1; + auto camera2 = camera1; for (++camera2; camera2 != inverse_visibility_set.end(); ++camera2) { ++(camera_pairs[make_pair(*camera1, *camera2)]); } } } - WeightedGraph<int>* graph = new WeightedGraph<int>; + auto graph = std::make_unique<WeightedGraph<int>>(); // Add vertices and initialize the pairs for self edges so that self // edges are guaranteed. This is needed for the Canonical views @@ -146,7 +147,7 @@ WeightedGraph<int>* CreateSchurComplementGraph( graph->AddEdge(camera1, camera2, weight); } - VLOG(2) << "Schur complement graph time: " << (time(NULL) - start_time); + VLOG(2) << "Schur complement graph time: " << (time(nullptr) - start_time); return graph; } diff --git a/extern/ceres/internal/ceres/visibility.h b/extern/ceres/internal/ceres/visibility.h index 68c6723fad7..d8f6968d98f 100644 --- a/extern/ceres/internal/ceres/visibility.h +++ b/extern/ceres/internal/ceres/visibility.h @@ -35,11 +35,13 @@ #ifndef CERES_INTERNAL_VISIBILITY_H_ #define CERES_INTERNAL_VISIBILITY_H_ +#include <memory> #include <set> #include <vector> #include "ceres/graph.h" -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" namespace ceres { namespace internal { @@ -54,7 +56,7 @@ struct CompressedRowBlockStructure; // // In a structure from motion problem, e_blocks correspond to 3D // points and f_blocks correspond to cameras. -CERES_EXPORT_INTERNAL void ComputeVisibility( +CERES_NO_EXPORT void ComputeVisibility( const CompressedRowBlockStructure& block_structure, int num_eliminate_blocks, std::vector<std::set<int>>* visibility); @@ -72,10 +74,12 @@ CERES_EXPORT_INTERNAL void ComputeVisibility( // // Caller acquires ownership of the returned WeightedGraph pointer // (heap-allocated). -CERES_EXPORT_INTERNAL WeightedGraph<int>* CreateSchurComplementGraph( +CERES_NO_EXPORT std::unique_ptr<WeightedGraph<int>> CreateSchurComplementGraph( const std::vector<std::set<int>>& visibility); } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_VISIBILITY_H_ diff --git a/extern/ceres/internal/ceres/visibility_based_preconditioner.cc b/extern/ceres/internal/ceres/visibility_based_preconditioner.cc index 0cf4afaae06..831a8663027 100644 --- a/extern/ceres/internal/ceres/visibility_based_preconditioner.cc +++ b/extern/ceres/internal/ceres/visibility_based_preconditioner.cc @@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2015 Google Inc. All rights reserved. +// Copyright 2022 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -70,9 +70,8 @@ static constexpr double kCanonicalViewsSimilarityPenaltyWeight = 0.0; static constexpr double kSingleLinkageMinSimilarity = 0.9; VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( - const CompressedRowBlockStructure& bs, - const Preconditioner::Options& options) - : options_(options), num_blocks_(0), num_clusters_(0) { + const CompressedRowBlockStructure& bs, Preconditioner::Options options) + : options_(std::move(options)), num_blocks_(0), num_clusters_(0) { CHECK_GT(options_.elimination_groups.size(), 1); CHECK_GT(options_.elimination_groups[0], 0); CHECK(options_.type == CLUSTER_JACOBI || options_.type == CLUSTER_TRIDIAGONAL) @@ -80,7 +79,7 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( num_blocks_ = bs.cols.size() - options_.elimination_groups[0]; CHECK_GT(num_blocks_, 0) << "Jacobian should have at least 1 f_block for " << "visibility based preconditioning."; - CHECK(options_.context != NULL); + CHECK(options_.context != nullptr); // Vector of camera block sizes block_size_.resize(num_blocks_); @@ -88,7 +87,7 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( block_size_[i] = bs.cols[i + options_.elimination_groups[0]].size; } - const time_t start_time = time(NULL); + const time_t start_time = time(nullptr); switch (options_.type) { case CLUSTER_JACOBI: ComputeClusterJacobiSparsity(bs); @@ -99,11 +98,11 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( default: LOG(FATAL) << "Unknown preconditioner type"; } - const time_t structure_time = time(NULL); + const time_t structure_time = time(nullptr); InitStorage(bs); - const time_t storage_time = time(NULL); + const time_t storage_time = time(nullptr); InitEliminator(bs); - const time_t eliminator_time = time(NULL); + const time_t eliminator_time = time(nullptr); LinearSolver::Options sparse_cholesky_options; sparse_cholesky_options.sparse_linear_algebra_library_type = @@ -118,14 +117,14 @@ VisibilityBasedPreconditioner::VisibilityBasedPreconditioner( sparse_cholesky_options.use_postordering = true; sparse_cholesky_ = SparseCholesky::Create(sparse_cholesky_options); - const time_t init_time = time(NULL); + const time_t init_time = time(nullptr); VLOG(2) << "init time: " << init_time - start_time << " structure time: " << structure_time - start_time << " storage time:" << storage_time - structure_time << " eliminator time: " << eliminator_time - storage_time; } -VisibilityBasedPreconditioner::~VisibilityBasedPreconditioner() {} +VisibilityBasedPreconditioner::~VisibilityBasedPreconditioner() = default; // Determine the sparsity structure of the CLUSTER_JACOBI // preconditioner. It clusters cameras using their scene @@ -162,11 +161,9 @@ void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity( // maximum spanning forest of this graph. vector<set<int>> cluster_visibility; ComputeClusterVisibility(visibility, &cluster_visibility); - std::unique_ptr<WeightedGraph<int>> cluster_graph( - CreateClusterGraph(cluster_visibility)); + auto cluster_graph = CreateClusterGraph(cluster_visibility); CHECK(cluster_graph != nullptr); - std::unique_ptr<WeightedGraph<int>> forest( - Degree2MaximumSpanningForest(*cluster_graph)); + auto forest = Degree2MaximumSpanningForest(*cluster_graph); CHECK(forest != nullptr); ForestToClusterPairs(*forest, &cluster_pairs_); } @@ -175,7 +172,8 @@ void VisibilityBasedPreconditioner::ComputeClusterTridiagonalSparsity( void VisibilityBasedPreconditioner::InitStorage( const CompressedRowBlockStructure& bs) { ComputeBlockPairsInPreconditioner(bs); - m_.reset(new BlockRandomAccessSparseMatrix(block_size_, block_pairs_)); + m_ = std::make_unique<BlockRandomAccessSparseMatrix>(block_size_, + block_pairs_); } // Call the canonical views algorithm and cluster the cameras based on @@ -186,8 +184,7 @@ void VisibilityBasedPreconditioner::InitStorage( // memberships for each camera block. void VisibilityBasedPreconditioner::ClusterCameras( const vector<set<int>>& visibility) { - std::unique_ptr<WeightedGraph<int>> schur_complement_graph( - CreateSchurComplementGraph(visibility)); + auto schur_complement_graph = CreateSchurComplementGraph(visibility); CHECK(schur_complement_graph != nullptr); std::unordered_map<int, int> membership; @@ -285,14 +282,12 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( } } - for (set<int>::const_iterator block1 = f_blocks.begin(); - block1 != f_blocks.end(); - ++block1) { - set<int>::const_iterator block2 = block1; + for (auto block1 = f_blocks.begin(); block1 != f_blocks.end(); ++block1) { + auto block2 = block1; ++block2; for (; block2 != f_blocks.end(); ++block2) { if (IsBlockPairInPreconditioner(*block1, *block2)) { - block_pairs_.insert(make_pair(*block1, *block2)); + block_pairs_.emplace(*block1, *block2); } } } @@ -304,8 +299,8 @@ void VisibilityBasedPreconditioner::ComputeBlockPairsInPreconditioner( CHECK_GE(row.cells.front().block_id, num_eliminate_blocks); for (int i = 0; i < row.cells.size(); ++i) { const int block1 = row.cells[i].block_id - num_eliminate_blocks; - for (int j = 0; j < row.cells.size(); ++j) { - const int block2 = row.cells[j].block_id - num_eliminate_blocks; + for (const auto& cell : row.cells) { + const int block2 = cell.block_id - num_eliminate_blocks; if (block1 <= block2) { if (IsBlockPairInPreconditioner(block1, block2)) { block_pairs_.insert(make_pair(block1, block2)); @@ -328,7 +323,7 @@ void VisibilityBasedPreconditioner::InitEliminator( eliminator_options.f_block_size = options_.f_block_size; eliminator_options.row_block_size = options_.row_block_size; eliminator_options.context = options_.context; - eliminator_.reset(SchurEliminatorBase::Create(eliminator_options)); + eliminator_ = SchurEliminatorBase::Create(eliminator_options); const bool kFullRankETE = true; eliminator_->Init( eliminator_options.elimination_groups[0], kFullRankETE, &bs); @@ -337,7 +332,7 @@ void VisibilityBasedPreconditioner::InitEliminator( // Update the values of the preconditioner matrix and factorize it. bool VisibilityBasedPreconditioner::UpdateImpl(const BlockSparseMatrix& A, const double* D) { - const time_t start_time = time(NULL); + const time_t start_time = time(nullptr); const int num_rows = m_->num_rows(); CHECK_GT(num_rows, 0); @@ -375,7 +370,7 @@ bool VisibilityBasedPreconditioner::UpdateImpl(const BlockSparseMatrix& A, status = Factorize(); } - VLOG(2) << "Compute time: " << time(NULL) - start_time; + VLOG(2) << "Compute time: " << time(nullptr) - start_time; return (status == LINEAR_SOLVER_SUCCESS); } @@ -395,7 +390,7 @@ void VisibilityBasedPreconditioner::ScaleOffDiagonalCells() { int r, c, row_stride, col_stride; CellInfo* cell_info = m_->GetCell(block1, block2, &r, &c, &row_stride, &col_stride); - CHECK(cell_info != NULL) + CHECK(cell_info != nullptr) << "Cell missing for block pair (" << block1 << "," << block2 << ")" << " cluster pair (" << cluster_membership_[block1] << " " << cluster_membership_[block2] << ")"; @@ -420,11 +415,10 @@ LinearSolverTerminationType VisibilityBasedPreconditioner::Factorize() { const CompressedRowSparseMatrix::StorageType storage_type = sparse_cholesky_->StorageType(); if (storage_type == CompressedRowSparseMatrix::UPPER_TRIANGULAR) { - lhs.reset(CompressedRowSparseMatrix::FromTripletSparseMatrix(*tsm)); + lhs = CompressedRowSparseMatrix::FromTripletSparseMatrix(*tsm); lhs->set_storage_type(CompressedRowSparseMatrix::UPPER_TRIANGULAR); } else { - lhs.reset( - CompressedRowSparseMatrix::FromTripletSparseMatrixTransposed(*tsm)); + lhs = CompressedRowSparseMatrix::FromTripletSparseMatrixTransposed(*tsm); lhs->set_storage_type(CompressedRowSparseMatrix::LOWER_TRIANGULAR); } @@ -503,9 +497,10 @@ void VisibilityBasedPreconditioner::ComputeClusterVisibility( // Construct a graph whose vertices are the clusters, and the edge // weights are the number of 3D points visible to cameras in both the // vertices. -WeightedGraph<int>* VisibilityBasedPreconditioner::CreateClusterGraph( +std::unique_ptr<WeightedGraph<int>> +VisibilityBasedPreconditioner::CreateClusterGraph( const vector<set<int>>& cluster_visibility) const { - WeightedGraph<int>* cluster_graph = new WeightedGraph<int>; + auto cluster_graph = std::make_unique<WeightedGraph<int>>(); for (int i = 0; i < num_clusters_; ++i) { cluster_graph->AddVertex(i); diff --git a/extern/ceres/internal/ceres/visibility_based_preconditioner.h b/extern/ceres/internal/ceres/visibility_based_preconditioner.h index 0457b9a376a..8079dc3f3ce 100644 --- a/extern/ceres/internal/ceres/visibility_based_preconditioner.h +++ b/extern/ceres/internal/ceres/visibility_based_preconditioner.h @@ -122,9 +122,10 @@ class SchurEliminatorBase; // options.elimination_groups.push_back(num_cameras); // VisibilityBasedPreconditioner preconditioner( // *A.block_structure(), options); -// preconditioner.Update(A, NULL); +// preconditioner.Update(A, nullptr); // preconditioner.RightMultiply(x, y); -class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { +class CERES_NO_EXPORT VisibilityBasedPreconditioner + : public BlockSparseMatrixPreconditioner { public: // Initialize the symbolic structure of the preconditioner. bs is // the block structure of the linear system to be solved. It is used @@ -133,11 +134,11 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { // It has the same structural requirement as other Schur complement // based solvers. Please see schur_eliminator.h for more details. VisibilityBasedPreconditioner(const CompressedRowBlockStructure& bs, - const Preconditioner::Options& options); + Preconditioner::Options options); VisibilityBasedPreconditioner(const VisibilityBasedPreconditioner&) = delete; void operator=(const VisibilityBasedPreconditioner&) = delete; - virtual ~VisibilityBasedPreconditioner(); + ~VisibilityBasedPreconditioner() override; // Preconditioner interface void RightMultiply(const double* x, double* y) const final; @@ -160,7 +161,7 @@ class VisibilityBasedPreconditioner : public BlockSparseMatrixPreconditioner { void ComputeClusterVisibility( const std::vector<std::set<int>>& visibility, std::vector<std::set<int>>* cluster_visibility) const; - WeightedGraph<int>* CreateClusterGraph( + std::unique_ptr<WeightedGraph<int>> CreateClusterGraph( const std::vector<std::set<int>>& visibility) const; void ForestToClusterPairs( const WeightedGraph<int>& forest, diff --git a/extern/ceres/internal/ceres/wall_time.cc b/extern/ceres/internal/ceres/wall_time.cc index 716392741e9..a54ab640b3e 100644 --- a/extern/ceres/internal/ceres/wall_time.cc +++ b/extern/ceres/internal/ceres/wall_time.cc @@ -30,6 +30,8 @@ #include "ceres/wall_time.h" +#include "ceres/internal/config.h" + #ifdef CERES_USE_OPENMP #include <omp.h> #else @@ -58,7 +60,7 @@ double WallTimeInSeconds() { static_cast<double>(frequency.QuadPart); #else timeval time_val; - gettimeofday(&time_val, NULL); + gettimeofday(&time_val, nullptr); return (time_val.tv_sec + time_val.tv_usec * 1e-6); #endif #endif diff --git a/extern/ceres/internal/ceres/wall_time.h b/extern/ceres/internal/ceres/wall_time.h index 9c92e9e60ef..f093eed0418 100644 --- a/extern/ceres/internal/ceres/wall_time.h +++ b/extern/ceres/internal/ceres/wall_time.h @@ -34,7 +34,8 @@ #include <map> #include <string> -#include "ceres/internal/port.h" +#include "ceres/internal/disable_warnings.h" +#include "ceres/internal/export.h" #include "ceres/stringprintf.h" #include "glog/logging.h" @@ -45,7 +46,7 @@ namespace internal { // OpenMP is available then the high precision openmp_get_wtime() // function is used. Otherwise on unixes, gettimeofday is used. The // granularity is in seconds on windows systems. -CERES_EXPORT_INTERNAL double WallTimeInSeconds(); +CERES_NO_EXPORT double WallTimeInSeconds(); // Log a series of events, recording for each event the time elapsed // since the last event and since the creation of the object. @@ -71,7 +72,7 @@ CERES_EXPORT_INTERNAL double WallTimeInSeconds(); // Bar1: time1 time1 // Bar2: time2 time1 + time2; // Total: time3 time1 + time2 + time3; -class EventLogger { +class CERES_NO_EXPORT EventLogger { public: explicit EventLogger(const std::string& logger_name); ~EventLogger(); @@ -86,4 +87,6 @@ class EventLogger { } // namespace internal } // namespace ceres +#include "ceres/internal/reenable_warnings.h" + #endif // CERES_INTERNAL_WALL_TIME_H_ |