mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 08:34:37 +08:00
Update minimum required C++ version for Ceres to C++14
- Removes all workarounds for pre-C++14 versions - Removes '11' qualifier from C++ threading option and associated defines. - Fix missing inclusion of 'Multithreading' in reported Ceres components when C++ threading model is enabled. - Update Sphinx documentation to specify C++14 as minimum requirement. Change-Id: I706c8b367b3221e3c4d1a0aaf669a8f9c911e438
This commit is contained in:
+10
-8
@@ -32,19 +32,19 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_policy(VERSION 3.5)
|
||||
|
||||
# Set the C++ version (must be >= C++11) when compiling Ceres.
|
||||
# Set the C++ version (must be >= C++14) when compiling Ceres.
|
||||
#
|
||||
# Reflect a user-specified (via -D) CMAKE_CXX_STANDARD if present, otherwise
|
||||
# default to C++11.
|
||||
# default to C++14.
|
||||
set(DEFAULT_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
||||
if (NOT DEFAULT_CXX_STANDARD)
|
||||
set(DEFAULT_CXX_STANDARD 11)
|
||||
set(DEFAULT_CXX_STANDARD 14)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD ${DEFAULT_CXX_STANDARD} CACHE STRING
|
||||
"C++ standard (minimum 11)" FORCE)
|
||||
"C++ standard (minimum 14)" FORCE)
|
||||
# Restrict CMAKE_CXX_STANDARD to the valid versions permitted and ensure that
|
||||
# if one was forced via -D that it is in the valid set.
|
||||
set(ALLOWED_CXX_STANDARDS 11 14 17 20)
|
||||
set(ALLOWED_CXX_STANDARDS 14 17 20)
|
||||
set_property(CACHE CMAKE_CXX_STANDARD PROPERTY STRINGS ${ALLOWED_CXX_STANDARDS})
|
||||
list(FIND ALLOWED_CXX_STANDARDS ${CMAKE_CXX_STANDARD} POSITION)
|
||||
if (POSITION LESS 0)
|
||||
@@ -56,11 +56,13 @@ endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "")
|
||||
mark_as_advanced(CMAKE_CXX_STANDARD_REQUIRED)
|
||||
|
||||
# MSVC versions < 2013 did not fully support >= C++11.
|
||||
# MSVC versions < 2015 did not fully support >= C++14, and technically even
|
||||
# 2015 did not support a couple of smaller features
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC AND
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0)
|
||||
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0)
|
||||
message(FATAL_ERROR "Invalid CMAKE_CXX_COMPILER_VERSION: "
|
||||
"${CMAKE_CXX_COMPILER_VERSION}. Ceres requires at least MSVC 2013 Update 4+")
|
||||
"${CMAKE_CXX_COMPILER_VERSION}. Ceres requires at least MSVC 2015 for "
|
||||
"C++14 support.")
|
||||
endif()
|
||||
|
||||
# On macOS, add the Homebrew prefix (with appropriate suffixes) to the
|
||||
|
||||
+1
-1
@@ -196,7 +196,7 @@ def ceres_library(name,
|
||||
"CERES_NO_ACCELERATE_SPARSE",
|
||||
"CERES_NO_LAPACK",
|
||||
"CERES_USE_EIGEN_SPARSE",
|
||||
"CERES_USE_CXX11_THREADS",
|
||||
"CERES_USE_CXX_THREADS",
|
||||
],
|
||||
includes = [
|
||||
"config",
|
||||
|
||||
@@ -84,6 +84,8 @@ function(ceres_compile_options_to_components CURRENT_CERES_COMPILE_OPTIONS CERES
|
||||
CERES_RESTRICT_SCHUR_SPECIALIZATION "SchurSpecializations")
|
||||
add_to_output_if_found(CURRENT_CERES_COMPILE_OPTIONS ${CERES_COMPONENTS_VAR}
|
||||
CERES_USE_OPENMP "OpenMP;Multithreading")
|
||||
add_to_output_if_found(CURRENT_CERES_COMPILE_OPTIONS ${CERES_COMPONENTS_VAR}
|
||||
CERES_USE_CXX_THREADS "Multithreading")
|
||||
# Remove duplicates of SparseLinearAlgebraLibrary if multiple sparse backends
|
||||
# are present.
|
||||
list(REMOVE_DUPLICATES ${CERES_COMPONENTS_VAR})
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
# Author: alexs.mac@gmail.com (Alex Stewart)
|
||||
|
||||
# Ordered by expected preference.
|
||||
set(CERES_THREADING_MODELS "CXX11_THREADS;OPENMP;NO_THREADS")
|
||||
set(CERES_THREADING_MODELS "CXX_THREADS;OPENMP;NO_THREADS")
|
||||
|
||||
function(find_available_ceres_threading_models CERES_THREADING_MODELS_AVAILABLE_VAR)
|
||||
set(CERES_THREADING_MODELS_AVAILABLE ${CERES_THREADING_MODELS})
|
||||
@@ -48,7 +48,7 @@ function(find_available_ceres_threading_models CERES_THREADING_MODELS_AVAILABLE_
|
||||
endfunction()
|
||||
|
||||
macro(set_ceres_threading_model_to_cxx11_threads)
|
||||
list(APPEND CERES_COMPILE_OPTIONS CERES_USE_CXX11_THREADS)
|
||||
list(APPEND CERES_COMPILE_OPTIONS CERES_USE_CXX_THREADS)
|
||||
endmacro()
|
||||
|
||||
macro(set_ceres_threading_model_to_openmp)
|
||||
@@ -63,7 +63,7 @@ macro(set_ceres_threading_model_to_no_threads)
|
||||
endmacro()
|
||||
|
||||
macro(set_ceres_threading_model CERES_THREADING_MODEL_TO_SET)
|
||||
if ("${CERES_THREADING_MODEL_TO_SET}" STREQUAL "CXX11_THREADS")
|
||||
if ("${CERES_THREADING_MODEL_TO_SET}" STREQUAL "CXX_THREADS")
|
||||
set_ceres_threading_model_to_cxx11_threads()
|
||||
elseif ("${CERES_THREADING_MODEL_TO_SET}" STREQUAL "OPENMP")
|
||||
set_ceres_threading_model_to_openmp()
|
||||
|
||||
+3
-3
@@ -73,10 +73,10 @@
|
||||
|
||||
// If defined, Ceres was compiled without multithreading support.
|
||||
@CERES_NO_THREADS@
|
||||
// If defined Ceres was compiled with OpenMP multithreading support.
|
||||
// If defined Ceres was compiled with OpenMP multithreading.
|
||||
@CERES_USE_OPENMP@
|
||||
// If defined Ceres was compiled with C++11 thread support.
|
||||
@CERES_USE_CXX11_THREADS@
|
||||
// If defined Ceres was compiled with modern C++ multithreading.
|
||||
@CERES_USE_CXX_THREADS@
|
||||
|
||||
// If defined, Ceres was built as a shared library.
|
||||
@CERES_USING_SHARED_LIBRARY@
|
||||
|
||||
@@ -54,8 +54,9 @@ Why?
|
||||
of Non-linear Conjugate Gradients, BFGS and LBFGS.
|
||||
|
||||
* **Speed** - Ceres Solver has been extensively optimized, with C++
|
||||
templating, hand written linear algebra routines and OpenMP or C++11 threads
|
||||
based multithreading of the Jacobian evaluation and the linear solvers.
|
||||
templating, hand written linear algebra routines and OpenMP or
|
||||
modern C++ threads based multithreading of the Jacobian evaluation
|
||||
and the linear solvers.
|
||||
|
||||
* **Solution Quality** Ceres is the `best performing`_ solver on the NIST
|
||||
problem set used by Mondragon and Borchers for benchmarking
|
||||
|
||||
@@ -23,9 +23,8 @@ Dependencies
|
||||
|
||||
.. NOTE ::
|
||||
|
||||
All versions of Ceres > 1.14 require a **fully C++11-compliant**
|
||||
compiler. In versions <= 1.14, C++11 was an optional requirement
|
||||
controlled by the ``CXX11 [Default: OFF]`` build option.
|
||||
Starting with v2.0 Ceres requires a **fully C++14-compliant**
|
||||
compiler. In versions <= 1.14, C++11 was an optional requirement.
|
||||
|
||||
Ceres relies on a number of open source libraries, some of which are
|
||||
optional. For details on customizing the build process, see
|
||||
@@ -378,7 +377,7 @@ Windows
|
||||
<https://github.com/tbennun/ceres-windows>`_ for Ceres Solver by Tal
|
||||
Ben-Nun.
|
||||
|
||||
On Windows, we support building with Visual Studio 2013 Release 4 or newer. Note
|
||||
On Windows, we support building with Visual Studio 2015.2 of newer. Note
|
||||
that the Windows port is less featureful and less tested than the
|
||||
Linux or Mac OS X versions due to the lack of an officially supported
|
||||
way of building SuiteSparse and CXSparse. There are however a number
|
||||
@@ -709,7 +708,7 @@ Options controlling Ceres configuration
|
||||
gains in the ``SPARSE_SCHUR`` solver, you can disable some of the
|
||||
template specializations by turning this ``OFF``.
|
||||
|
||||
#. ``CERES_THREADING_MODEL [Default: CXX11_THREADS > OPENMP > NO_THREADS]``:
|
||||
#. ``CERES_THREADING_MODEL [Default: CXX_THREADS > OPENMP > NO_THREADS]``:
|
||||
Multi-threading backend Ceres should be compiled with. This will
|
||||
automatically be set to only accept the available subset of threading
|
||||
options in the CMake GUI.
|
||||
@@ -904,8 +903,6 @@ The Ceres components which can be specified are:
|
||||
#. ``Multithreading``: Ceres built with *a* multithreading library.
|
||||
This is equivalent to (``CERES_THREAD != NO_THREADS``).
|
||||
|
||||
#. ``C++11``: Ceres built with C++11.
|
||||
|
||||
To specify one/multiple Ceres components use the ``COMPONENTS`` argument to
|
||||
`find_package()
|
||||
<http://www.cmake.org/cmake/help/v3.2/command/find_package.html>`_ like so:
|
||||
|
||||
@@ -2226,7 +2226,7 @@ The three arrays will be:
|
||||
Number of threads actually used by the solver for Jacobian and
|
||||
residual evaluation. This number is not equal to
|
||||
:member:`Solver::Summary::num_threads_given` if none of `OpenMP`
|
||||
or `CXX11_THREADS` is available.
|
||||
or `CXX_THREADS` is available.
|
||||
|
||||
.. member:: LinearSolverType Solver::Summary::linear_solver_type_given
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ target_link_libraries(rosenbrock Ceres::ceres)
|
||||
|
||||
add_executable(curve_fitting_c curve_fitting.c)
|
||||
target_link_libraries(curve_fitting_c Ceres::ceres)
|
||||
# Force CMake to link curve_fitting_c using the C linker, this is important
|
||||
# when Ceres was compiled using C++11 to ensure that -std=c++11 is not passed
|
||||
# through.
|
||||
# Force CMake to link curve_fitting_c using the C linker.
|
||||
set_target_properties(curve_fitting_c PROPERTIES LINKER_LANGUAGE C)
|
||||
# As this is a C file #including <math.h> we have to explicitly add the math
|
||||
# library (libm). Although some compilers (dependent upon options) will accept
|
||||
|
||||
@@ -89,12 +89,12 @@
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/dynamic_cost_function_to_functor.h"
|
||||
#include "ceres/internal/fixed_array.h"
|
||||
#include "ceres/internal/integer_sequence.h"
|
||||
#include "ceres/internal/parameter_dims.h"
|
||||
#include "ceres/internal/port.h"
|
||||
#include "ceres/types.h"
|
||||
@@ -144,7 +144,7 @@ class CostFunctionToFunctor {
|
||||
|
||||
// Extract parameter block pointers from params.
|
||||
using Indices =
|
||||
internal::make_integer_sequence<int,
|
||||
std::make_integer_sequence<int,
|
||||
ParameterDims::kNumParameterBlocks>;
|
||||
std::array<const T*, ParameterDims::kNumParameterBlocks> parameter_blocks =
|
||||
GetParameterPointers<T>(params, Indices());
|
||||
@@ -158,7 +158,7 @@ class CostFunctionToFunctor {
|
||||
template <typename T, typename Tuple, int... Indices>
|
||||
static std::array<const T*, ParameterDims::kNumParameterBlocks>
|
||||
GetParameterPointers(const Tuple& paramPointers,
|
||||
internal::integer_sequence<int, Indices...>) {
|
||||
std::integer_sequence<int, Indices...>) {
|
||||
return std::array<const T*, ParameterDims::kNumParameterBlocks>{
|
||||
{std::get<Indices>(paramPointers)...}};
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: algorithm.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file contains Google extensions to the standard <algorithm> C++
|
||||
// header.
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_ALGORITHM_H_
|
||||
#define CERES_PUBLIC_INTERNAL_ALGORITHM_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`.
|
||||
struct EqualTo {
|
||||
template <typename T, typename U>
|
||||
bool operator()(const T& a, const U& b) const {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool EqualImpl(InputIter1 first1,
|
||||
InputIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2,
|
||||
Pred pred,
|
||||
std::input_iterator_tag,
|
||||
std::input_iterator_tag) {
|
||||
while (true) {
|
||||
if (first1 == last1) return first2 == last2;
|
||||
if (first2 == last2) return false;
|
||||
if (!pred(*first1, *first2)) return false;
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool EqualImpl(InputIter1 first1,
|
||||
InputIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2,
|
||||
Pred&& pred,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag) {
|
||||
return (last1 - first1 == last2 - first2) &&
|
||||
std::equal(first1, last1, first2, std::forward<Pred>(pred));
|
||||
}
|
||||
|
||||
// When we are using our own internal predicate that just applies operator==, we
|
||||
// forward to the non-predicate form of std::equal. This enables an optimization
|
||||
// in libstdc++ that can result in std::memcmp being used for integer types.
|
||||
template <typename InputIter1, typename InputIter2>
|
||||
bool EqualImpl(InputIter1 first1,
|
||||
InputIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2,
|
||||
internal::EqualTo /* unused */,
|
||||
std::random_access_iterator_tag,
|
||||
std::random_access_iterator_tag) {
|
||||
return (last1 - first1 == last2 - first2) &&
|
||||
std::equal(first1, last1, first2);
|
||||
}
|
||||
|
||||
// Compares the equality of two ranges specified by pairs of iterators, using
|
||||
// the given predicate, returning true iff for each corresponding iterator i1
|
||||
// and i2 in the first and second range respectively, pred(*i1, *i2) == true
|
||||
//
|
||||
// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`)
|
||||
// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are
|
||||
// both random-access iterators, and `last1` - `first1` != `last2` - `first2`,
|
||||
// then the predicate is never invoked and the function returns false.
|
||||
//
|
||||
// This is a C++11-compatible implementation of C++14 `std::equal`. See
|
||||
// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
|
||||
template <typename InputIter1, typename InputIter2, typename Pred>
|
||||
bool equal(InputIter1 first1,
|
||||
InputIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2,
|
||||
Pred&& pred) {
|
||||
return internal::EqualImpl(
|
||||
first1,
|
||||
last1,
|
||||
first2,
|
||||
last2,
|
||||
std::forward<Pred>(pred),
|
||||
typename std::iterator_traits<InputIter1>::iterator_category{},
|
||||
typename std::iterator_traits<InputIter2>::iterator_category{});
|
||||
}
|
||||
|
||||
// Performs comparison of two ranges specified by pairs of iterators using
|
||||
// operator==.
|
||||
template <typename InputIter1, typename InputIter2>
|
||||
bool equal(InputIter1 first1,
|
||||
InputIter1 last1,
|
||||
InputIter2 first2,
|
||||
InputIter2 last2) {
|
||||
return internal::equal(first1, last1, first2, last2, internal::EqualTo{});
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
#endif // CERES_PUBLIC_INTERNAL_ALGORITHM_H_
|
||||
@@ -143,6 +143,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#include "ceres/internal/array_selector.h"
|
||||
#include "ceres/internal/eigen.h"
|
||||
@@ -213,14 +214,14 @@ template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
||||
struct Make1stOrderPerturbations;
|
||||
|
||||
template <int N, int... Ns, int ParameterIdx, int Offset>
|
||||
struct Make1stOrderPerturbations<integer_sequence<int, N, Ns...>,
|
||||
struct Make1stOrderPerturbations<std::integer_sequence<int, N, Ns...>,
|
||||
ParameterIdx,
|
||||
Offset> {
|
||||
template <typename T, typename JetT>
|
||||
inline static void Apply(T const* const* parameters, JetT* x) {
|
||||
Make1stOrderPerturbation<0, N, Offset, T, JetT>::Apply(
|
||||
parameters[ParameterIdx], x + Offset);
|
||||
Make1stOrderPerturbations<integer_sequence<int, Ns...>,
|
||||
Make1stOrderPerturbations<std::integer_sequence<int, Ns...>,
|
||||
ParameterIdx + 1,
|
||||
Offset + N>::Apply(parameters, x);
|
||||
}
|
||||
@@ -228,7 +229,7 @@ struct Make1stOrderPerturbations<integer_sequence<int, N, Ns...>,
|
||||
|
||||
// End of 'recursion'. Nothing more to do.
|
||||
template <int ParameterIdx, int Total>
|
||||
struct Make1stOrderPerturbations<integer_sequence<int>, ParameterIdx, Total> {
|
||||
struct Make1stOrderPerturbations<std::integer_sequence<int>, ParameterIdx, Total> {
|
||||
template <typename T, typename JetT>
|
||||
static void Apply(T const* const* /* NOT USED */, JetT* /* NOT USED */) {}
|
||||
};
|
||||
@@ -276,7 +277,7 @@ template <typename Seq, int ParameterIdx = 0, int Offset = 0>
|
||||
struct Take1stOrderParts;
|
||||
|
||||
template <int N, int... Ns, int ParameterIdx, int Offset>
|
||||
struct Take1stOrderParts<integer_sequence<int, N, Ns...>,
|
||||
struct Take1stOrderParts<std::integer_sequence<int, N, Ns...>,
|
||||
ParameterIdx,
|
||||
Offset> {
|
||||
template <typename JetT, typename T>
|
||||
@@ -284,7 +285,7 @@ struct Take1stOrderParts<integer_sequence<int, N, Ns...>,
|
||||
if (jacobians[ParameterIdx]) {
|
||||
Take1stOrderPart<Offset, N>(num_outputs, output, jacobians[ParameterIdx]);
|
||||
}
|
||||
Take1stOrderParts<integer_sequence<int, Ns...>,
|
||||
Take1stOrderParts<std::integer_sequence<int, Ns...>,
|
||||
ParameterIdx + 1,
|
||||
Offset + N>::Apply(num_outputs, output, jacobians);
|
||||
}
|
||||
@@ -292,7 +293,7 @@ struct Take1stOrderParts<integer_sequence<int, N, Ns...>,
|
||||
|
||||
// End of 'recursion'. Nothing more to do.
|
||||
template <int ParameterIdx, int Offset>
|
||||
struct Take1stOrderParts<integer_sequence<int>, ParameterIdx, Offset> {
|
||||
struct Take1stOrderParts<std::integer_sequence<int>, ParameterIdx, Offset> {
|
||||
template <typename T, typename JetT>
|
||||
static void Apply(int /* NOT USED*/,
|
||||
JetT* /* NOT USED*/,
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
#include <Eigen/Core> // For Eigen::aligned_allocator
|
||||
|
||||
#include "ceres/internal/algorithm.h"
|
||||
#include "ceres/internal/memory.h"
|
||||
#include "glog/logging.h"
|
||||
|
||||
@@ -312,7 +311,7 @@ class FixedArray {
|
||||
// Relational operators. Equality operators are elementwise using
|
||||
// `operator==`, while order operators order FixedArrays lexicographically.
|
||||
friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
return internal::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2018 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: jodebo_beck@gmx.de (Johannes Beck)
|
||||
//
|
||||
// This class mimics std::integer_sequence. That is the reason to follow the
|
||||
// naming convention of the stl and not the google one. Once Ceres switches
|
||||
// to c++ 14 this class can be removed.
|
||||
|
||||
#ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
|
||||
#define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
// We have at least c++ 14 support. Use integer_sequence from the standard.
|
||||
// Sometimes the STL implementation uses a compiler intrinsic to generate
|
||||
// the sequences which will speed up compilation.
|
||||
#include <utility>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
template <typename T, T... Ns>
|
||||
using integer_sequence = std::integer_sequence<T, Ns...>;
|
||||
|
||||
template <typename T, T N>
|
||||
using make_integer_sequence = std::make_integer_sequence<T, N>;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
#else
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
template <typename T, T... Ns>
|
||||
struct integer_sequence {
|
||||
using value_type = T;
|
||||
};
|
||||
|
||||
// Implementation of make_integer_sequence.
|
||||
//
|
||||
// Recursively instantiate make_integer_sequence_impl until Ns
|
||||
// contains the sequence 0, 1, ..., Total-1.
|
||||
//
|
||||
// Example for Total = 4:
|
||||
// T CurIdx, Total, Ns...
|
||||
// make_integer_sequence_impl<int, 0, 4 >
|
||||
// make_integer_sequence_impl<int, 1, 4, 0 >
|
||||
// make_integer_sequence_impl<int, 2, 4, 0, 1 >
|
||||
// make_integer_sequence_impl<int, 3, 4, 0, 1, 2 >
|
||||
// make_integer_sequence_impl<int, 4, 4, 0, 1, 2, 3>
|
||||
// ^^^^^^^^^^
|
||||
// resulting sequence.
|
||||
//
|
||||
// The implemented algorithm has linear complexity for simplicity. A O(log(N))
|
||||
// implementation can be found e.g. here:
|
||||
// https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
|
||||
template <typename T, T CurIdx, T Total, T... Ns>
|
||||
struct make_integer_sequence_impl {
|
||||
using type = typename make_integer_sequence_impl<T, CurIdx + 1, Total, Ns...,
|
||||
CurIdx>::type;
|
||||
};
|
||||
|
||||
// End of 'recursion' when CurIdx reaches Total. All indices 0, 1, ..., N-1 are
|
||||
// contained in Ns. The final integer_sequence is created here.
|
||||
template <typename T, T Total, T... Ns>
|
||||
struct make_integer_sequence_impl<T, Total, Total, Ns...> {
|
||||
using type = integer_sequence<T, Ns...>;
|
||||
};
|
||||
|
||||
// A helper alias template to simplify creation of integer_sequence with 0, 1,
|
||||
// ..., N-1 as Ns:
|
||||
template <typename T, T N>
|
||||
using make_integer_sequence =
|
||||
typename make_integer_sequence_impl<T, 0, N>::type;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_H_
|
||||
@@ -35,7 +35,7 @@
|
||||
#ifndef CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
||||
#define CERES_PUBLIC_INTERNAL_INTEGER_SEQUENCE_ALGORITHM_H_
|
||||
|
||||
#include "integer_sequence.h"
|
||||
#include <utility>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
@@ -61,33 +61,33 @@ struct SumImpl;
|
||||
|
||||
// Strip of and sum the first number.
|
||||
template <typename T, T N, T... Ns>
|
||||
struct SumImpl<integer_sequence<T, N, Ns...>> {
|
||||
static constexpr T Value = N + SumImpl<integer_sequence<T, Ns...>>::Value;
|
||||
struct SumImpl<std::integer_sequence<T, N, Ns...>> {
|
||||
static constexpr T Value = N + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Strip of and sum the first two numbers.
|
||||
template <typename T, T N1, T N2, T... Ns>
|
||||
struct SumImpl<integer_sequence<T, N1, N2, Ns...>> {
|
||||
struct SumImpl<std::integer_sequence<T, N1, N2, Ns...>> {
|
||||
static constexpr T Value =
|
||||
N1 + N2 + SumImpl<integer_sequence<T, Ns...>>::Value;
|
||||
N1 + N2 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Strip of and sum the first four numbers.
|
||||
template <typename T, T N1, T N2, T N3, T N4, T... Ns>
|
||||
struct SumImpl<integer_sequence<T, N1, N2, N3, N4, Ns...>> {
|
||||
struct SumImpl<std::integer_sequence<T, N1, N2, N3, N4, Ns...>> {
|
||||
static constexpr T Value =
|
||||
N1 + N2 + N3 + N4 + SumImpl<integer_sequence<T, Ns...>>::Value;
|
||||
N1 + N2 + N3 + N4 + SumImpl<std::integer_sequence<T, Ns...>>::Value;
|
||||
};
|
||||
|
||||
// Only one number is left. 'Value' is just that number ('recursion' ends).
|
||||
template <typename T, T N>
|
||||
struct SumImpl<integer_sequence<T, N>> {
|
||||
struct SumImpl<std::integer_sequence<T, N>> {
|
||||
static constexpr T Value = N;
|
||||
};
|
||||
|
||||
// No number is left. 'Value' is the identity element (for sum this is zero).
|
||||
template <typename T>
|
||||
struct SumImpl<integer_sequence<T>> {
|
||||
struct SumImpl<std::integer_sequence<T>> {
|
||||
static constexpr T Value = T(0);
|
||||
};
|
||||
|
||||
@@ -129,16 +129,16 @@ template <typename T, T Sum, typename SeqIn, typename SeqOut>
|
||||
struct ExclusiveScanImpl;
|
||||
|
||||
template <typename T, T Sum, T N, T... Ns, T... Rs>
|
||||
struct ExclusiveScanImpl<T, Sum, integer_sequence<T, N, Ns...>,
|
||||
integer_sequence<T, Rs...>> {
|
||||
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T, N, Ns...>,
|
||||
std::integer_sequence<T, Rs...>> {
|
||||
using Type =
|
||||
typename ExclusiveScanImpl<T, Sum + N, integer_sequence<T, Ns...>,
|
||||
integer_sequence<T, Rs..., Sum>>::Type;
|
||||
typename ExclusiveScanImpl<T, Sum + N, std::integer_sequence<T, Ns...>,
|
||||
std::integer_sequence<T, Rs..., Sum>>::Type;
|
||||
};
|
||||
|
||||
// End of 'recursion'. The resulting type is SeqOut.
|
||||
template <typename T, T Sum, typename SeqOut>
|
||||
struct ExclusiveScanImpl<T, Sum, integer_sequence<T>, SeqOut> {
|
||||
struct ExclusiveScanImpl<T, Sum, std::integer_sequence<T>, SeqOut> {
|
||||
using Type = SeqOut;
|
||||
};
|
||||
|
||||
@@ -152,7 +152,7 @@ class ExclusiveScanT {
|
||||
|
||||
public:
|
||||
using Type =
|
||||
typename ExclusiveScanImpl<T, T(0), Seq, integer_sequence<T>>::Type;
|
||||
typename ExclusiveScanImpl<T, T(0), Seq, std::integer_sequence<T>>::Type;
|
||||
};
|
||||
|
||||
// Helper to use exclusive scan without typename.
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define CERES_PUBLIC_INTERNAL_NUMERIC_DIFF_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include "Eigen/Dense"
|
||||
#include "Eigen/StdVector"
|
||||
@@ -437,7 +438,7 @@ struct EvaluateJacobianForParameterBlocks;
|
||||
|
||||
template <typename ParameterDims, int N, int... Ns, int ParameterIdx>
|
||||
struct EvaluateJacobianForParameterBlocks<ParameterDims,
|
||||
integer_sequence<int, N, Ns...>,
|
||||
std::integer_sequence<int, N, Ns...>,
|
||||
ParameterIdx> {
|
||||
template <NumericDiffMethodType method,
|
||||
int kNumResiduals,
|
||||
@@ -468,7 +469,7 @@ struct EvaluateJacobianForParameterBlocks<ParameterDims,
|
||||
}
|
||||
|
||||
return EvaluateJacobianForParameterBlocks<ParameterDims,
|
||||
integer_sequence<int, Ns...>,
|
||||
std::integer_sequence<int, Ns...>,
|
||||
ParameterIdx + 1>::
|
||||
template Apply<method, kNumResiduals>(functor,
|
||||
residuals_at_eval_point,
|
||||
@@ -481,7 +482,7 @@ struct EvaluateJacobianForParameterBlocks<ParameterDims,
|
||||
|
||||
// End of 'recursion'. Nothing more to do.
|
||||
template <typename ParameterDims, int ParameterIdx>
|
||||
struct EvaluateJacobianForParameterBlocks<ParameterDims, integer_sequence<int>,
|
||||
struct EvaluateJacobianForParameterBlocks<ParameterDims, std::integer_sequence<int>,
|
||||
ParameterIdx> {
|
||||
template <NumericDiffMethodType method, int kNumResiduals,
|
||||
typename CostFunctor>
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#define CERES_PUBLIC_INTERNAL_PARAMETER_DIMS_H_
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#include "ceres/internal/integer_sequence.h"
|
||||
#include "ceres/internal/integer_sequence_algorithm.h"
|
||||
|
||||
namespace ceres {
|
||||
@@ -41,16 +41,16 @@ namespace internal {
|
||||
|
||||
// Checks, whether the given parameter block sizes are valid. Valid means every
|
||||
// dimension is bigger than zero.
|
||||
constexpr bool IsValidParameterDimensionSequence(integer_sequence<int>) {
|
||||
constexpr bool IsValidParameterDimensionSequence(std::integer_sequence<int>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int N, int... Ts>
|
||||
constexpr bool IsValidParameterDimensionSequence(
|
||||
integer_sequence<int, N, Ts...>) {
|
||||
std::integer_sequence<int, N, Ts...>) {
|
||||
return (N <= 0) ? false
|
||||
: IsValidParameterDimensionSequence(
|
||||
integer_sequence<int, Ts...>());
|
||||
std::integer_sequence<int, Ts...>());
|
||||
}
|
||||
|
||||
// Helper class that represents the parameter dimensions. The parameter
|
||||
@@ -66,7 +66,7 @@ constexpr bool IsValidParameterDimensionSequence(
|
||||
template <bool IsDynamic, int... Ns>
|
||||
class ParameterDims {
|
||||
public:
|
||||
using Parameters = integer_sequence<int, Ns...>;
|
||||
using Parameters = std::integer_sequence<int, Ns...>;
|
||||
|
||||
// The parameter dimensions are only valid if all parameter block dimensions
|
||||
// are greater than zero.
|
||||
@@ -82,7 +82,7 @@ class ParameterDims {
|
||||
"At least one parameter block must be specified.");
|
||||
|
||||
static constexpr int kNumParameters =
|
||||
Sum<integer_sequence<int, Ns...>>::Value;
|
||||
Sum<std::integer_sequence<int, Ns...>>::Value;
|
||||
|
||||
static constexpr int GetDim(int dim) { return params_[dim]; }
|
||||
|
||||
@@ -98,7 +98,7 @@ class ParameterDims {
|
||||
private:
|
||||
template <typename T, int... Indices>
|
||||
static inline std::array<T*, kNumParameterBlocks> GetUnpackedParameters(
|
||||
T* ptr, integer_sequence<int, Indices...>) {
|
||||
T* ptr, std::integer_sequence<int, Indices...>) {
|
||||
return std::array<T*, kNumParameterBlocks>{{ptr + Indices...}};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,19 +35,19 @@
|
||||
#include "ceres/internal/config.h"
|
||||
|
||||
#if defined(CERES_USE_OPENMP)
|
||||
# if defined(CERES_USE_CXX11_THREADS) || defined(CERES_NO_THREADS)
|
||||
# error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX11_THREADS and CERES_NO_THREADS
|
||||
# if defined(CERES_USE_CXX_THREADS) || defined(CERES_NO_THREADS)
|
||||
# error CERES_USE_OPENMP is mutually exclusive to CERES_USE_CXX_THREADS and CERES_NO_THREADS
|
||||
# endif
|
||||
#elif defined(CERES_USE_CXX11_THREADS)
|
||||
#elif defined(CERES_USE_CXX_THREADS)
|
||||
# if defined(CERES_USE_OPENMP) || defined(CERES_NO_THREADS)
|
||||
# error CERES_USE_CXX11_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX11_THREADS and CERES_NO_THREADS
|
||||
# error CERES_USE_CXX_THREADS is mutually exclusive to CERES_USE_OPENMP, CERES_USE_CXX_THREADS and CERES_NO_THREADS
|
||||
# endif
|
||||
#elif defined(CERES_NO_THREADS)
|
||||
# if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX11_THREADS)
|
||||
# error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX11_THREADS
|
||||
# if defined(CERES_USE_OPENMP) || defined(CERES_USE_CXX_THREADS)
|
||||
# error CERES_NO_THREADS is mutually exclusive to CERES_USE_OPENMP and CERES_USE_CXX_THREADS
|
||||
# endif
|
||||
#else
|
||||
# error One of CERES_USE_OPENMP, CERES_USE_CXX11_THREADS or CERES_NO_THREADS must be defined.
|
||||
# error One of CERES_USE_OPENMP, CERES_USE_CXX_THREADS or CERES_NO_THREADS must be defined.
|
||||
#endif
|
||||
|
||||
// CERES_NO_SPARSE should be automatically defined by config.h if Ceres was
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "ceres/cost_function.h"
|
||||
#include "ceres/internal/parameter_dims.h"
|
||||
@@ -47,7 +48,7 @@ namespace internal {
|
||||
template <typename Functor, typename T, int... Indices>
|
||||
inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
|
||||
T* output, std::false_type /*is_dynamic*/,
|
||||
integer_sequence<int, Indices...>) {
|
||||
std::integer_sequence<int, Indices...>) {
|
||||
static_assert(sizeof...(Indices),
|
||||
"Invalid number of parameter blocks. At least one parameter "
|
||||
"block must be specified.");
|
||||
@@ -58,7 +59,7 @@ inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
|
||||
template <typename Functor, typename T>
|
||||
inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
|
||||
T* output, std::true_type /*is_dynamic*/,
|
||||
integer_sequence<int>) {
|
||||
std::integer_sequence<int>) {
|
||||
return functor(input, output);
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ template <typename ParameterDims, typename Functor, typename T>
|
||||
inline bool VariadicEvaluateImpl(const Functor& functor, T const* const* input,
|
||||
T* output, const void* /* NOT USED */) {
|
||||
using ParameterBlockIndices =
|
||||
make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
|
||||
std::make_integer_sequence<int, ParameterDims::kNumParameterBlocks>;
|
||||
using IsDynamic = std::integral_constant<bool, ParameterDims::kIsDynamic>;
|
||||
return VariadicEvaluateImpl(functor, input, output, IsDynamic(),
|
||||
ParameterBlockIndices());
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
# Avoid 'xxx.cc has no symbols' warnings from source files which are 'empty'
|
||||
# when their enclosing #ifdefs are disabled.
|
||||
if (CERES_THREADING_MODEL STREQUAL "CXX11_THREADS")
|
||||
if (CERES_THREADING_MODEL STREQUAL "CXX_THREADS")
|
||||
set(CERES_PARALLEL_FOR_SRC parallel_for_cxx.cc thread_pool.cc)
|
||||
elseif (CERES_THREADING_MODEL STREQUAL "OPENMP")
|
||||
set(CERES_PARALLEL_FOR_SRC parallel_for_openmp.cc)
|
||||
@@ -397,7 +397,6 @@ if (BUILD_TESTING AND GFLAGS)
|
||||
${Ceres_SOURCE_DIR}/data)
|
||||
endmacro (CERES_TEST)
|
||||
|
||||
ceres_test(algorithm)
|
||||
ceres_test(array_utils)
|
||||
ceres_test(array_selector)
|
||||
ceres_test(autodiff)
|
||||
@@ -442,7 +441,6 @@ if (BUILD_TESTING AND GFLAGS)
|
||||
ceres_test(implicit_schur_complement)
|
||||
ceres_test(inner_product_computer)
|
||||
ceres_test(invert_psd_matrix)
|
||||
ceres_test(integer_sequence)
|
||||
ceres_test(integer_sequence_algorithm)
|
||||
ceres_test(is_close)
|
||||
ceres_test(iterative_refiner)
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
// Copyright 2017 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ceres/internal/algorithm.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(EqualTest, DefaultComparisonRandomAccess) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> v2 = v1;
|
||||
std::vector<int> v3 = {1, 2};
|
||||
std::vector<int> v4 = {1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, DefaultComparison) {
|
||||
std::list<int> lst1{1, 2, 3};
|
||||
std::list<int> lst2 = lst1;
|
||||
std::list<int> lst3{1, 2};
|
||||
std::list<int> lst4{1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(ceres::internal::equal(
|
||||
lst1.begin(), lst1.end(), lst2.begin(), lst2.end()));
|
||||
EXPECT_FALSE(ceres::internal::equal(
|
||||
lst1.begin(), lst1.end(), lst3.begin(), lst3.end()));
|
||||
EXPECT_FALSE(ceres::internal::equal(
|
||||
lst1.begin(), lst1.end(), lst4.begin(), lst4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, EmptyRange) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> empty1;
|
||||
std::vector<int> empty2;
|
||||
|
||||
EXPECT_FALSE(ceres::internal::equal(
|
||||
v1.begin(), v1.end(), empty1.begin(), empty1.end()));
|
||||
EXPECT_FALSE(ceres::internal::equal(
|
||||
empty1.begin(), empty1.end(), v1.begin(), v1.end()));
|
||||
EXPECT_TRUE(ceres::internal::equal(
|
||||
empty1.begin(), empty1.end(), empty2.begin(), empty2.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MixedIterTypes) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::list<int> lst1{v1.begin(), v1.end()};
|
||||
std::list<int> lst2{1, 2, 4};
|
||||
std::list<int> lst3{1, 2};
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), lst1.begin(), lst1.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), lst2.begin(), lst2.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), lst3.begin(), lst3.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MixedValueTypes) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<char> v2{1, 2, 3};
|
||||
std::vector<char> v3{1, 2};
|
||||
std::vector<char> v4{1, 2, 4};
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, WeirdIterators) {
|
||||
std::vector<bool> v1{true, false};
|
||||
std::vector<bool> v2 = v1;
|
||||
std::vector<bool> v3{true};
|
||||
std::vector<bool> v4{true, true, true};
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v2.begin(), v2.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v3.begin(), v3.end()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v4.begin(), v4.end()));
|
||||
}
|
||||
|
||||
TEST(EqualTest, CustomComparison) {
|
||||
int n[] = {1, 2, 3, 4};
|
||||
std::vector<int*> v1{&n[0], &n[1], &n[2]};
|
||||
std::vector<int*> v2 = v1;
|
||||
std::vector<int*> v3{&n[0], &n[1], &n[3]};
|
||||
std::vector<int*> v4{&n[0], &n[1]};
|
||||
|
||||
auto eq = [](int* a, int* b) { return *a == *b; };
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), eq));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v3.begin(), v3.end(), eq));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v4.begin(), v4.end(), eq));
|
||||
}
|
||||
|
||||
TEST(EqualTest, MoveOnlyPredicate) {
|
||||
std::vector<int> v1{1, 2, 3};
|
||||
std::vector<int> v2{4, 5, 6};
|
||||
|
||||
// move-only equality predicate
|
||||
struct Eq {
|
||||
Eq() = default;
|
||||
Eq(Eq&&) = default;
|
||||
Eq(const Eq&) = delete;
|
||||
Eq& operator=(const Eq&) = delete;
|
||||
bool operator()(const int a, const int b) const { return a == b; }
|
||||
};
|
||||
|
||||
EXPECT_TRUE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v1.begin(), v1.end(), Eq()));
|
||||
EXPECT_FALSE(
|
||||
ceres::internal::equal(v1.begin(), v1.end(), v2.begin(), v2.end(), Eq()));
|
||||
}
|
||||
|
||||
struct CountingTrivialPred {
|
||||
int* count;
|
||||
bool operator()(int, int) const {
|
||||
++*count;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(EqualTest, RandomAccessComplexity) {
|
||||
std::vector<int> v1{1, 1, 3};
|
||||
std::vector<int> v2 = v1;
|
||||
std::vector<int> v3{1, 2};
|
||||
|
||||
do {
|
||||
int count = 0;
|
||||
ceres::internal::equal(v1.begin(),
|
||||
v1.end(),
|
||||
v2.begin(),
|
||||
v2.end(),
|
||||
CountingTrivialPred{&count});
|
||||
EXPECT_LE(count, 3);
|
||||
} while (std::next_permutation(v2.begin(), v2.end()));
|
||||
|
||||
int count = 0;
|
||||
ceres::internal::equal(
|
||||
v1.begin(), v1.end(), v3.begin(), v3.end(), CountingTrivialPred{&count});
|
||||
EXPECT_EQ(count, 0);
|
||||
}
|
||||
} // namespace
|
||||
@@ -31,7 +31,7 @@
|
||||
// This include must come before any #ifndef check on Ceres compile options.
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
@@ -304,4 +304,4 @@ TEST(ConcurrentQueue, StopAndEnableWaiters) {
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
@@ -34,9 +34,9 @@ namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
void ContextImpl::EnsureMinimumThreads(int num_threads) {
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
thread_pool.Resize(num_threads);
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
|
||||
#include "ceres/context.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
#include "ceres/thread_pool.h"
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
@@ -51,14 +51,14 @@ class ContextImpl : public Context {
|
||||
|
||||
virtual ~ContextImpl() {}
|
||||
|
||||
// When compiled with C++11 threading support, resize the thread pool to have
|
||||
// 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.
|
||||
void EnsureMinimumThreads(int num_threads);
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
ThreadPool thread_pool;
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -31,39 +31,40 @@
|
||||
#include "ceres/internal/integer_sequence_algorithm.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Unit tests for summation of integer sequence.
|
||||
static_assert(Sum<integer_sequence<int>>::Value == 0,
|
||||
static_assert(Sum<std::integer_sequence<int>>::Value == 0,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
static_assert(Sum<integer_sequence<int, 2>>::Value == 2,
|
||||
static_assert(Sum<std::integer_sequence<int, 2>>::Value == 2,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
static_assert(Sum<integer_sequence<int, 2, 3>>::Value == 5,
|
||||
static_assert(Sum<std::integer_sequence<int, 2, 3>>::Value == 5,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
static_assert(Sum<integer_sequence<int, 2, 3, 10>>::Value == 15,
|
||||
static_assert(Sum<std::integer_sequence<int, 2, 3, 10>>::Value == 15,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
static_assert(Sum<integer_sequence<int, 2, 3, 10, 4>>::Value == 19,
|
||||
static_assert(Sum<std::integer_sequence<int, 2, 3, 10, 4>>::Value == 19,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
static_assert(Sum<integer_sequence<int, 2, 3, 10, 4, 1>>::Value == 20,
|
||||
static_assert(Sum<std::integer_sequence<int, 2, 3, 10, 4, 1>>::Value == 20,
|
||||
"Unit test of summing up an integer sequence failed.");
|
||||
|
||||
// Unit tests for exclusive scan of integer sequence.
|
||||
static_assert(std::is_same<ExclusiveScan<integer_sequence<int>>,
|
||||
integer_sequence<int>>::value,
|
||||
static_assert(std::is_same<ExclusiveScan<std::integer_sequence<int>>,
|
||||
std::integer_sequence<int>>::value,
|
||||
"Unit test of calculating the exclusive scan of an integer "
|
||||
"sequence failed.");
|
||||
static_assert(std::is_same<ExclusiveScan<integer_sequence<int, 2>>,
|
||||
integer_sequence<int, 0>>::value,
|
||||
static_assert(std::is_same<ExclusiveScan<std::integer_sequence<int, 2>>,
|
||||
std::integer_sequence<int, 0>>::value,
|
||||
"Unit test of calculating the exclusive scan of an integer "
|
||||
"sequence failed.");
|
||||
static_assert(std::is_same<ExclusiveScan<integer_sequence<int, 2, 1>>,
|
||||
integer_sequence<int, 0, 2>>::value,
|
||||
static_assert(std::is_same<ExclusiveScan<std::integer_sequence<int, 2, 1>>,
|
||||
std::integer_sequence<int, 0, 2>>::value,
|
||||
"Unit test of calculating the exclusive scan of an integer "
|
||||
"sequence failed.");
|
||||
static_assert(std::is_same<ExclusiveScan<integer_sequence<int, 2, 1, 10>>,
|
||||
integer_sequence<int, 0, 2, 3>>::value,
|
||||
static_assert(std::is_same<ExclusiveScan<std::integer_sequence<int, 2, 1, 10>>,
|
||||
std::integer_sequence<int, 0, 2, 3>>::value,
|
||||
"Unit test of calculating the exclusive scan of an integer "
|
||||
"sequence failed.");
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
// Ceres Solver - A fast non-linear least squares minimizer
|
||||
// Copyright 2018 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: jodebo_beck@gmx.de (Johannes Beck)
|
||||
|
||||
#include "ceres/internal/integer_sequence.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Unit test for integer_sequence<...>::value_type
|
||||
static_assert(std::is_same<integer_sequence<unsigned int, 0>::value_type,
|
||||
unsigned int>::value,
|
||||
"Unit test of integer sequence value type failed.");
|
||||
|
||||
// Unit tests for make_integer_sequence
|
||||
static_assert(
|
||||
std::is_same<make_integer_sequence<int, 0>, integer_sequence<int>>::value,
|
||||
"Unit test of make integer sequence failed.");
|
||||
static_assert(std::is_same<make_integer_sequence<int, 1>,
|
||||
integer_sequence<int, 0>>::value,
|
||||
"Unit test of make integer sequence failed.");
|
||||
static_assert(std::is_same<make_integer_sequence<int, 2>,
|
||||
integer_sequence<int, 0, 1>>::value,
|
||||
"Unit test of make integer sequence failed.");
|
||||
static_assert(std::is_same<make_integer_sequence<int, 3>,
|
||||
integer_sequence<int, 0, 1, 2>>::value,
|
||||
"Unit test of make integer sequence failed.");
|
||||
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
@@ -31,7 +31,7 @@
|
||||
// This include must come before any #ifndef check on Ceres compile options.
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
|
||||
#include "ceres/parallel_for.h"
|
||||
|
||||
@@ -244,4 +244,4 @@ void ParallelFor(ContextImpl* context,
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
@@ -26,28 +26,29 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Is valid parameter dims unit test
|
||||
static_assert(IsValidParameterDimensionSequence(integer_sequence<int>()) ==
|
||||
static_assert(IsValidParameterDimensionSequence(std::integer_sequence<int>()) ==
|
||||
true,
|
||||
"Unit test of is valid parameter dimension sequence failed.");
|
||||
static_assert(
|
||||
IsValidParameterDimensionSequence(integer_sequence<int, 2, 1>()) == true,
|
||||
IsValidParameterDimensionSequence(std::integer_sequence<int, 2, 1>()) == true,
|
||||
"Unit test of is valid parameter dimension sequence failed.");
|
||||
static_assert(
|
||||
IsValidParameterDimensionSequence(integer_sequence<int, 0, 1>()) == false,
|
||||
IsValidParameterDimensionSequence(std::integer_sequence<int, 0, 1>()) == false,
|
||||
"Unit test of is valid parameter dimension sequence failed.");
|
||||
static_assert(
|
||||
IsValidParameterDimensionSequence(integer_sequence<int, 3, 0>()) == false,
|
||||
IsValidParameterDimensionSequence(std::integer_sequence<int, 3, 0>()) == false,
|
||||
"Unit test of is valid parameter dimension sequence failed.");
|
||||
|
||||
// Static parameter dims unit test
|
||||
static_assert(
|
||||
std::is_same<StaticParameterDims<4, 2, 1>::Parameters,
|
||||
integer_sequence<int, 4, 2, 1>>::value == true,
|
||||
std::integer_sequence<int, 4, 2, 1>>::value == true,
|
||||
"Unit test of type 'parameters' for static parameter dims failed.");
|
||||
|
||||
static_assert(StaticParameterDims<4, 2, 1>::kIsValid == true,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
// residual jacobians are written directly into their final position in the
|
||||
// block sparse matrix by the user's CostFunction; there is no copying.
|
||||
//
|
||||
// The evaluation is threaded with OpenMP or C++11 threads.
|
||||
// The evaluation is threaded with OpenMP or C++ threads.
|
||||
//
|
||||
// The EvaluatePreparer and JacobianWriter interfaces are as follows:
|
||||
//
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "ceres/internal/integer_sequence_algorithm.h"
|
||||
@@ -69,7 +70,7 @@ class MockCostFunctionBase : public SizedCostFunction<kNumResiduals, Ns...> {
|
||||
bool Evaluate(double const* const* parameters,
|
||||
double* residuals,
|
||||
double** jacobians) const final {
|
||||
const int kNumParameters = Sum<integer_sequence<int, Ns...>>::Value;
|
||||
const int kNumParameters = Sum<std::integer_sequence<int, Ns...>>::Value;
|
||||
|
||||
for (int i = 0; i < kNumResiduals; ++i) {
|
||||
residuals[i] = kNumResiduals + kNumParameters;
|
||||
|
||||
@@ -43,28 +43,6 @@ namespace internal {
|
||||
|
||||
using std::string;
|
||||
|
||||
// va_copy() was defined in the C99 standard. However, it did not appear in the
|
||||
// C++ standard until C++11. This means that if Ceres is being compiled with a
|
||||
// strict pre-C++11 standard (e.g. -std=c++03), va_copy() will NOT be defined,
|
||||
// as we are using the C++ compiler (it would however be defined if we were
|
||||
// using the C compiler). Note however that both GCC & Clang will in fact
|
||||
// define va_copy() when compiling for C++ if the C++ standard is not explicitly
|
||||
// specified (i.e. no -std=c++<XX> arg), even though it should not strictly be
|
||||
// defined unless -std=c++11 (or greater) was passed.
|
||||
#if !defined(va_copy)
|
||||
#if defined (__GNUC__)
|
||||
// On GCC/Clang, if va_copy() is not defined (C++ standard < C++11 explicitly
|
||||
// specified), use the internal __va_copy() version, which should be present
|
||||
// in even very old GCC versions.
|
||||
#define va_copy(d, s) __va_copy(d, s)
|
||||
#else
|
||||
// Some older versions of MSVC do not have va_copy(), in which case define it.
|
||||
// Although this is required for older MSVC versions, it should also work for
|
||||
// other non-GCC/Clang compilers which also do not defined va_copy().
|
||||
#define va_copy(d, s) ((d) = (s))
|
||||
#endif // defined (__GNUC__)
|
||||
#endif // !defined(va_copy)
|
||||
|
||||
void StringAppendV(string* dst, const char* format, va_list ap) {
|
||||
// First try with a small fixed size buffer
|
||||
char space[1024];
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
// This include must come before any #ifndef check on Ceres compile options.
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
|
||||
#include "ceres/thread_pool.h"
|
||||
|
||||
@@ -113,4 +113,4 @@ void ThreadPool::Stop() {
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
// This include must come before any #ifndef check on Ceres compile options.
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
|
||||
#include "ceres/thread_pool.h"
|
||||
|
||||
@@ -197,4 +197,4 @@ TEST(ThreadPool, Resize) {
|
||||
} // namespace internal
|
||||
} // namespace ceres
|
||||
|
||||
#endif // CERES_USE_CXX11_THREADS
|
||||
#endif // CERES_USE_CXX_THREADS
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace internal {
|
||||
|
||||
ThreadTokenProvider::ThreadTokenProvider(int num_threads) {
|
||||
(void)num_threads;
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
for (int i = 0; i < num_threads; i++) {
|
||||
pool_.Push(i);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ int ThreadTokenProvider::Acquire() {
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
int thread_id;
|
||||
CHECK(pool_.Wait(&thread_id));
|
||||
return thread_id;
|
||||
@@ -66,7 +66,7 @@ int ThreadTokenProvider::Acquire() {
|
||||
|
||||
void ThreadTokenProvider::Release(int thread_id) {
|
||||
(void)thread_id;
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
pool_.Push(thread_id);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
#include "ceres/internal/config.h"
|
||||
#include "ceres/internal/port.h"
|
||||
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
#include "ceres/concurrent_queue.h"
|
||||
#endif
|
||||
|
||||
namespace ceres {
|
||||
namespace internal {
|
||||
|
||||
// Helper for C++11 thread number identification that is similar to
|
||||
// omp_get_thread_num() behaviour. This is necessary to support C++11
|
||||
// Helper for C++ thread number identification that is similar to
|
||||
// omp_get_thread_num() behaviour. This is necessary to support C++
|
||||
// threading with a sequential thread id. This is used to access preallocated
|
||||
// resources in the parallelized code parts. The sequence of tokens varies from
|
||||
// 0 to num_threads - 1 that can be acquired to identify the thread in a thread
|
||||
@@ -78,7 +78,7 @@ class ThreadTokenProvider {
|
||||
void Release(int thread_id);
|
||||
|
||||
private:
|
||||
#ifdef CERES_USE_CXX11_THREADS
|
||||
#ifdef CERES_USE_CXX_THREADS
|
||||
// This queue initially holds a sequence from 0..num_threads-1. Every
|
||||
// Acquire() call the first number is removed from here. When the token is not
|
||||
// needed anymore it shall be given back with corresponding Release()
|
||||
|
||||
Reference in New Issue
Block a user