Automatic Differentiation
 
Loading...
Searching...
No Matches
arena_matrix.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_REV_CORE_ARENA_MATRIX_HPP
2#define STAN_MATH_REV_CORE_ARENA_MATRIX_HPP
3
10namespace stan {
11namespace math {
12
13template <typename MatrixType>
14class arena_matrix<MatrixType, require_eigen_dense_base_t<MatrixType>>
15 : public Eigen::Map<MatrixType> {
16 public:
18 using Base = Eigen::Map<MatrixType>;
19 using PlainObject = std::decay_t<MatrixType>;
20 static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime;
21 static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime;
22
27 : Base::Map(nullptr,
28 RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime,
29 ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {
30 }
31
37 arena_matrix(Eigen::Index rows, Eigen::Index cols)
38 : Base::Map(
39 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(rows * cols),
40 rows, cols) {}
41
47 explicit arena_matrix(Eigen::Index size)
48 : Base::Map(
49 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(size),
50 size) {}
51
52 private:
53 template <typename T>
54 constexpr auto get_rows(const T& x) {
55 return (RowsAtCompileTime == 1 && T::ColsAtCompileTime == 1)
56 || (ColsAtCompileTime == 1 && T::RowsAtCompileTime == 1)
57 ? x.cols()
58 : x.rows();
59 }
60 template <typename T>
61 constexpr auto get_cols(const T& x) {
62 return (RowsAtCompileTime == 1 && T::ColsAtCompileTime == 1)
63 || (ColsAtCompileTime == 1 && T::RowsAtCompileTime == 1)
64 ? x.rows()
65 : x.cols();
66 }
67
68 public:
73 template <typename T, require_eigen_t<T>* = nullptr>
74 arena_matrix(const T& other) // NOLINT
75 : Base::Map(ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
76 other.size()),
77 get_rows(other), get_cols(other)) {
78 *this = other;
79 }
86 template <typename T, require_eigen_t<T>* = nullptr>
87 arena_matrix& operator=(const T& other) {
88 new (this) Base(
89 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(other.size()),
90 get_rows(other), get_cols(other));
91 Base::operator=(other);
92 return *this;
93 }
94
104 template <typename T, require_eigen_t<T>* = nullptr,
105 require_not_arena_matrix_t<T>* = nullptr,
106 require_t<std::is_rvalue_reference<T&&>>* = nullptr,
107 require_plain_type_t<T>* = nullptr,
108 require_same_t<T, MatrixType>* = nullptr>
109 arena_matrix(T&& other) // NOLINT
110 : Base::Map([](auto&& x) {
111 using base_map_t =
113 auto other_ptr = make_chainable_ptr(std::move(x));
114 // other has it's rows and cols swapped already if it needed that
115 return base_map_t(&(other_ptr->coeffRef(0)), other_ptr->rows(),
116 other_ptr->cols());
117 }(std::move(other))) {}
118
126 template <typename T, require_eigen_t<T>* = nullptr,
127 require_not_arena_matrix_t<T>* = nullptr,
128 require_t<std::is_rvalue_reference<T&&>>* = nullptr,
129 require_plain_type_t<T>* = nullptr,
130 require_same_t<T, MatrixType>* = nullptr>
132 auto other_ptr = make_chainable_ptr(std::move(other));
133 new (this)
134 Base(&(other_ptr->coeffRef(0)), other_ptr->rows(), other_ptr->cols());
135 return *this;
136 }
137
143 arena_matrix(const Base& other) // NOLINT
144 : Base::Map(other) {}
145
151 : Base::Map(const_cast<Scalar*>(other.data()), other.rows(),
152 other.cols()) {}
153
154 // without this using, compiler prefers combination of implicit construction
155 // and copy assignment to the inherited operator when assigned an expression
156 using Base::operator=;
157
164 // placement new changes what data map points to - there is no allocation
165 new (this)
166 Base(const_cast<Scalar*>(other.data()), other.rows(), other.cols());
167 return *this;
168 }
169
175 template <typename T>
176 void deep_copy(const T& x) {
177 Base::operator=(x);
178 }
179};
180
181template <typename MatrixType>
182class arena_matrix<MatrixType, require_eigen_sparse_base_t<MatrixType>>
183 : public Eigen::Map<MatrixType> {
184 public:
186 using Base = Eigen::Map<MatrixType>;
187 using PlainObject = std::decay_t<MatrixType>;
188 using StorageIndex = typename PlainObject::StorageIndex;
189
193 arena_matrix() : Base::Map(0, 0, 0, nullptr, nullptr, nullptr) {}
214 arena_matrix(Eigen::Index rows, Eigen::Index cols, Eigen::Index nnz,
215 StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr,
216 Scalar* valuePtr, StorageIndex* innerNonZerosPtr = nullptr)
217 : Base::Map(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr,
218 innerNonZerosPtr) {}
219
220 private:
221 template <typename T, typename Integral>
222 inline T* copy_vector(const T* ptr, Integral size) {
223 if (size == 0)
224 return nullptr;
226 std::copy_n(ptr, size, ret);
227 return ret;
228 }
229
230 public:
235 template <typename T, require_same_t<T, PlainObject>* = nullptr>
236 arena_matrix(T&& other) // NOLINT
237 : Base::Map(
238 other.rows(), other.cols(), other.nonZeros(),
239 copy_vector(other.outerIndexPtr(), other.outerSize() + 1),
240 copy_vector(other.innerIndexPtr(), other.nonZeros()),
241 copy_vector(other.valuePtr(), other.nonZeros()),
242 copy_vector(
243 other.innerNonZeroPtr(),
244 other.innerNonZeroPtr() == nullptr ? 0 : other.innerSize())) {}
245
250 template <typename S, require_convertible_t<S&, PlainObject>* = nullptr,
251 require_not_same_t<S, PlainObject>* = nullptr>
252 arena_matrix(S&& other) // NOLINT
253 : arena_matrix(PlainObject(std::forward<S>(other))) {}
254
260 arena_matrix(const Base& other) // NOLINT
261 : Base(other) {}
262
270 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
271 const_cast<StorageIndex*>(other.outerIndexPtr()),
272 const_cast<StorageIndex*>(other.innerIndexPtr()),
273 const_cast<Scalar*>(other.valuePtr()),
274 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
282 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
283 const_cast<StorageIndex*>(other.outerIndexPtr()),
284 const_cast<StorageIndex*>(other.innerIndexPtr()),
285 const_cast<Scalar*>(other.valuePtr()),
286 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
294 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
295 const_cast<StorageIndex*>(other.outerIndexPtr()),
296 const_cast<StorageIndex*>(other.innerIndexPtr()),
297 const_cast<Scalar*>(other.valuePtr()),
298 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
299
300 // without this using, compiler prefers combination of implicit construction
301 // and copy assignment to the inherited operator when assigned an expression
302 using Base::operator=;
303
310 template <typename ArenaMatrix,
312 arena_matrix<MatrixType>>* = nullptr>
313 arena_matrix& operator=(ArenaMatrix&& other) {
314 // placement new changes what data map points to - there is no allocation
315 new (this) Base(other.rows(), other.cols(), other.nonZeros(),
316 const_cast<StorageIndex*>(other.outerIndexPtr()),
317 const_cast<StorageIndex*>(other.innerIndexPtr()),
318 const_cast<Scalar*>(other.valuePtr()),
319 const_cast<StorageIndex*>(other.innerNonZeroPtr()));
320 return *this;
321 }
322
330 template <typename Expr,
332 arena_matrix& operator=(Expr&& expr) {
333 new (this) arena_matrix(std::forward<Expr>(expr));
334 return *this;
335 }
336
337 private:
348 template <typename F, typename Expr,
351 inline void inplace_ops_impl(F&& f, Expr&& other) {
352 auto&& x = to_ref(other);
353 auto* val_ptr = (*this).valuePtr();
354 auto* x_val_ptr = x.valuePtr();
355 const auto non_zeros = (*this).nonZeros();
356 for (Eigen::Index i = 0; i < non_zeros; ++i) {
357 f(val_ptr[i], x_val_ptr[i]);
358 }
359 }
360
371 template <typename F, typename Expr,
374 inline void inplace_ops_impl(F&& f, Expr&& other) {
375 auto&& x = to_ref(other);
376 for (int k = 0; k < (*this).outerSize(); ++k) {
377 typename Base::InnerIterator it(*this, k);
378 typename std::decay_t<Expr>::InnerIterator iz(x, k);
379 for (; static_cast<bool>(it) && static_cast<bool>(iz); ++it, ++iz) {
380 f(it.valueRef(), iz.value());
381 }
382 }
383 }
384
395 template <typename F, typename Expr,
398 inline void inplace_ops_impl(F&& f, Expr&& other) {
399 auto&& x = to_ref(other);
400 for (int k = 0; k < (*this).outerSize(); ++k) {
401 typename Base::InnerIterator it(*this, k);
402 for (; static_cast<bool>(it); ++it) {
403 f(it.valueRef(), x(it.row(), it.col()));
404 }
405 }
406 }
407
418 template <typename F, typename T,
420 inline void inplace_ops_impl(F&& f, T&& other) {
421 auto* val_ptr = (*this).valuePtr();
422 const auto non_zeros = (*this).nonZeros();
423 for (Eigen::Index i = 0; i < non_zeros; ++i) {
424 f(val_ptr[i], other);
425 }
426 }
427
428 public:
441 template <typename T>
442 inline arena_matrix& operator+=(T&& other) {
443 inplace_ops_impl(
444 [](auto&& x, auto&& y) {
445 x += y;
446 return;
447 },
448 std::forward<T>(other));
449 return *this;
450 }
451
464 template <typename T>
465 inline arena_matrix& operator-=(T&& other) {
466 inplace_ops_impl(
467 [](auto&& x, auto&& y) {
468 x -= y;
469 return;
470 },
471 std::forward<T>(other));
472 return *this;
473 }
474};
475
476} // namespace math
477} // namespace stan
478
479namespace Eigen {
480namespace internal {
481
482template <typename T>
483struct traits<stan::math::arena_matrix<T>> {
484 using base = traits<Eigen::Map<T>>;
485 using Scalar = typename base::Scalar;
486 using XprKind = typename Eigen::internal::traits<std::decay_t<T>>::XprKind;
487 enum {
488 PlainObjectTypeInnerSize = base::PlainObjectTypeInnerSize,
489 InnerStrideAtCompileTime = base::InnerStrideAtCompileTime,
490 OuterStrideAtCompileTime = base::OuterStrideAtCompileTime,
491 Alignment = base::Alignment,
492 Flags = base::Flags
493 };
494};
495
496} // namespace internal
497} // namespace Eigen
498
499#endif
arena_matrix(const arena_matrix< MatrixType > &other)
Copy constructor.
arena_matrix(Eigen::Index size)
Constructs arena_matrix with given size.
arena_matrix(const Base &other)
Constructs arena_matrix from an expression.
arena_matrix & operator=(const T &other)
Overwrite the current arena_matrix with new memory and assign a matrix to it.
arena_matrix(Eigen::Index rows, Eigen::Index cols)
Constructs arena_matrix with given number of rows and columns.
arena_matrix(const T &other)
Constructs arena_matrix from an expression.
arena_matrix(T &&other)
Constructs arena_matrix from an rvalue expression that is a plain_type, then movies it to the object ...
arena_matrix & operator=(T &&other)
Assignment operator for assigning an expression.
void deep_copy(const T &x)
Forces hard copying matrices into an arena matrix.
arena_matrix & operator=(const arena_matrix< MatrixType > &other)
Copy assignment operator.
void inplace_ops_impl(F &&f, Expr &&other)
inplace operations functor for Sparse (.
arena_matrix(Eigen::Index rows, Eigen::Index cols, Eigen::Index nnz, StorageIndex *outerIndexPtr, StorageIndex *innerIndexPtr, Scalar *valuePtr, StorageIndex *innerNonZerosPtr=nullptr)
Constructor for CDC formatted data.
void inplace_ops_impl(F &&f, T &&other)
inplace operations functor for Sparse (.
arena_matrix & operator=(ArenaMatrix &&other)
Copy assignment operator.
arena_matrix & operator=(Expr &&expr)
Assignment operator for assigning an expression.
arena_matrix(const arena_matrix< MatrixType > &other)
Const copy constructor.
arena_matrix(S &&other)
Constructs arena_matrix from an Eigen expression.
arena_matrix(const Base &other)
Constructs arena_matrix from an expression.
arena_matrix(T &&other)
Constructs arena_matrix from an Eigen::SparseMatrix.
Equivalent to Eigen::Matrix, except that the data is stored on AD stack.
T * alloc_array(size_t n)
Allocate an array on the arena of the specified size to hold values of the specified template paramet...
require_not_t< std::is_convertible< std::decay_t< T >, std::decay_t< S > > > require_not_convertible_t
Require types T and S does not satisfy std::is_convertible.
require_t< std::is_convertible< std::decay_t< T >, std::decay_t< S > > > require_convertible_t
Require types T and S satisfies std::is_convertible.
require_t< is_eigen_dense_base< std::decay_t< T > > > require_eigen_dense_base_t
Require type satisfies is_eigen_dense_base.
require_t< is_eigen_sparse_base< std::decay_t< T > > > require_eigen_sparse_base_t
Require type satisfies is_eigen_sparse_base.
int64_t cols(const T_x &x)
Returns the number of columns in the specified kernel generator expression.
Definition cols.hpp:21
int64_t rows(const T_x &x)
Returns the number of rows in the specified kernel generator expression.
Definition rows.hpp:22
require_not_t< std::is_same< std::decay_t< T >, std::decay_t< S > > > require_not_same_t
Require types T and S does not satisfy std::is_same.
require_t< std::is_same< std::decay_t< T >, std::decay_t< S > > > require_same_t
Require types T and S satisfies std::is_same.
typename value_type< T >::type value_type_t
Helper function for accessing underlying type.
int64_t size(const T &m)
Returns the size (number of the elements) of a matrix_cl or var_value<matrix_cl<T>>.
Definition size.hpp:19
(Expert) Numerical traits for algorithmic differentiation variables.
auto make_chainable_ptr(T &&obj)
Store the given object in a chainable_object so it is destructed only when the chainable stack memory...
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:17
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...
STL namespace.
typename Eigen::internal::traits< std::decay_t< T > >::XprKind XprKind
static thread_local AutodiffStackStorage * instance_
This struct always provides access to the autodiff stack using the singleton pattern.