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
9namespace stan {
10namespace math {
11
12template <typename MatrixType>
13class arena_matrix<MatrixType, require_eigen_dense_base_t<MatrixType>>
14 : public Eigen::Map<MatrixType> {
15 public:
17 using Base = Eigen::Map<MatrixType>;
18 using PlainObject = std::decay_t<MatrixType>;
19 static constexpr int RowsAtCompileTime = MatrixType::RowsAtCompileTime;
20 static constexpr int ColsAtCompileTime = MatrixType::ColsAtCompileTime;
21
26 : Base::Map(nullptr,
27 RowsAtCompileTime == Eigen::Dynamic ? 0 : RowsAtCompileTime,
28 ColsAtCompileTime == Eigen::Dynamic ? 0 : ColsAtCompileTime) {
29 }
30
36 arena_matrix(Eigen::Index rows, Eigen::Index cols)
37 : Base::Map(
38 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(rows * cols),
39 rows, cols) {}
40
46 explicit arena_matrix(Eigen::Index size)
47 : Base::Map(
48 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(size),
49 size) {}
50
55 template <typename T, require_eigen_t<T>* = nullptr>
56 arena_matrix(const T& other) // NOLINT
57 : Base::Map(
58 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(
59 other.size()),
60 (RowsAtCompileTime == 1 && T::ColsAtCompileTime == 1)
61 || (ColsAtCompileTime == 1 && T::RowsAtCompileTime == 1)
62 ? other.cols()
63 : other.rows(),
64 (RowsAtCompileTime == 1 && T::ColsAtCompileTime == 1)
65 || (ColsAtCompileTime == 1 && T::RowsAtCompileTime == 1)
66 ? other.rows()
67 : other.cols()) {
68 *this = other;
69 }
70
76 arena_matrix(const Base& other) // NOLINT
77 : Base::Map(other) {}
78
84 : Base::Map(const_cast<Scalar*>(other.data()), other.rows(),
85 other.cols()) {}
86
87 // without this using, compiler prefers combination of implicit construction
88 // and copy assignment to the inherited operator when assigned an expression
89 using Base::operator=;
90
97 // placement new changes what data map points to - there is no allocation
98 new (this)
99 Base(const_cast<Scalar*>(other.data()), other.rows(), other.cols());
100 return *this;
101 }
102
108 template <typename T>
109 arena_matrix& operator=(const T& a) {
110 // do we need to transpose?
111 if ((RowsAtCompileTime == 1 && T::ColsAtCompileTime == 1)
112 || (ColsAtCompileTime == 1 && T::RowsAtCompileTime == 1)) {
113 // placement new changes what data map points to - there is no allocation
114 new (this) Base(
115 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(a.size()),
116 a.cols(), a.rows());
117
118 } else {
119 new (this) Base(
120 ChainableStack::instance_->memalloc_.alloc_array<Scalar>(a.size()),
121 a.rows(), a.cols());
122 }
123 Base::operator=(a);
124 return *this;
125 }
131 template <typename T>
132 void deep_copy(const T& x) {
133 Base::operator=(x);
134 }
135};
136
137template <typename MatrixType>
138class arena_matrix<MatrixType, require_eigen_sparse_base_t<MatrixType>>
139 : public Eigen::Map<MatrixType> {
140 public:
142 using Base = Eigen::Map<MatrixType>;
143 using PlainObject = std::decay_t<MatrixType>;
144 using StorageIndex = typename PlainObject::StorageIndex;
145
149 arena_matrix() : Base::Map(0, 0, 0, nullptr, nullptr, nullptr) {}
170 arena_matrix(Eigen::Index rows, Eigen::Index cols, Eigen::Index nnz,
171 StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr,
172 Scalar* valuePtr, StorageIndex* innerNonZerosPtr = nullptr)
173 : Base::Map(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr,
174 innerNonZerosPtr) {}
175
176 private:
177 template <typename T, typename Integral>
178 inline T* copy_vector(const T* ptr, Integral size) {
179 if (size == 0)
180 return nullptr;
182 std::copy_n(ptr, size, ret);
183 return ret;
184 }
185
186 public:
191 template <typename T, require_same_t<T, PlainObject>* = nullptr>
192 arena_matrix(T&& other) // NOLINT
193 : Base::Map(
194 other.rows(), other.cols(), other.nonZeros(),
195 copy_vector(other.outerIndexPtr(), other.outerSize() + 1),
196 copy_vector(other.innerIndexPtr(), other.nonZeros()),
197 copy_vector(other.valuePtr(), other.nonZeros()),
198 copy_vector(
199 other.innerNonZeroPtr(),
200 other.innerNonZeroPtr() == nullptr ? 0 : other.innerSize())) {}
201
206 template <typename S, require_convertible_t<S&, PlainObject>* = nullptr,
207 require_not_same_t<S, PlainObject>* = nullptr>
208 arena_matrix(S&& other) // NOLINT
209 : arena_matrix(PlainObject(std::forward<S>(other))) {}
210
216 arena_matrix(const Base& other) // NOLINT
217 : Base(other) {}
218
226 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
227 const_cast<StorageIndex*>(other.outerIndexPtr()),
228 const_cast<StorageIndex*>(other.innerIndexPtr()),
229 const_cast<Scalar*>(other.valuePtr()),
230 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
238 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
239 const_cast<StorageIndex*>(other.outerIndexPtr()),
240 const_cast<StorageIndex*>(other.innerIndexPtr()),
241 const_cast<Scalar*>(other.valuePtr()),
242 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
250 : Base::Map(other.rows(), other.cols(), other.nonZeros(),
251 const_cast<StorageIndex*>(other.outerIndexPtr()),
252 const_cast<StorageIndex*>(other.innerIndexPtr()),
253 const_cast<Scalar*>(other.valuePtr()),
254 const_cast<StorageIndex*>(other.innerNonZeroPtr())) {}
255
256 // without this using, compiler prefers combination of implicit construction
257 // and copy assignment to the inherited operator when assigned an expression
258 using Base::operator=;
259
266 template <typename ArenaMatrix,
268 arena_matrix<MatrixType>>* = nullptr>
269 arena_matrix& operator=(ArenaMatrix&& other) {
270 // placement new changes what data map points to - there is no allocation
271 new (this) Base(other.rows(), other.cols(), other.nonZeros(),
272 const_cast<StorageIndex*>(other.outerIndexPtr()),
273 const_cast<StorageIndex*>(other.innerIndexPtr()),
274 const_cast<Scalar*>(other.valuePtr()),
275 const_cast<StorageIndex*>(other.innerNonZeroPtr()));
276 return *this;
277 }
278
286 template <typename Expr,
288 arena_matrix& operator=(Expr&& expr) {
289 new (this) arena_matrix(std::forward<Expr>(expr));
290 return *this;
291 }
292
293 private:
304 template <typename F, typename Expr,
307 inline void inplace_ops_impl(F&& f, Expr&& other) {
308 auto&& x = to_ref(other);
309 auto* val_ptr = (*this).valuePtr();
310 auto* x_val_ptr = x.valuePtr();
311 const auto non_zeros = (*this).nonZeros();
312 for (Eigen::Index i = 0; i < non_zeros; ++i) {
313 f(val_ptr[i], x_val_ptr[i]);
314 }
315 }
316
327 template <typename F, typename Expr,
330 inline void inplace_ops_impl(F&& f, Expr&& other) {
331 auto&& x = to_ref(other);
332 for (int k = 0; k < (*this).outerSize(); ++k) {
333 typename Base::InnerIterator it(*this, k);
334 typename std::decay_t<Expr>::InnerIterator iz(x, k);
335 for (; static_cast<bool>(it) && static_cast<bool>(iz); ++it, ++iz) {
336 f(it.valueRef(), iz.value());
337 }
338 }
339 }
340
351 template <typename F, typename Expr,
354 inline void inplace_ops_impl(F&& f, Expr&& other) {
355 auto&& x = to_ref(other);
356 for (int k = 0; k < (*this).outerSize(); ++k) {
357 typename Base::InnerIterator it(*this, k);
358 for (; static_cast<bool>(it); ++it) {
359 f(it.valueRef(), x(it.row(), it.col()));
360 }
361 }
362 }
363
374 template <typename F, typename T,
376 inline void inplace_ops_impl(F&& f, T&& other) {
377 auto* val_ptr = (*this).valuePtr();
378 const auto non_zeros = (*this).nonZeros();
379 for (Eigen::Index i = 0; i < non_zeros; ++i) {
380 f(val_ptr[i], other);
381 }
382 }
383
384 public:
397 template <typename T>
398 inline arena_matrix& operator+=(T&& other) {
399 inplace_ops_impl(
400 [](auto&& x, auto&& y) {
401 x += y;
402 return;
403 },
404 std::forward<T>(other));
405 return *this;
406 }
407
420 template <typename T>
421 inline arena_matrix& operator-=(T&& other) {
422 inplace_ops_impl(
423 [](auto&& x, auto&& y) {
424 x -= y;
425 return;
426 },
427 std::forward<T>(other));
428 return *this;
429 }
430};
431
432} // namespace math
433} // namespace stan
434
435namespace Eigen {
436namespace internal {
437
438template <typename T>
439struct traits<stan::math::arena_matrix<T>> {
440 using base = traits<Eigen::Map<T>>;
441 using XprKind = typename Eigen::internal::traits<std::decay_t<T>>::XprKind;
442 enum {
443 PlainObjectTypeInnerSize = base::PlainObjectTypeInnerSize,
444 InnerStrideAtCompileTime = base::InnerStrideAtCompileTime,
445 OuterStrideAtCompileTime = base::OuterStrideAtCompileTime,
446 Alignment = base::Alignment,
447 Flags = base::Flags
448 };
449};
450
451} // namespace internal
452} // namespace Eigen
453
454#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 &a)
Assignment operator for assigning an expression.
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.
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.
int rows(const T_x &x)
Returns the number of rows in the specified kernel generator expression.
Definition rows.hpp:21
int cols(const T_x &x)
Returns the number of columns in the specified kernel generator expression.
Definition cols.hpp:20
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.
size_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:18
(Expert) Numerical traits for algorithmic differentiation variables.
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 ...
Definition fvar.hpp:9
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.