14#include <lagrange/Logger.h>
15#include <lagrange/common.h>
16#include <lagrange/experimental/Scalar.h>
17#include <lagrange/utils/assert.h>
18#include <lagrange/utils/build.h>
19#include <lagrange/utils/range.h>
20#include <lagrange/utils/strings.h>
28namespace experimental {
30template <
typename Data>
38 using Index = Eigen::Index;
41 ArrayBase(ScalarEnum type)
45 virtual ~ArrayBase() =
default;
48 template <
typename TargetType>
49 Eigen::Map<TargetType> view()
52 is_compatible<TargetType>(),
53 "Target view type is not compatible with the data.");
54 return Eigen::Map<TargetType>(data<typename TargetType::Scalar>(), rows(), cols());
57 template <
typename TargetType>
58 Eigen::Map<const TargetType> view()
const
61 is_compatible<TargetType>(),
62 "Target view type is not compatible with the data.");
63 return Eigen::Map<const TargetType>(data<typename TargetType::Scalar>(), rows(), cols());
66 virtual std::any get_type_info()
const = 0;
68 template <
typename Derived>
69 bool is_base_of()
const
71 std::any info = get_type_info();
72 return std::any_cast<ArrayTypeInfo<Derived>>(&info) !=
nullptr;
75 template <
typename DerivedPtr>
76 auto down_cast() -> std::add_pointer_t<std::decay_t<std::remove_pointer_t<DerivedPtr>>>
78 using Derived = std::decay_t<std::remove_pointer_t<DerivedPtr>>;
79#if LAGRANGE_ENABLE_RTTI
80 return dynamic_cast<Derived*
>(
this);
82 if (is_base_of<Derived>()) {
83 return static_cast<Derived*
>(
this);
89 template <
typename DerivedPtr>
90 auto down_cast()
const
91 -> std::add_pointer_t<std::add_const_t<std::decay_t<std::remove_pointer_t<DerivedPtr>>>>
93 using Derived = std::decay_t<std::remove_pointer_t<DerivedPtr>>;
94#if LAGRANGE_ENABLE_RTTI
95 return dynamic_cast<const Derived*
>(
this);
97 if (is_base_of<Derived>()) {
98 return static_cast<const Derived*
>(
this);
104 template <
typename Derived>
105 void set(
const Eigen::MatrixBase<Derived>& data);
107 template <
typename Derived>
108 void set(Eigen::MatrixBase<Derived>&& data);
110 ScalarEnum get_scalar_type()
const {
return m_scalar_type; }
112 template <
typename TargetType>
113 const auto& get()
const;
115 template <
typename TargetType>
118 template <
typename Scalar>
122 return static_cast<Scalar*
>(data());
125 template <
typename Scalar>
126 const Scalar* data()
const
129 return static_cast<const Scalar*
>(data());
132 virtual Index rows()
const = 0;
133 virtual Index cols()
const = 0;
134 virtual bool is_row_major()
const = 0;
135 virtual void* data() = 0;
136 virtual const void* data()
const = 0;
137 virtual void resize(Index, Index) = 0;
138 virtual std::unique_ptr<ArrayBase> clone()
const = 0;
140 using IndexFunction = std::function<Index(Index)>;
141 using WeightedIndexFunction =
142 std::function<void(Index, std::vector<std::pair<Index, double>>&)>;
144 template <
typename T>
145 std::unique_ptr<ArrayBase> row_slice(
const std::vector<T>& row_indices)
const
148 return safe_cast<Index>(row_indices[i]);
159 virtual std::unique_ptr<ArrayBase>
row_slice(Index num_rows,
const IndexFunction& mapping_fn)
171 const WeightedIndexFunction& mapping_fn)
const = 0;
173 virtual std::string type_name()
const = 0;
176 template <
typename TargetType>
177 bool is_compatible(
bool ignore_storage_order =
false)
const;
179 template <
typename Derived>
180 static std::unique_ptr<ArrayBase> row_slice_impl(
181 const Eigen::MatrixBase<Derived>& matrix,
183 const IndexFunction& mapping);
185 template <
typename Derived>
187 enable_if_t<std::is_integral<typename Derived::Scalar>::value, std::unique_ptr<ArrayBase>>
189 const Eigen::MatrixBase<Derived>& matrix,
191 const WeightedIndexFunction& mapping);
193 template <
typename Derived>
195 enable_if_t<!std::is_integral<typename Derived::Scalar>::value, std::unique_ptr<ArrayBase>>
197 const Eigen::MatrixBase<Derived>& matrix,
199 const WeightedIndexFunction& mapping);
202 const ScalarEnum m_scalar_type;
209template <
typename _EigenType>
210class EigenArray :
public ArrayBase
213 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
214 using EigenType = _EigenType;
215 using Self = EigenArray<EigenType>;
216 using Index = ArrayBase::Index;
217 using ArrayBase::WeightedIndexFunction;
219 std::is_base_of<typename Eigen::EigenBase<EigenType>, EigenType>::value,
220 "Template parameter `_EigenType` is not an Eigen type!");
221 static_assert(!std::is_const<EigenType>::value,
"EigenType should not be const type.");
222 static_assert(!std::is_reference<EigenType>::value,
"EigenType should not be reference type.");
226 : ArrayBase(ScalarToEnum_v<typename EigenType::Scalar>)
229 template <
typename T>
230 explicit EigenArray(
const Eigen::MatrixBase<T>& data)
231 : ArrayBase(ScalarToEnum_v<typename EigenType::Scalar>)
235 template <
typename T>
236 explicit EigenArray(Eigen::MatrixBase<T>&& data)
237 : ArrayBase(ScalarToEnum_v<typename EigenType::Scalar>)
238 , m_data(std::move(data.derived()))
241 std::any get_type_info()
const override {
return std::make_any<ArrayTypeInfo<Self>>(); }
244 EigenType& get_ref() {
return m_data; }
245 const EigenType& get_ref()
const {
return m_data; }
247 template <
typename Derived>
248 void set(Derived&& data)
250 m_data = std::forward<Derived>(data);
253 Index rows()
const override {
return m_data.rows(); }
254 Index cols()
const override {
return m_data.cols(); }
255 bool is_row_major()
const override {
return EigenType::IsRowMajor != 0; }
256 void* data()
override {
return static_cast<void*
>(m_data.derived().data()); }
257 const void* data()
const override {
return static_cast<const void*
>(m_data.derived().data()); }
258 void resize(Index r, Index c)
override { m_data.resize(r, c); }
260 std::unique_ptr<ArrayBase> clone()
const override
262 return std::make_unique<EigenArray<EigenType>>(m_data);
265 std::unique_ptr<ArrayBase>
row_slice(Index num_rows,
const IndexFunction& mapping_fn)
268 return row_slice_impl(m_data, num_rows, mapping_fn);
270 std::unique_ptr<ArrayBase>
row_slice(Index num_rows,
const WeightedIndexFunction& mapping_fn)
273 return row_slice_impl(m_data, num_rows, mapping_fn);
276 std::string type_name()
const override
280 "EigenArray<Eigen::Matrix<{}, {}, {}, {}>>",
282 static_cast<int>(EigenType::RowsAtCompileTime),
283 static_cast<int>(EigenType::ColsAtCompileTime),
284 static_cast<int>(EigenType::Options));
296template <typename _EigenType, bool IsConst = std::is_const<_EigenType>::value>
299template <
typename _EigenType>
303 using EigenType = _EigenType;
305 using DecayedEigenType = std::decay_t<_EigenType>;
306 using Index = ArrayBase::Index;
307 using ArrayBase::WeightedIndexFunction;
309 std::is_base_of<typename Eigen::EigenBase<DecayedEigenType>, DecayedEigenType>::value,
310 "Template parameter `_EigenType` is not an Eigen type!");
311 static_assert(!std::is_const<EigenType>::value,
"EigenType should not be const type.");
312 static_assert(!std::is_reference<EigenType>::value,
"EigenType should not be reference type.");
315 template <
typename T>
318 , m_data(data.derived())
321 std::any get_type_info()
const override {
return std::make_any<ArrayTypeInfo<Self>>(); }
324 EigenType& get_ref() {
return m_data; }
325 const EigenType& get_ref()
const {
return m_data; }
327 template <
typename Derived>
328 void set(Derived&& data)
330 m_data = std::forward<Derived>(data);
333 Index rows()
const override {
return m_data.rows(); }
334 Index cols()
const override {
return m_data.cols(); }
335 bool is_row_major()
const override {
return EigenType::IsRowMajor != 0; }
336 void* data()
override {
return static_cast<void*
>(m_data.derived().data()); }
337 const void* data()
const override {
return static_cast<const void*
>(m_data.derived().data()); }
338 void resize(Index r, Index c)
override { m_data.resize(r, c); }
340 std::unique_ptr<ArrayBase> clone()
const override
342 return std::make_unique<EigenArray<DecayedEigenType>>(m_data);
345 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const IndexFunction& mapping_fn)
348 return row_slice_impl(m_data, num_rows, mapping_fn);
350 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const WeightedIndexFunction& mapping_fn)
353 return row_slice_impl(m_data, num_rows, mapping_fn);
356 std::string type_name()
const override
358 std::string scalar_name(ScalarToEnum<typename EigenType::Scalar>::name);
360 "EigenArrayRef<Eigen::Matrix<{}, {}, {}, {}>>",
362 static_cast<int>(EigenType::RowsAtCompileTime),
363 static_cast<int>(EigenType::ColsAtCompileTime),
364 static_cast<int>(EigenType::Options));
371template <
typename _EigenType>
375 using EigenType = _EigenType;
376 using Self = EigenArrayRef<_EigenType, true>;
377 using DecayedEigenType = std::decay_t<_EigenType>;
378 using Index = ArrayBase::Index;
379 using ArrayBase::WeightedIndexFunction;
381 std::is_base_of<typename Eigen::EigenBase<DecayedEigenType>, DecayedEigenType>::value,
382 "Template parameter `_EigenType` is not an Eigen type!");
383 static_assert(std::is_const<EigenType>::value,
"EigenType must const type.");
384 static_assert(!std::is_reference<EigenType>::value,
"EigenType should not be reference type.");
387 template <
typename T>
388 explicit EigenArrayRef(
const Eigen::MatrixBase<T>& data)
389 : ArrayBase(ScalarToEnum_v<typename EigenType::
Scalar>)
390 , m_data(data.derived())
393 std::any get_type_info()
const override {
return std::make_any<ArrayTypeInfo<Self>>(); }
396 const EigenType& get_ref()
const {
return m_data; }
398 Index rows()
const override {
return m_data.rows(); }
399 Index cols()
const override {
return m_data.cols(); }
400 bool is_row_major()
const override {
return EigenType::IsRowMajor != 0; }
401 const void* data()
const override {
return static_cast<const void*
>(m_data.derived().data()); }
402 void* data()
override {
throw std::runtime_error(
"This method is not supported"); }
404 void resize(Index r, Index c)
override
406 if (r != m_data.rows() || c != m_data.cols()) {
407 throw std::runtime_error(
"Resizing const EigenArrayRef is not allowed.");
411 std::unique_ptr<ArrayBase> clone()
const override
413 return std::make_unique<EigenArray<DecayedEigenType>>(m_data);
416 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const IndexFunction& mapping_fn)
419 return row_slice_impl(m_data, num_rows, mapping_fn);
421 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const WeightedIndexFunction& mapping_fn)
424 return row_slice_impl(m_data, num_rows, mapping_fn);
427 std::string type_name()
const override
429 std::string scalar_name(ScalarToEnum<typename EigenType::Scalar>::name);
431 "EigenArrayRef<const Eigen::Matrix<{}, {}, {}, {}>>",
433 static_cast<int>(EigenType::RowsAtCompileTime),
434 static_cast<int>(EigenType::ColsAtCompileTime),
435 static_cast<int>(EigenType::Options));
449 int _Rows = Eigen::Dynamic,
450 int _Cols = Eigen::Dynamic,
451 int _Options = Eigen::RowMajor,
452 bool IsConst = std::is_const<_Scalar>::value>
455template <
typename _Scalar,
int _Rows,
int _Cols,
int _Options>
461 using Index = ArrayBase::Index;
462 using EigenType = Eigen::Matrix<Scalar, _Rows, _Cols, _Options>;
463 using EigenMap = Eigen::Map<EigenType>;
464 using ConstEigenMap = Eigen::Map<const EigenType>;
465 using ArrayBase::WeightedIndexFunction;
470 , m_data(data, rows, cols)
473 std::any get_type_info()
const override {
return std::make_any<ArrayTypeInfo<Self>>(); }
476 EigenMap& get_ref() {
return m_data; }
477 ConstEigenMap get_ref()
const {
return m_data; }
479 template <
typename Derived>
480 void set(
const Eigen::MatrixBase<Derived>& data)
485 void set(
Scalar* data, Index rows, Index cols) { m_data = EigenMap(data, rows, cols); }
487 Index rows()
const override {
return m_data.rows(); }
488 Index cols()
const override {
return m_data.cols(); }
489 bool is_row_major()
const override {
return EigenType::IsRowMajor != 0; }
490 void* data()
override {
return static_cast<void*
>(m_data.data()); }
491 const void* data()
const override {
return static_cast<const void*
>(m_data.data()); }
492 void resize(Index r, Index c)
override
494 if (r != m_data.rows() || c != m_data.cols()) {
495 throw std::runtime_error(
"Resizing RawArray is not allowed.");
499 std::unique_ptr<ArrayBase> clone()
const override
501 return std::make_unique<EigenArray<EigenType>>(m_data);
504 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const IndexFunction& mapping_fn)
507 return row_slice_impl(m_data, num_rows, mapping_fn);
509 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const WeightedIndexFunction& mapping_fn)
512 return row_slice_impl(m_data, num_rows, mapping_fn);
515 std::string type_name()
const override
517 std::string scalar_name(ScalarToEnum<Scalar>::name);
518 return string_format(
"RawArray<{}, {}, {}, {}>", scalar_name, _Rows, _Cols, _Options);
525template <
typename _Scalar,
int _Rows,
int _Cols,
int _Options>
529 using Self = RawArray<_Scalar, _Rows, _Cols, _Options, true>;
530 using Scalar = std::decay_t<_Scalar>;
531 using Index = ArrayBase::Index;
532 using EigenType = Eigen::Matrix<Scalar, _Rows, _Cols, _Options>;
533 using EigenMap = Eigen::Map<const EigenType>;
534 using ArrayBase::WeightedIndexFunction;
537 RawArray(
const Scalar* data, Index rows, Index cols)
538 : ArrayBase(ScalarToEnum_v<typename EigenType::
Scalar>)
539 , m_data(data, rows, cols)
542 std::any get_type_info()
const override {
return std::make_any<ArrayTypeInfo<Self>>(); }
545 const EigenMap& get_ref()
const {
return m_data; }
547 Index rows()
const override {
return m_data.rows(); }
548 Index cols()
const override {
return m_data.cols(); }
549 bool is_row_major()
const override {
return EigenType::IsRowMajor != 0; }
550 const void* data()
const override {
return static_cast<const void*
>(m_data.data()); }
551 void* data()
override {
throw std::runtime_error(
"This method is not supported"); }
553 void resize(Index r, Index c)
override
555 if (r != m_data.rows() || c != m_data.cols()) {
556 throw std::runtime_error(
"Resizing RawArray is not allowed.");
560 std::unique_ptr<ArrayBase> clone()
const override
562 return std::make_unique<EigenArray<EigenType>>(m_data);
565 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const IndexFunction& mapping_fn)
568 return row_slice_impl(m_data, num_rows, mapping_fn);
570 std::unique_ptr<ArrayBase> row_slice(Index num_rows,
const WeightedIndexFunction& mapping_fn)
573 return row_slice_impl(m_data, num_rows, mapping_fn);
576 std::string type_name()
const override
578 std::string scalar_name(ScalarToEnum<Scalar>::name);
579 return string_format(
"RawArray<const {}, {}, {}, {}>", scalar_name, _Rows, _Cols, _Options);
583 const EigenMap m_data;
589#include "Array.impl.h"
590#include "Array.serialization.h"
virtual std::unique_ptr< ArrayBase > row_slice(Index num_rows, const IndexFunction &mapping_fn) const =0
Using index function for row mapping.
virtual std::unique_ptr< ArrayBase > row_slice(Index num_rows, const WeightedIndexFunction &mapping_fn) const =0
This is the most generic version of row_slice method.
std::unique_ptr< ArrayBase > row_slice(Index num_rows, const IndexFunction &mapping_fn) const override
Using index function for row mapping.
Definition Array.h:265
std::unique_ptr< ArrayBase > row_slice(Index num_rows, const WeightedIndexFunction &mapping_fn) const override
This is the most generic version of row_slice method.
Definition Array.h:270
This class is a thin wrapper around an Eigen matrix.
Definition Array.h:297
This class provide a thin wrapper around a raw array.
Definition Array.h:453
@ Scalar
Mesh attribute must have exactly 1 channel.
Definition AttributeFwd.h:56
#define la_runtime_assert(...)
Runtime assertion check.
Definition assert.h:177
std::string string_format(lagrange::format_string< Args... > format, Args &&... args)
Format args according to the format string fmt, and return the result as a string.
Definition strings.h:97
constexpr auto safe_cast(SourceType value) -> std::enable_if_t<!std::is_same< SourceType, TargetType >::value, TargetType >
Perform safe cast from SourceType to TargetType, where "safe" means:
Definition safe_cast.h:51
Main namespace for Lagrange.