ceres::internal::FixedArray -> absl::FixedArray
Ceres Solver was using an old forked version of FixedArray,
now that we are using absl, we can use the official version
that ships with it.
Change-Id: Ic88d7f6e8a49b928d611f7cbb04172452b322b01
diff --git a/include/ceres/autodiff_first_order_function.h b/include/ceres/autodiff_first_order_function.h
index 6cd1b13..2dca8f3 100644
--- a/include/ceres/autodiff_first_order_function.h
+++ b/include/ceres/autodiff_first_order_function.h
@@ -34,9 +34,9 @@
#include <memory>
#include <type_traits>
+#include "absl/container/fixed_array.h"
#include "ceres/first_order_function.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/jet.h"
#include "ceres/types.h"
@@ -131,7 +131,7 @@
}
using JetT = Jet<double, kNumParameters>;
- internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(kNumParameters);
+ absl::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(kNumParameters);
for (int i = 0; i < kNumParameters; ++i) {
x[i].a = parameters[i];
x[i].v.setZero();
diff --git a/include/ceres/dynamic_autodiff_cost_function.h b/include/ceres/dynamic_autodiff_cost_function.h
index 7b4e876..7efdad0 100644
--- a/include/ceres/dynamic_autodiff_cost_function.h
+++ b/include/ceres/dynamic_autodiff_cost_function.h
@@ -38,9 +38,9 @@
#include <type_traits>
#include <vector>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "ceres/dynamic_cost_function.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/jet.h"
#include "ceres/types.h"
@@ -149,14 +149,13 @@
// Allocate scratch space for the strided evaluation.
using JetT = Jet<double, Stride>;
- internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> input_jets(
- num_parameters);
- internal::FixedArray<JetT, (256 * 7) / sizeof(JetT)> output_jets(
+ absl::FixedArray<JetT, (256 * 7) / sizeof(JetT)> input_jets(num_parameters);
+ absl::FixedArray<JetT, (256 * 7) / sizeof(JetT)> output_jets(
num_residuals());
// Make the parameter pack that is sent to the functor (reused).
- internal::FixedArray<Jet<double, Stride>*> jet_parameters(
- num_parameter_blocks, nullptr);
+ absl::FixedArray<Jet<double, Stride>*> jet_parameters(num_parameter_blocks,
+ nullptr);
int num_active_parameters = 0;
// To handle constant parameters between non-constant parameter blocks, the
diff --git a/include/ceres/dynamic_cost_function_to_functor.h b/include/ceres/dynamic_cost_function_to_functor.h
index 331d367..bc2fd3b 100644
--- a/include/ceres/dynamic_cost_function_to_functor.h
+++ b/include/ceres/dynamic_cost_function_to_functor.h
@@ -36,11 +36,11 @@
#include <numeric>
#include <vector>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "ceres/dynamic_cost_function.h"
#include "ceres/internal/disable_warnings.h"
#include "ceres/internal/export.h"
-#include "ceres/internal/fixed_array.h"
namespace ceres {
@@ -130,11 +130,11 @@
const int num_parameters = std::accumulate(
parameter_block_sizes.begin(), parameter_block_sizes.end(), 0);
- internal::FixedArray<double> parameters(num_parameters);
- internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
- internal::FixedArray<double> jacobians(num_residuals * num_parameters);
- internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
- internal::FixedArray<double> residuals(num_residuals);
+ absl::FixedArray<double> parameters(num_parameters);
+ absl::FixedArray<double*> parameter_blocks(num_parameter_blocks);
+ absl::FixedArray<double> jacobians(num_residuals * num_parameters);
+ absl::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
+ absl::FixedArray<double> residuals(num_residuals);
// Build a set of arrays to get the residuals and jacobians from
// the CostFunction wrapped by this functor.
diff --git a/include/ceres/gradient_checker.h b/include/ceres/gradient_checker.h
index 765d53c..7490cd6 100644
--- a/include/ceres/gradient_checker.h
+++ b/include/ceres/gradient_checker.h
@@ -43,7 +43,6 @@
#include "ceres/internal/disable_warnings.h"
#include "ceres/internal/eigen.h"
#include "ceres/internal/export.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/manifold.h"
namespace ceres {
diff --git a/include/ceres/internal/array_selector.h b/include/ceres/internal/array_selector.h
index 9480146..100b80d 100644
--- a/include/ceres/internal/array_selector.h
+++ b/include/ceres/internal/array_selector.h
@@ -35,7 +35,8 @@
#include <array>
#include <vector>
-#include "ceres/internal/fixed_array.h"
+#include "absl/container/fixed_array.h"
+#include "absl/log/check.h"
#include "ceres/types.h"
namespace ceres::internal {
@@ -47,7 +48,7 @@
// Three different containers are selected in different scenarios:
//
// num_elements == DYNAMIC:
-// -> ceres::internal::FixedArray<T, max_stack_size>(size)
+// -> absl::FixedArray<T, max_stack_size>(size)
// num_elements != DYNAMIC && num_elements <= max_stack_size
// -> std::array<T,num_elements>
@@ -71,9 +72,9 @@
max_num_elements_on_stack,
true,
fits_on_stack>
- : ceres::internal::FixedArray<T, max_num_elements_on_stack> {
+ : absl::FixedArray<T, max_num_elements_on_stack> {
explicit ArraySelector(int s)
- : ceres::internal::FixedArray<T, max_num_elements_on_stack>(s) {}
+ : absl::FixedArray<T, max_num_elements_on_stack>(s) {}
};
template <typename T, int num_elements, int max_num_elements_on_stack>
diff --git a/include/ceres/internal/fixed_array.h b/include/ceres/internal/fixed_array.h
deleted file mode 100644
index 68193c9..0000000
--- a/include/ceres/internal/fixed_array.h
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright 2018 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: fixed_array.h
-// -----------------------------------------------------------------------------
-//
-// A `FixedArray<T>` represents a non-resizable array of `T` where the length of
-// the array can be determined at run-time. It is a good replacement for
-// non-standard and deprecated uses of `alloca()` and variable length arrays
-// within the GCC extension. (See
-// https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
-//
-// `FixedArray` allocates small arrays inline, keeping performance fast by
-// avoiding heap operations. It also helps reduce the chances of
-// accidentally overflowing your stack if large input is passed to
-// your function.
-
-#ifndef CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
-#define CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
-
-#include <Eigen/Core> // For Eigen::aligned_allocator
-#include <algorithm>
-#include <cstddef>
-#include <initializer_list>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <tuple>
-#include <type_traits>
-
-#include "absl/log/check.h"
-#include "ceres/internal/memory.h"
-
-namespace ceres::internal {
-
-constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
-
-// The default fixed array allocator.
-//
-// As one can not easily detect if a struct contains or inherits from a fixed
-// size Eigen type, to be safe the Eigen::aligned_allocator is used by default.
-// But trivial types can never contain Eigen types, so std::allocator is used to
-// safe some heap memory.
-template <typename T>
-using FixedArrayDefaultAllocator =
- typename std::conditional<std::is_trivial<T>::value,
- std::allocator<T>,
- Eigen::aligned_allocator<T>>::type;
-
-// -----------------------------------------------------------------------------
-// FixedArray
-// -----------------------------------------------------------------------------
-//
-// A `FixedArray` provides a run-time fixed-size array, allocating a small array
-// inline for efficiency.
-//
-// Most users should not specify an `inline_elements` argument and let
-// `FixedArray` automatically determine the number of elements
-// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
-// `FixedArray` implementation will use inline storage for arrays with a
-// length <= `inline_elements`.
-//
-// Note that a `FixedArray` constructed with a `size_type` argument will
-// default-initialize its values by leaving trivially constructible types
-// uninitialized (e.g. int, int[4], double), and others default-constructed.
-// This matches the behavior of c-style arrays and `std::array`, but not
-// `std::vector`.
-//
-// Note that `FixedArray` does not provide a public allocator; if it requires a
-// heap allocation, it will do so with global `::operator new[]()` and
-// `::operator delete[]()`, even if T provides class-scope overrides for these
-// operators.
-template <typename T,
- size_t N = kFixedArrayUseDefault,
- typename A = FixedArrayDefaultAllocator<T>>
-class FixedArray {
- static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
- "Arrays with unknown bounds cannot be used with FixedArray.");
-
- static constexpr size_t kInlineBytesDefault = 256;
-
- using AllocatorTraits = std::allocator_traits<A>;
- // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
- // but this seems to be mostly pedantic.
- template <typename Iterator>
- using EnableIfForwardIterator = typename std::enable_if<std::is_convertible<
- typename std::iterator_traits<Iterator>::iterator_category,
- std::forward_iterator_tag>::value>::type;
- static constexpr bool DefaultConstructorIsNonTrivial() {
- return !std::is_trivially_default_constructible<StorageElement>::value;
- }
-
- public:
- using allocator_type = typename AllocatorTraits::allocator_type;
- using value_type = typename AllocatorTraits::value_type;
- using pointer = typename AllocatorTraits::pointer;
- using const_pointer = typename AllocatorTraits::const_pointer;
- using reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename AllocatorTraits::size_type;
- using difference_type = typename AllocatorTraits::difference_type;
- using iterator = pointer;
- using const_iterator = const_pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-
- static constexpr size_type inline_elements =
- (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
- : static_cast<size_type>(N));
-
- FixedArray(const FixedArray& other,
- const allocator_type& a = allocator_type())
- : FixedArray(other.begin(), other.end(), a) {}
-
- FixedArray(FixedArray&& other, const allocator_type& a = allocator_type())
- : FixedArray(std::make_move_iterator(other.begin()),
- std::make_move_iterator(other.end()),
- a) {}
-
- // Creates an array object that can store `n` elements.
- // Note that trivially constructible elements will be uninitialized.
- explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
- : storage_(n, a) {
- if (DefaultConstructorIsNonTrivial()) {
- ConstructRange(storage_.alloc(), storage_.begin(), storage_.end());
- }
- }
-
- // Creates an array initialized with `n` copies of `val`.
- FixedArray(size_type n,
- const value_type& val,
- const allocator_type& a = allocator_type())
- : storage_(n, a) {
- ConstructRange(storage_.alloc(), storage_.begin(), storage_.end(), val);
- }
-
- // Creates an array initialized with the size and contents of `init_list`.
- FixedArray(std::initializer_list<value_type> init_list,
- const allocator_type& a = allocator_type())
- : FixedArray(init_list.begin(), init_list.end(), a) {}
-
- // Creates an array initialized with the elements from the input
- // range. The array's size will always be `std::distance(first, last)`.
- // REQUIRES: Iterator must be a forward_iterator or better.
- template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
- FixedArray(Iterator first,
- Iterator last,
- const allocator_type& a = allocator_type())
- : storage_(std::distance(first, last), a) {
- CopyRange(storage_.alloc(), storage_.begin(), first, last);
- }
-
- ~FixedArray() noexcept {
- for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
- AllocatorTraits::destroy(storage_.alloc(), cur);
- }
- }
-
- // Assignments are deleted because they break the invariant that the size of a
- // `FixedArray` never changes.
- void operator=(FixedArray&&) = delete;
- void operator=(const FixedArray&) = delete;
-
- // FixedArray::size()
- //
- // Returns the length of the fixed array.
- size_type size() const { return storage_.size(); }
-
- // FixedArray::max_size()
- //
- // Returns the largest possible value of `std::distance(begin(), end())` for a
- // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
- // over the number of bytes taken by T.
- constexpr size_type max_size() const {
- return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
- }
-
- // FixedArray::empty()
- //
- // Returns whether or not the fixed array is empty.
- bool empty() const { return size() == 0; }
-
- // FixedArray::memsize()
- //
- // Returns the memory size of the fixed array in bytes.
- size_t memsize() const { return size() * sizeof(value_type); }
-
- // FixedArray::data()
- //
- // Returns a const T* pointer to elements of the `FixedArray`. This pointer
- // can be used to access (but not modify) the contained elements.
- const_pointer data() const { return AsValueType(storage_.begin()); }
-
- // Overload of FixedArray::data() to return a T* pointer to elements of the
- // fixed array. This pointer can be used to access and modify the contained
- // elements.
- pointer data() { return AsValueType(storage_.begin()); }
-
- // FixedArray::operator[]
- //
- // Returns a reference the ith element of the fixed array.
- // REQUIRES: 0 <= i < size()
- reference operator[](size_type i) {
- DCHECK_LT(i, size());
- return data()[i];
- }
-
- // Overload of FixedArray::operator()[] to return a const reference to the
- // ith element of the fixed array.
- // REQUIRES: 0 <= i < size()
- const_reference operator[](size_type i) const {
- DCHECK_LT(i, size());
- return data()[i];
- }
-
- // FixedArray::front()
- //
- // Returns a reference to the first element of the fixed array.
- reference front() { return *begin(); }
-
- // Overload of FixedArray::front() to return a reference to the first element
- // of a fixed array of const values.
- const_reference front() const { return *begin(); }
-
- // FixedArray::back()
- //
- // Returns a reference to the last element of the fixed array.
- reference back() { return *(end() - 1); }
-
- // Overload of FixedArray::back() to return a reference to the last element
- // of a fixed array of const values.
- const_reference back() const { return *(end() - 1); }
-
- // FixedArray::begin()
- //
- // Returns an iterator to the beginning of the fixed array.
- iterator begin() { return data(); }
-
- // Overload of FixedArray::begin() to return a const iterator to the
- // beginning of the fixed array.
- const_iterator begin() const { return data(); }
-
- // FixedArray::cbegin()
- //
- // Returns a const iterator to the beginning of the fixed array.
- const_iterator cbegin() const { return begin(); }
-
- // FixedArray::end()
- //
- // Returns an iterator to the end of the fixed array.
- iterator end() { return data() + size(); }
-
- // Overload of FixedArray::end() to return a const iterator to the end of the
- // fixed array.
- const_iterator end() const { return data() + size(); }
-
- // FixedArray::cend()
- //
- // Returns a const iterator to the end of the fixed array.
- const_iterator cend() const { return end(); }
-
- // FixedArray::rbegin()
- //
- // Returns a reverse iterator from the end of the fixed array.
- reverse_iterator rbegin() { return reverse_iterator(end()); }
-
- // Overload of FixedArray::rbegin() to return a const reverse iterator from
- // the end of the fixed array.
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator(end());
- }
-
- // FixedArray::crbegin()
- //
- // Returns a const reverse iterator from the end of the fixed array.
- const_reverse_iterator crbegin() const { return rbegin(); }
-
- // FixedArray::rend()
- //
- // Returns a reverse iterator from the beginning of the fixed array.
- reverse_iterator rend() { return reverse_iterator(begin()); }
-
- // Overload of FixedArray::rend() for returning a const reverse iterator
- // from the beginning of the fixed array.
- const_reverse_iterator rend() const {
- return const_reverse_iterator(begin());
- }
-
- // FixedArray::crend()
- //
- // Returns a reverse iterator from the beginning of the fixed array.
- const_reverse_iterator crend() const { return rend(); }
-
- // FixedArray::fill()
- //
- // Assigns the given `value` to all elements in the fixed array.
- void fill(const value_type& val) { std::fill(begin(), end(), val); }
-
- // Relational operators. Equality operators are elementwise using
- // `operator==`, while order operators order FixedArrays lexicographically.
- friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
- return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
-
- friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(lhs == rhs);
- }
-
- friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
- return std::lexicographical_compare(
- lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
- }
-
- friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
- return rhs < lhs;
- }
-
- friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(rhs < lhs);
- }
-
- friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
- return !(lhs < rhs);
- }
-
- private:
- // StorageElement
- //
- // For FixedArrays with a C-style-array value_type, StorageElement is a POD
- // wrapper struct called StorageElementWrapper that holds the value_type
- // instance inside. This is needed for construction and destruction of the
- // entire array regardless of how many dimensions it has. For all other cases,
- // StorageElement is just an alias of value_type.
- //
- // Maintainer's Note: The simpler solution would be to simply wrap value_type
- // in a struct whether it's an array or not. That causes some paranoid
- // diagnostics to misfire, believing that 'data()' returns a pointer to a
- // single element, rather than the packed array that it really is.
- // e.g.:
- //
- // FixedArray<char> buf(1);
- // sprintf(buf.data(), "foo");
- //
- // error: call to int __builtin___sprintf_chk(etc...)
- // will always overflow destination buffer [-Werror]
- //
- template <typename OuterT,
- typename InnerT = typename std::remove_extent<OuterT>::type,
- size_t InnerN = std::extent<OuterT>::value>
- struct StorageElementWrapper {
- InnerT array[InnerN];
- };
-
- using StorageElement =
- typename std::conditional<std::is_array<value_type>::value,
- StorageElementWrapper<value_type>,
- value_type>::type;
-
- static pointer AsValueType(pointer ptr) { return ptr; }
- static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
- return std::addressof(ptr->array);
- }
-
- static_assert(sizeof(StorageElement) == sizeof(value_type));
- static_assert(alignof(StorageElement) == alignof(value_type));
-
- class NonEmptyInlinedStorage {
- public:
- StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
- void AnnotateConstruct(size_type) {}
- void AnnotateDestruct(size_type) {}
-
- // #ifdef ADDRESS_SANITIZER
- // void* RedzoneBegin() { return &redzone_begin_; }
- // void* RedzoneEnd() { return &redzone_end_ + 1; }
- // #endif // ADDRESS_SANITIZER
-
- private:
- // ADDRESS_SANITIZER_REDZONE(redzone_begin_);
- alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
- // ADDRESS_SANITIZER_REDZONE(redzone_end_);
- };
-
- class EmptyInlinedStorage {
- public:
- StorageElement* data() { return nullptr; }
- void AnnotateConstruct(size_type) {}
- void AnnotateDestruct(size_type) {}
- };
-
- using InlinedStorage =
- typename std::conditional<inline_elements == 0,
- EmptyInlinedStorage,
- NonEmptyInlinedStorage>::type;
-
- // Storage
- //
- // An instance of Storage manages the inline and out-of-line memory for
- // instances of FixedArray. This guarantees that even when construction of
- // individual elements fails in the FixedArray constructor body, the
- // destructor for Storage will still be called and out-of-line memory will be
- // properly deallocated.
- //
- class Storage : public InlinedStorage {
- public:
- Storage(size_type n, const allocator_type& a)
- : size_alloc_(n, a), data_(InitializeData()) {}
-
- ~Storage() noexcept {
- if (UsingInlinedStorage(size())) {
- InlinedStorage::AnnotateDestruct(size());
- } else {
- AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
- }
- }
-
- size_type size() const { return std::get<0>(size_alloc_); }
- StorageElement* begin() const { return data_; }
- StorageElement* end() const { return begin() + size(); }
- allocator_type& alloc() { return std::get<1>(size_alloc_); }
-
- private:
- static bool UsingInlinedStorage(size_type n) {
- return n <= inline_elements;
- }
-
- StorageElement* InitializeData() {
- if (UsingInlinedStorage(size())) {
- InlinedStorage::AnnotateConstruct(size());
- return InlinedStorage::data();
- } else {
- return reinterpret_cast<StorageElement*>(
- AllocatorTraits::allocate(alloc(), size()));
- }
- }
-
- // Using std::tuple and not absl::CompressedTuple, as it has a lot of
- // dependencies to other absl headers.
- std::tuple<size_type, allocator_type> size_alloc_;
- StorageElement* data_;
- };
-
- Storage storage_;
-};
-
-template <typename T, size_t N, typename A>
-constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
-
-template <typename T, size_t N, typename A>
-constexpr typename FixedArray<T, N, A>::size_type
- FixedArray<T, N, A>::inline_elements;
-
-} // namespace ceres::internal
-
-#endif // CERES_PUBLIC_INTERNAL_FIXED_ARRAY_H_
diff --git a/include/ceres/internal/numeric_diff.h b/include/ceres/internal/numeric_diff.h
index 4031631..976b27f 100644
--- a/include/ceres/internal/numeric_diff.h
+++ b/include/ceres/internal/numeric_diff.h
@@ -40,9 +40,9 @@
#include "Eigen/Dense"
#include "Eigen/StdVector"
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "ceres/cost_function.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/internal/variadic_evaluate.h"
#include "ceres/numeric_diff_options.h"
#include "ceres/types.h"
@@ -125,8 +125,8 @@
// For each parameter in the parameter block, use finite differences to
// compute the derivative for that parameter.
- FixedArray<double> temp_residual_array(num_residuals_internal);
- FixedArray<double> residual_array(num_residuals_internal);
+ absl::FixedArray<double> temp_residual_array(num_residuals_internal);
+ absl::FixedArray<double> residual_array(num_residuals_internal);
Map<ResidualVector> residuals(residual_array.data(),
num_residuals_internal);
diff --git a/include/ceres/numeric_diff_cost_function.h b/include/ceres/numeric_diff_cost_function.h
index f2a377b..47e4af4 100644
--- a/include/ceres/numeric_diff_cost_function.h
+++ b/include/ceres/numeric_diff_cost_function.h
@@ -228,7 +228,7 @@
bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const override {
- using internal::FixedArray;
+ using absl::FixedArray;
using internal::NumericDiff;
using ParameterDims =
diff --git a/include/ceres/numeric_diff_first_order_function.h b/include/ceres/numeric_diff_first_order_function.h
index 790cbcd..a9a7798 100644
--- a/include/ceres/numeric_diff_first_order_function.h
+++ b/include/ceres/numeric_diff_first_order_function.h
@@ -36,10 +36,10 @@
#include <type_traits>
#include <utility>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "ceres/first_order_function.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/internal/numeric_diff.h"
#include "ceres/internal/parameter_dims.h"
#include "ceres/internal/variadic_evaluate.h"
@@ -197,7 +197,7 @@
}
// Create a copy of the parameters which will get mutated.
- internal::FixedArray<double, 32> parameters_copy(num_parameters_);
+ absl::FixedArray<double> parameters_copy(num_parameters_);
std::copy_n(parameters, num_parameters_, parameters_copy.data());
double* parameters_ptr = parameters_copy.data();
constexpr int kNumResiduals = 1;
diff --git a/include/ceres/product_manifold.h b/include/ceres/product_manifold.h
index ed2d1f4..9fc836e 100644
--- a/include/ceres/product_manifold.h
+++ b/include/ceres/product_manifold.h
@@ -42,8 +42,8 @@
#include <type_traits>
#include <utility>
+#include "absl/container/fixed_array.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/internal/port.h"
#include "ceres/manifold.h"
@@ -117,7 +117,7 @@
bool PlusJacobian(const double* x, double* jacobian_ptr) const override {
MatrixRef jacobian(jacobian_ptr, AmbientSize(), TangentSize());
jacobian.setZero();
- internal::FixedArray<double> buffer(buffer_size_);
+ absl::FixedArray<double> buffer(buffer_size_);
return PlusJacobianImpl(
x, jacobian, buffer, std::make_index_sequence<kNumManifolds>{});
@@ -126,7 +126,7 @@
bool MinusJacobian(const double* x, double* jacobian_ptr) const override {
MatrixRef jacobian(jacobian_ptr, TangentSize(), AmbientSize());
jacobian.setZero();
- internal::FixedArray<double> buffer(buffer_size_);
+ absl::FixedArray<double> buffer(buffer_size_);
return MinusJacobianImpl(
x, jacobian, buffer, std::make_index_sequence<kNumManifolds>{});
@@ -199,7 +199,7 @@
template <std::size_t Index0, std::size_t... Indices>
bool PlusJacobianImpl(const double* x,
MatrixRef& jacobian,
- internal::FixedArray<double>& buffer,
+ absl::FixedArray<double>& buffer,
std::index_sequence<Index0, Indices...>) const {
if (!Dereference(std::get<Index0>(manifolds_))
.PlusJacobian(x + ambient_offsets_[Index0], buffer.data())) {
@@ -217,18 +217,17 @@
x, jacobian, buffer, std::index_sequence<Indices...>{});
}
- static constexpr bool PlusJacobianImpl(
- const double* /*x*/,
- MatrixRef& /*jacobian*/,
- internal::FixedArray<double>& /*buffer*/,
- std::index_sequence<>) noexcept {
+ static constexpr bool PlusJacobianImpl(const double* /*x*/,
+ MatrixRef& /*jacobian*/,
+ absl::FixedArray<double>& /*buffer*/,
+ std::index_sequence<>) noexcept {
return true;
}
template <std::size_t Index0, std::size_t... Indices>
bool MinusJacobianImpl(const double* x,
MatrixRef& jacobian,
- internal::FixedArray<double>& buffer,
+ absl::FixedArray<double>& buffer,
std::index_sequence<Index0, Indices...>) const {
if (!Dereference(std::get<Index0>(manifolds_))
.MinusJacobian(x + ambient_offsets_[Index0], buffer.data())) {
@@ -246,11 +245,10 @@
x, jacobian, buffer, std::index_sequence<Indices...>{});
}
- static constexpr bool MinusJacobianImpl(
- const double* /*x*/,
- MatrixRef& /*jacobian*/,
- internal::FixedArray<double>& /*buffer*/,
- std::index_sequence<>) noexcept {
+ static constexpr bool MinusJacobianImpl(const double* /*x*/,
+ MatrixRef& /*jacobian*/,
+ absl::FixedArray<double>& /*buffer*/,
+ std::index_sequence<>) noexcept {
return true;
}
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt
index f30ba00..808e0ed 100644
--- a/internal/ceres/CMakeLists.txt
+++ b/internal/ceres/CMakeLists.txt
@@ -39,6 +39,7 @@
list(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES absl::log)
list(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES absl::check)
+list(APPEND CERES_LIBRARY_PUBLIC_DEPENDENCIES absl::fixed_array)
# Source files that contain public symbols and live in the ceres namespaces.
# Such symbols are expected to be marked with CERES_EXPORT and the files below
@@ -450,7 +451,6 @@
ceres_test(dynamic_sparsity)
ceres_test(evaluation_callback)
ceres_test(evaluator)
- ceres_test(fixed_array)
ceres_test(gradient_checker)
ceres_test(gradient_checking_cost_function)
ceres_test(gradient_problem)
diff --git a/internal/ceres/array_selector_test.cc b/internal/ceres/array_selector_test.cc
index 36155f1..0b6c893 100644
--- a/internal/ceres/array_selector_test.cc
+++ b/internal/ceres/array_selector_test.cc
@@ -35,7 +35,7 @@
#include <type_traits>
#include <vector>
-#include "ceres/internal/fixed_array.h"
+#include "absl/container/fixed_array.h"
#include "ceres/types.h"
#include "gtest/gtest.h"
@@ -47,12 +47,12 @@
TEST(ArraySelector, FixedArray) {
ArraySelector<int, DYNAMIC, 20> array1(10);
static_assert(
- std::is_base_of<internal::FixedArray<int, 20>, decltype(array1)>::value);
+ std::is_base_of<absl::FixedArray<int, 20>, decltype(array1)>::value);
EXPECT_EQ(array1.size(), 10);
ArraySelector<int, DYNAMIC, 10> array2(20);
static_assert(
- std::is_base_of<internal::FixedArray<int, 10>, decltype(array2)>::value);
+ std::is_base_of<absl::FixedArray<int, 10>, decltype(array2)>::value);
EXPECT_EQ(array2.size(), 20);
}
diff --git a/internal/ceres/autodiff_test.cc b/internal/ceres/autodiff_test.cc
index b50327c..787adf8 100644
--- a/internal/ceres/autodiff_test.cc
+++ b/internal/ceres/autodiff_test.cc
@@ -34,6 +34,7 @@
#include <iterator>
#include <random>
+#include "absl/container/fixed_array.h"
#include "gtest/gtest.h"
namespace ceres::internal {
@@ -666,7 +667,7 @@
y += 1;
using JetT = Jet<double, 2>;
- FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(3);
+ absl::FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(3);
// Need this to makes sure that x does not get optimized out.
x[0] = x[0] + JetT(1.0);
diff --git a/internal/ceres/eigen_vector_ops.h b/internal/ceres/eigen_vector_ops.h
index 6ebff88..cc0a59b 100644
--- a/internal/ceres/eigen_vector_ops.h
+++ b/internal/ceres/eigen_vector_ops.h
@@ -33,8 +33,8 @@
#include <numeric>
+#include "absl/container/fixed_array.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/parallel_for.h"
#include "ceres/parallel_vector_ops.h"
@@ -47,7 +47,7 @@
inline double Norm(const Eigen::DenseBase<Derived>& x,
ContextImpl* context,
int num_threads) {
- FixedArray<double> norms(num_threads, 0.);
+ absl::FixedArray<double> norms(num_threads, 0.);
ParallelFor(
context,
0,
@@ -77,7 +77,7 @@
const VectorLikeY& y,
ContextImpl* context,
int num_threads) {
- FixedArray<double> dots(num_threads, 0.);
+ absl::FixedArray<double> dots(num_threads, 0.);
ParallelFor(
context,
0,
diff --git a/internal/ceres/fixed_array_test.cc b/internal/ceres/fixed_array_test.cc
deleted file mode 100644
index 66b3fbf..0000000
--- a/internal/ceres/fixed_array_test.cc
+++ /dev/null
@@ -1,835 +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/fixed_array.h"
-
-#include <cstdio>
-#include <cstring>
-#include <list>
-#include <memory>
-#include <numeric>
-#include <scoped_allocator>
-#include <stdexcept>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-using ::testing::ElementsAreArray;
-
-namespace {
-
-// CERES_INTERNAL_ARRAYSIZE()
-//
-// Returns the number of elements in an array as a compile-time constant, which
-// can be used in defining new arrays. If you use this macro on a pointer by
-// mistake, you will get a compile-time error.
-#define CERES_INTERNAL_ARRAYSIZE(array) (sizeof(ArraySizeHelper(array)))
-
-// Note: this internal template function declaration is used by
-// CERES_INTERNAL_ARRAYSIZE. The function doesn't need a definition, as we only
-// use its type.
-template <typename T, size_t N>
-auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
-
-// Helper routine to determine if a ceres::internal::FixedArray used stack
-// allocation.
-template <typename ArrayType>
-static bool IsOnStack(const ArrayType& a) {
- return a.size() <= ArrayType::inline_elements;
-}
-
-class ConstructionTester {
- public:
- ConstructionTester() : self_ptr_(this) { constructions++; }
- ~ConstructionTester() {
- assert(self_ptr_ == this);
- self_ptr_ = nullptr;
- destructions++;
- }
-
- // These are incremented as elements are constructed and destructed so we can
- // be sure all elements are properly cleaned up.
- static int constructions;
- static int destructions;
-
- void CheckConstructed() { assert(self_ptr_ == this); }
-
- void set(int value) { value_ = value; }
- int get() { return value_; }
-
- private:
- // self_ptr_ should always point to 'this' -- that's how we can be sure the
- // constructor has been called.
- ConstructionTester* self_ptr_;
- int value_{0};
-};
-
-int ConstructionTester::constructions = 0;
-int ConstructionTester::destructions = 0;
-
-// ThreeInts will initialize its three ints to the value stored in
-// ThreeInts::counter. The constructor increments counter so that each object
-// in an array of ThreeInts will have different values.
-class ThreeInts {
- public:
- ThreeInts() {
- x_ = counter;
- y_ = counter;
- z_ = counter;
- ++counter;
- }
-
- static int counter;
-
- int x_, y_, z_;
-};
-
-int ThreeInts::counter = 0;
-
-TEST(FixedArrayTest, CopyCtor) {
- ceres::internal::FixedArray<int, 10> on_stack(5);
- std::iota(on_stack.begin(), on_stack.end(), 0);
- ceres::internal::FixedArray<int, 10> stack_copy = on_stack;
- EXPECT_THAT(stack_copy, ElementsAreArray(on_stack));
- EXPECT_TRUE(IsOnStack(stack_copy));
-
- ceres::internal::FixedArray<int, 10> allocated(15);
- std::iota(allocated.begin(), allocated.end(), 0);
- ceres::internal::FixedArray<int, 10> alloced_copy = allocated;
- EXPECT_THAT(alloced_copy, ElementsAreArray(allocated));
- EXPECT_FALSE(IsOnStack(alloced_copy));
-}
-
-TEST(FixedArrayTest, MoveCtor) {
- ceres::internal::FixedArray<std::unique_ptr<int>, 10> on_stack(5);
- for (int i = 0; i < 5; ++i) {
- on_stack[i] = std::make_unique<int>(i);
- }
-
- ceres::internal::FixedArray<std::unique_ptr<int>, 10> stack_copy =
- std::move(on_stack);
- for (int i = 0; i < 5; ++i) EXPECT_EQ(*(stack_copy[i]), i);
- EXPECT_EQ(stack_copy.size(), on_stack.size());
-
- ceres::internal::FixedArray<std::unique_ptr<int>, 10> allocated(15);
- for (int i = 0; i < 15; ++i) {
- allocated[i] = std::make_unique<int>(i);
- }
-
- ceres::internal::FixedArray<std::unique_ptr<int>, 10> alloced_copy =
- std::move(allocated);
- for (int i = 0; i < 15; ++i) EXPECT_EQ(*(alloced_copy[i]), i);
- EXPECT_EQ(allocated.size(), alloced_copy.size());
-}
-
-TEST(FixedArrayTest, SmallObjects) {
- // Small object arrays
- {
- // Short arrays should be on the stack
- ceres::internal::FixedArray<int> array(4);
- EXPECT_TRUE(IsOnStack(array));
- }
-
- {
- // Large arrays should be on the heap
- ceres::internal::FixedArray<int> array(1048576);
- EXPECT_FALSE(IsOnStack(array));
- }
-
- {
- // Arrays of <= default size should be on the stack
- ceres::internal::FixedArray<int, 100> array(100);
- EXPECT_TRUE(IsOnStack(array));
- }
-
- {
- // Arrays of > default size should be on the heap
- ceres::internal::FixedArray<int, 100> array(101);
- EXPECT_FALSE(IsOnStack(array));
- }
-
- {
- // Arrays with different size elements should use approximately
- // same amount of stack space
- ceres::internal::FixedArray<int> array1(0);
- ceres::internal::FixedArray<char> array2(0);
- EXPECT_LE(sizeof(array1), sizeof(array2) + 100);
- EXPECT_LE(sizeof(array2), sizeof(array1) + 100);
- }
-
- {
- // Ensure that vectors are properly constructed inside a fixed array.
- ceres::internal::FixedArray<std::vector<int>> array(2);
- EXPECT_EQ(0, array[0].size());
- EXPECT_EQ(0, array[1].size());
- }
-
- {
- // Regardless of ceres::internal::FixedArray implementation, check that a
- // type with a low alignment requirement and a non power-of-two size is
- // initialized correctly.
- ThreeInts::counter = 1;
- ceres::internal::FixedArray<ThreeInts> array(2);
- EXPECT_EQ(1, array[0].x_);
- EXPECT_EQ(1, array[0].y_);
- EXPECT_EQ(1, array[0].z_);
- EXPECT_EQ(2, array[1].x_);
- EXPECT_EQ(2, array[1].y_);
- EXPECT_EQ(2, array[1].z_);
- }
-}
-
-TEST(FixedArrayRelationalsTest, EqualArrays) {
- for (int i = 0; i < 10; ++i) {
- ceres::internal::FixedArray<int, 5> a1(i);
- std::iota(a1.begin(), a1.end(), 0);
- ceres::internal::FixedArray<int, 5> a2(a1.begin(), a1.end());
-
- EXPECT_TRUE(a1 == a2);
- EXPECT_FALSE(a1 != a2);
- EXPECT_TRUE(a2 == a1);
- EXPECT_FALSE(a2 != a1);
- EXPECT_FALSE(a1 < a2);
- EXPECT_FALSE(a1 > a2);
- EXPECT_FALSE(a2 < a1);
- EXPECT_FALSE(a2 > a1);
- EXPECT_TRUE(a1 <= a2);
- EXPECT_TRUE(a1 >= a2);
- EXPECT_TRUE(a2 <= a1);
- EXPECT_TRUE(a2 >= a1);
- }
-}
-
-TEST(FixedArrayRelationalsTest, UnequalArrays) {
- for (int i = 1; i < 10; ++i) {
- ceres::internal::FixedArray<int, 5> a1(i);
- std::iota(a1.begin(), a1.end(), 0);
- ceres::internal::FixedArray<int, 5> a2(a1.begin(), a1.end());
- --a2[i / 2];
-
- EXPECT_FALSE(a1 == a2);
- EXPECT_TRUE(a1 != a2);
- EXPECT_FALSE(a2 == a1);
- EXPECT_TRUE(a2 != a1);
- EXPECT_FALSE(a1 < a2);
- EXPECT_TRUE(a1 > a2);
- EXPECT_TRUE(a2 < a1);
- EXPECT_FALSE(a2 > a1);
- EXPECT_FALSE(a1 <= a2);
- EXPECT_TRUE(a1 >= a2);
- EXPECT_TRUE(a2 <= a1);
- EXPECT_FALSE(a2 >= a1);
- }
-}
-
-template <int stack_elements>
-static void TestArray(int n) {
- SCOPED_TRACE(n);
- SCOPED_TRACE(stack_elements);
- ConstructionTester::constructions = 0;
- ConstructionTester::destructions = 0;
- {
- ceres::internal::FixedArray<ConstructionTester, stack_elements> array(n);
-
- EXPECT_THAT(array.size(), n);
- EXPECT_THAT(array.memsize(), sizeof(ConstructionTester) * n);
- EXPECT_THAT(array.begin() + n, array.end());
-
- // Check that all elements were constructed
- for (int i = 0; i < n; i++) {
- array[i].CheckConstructed();
- }
- // Check that no other elements were constructed
- EXPECT_THAT(ConstructionTester::constructions, n);
-
- // Test operator[]
- for (int i = 0; i < n; i++) {
- array[i].set(i);
- }
- for (int i = 0; i < n; i++) {
- EXPECT_THAT(array[i].get(), i);
- EXPECT_THAT(array.data()[i].get(), i);
- }
-
- // Test data()
- for (int i = 0; i < n; i++) {
- array.data()[i].set(i + 1);
- }
- for (int i = 0; i < n; i++) {
- EXPECT_THAT(array[i].get(), i + 1);
- EXPECT_THAT(array.data()[i].get(), i + 1);
- }
- } // Close scope containing 'array'.
-
- // Check that all constructed elements were destructed.
- EXPECT_EQ(ConstructionTester::constructions,
- ConstructionTester::destructions);
-}
-
-template <int elements_per_inner_array, int inline_elements>
-static void TestArrayOfArrays(int n) {
- SCOPED_TRACE(n);
- SCOPED_TRACE(inline_elements);
- SCOPED_TRACE(elements_per_inner_array);
- ConstructionTester::constructions = 0;
- ConstructionTester::destructions = 0;
- {
- using InnerArray = ConstructionTester[elements_per_inner_array];
- // Heap-allocate the FixedArray to avoid blowing the stack frame.
- auto array_ptr = std::unique_ptr<
- ceres::internal::FixedArray<InnerArray, inline_elements>>(
- new ceres::internal::FixedArray<InnerArray, inline_elements>(n));
- auto& array = *array_ptr;
-
- ASSERT_EQ(array.size(), n);
- ASSERT_EQ(array.memsize(),
- sizeof(ConstructionTester) * elements_per_inner_array * n);
- ASSERT_EQ(array.begin() + n, array.end());
-
- // Check that all elements were constructed
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < elements_per_inner_array; j++) {
- (array[i])[j].CheckConstructed();
- }
- }
- // Check that no other elements were constructed
- ASSERT_EQ(ConstructionTester::constructions, n * elements_per_inner_array);
-
- // Test operator[]
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < elements_per_inner_array; j++) {
- (array[i])[j].set(i * elements_per_inner_array + j);
- }
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < elements_per_inner_array; j++) {
- ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);
- ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j);
- }
- }
-
- // Test data()
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < elements_per_inner_array; j++) {
- (array.data()[i])[j].set((i + 1) * elements_per_inner_array + j);
- }
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < elements_per_inner_array; j++) {
- ASSERT_EQ((array[i])[j].get(), (i + 1) * elements_per_inner_array + j);
- ASSERT_EQ((array.data()[i])[j].get(),
- (i + 1) * elements_per_inner_array + j);
- }
- }
- } // Close scope containing 'array'.
-
- // Check that all constructed elements were destructed.
- EXPECT_EQ(ConstructionTester::constructions,
- ConstructionTester::destructions);
-}
-
-TEST(IteratorConstructorTest, NonInline) {
- int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
- ceres::internal::FixedArray<int, CERES_INTERNAL_ARRAYSIZE(kInput) - 1> const
- fixed(kInput, kInput + CERES_INTERNAL_ARRAYSIZE(kInput));
- ASSERT_EQ(CERES_INTERNAL_ARRAYSIZE(kInput), fixed.size());
- for (size_t i = 0; i < CERES_INTERNAL_ARRAYSIZE(kInput); ++i) {
- ASSERT_EQ(kInput[i], fixed[i]);
- }
-}
-
-TEST(IteratorConstructorTest, Inline) {
- int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
- ceres::internal::FixedArray<int, CERES_INTERNAL_ARRAYSIZE(kInput)> const
- fixed(kInput, kInput + CERES_INTERNAL_ARRAYSIZE(kInput));
- ASSERT_EQ(CERES_INTERNAL_ARRAYSIZE(kInput), fixed.size());
- for (size_t i = 0; i < CERES_INTERNAL_ARRAYSIZE(kInput); ++i) {
- ASSERT_EQ(kInput[i], fixed[i]);
- }
-}
-
-TEST(IteratorConstructorTest, NonPod) {
- char const* kInput[] = {
- "red", "orange", "yellow", "green", "blue", "indigo", "violet"};
- ceres::internal::FixedArray<std::string> const fixed(
- kInput, kInput + CERES_INTERNAL_ARRAYSIZE(kInput));
- ASSERT_EQ(CERES_INTERNAL_ARRAYSIZE(kInput), fixed.size());
- for (size_t i = 0; i < CERES_INTERNAL_ARRAYSIZE(kInput); ++i) {
- ASSERT_EQ(kInput[i], fixed[i]);
- }
-}
-
-TEST(IteratorConstructorTest, FromEmptyVector) {
- std::vector<int> const empty;
- ceres::internal::FixedArray<int> const fixed(empty.begin(), empty.end());
- EXPECT_EQ(0, fixed.size());
- EXPECT_EQ(empty.size(), fixed.size());
-}
-
-TEST(IteratorConstructorTest, FromNonEmptyVector) {
- int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
- std::vector<int> const items(kInput,
- kInput + CERES_INTERNAL_ARRAYSIZE(kInput));
- ceres::internal::FixedArray<int> const fixed(items.begin(), items.end());
- ASSERT_EQ(items.size(), fixed.size());
- for (size_t i = 0; i < items.size(); ++i) {
- ASSERT_EQ(items[i], fixed[i]);
- }
-}
-
-TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {
- int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
- std::list<int> const items(kInput, kInput + CERES_INTERNAL_ARRAYSIZE(kInput));
- ceres::internal::FixedArray<int> const fixed(items.begin(), items.end());
- EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
-}
-
-TEST(InitListConstructorTest, InitListConstruction) {
- ceres::internal::FixedArray<int> fixed = {1, 2, 3};
- EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));
-}
-
-TEST(FillConstructorTest, NonEmptyArrays) {
- ceres::internal::FixedArray<int> stack_array(4, 1);
- EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
-
- ceres::internal::FixedArray<int, 0> heap_array(4, 1);
- EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
-}
-
-TEST(FillConstructorTest, EmptyArray) {
- ceres::internal::FixedArray<int> empty_fill(0, 1);
- ceres::internal::FixedArray<int> empty_size(0);
- EXPECT_EQ(empty_fill, empty_size);
-}
-
-TEST(FillConstructorTest, NotTriviallyCopyable) {
- std::string str = "abcd";
- ceres::internal::FixedArray<std::string> strings = {str, str, str, str};
-
- ceres::internal::FixedArray<std::string> array(4, str);
- EXPECT_EQ(array, strings);
-}
-
-TEST(FillConstructorTest, Disambiguation) {
- ceres::internal::FixedArray<size_t> a(1, 2);
- EXPECT_THAT(a, testing::ElementsAre(2));
-}
-
-TEST(FixedArrayTest, ManySizedArrays) {
- std::vector<int> sizes;
- for (int i = 1; i < 100; i++) sizes.push_back(i);
- for (int i = 100; i <= 1000; i += 100) sizes.push_back(i);
- for (int n : sizes) {
- TestArray<0>(n);
- TestArray<1>(n);
- TestArray<64>(n);
- TestArray<1000>(n);
- }
-}
-
-TEST(FixedArrayTest, ManySizedArraysOfArraysOf1) {
- for (int n = 1; n < 1000; n++) {
- ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 0>(n)));
- ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1>(n)));
- ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 64>(n)));
- ASSERT_NO_FATAL_FAILURE((TestArrayOfArrays<1, 1000>(n)));
- }
-}
-
-TEST(FixedArrayTest, ManySizedArraysOfArraysOf2) {
- for (int n = 1; n < 1000; n++) {
- TestArrayOfArrays<2, 0>(n);
- TestArrayOfArrays<2, 1>(n);
- TestArrayOfArrays<2, 64>(n);
- TestArrayOfArrays<2, 1000>(n);
- }
-}
-
-// If value_type is put inside of a struct container,
-// we might evoke this error in a hardened build unless data() is carefully
-// written, so check on that.
-// error: call to int __builtin___sprintf_chk(etc...)
-// will always overflow destination buffer [-Werror]
-TEST(FixedArrayTest, AvoidParanoidDiagnostics) {
- ceres::internal::FixedArray<char, 32> buf(32);
- snprintf(buf.data(), 32, "foo");
-}
-
-TEST(FixedArrayTest, TooBigInlinedSpace) {
- struct TooBig {
- char c[1 << 20];
- }; // too big for even one on the stack
-
- // Simulate the data members of ceres::internal::FixedArray, a pointer and a
- // size_t.
- struct Data {
- std::tuple<size_t, std::allocator<double>> size_alloc_;
- TooBig* p;
- };
-
- // Make sure TooBig objects are not inlined for 0 or default size.
- static_assert(
- sizeof(ceres::internal::FixedArray<TooBig, 0>) == sizeof(Data),
- "0-sized ceres::internal::FixedArray should have same size as Data.");
- static_assert(
- alignof(ceres::internal::FixedArray<TooBig, 0>) == alignof(Data),
- "0-sized ceres::internal::FixedArray should have same alignment as "
- "Data.");
- static_assert(sizeof(ceres::internal::FixedArray<TooBig>) == sizeof(Data),
- "default-sized ceres::internal::FixedArray should have same "
- "size as Data");
- static_assert(alignof(ceres::internal::FixedArray<TooBig>) == alignof(Data),
- "default-sized ceres::internal::FixedArray should have same "
- "alignment as Data.");
-}
-
-// PickyDelete EXPECTs its class-scope deallocation funcs are unused.
-struct PickyDelete {
- void operator delete(void* p) {
- EXPECT_TRUE(false) << __FUNCTION__;
- ::operator delete(p);
- }
- void operator delete[](void* p) {
- EXPECT_TRUE(false) << __FUNCTION__;
- ::operator delete[](p);
- }
-};
-
-TEST(FixedArrayTest, UsesGlobalAlloc) {
- ceres::internal::FixedArray<PickyDelete, 0> a(5);
-}
-
-TEST(FixedArrayTest, Data) {
- static const int kInput[] = {2, 3, 5, 7, 11, 13, 17};
- ceres::internal::FixedArray<int> fa(std::begin(kInput), std::end(kInput));
- EXPECT_EQ(fa.data(), &*fa.begin());
- EXPECT_EQ(fa.data(), &fa[0]);
-
- const ceres::internal::FixedArray<int>& cfa = fa;
- EXPECT_EQ(cfa.data(), &*cfa.begin());
- EXPECT_EQ(cfa.data(), &cfa[0]);
-}
-
-TEST(FixedArrayTest, Empty) {
- ceres::internal::FixedArray<int> empty(0);
- ceres::internal::FixedArray<int> inline_filled(1);
- ceres::internal::FixedArray<int, 0> heap_filled(1);
- EXPECT_TRUE(empty.empty());
- EXPECT_FALSE(inline_filled.empty());
- EXPECT_FALSE(heap_filled.empty());
-}
-
-TEST(FixedArrayTest, FrontAndBack) {
- ceres::internal::FixedArray<int, 3 * sizeof(int)> inlined = {1, 2, 3};
- EXPECT_EQ(inlined.front(), 1);
- EXPECT_EQ(inlined.back(), 3);
-
- ceres::internal::FixedArray<int, 0> allocated = {1, 2, 3};
- EXPECT_EQ(allocated.front(), 1);
- EXPECT_EQ(allocated.back(), 3);
-
- ceres::internal::FixedArray<int> one_element = {1};
- EXPECT_EQ(one_element.front(), one_element.back());
-}
-
-TEST(FixedArrayTest, ReverseIteratorInlined) {
- ceres::internal::FixedArray<int, 5 * sizeof(int)> a = {0, 1, 2, 3, 4};
-
- int counter = 5;
- for (ceres::internal::FixedArray<int>::reverse_iterator iter = a.rbegin();
- iter != a.rend();
- ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-
- counter = 5;
- for (ceres::internal::FixedArray<int>::const_reverse_iterator iter =
- a.rbegin();
- iter != a.rend();
- ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-
- counter = 5;
- for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-}
-
-TEST(FixedArrayTest, ReverseIteratorAllocated) {
- ceres::internal::FixedArray<int, 0> a = {0, 1, 2, 3, 4};
-
- int counter = 5;
- for (ceres::internal::FixedArray<int>::reverse_iterator iter = a.rbegin();
- iter != a.rend();
- ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-
- counter = 5;
- for (ceres::internal::FixedArray<int>::const_reverse_iterator iter =
- a.rbegin();
- iter != a.rend();
- ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-
- counter = 5;
- for (auto iter = a.crbegin(); iter != a.crend(); ++iter) {
- counter--;
- EXPECT_EQ(counter, *iter);
- }
- EXPECT_EQ(counter, 0);
-}
-
-TEST(FixedArrayTest, Fill) {
- ceres::internal::FixedArray<int, 5 * sizeof(int)> inlined(5);
- int fill_val = 42;
- inlined.fill(fill_val);
- for (int i : inlined) EXPECT_EQ(i, fill_val);
-
- ceres::internal::FixedArray<int, 0> allocated(5);
- allocated.fill(fill_val);
- for (int i : allocated) EXPECT_EQ(i, fill_val);
-
- // It doesn't do anything, just make sure this compiles.
- ceres::internal::FixedArray<int> empty(0);
- empty.fill(fill_val);
-}
-
-// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
-#ifndef __GNUC__
-TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
- using T = char;
- constexpr auto capacity = 10;
- using FixedArrType = ceres::internal::FixedArray<T, capacity>;
- using FixedArrBuffType =
- typename std::aligned_storage<sizeof(FixedArrType),
- alignof(FixedArrType)>::type;
- constexpr auto scrubbed_bits = 0x95;
- constexpr auto length = capacity / 2;
-
- FixedArrBuffType buff;
- std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType));
-
- FixedArrType* arr =
- ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
- EXPECT_THAT(*arr, testing::Each(scrubbed_bits));
- arr->~FixedArrType();
-}
-#endif // __GNUC__
-
-// This is a stateful allocator, but the state lives outside of the
-// allocator (in whatever test is using the allocator). This is odd
-// but helps in tests where the allocator is propagated into nested
-// containers - that chain of allocators uses the same state and is
-// thus easier to query for aggregate allocation information.
-template <typename T>
-class CountingAllocator : public std::allocator<T> {
- public:
- using Alloc = std::allocator<T>;
- using size_type = typename Alloc::size_type;
-
- CountingAllocator() = default;
- explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
- CountingAllocator(int64_t* b, int64_t* a)
- : bytes_used_(b), instance_count_(a) {}
-
- template <typename U>
- explicit CountingAllocator(const CountingAllocator<U>& x)
- : Alloc(x),
- bytes_used_(x.bytes_used_),
- instance_count_(x.instance_count_) {}
-
- T* allocate(size_type n) {
- assert(bytes_used_ != nullptr);
- *bytes_used_ += n * sizeof(T);
- return Alloc::allocate(n);
- }
-
- void deallocate(T* p, size_type n) {
- Alloc::deallocate(p, n);
- assert(bytes_used_ != nullptr);
- *bytes_used_ -= n * sizeof(T);
- }
-
- int64_t* bytes_used_{nullptr};
- int64_t* instance_count_{nullptr};
-};
-
-TEST(AllocatorSupportTest, CountInlineAllocations) {
- constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
- using AllocFxdArr = ceres::internal::FixedArray<int, inlined_size, Alloc>;
-
- int64_t allocated = 0;
- int64_t active_instances = 0;
-
- {
- const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
-
- Alloc alloc(&allocated, &active_instances);
-
- AllocFxdArr arr(ia, ia + inlined_size, alloc);
- static_cast<void>(arr);
- }
-
- EXPECT_EQ(allocated, 0);
- EXPECT_EQ(active_instances, 0);
-}
-
-TEST(AllocatorSupportTest, CountOutoflineAllocations) {
- constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
- using AllocFxdArr = ceres::internal::FixedArray<int, inlined_size, Alloc>;
-
- int64_t allocated = 0;
- int64_t active_instances = 0;
-
- {
- const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
- Alloc alloc(&allocated, &active_instances);
-
- AllocFxdArr arr(ia, ia + CERES_INTERNAL_ARRAYSIZE(ia), alloc);
-
- EXPECT_EQ(allocated, arr.size() * sizeof(int));
- static_cast<void>(arr);
- }
-
- EXPECT_EQ(active_instances, 0);
-}
-
-TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
- constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
- using AllocFxdArr = ceres::internal::FixedArray<int, inlined_size, Alloc>;
-
- int64_t allocated1 = 0;
- int64_t allocated2 = 0;
- int64_t active_instances = 0;
- Alloc alloc(&allocated1, &active_instances);
- Alloc alloc2(&allocated2, &active_instances);
-
- {
- int initial_value = 1;
-
- AllocFxdArr arr1(inlined_size / 2, initial_value, alloc);
-
- EXPECT_EQ(allocated1, 0);
-
- AllocFxdArr arr2(arr1, alloc2);
-
- EXPECT_EQ(allocated2, 0);
- static_cast<void>(arr1);
- static_cast<void>(arr2);
- }
-
- EXPECT_EQ(active_instances, 0);
-}
-
-TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
- constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
- using AllocFxdArr = ceres::internal::FixedArray<int, inlined_size, Alloc>;
-
- int64_t allocated1 = 0;
- int64_t allocated2 = 0;
- int64_t active_instances = 0;
- Alloc alloc(&allocated1, &active_instances);
- Alloc alloc2(&allocated2, &active_instances);
-
- {
- int initial_value = 1;
-
- AllocFxdArr arr1(inlined_size * 2, initial_value, alloc);
-
- EXPECT_EQ(allocated1, arr1.size() * sizeof(int));
-
- AllocFxdArr arr2(arr1, alloc2);
-
- EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int));
- static_cast<void>(arr1);
- static_cast<void>(arr2);
- }
-
- EXPECT_EQ(active_instances, 0);
-}
-
-TEST(AllocatorSupportTest, SizeValAllocConstructor) {
- using testing::AllOf;
- using testing::Each;
- using testing::SizeIs;
-
- constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
- using AllocFxdArr = ceres::internal::FixedArray<int, inlined_size, Alloc>;
-
- {
- auto len = inlined_size / 2;
- auto val = 0;
- int64_t allocated = 0;
- AllocFxdArr arr(len, val, Alloc(&allocated));
-
- EXPECT_EQ(allocated, 0);
- EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
- }
-
- {
- auto len = inlined_size * 2;
- auto val = 0;
- int64_t allocated = 0;
- AllocFxdArr arr(len, val, Alloc(&allocated));
-
- EXPECT_EQ(allocated, len * sizeof(int));
- EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
- }
-}
-
-struct EigenStruct {
- Eigen::Vector4d data;
-};
-
-static_assert(
- std::is_same<ceres::internal::FixedArrayDefaultAllocator<double>,
- std::allocator<double>>::value,
- "Double is a trivial type, so std::allocator should be used here.");
-static_assert(
- std::is_same<ceres::internal::FixedArrayDefaultAllocator<double*>,
- std::allocator<double*>>::value,
- "A pointer is a trivial type, so std::allocator should be used here.");
-static_assert(
- std::is_same<ceres::internal::FixedArrayDefaultAllocator<Eigen::Matrix4d>,
- Eigen::aligned_allocator<Eigen::Matrix4d>>::value,
- "An Eigen::Matrix4d needs the Eigen::aligned_allocator for proper "
- "alignment.");
-static_assert(
- std::is_same<ceres::internal::FixedArrayDefaultAllocator<EigenStruct>,
- Eigen::aligned_allocator<EigenStruct>>::value,
- "A struct containing fixed size Eigen types needs Eigen::aligned_allocator "
- "for proper alignment.");
-
-} // namespace
diff --git a/internal/ceres/gradient_checker_test.cc b/internal/ceres/gradient_checker_test.cc
index 5d2ea14..0b9f3a6 100644
--- a/internal/ceres/gradient_checker_test.cc
+++ b/internal/ceres/gradient_checker_test.cc
@@ -37,6 +37,7 @@
#include <utility>
#include <vector>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "ceres/cost_function.h"
@@ -206,7 +207,7 @@
parameter_sizes[2] = 4;
// Make a random set of blocks.
- FixedArray<double*> parameters(num_parameters);
+ absl::FixedArray<double*> parameters(num_parameters);
std::mt19937 prng;
std::uniform_real_distribution<double> distribution(-1.0, 1.0);
auto randu = [&prng, &distribution] { return distribution(prng); };
diff --git a/internal/ceres/manifold.cc b/internal/ceres/manifold.cc
index bfb2a22..6bd320a 100644
--- a/internal/ceres/manifold.cc
+++ b/internal/ceres/manifold.cc
@@ -5,7 +5,6 @@
#include "absl/log/check.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
namespace ceres {
namespace {
diff --git a/internal/ceres/problem_impl.cc b/internal/ceres/problem_impl.cc
index eafbb20..cc86d2c 100644
--- a/internal/ceres/problem_impl.cc
+++ b/internal/ceres/problem_impl.cc
@@ -41,6 +41,7 @@
#include <utility>
#include <vector>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "ceres/casts.h"
@@ -52,7 +53,6 @@
#include "ceres/evaluation_callback.h"
#include "ceres/evaluator.h"
#include "ceres/internal/export.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/loss_function.h"
#include "ceres/manifold.h"
#include "ceres/map_util.h"
@@ -776,7 +776,7 @@
}
double dummy_cost = 0.0;
- FixedArray<double, 32> scratch(
+ absl::FixedArray<double> scratch(
residual_block->NumScratchDoublesForEvaluate());
return residual_block->Evaluate(apply_loss_function,
cost ? cost : &dummy_cost,
diff --git a/internal/ceres/residual_block.cc b/internal/ceres/residual_block.cc
index da6b88e..aeb761f 100644
--- a/internal/ceres/residual_block.cc
+++ b/internal/ceres/residual_block.cc
@@ -35,12 +35,12 @@
#include <cstddef>
#include <vector>
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "ceres/corrector.h"
#include "ceres/cost_function.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/loss_function.h"
#include "ceres/manifold.h"
#include "ceres/parameter_block.h"
@@ -77,13 +77,13 @@
// Collect the parameters from their blocks. This will rarely allocate, since
// residuals taking more than 8 parameter block arguments are rare.
- FixedArray<const double*, 8> parameters(num_parameter_blocks);
+ absl::FixedArray<const double*> parameters(num_parameter_blocks);
for (int i = 0; i < num_parameter_blocks; ++i) {
parameters[i] = parameter_blocks_[i]->state();
}
// Put pointers into the scratch space into global_jacobians as appropriate.
- FixedArray<double*, 8> global_jacobians(num_parameter_blocks);
+ absl::FixedArray<double*> global_jacobians(num_parameter_blocks);
if (jacobians != nullptr) {
for (int i = 0; i < num_parameter_blocks; ++i) {
const ParameterBlock* parameter_block = parameter_blocks_[i];
diff --git a/internal/ceres/schur_eliminator_impl.h b/internal/ceres/schur_eliminator_impl.h
index 545f906..6c287fd 100644
--- a/internal/ceres/schur_eliminator_impl.h
+++ b/internal/ceres/schur_eliminator_impl.h
@@ -54,12 +54,12 @@
#include <map>
#include "Eigen/Dense"
+#include "absl/container/fixed_array.h"
#include "absl/log/check.h"
#include "ceres/block_random_access_matrix.h"
#include "ceres/block_sparse_matrix.h"
#include "ceres/block_structure.h"
#include "ceres/internal/eigen.h"
-#include "ceres/internal/fixed_array.h"
#include "ceres/invert_psd_matrix.h"
#include "ceres/map_util.h"
#include "ceres/parallel_for.h"
@@ -249,7 +249,7 @@
ete.setZero();
}
- FixedArray<double, 8> g(e_block_size);
+ absl::FixedArray<double> g(e_block_size);
typename EigenTypes<kEBlockSize>::VectorRef gref(g.data(),
e_block_size);
gref.setZero();
@@ -283,7 +283,7 @@
// rhs = F'b - F'E(E'E)^(-1) E'b
if (rhs) {
- FixedArray<double, 8> inverse_ete_g(e_block_size);
+ absl::FixedArray<double> inverse_ete_g(e_block_size);
MatrixVectorMultiply<kEBlockSize, kEBlockSize, 0>(
inverse_ete.data(),
e_block_size,
@@ -336,7 +336,7 @@
const Cell& e_cell = row.cells.front();
DCHECK_EQ(e_block_id, e_cell.block_id);
- FixedArray<double, 8> sj(row.block.size);
+ absl::FixedArray<double> sj(row.block.size);
typename EigenTypes<kRowBlockSize>::VectorRef(sj.data(), row.block.size) =
typename EigenTypes<kRowBlockSize>::ConstVectorRef(