Eigen  5.0.1
 
Loading...
Searching...
No Matches
Fill.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2024 Charles Schlosser <cs.schlosser@gmail.com>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_FILL_H
12#define EIGEN_FILL_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <typename Xpr>
22struct eigen_fill_helper : std::false_type {};
23
24// Only enable std::fill_n for trivially copyable scalars. GCC's libstdc++
25// fill_n pessimizes non-trivially-copyable types (extra moves per iteration),
26// causing measurable regressions for types like AutoDiffScalar (issue #2956).
27template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
28struct eigen_fill_helper<Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>> : std::is_trivially_copyable<Scalar> {};
29
30template <typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
31struct eigen_fill_helper<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols>> : std::is_trivially_copyable<Scalar> {};
32
33template <typename Xpr, int BlockRows, int BlockCols>
34struct eigen_fill_helper<Block<Xpr, BlockRows, BlockCols, /*InnerPanel*/ true>> : eigen_fill_helper<Xpr> {};
35
36template <typename Xpr, int BlockRows, int BlockCols>
37struct eigen_fill_helper<Block<Xpr, BlockRows, BlockCols, /*InnerPanel*/ false>>
38 : bool_constant<eigen_fill_helper<Xpr>::value && (Xpr::IsRowMajor ? (BlockRows == 1) : (BlockCols == 1))> {};
39
40template <typename Xpr, int Options>
41struct eigen_fill_helper<Map<Xpr, Options, Stride<0, 0>>> : eigen_fill_helper<Xpr> {};
42
43template <typename Xpr, int Options, int OuterStride_>
44struct eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>>
45 : bool_constant<eigen_fill_helper<Xpr>::value && enum_eq_not_dynamic(OuterStride_, Xpr::InnerSizeAtCompileTime)> {};
46
47template <typename Xpr, int Options, int OuterStride_>
48struct eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 1>>>
49 : eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>> {};
50
51template <typename Xpr, int Options, int InnerStride_>
52struct eigen_fill_helper<Map<Xpr, Options, InnerStride<InnerStride_>>>
53 : eigen_fill_helper<Map<Xpr, Options, Stride<0, InnerStride_>>> {};
54
55template <typename Xpr, int Options, int OuterStride_>
56struct eigen_fill_helper<Map<Xpr, Options, OuterStride<OuterStride_>>>
57 : eigen_fill_helper<Map<Xpr, Options, Stride<OuterStride_, 0>>> {};
58
59template <typename Xpr>
60struct eigen_fill_impl<Xpr, /*use_fill*/ false> {
61 using Scalar = typename Xpr::Scalar;
62 using PlainObject = typename Xpr::PlainObject;
63 using Constant = typename PlainObject::ConstantReturnType;
64 static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const Scalar& val) {
65 const Constant src(dst.rows(), dst.cols(), val);
66 run(dst, src);
67 }
68 template <typename SrcXpr>
69 static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const SrcXpr& src) {
70 call_dense_assignment_loop(dst, src, assign_op<Scalar, Scalar>());
71 }
72};
73
74#if EIGEN_COMP_MSVC || defined(EIGEN_GPU_COMPILE_PHASE)
75template <typename Xpr>
76struct eigen_fill_impl<Xpr, /*use_fill*/ true> : eigen_fill_impl<Xpr, /*use_fill*/ false> {};
77#else
78template <typename Xpr>
79struct eigen_fill_impl<Xpr, /*use_fill*/ true> {
80 using Scalar = typename Xpr::Scalar;
81 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const Scalar& val) {
82 const Scalar val_copy = val;
83 using std::fill_n;
84 fill_n(dst.data(), dst.size(), val_copy);
85 }
86 template <typename SrcXpr>
87 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) {
88 resize_if_allowed(dst, src, assign_op<Scalar, Scalar>());
89 const Scalar& val = src.functor()();
90 run(dst, val);
91 }
92};
93#endif
94
95template <typename Xpr>
96struct eigen_memset_helper {
97 using Scalar = typename Xpr::Scalar;
98 static constexpr bool value = std::is_trivially_copyable<Scalar>::value &&
99 !static_cast<bool>(NumTraits<Scalar>::RequireInitialization) &&
100 eigen_fill_helper<Xpr>::value;
101};
102
103template <typename Xpr>
104struct eigen_zero_impl<Xpr, /*use_memset*/ false> {
105 using Scalar = typename Xpr::Scalar;
106 using PlainObject = typename Xpr::PlainObject;
107 using Zero = typename PlainObject::ZeroReturnType;
108 static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst) {
109 const Zero src(dst.rows(), dst.cols());
110 run(dst, src);
111 }
112 template <typename SrcXpr>
113 static EIGEN_DEVICE_FUNC constexpr void run(Xpr& dst, const SrcXpr& src) {
114 call_dense_assignment_loop(dst, src, assign_op<Scalar, Scalar>());
115 }
116};
117
118template <typename Xpr>
119struct eigen_zero_impl<Xpr, /*use_memset*/ true> {
120 using Scalar = typename Xpr::Scalar;
121 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst) {
122 Index size = dst.size();
123 EIGEN_IF_CONSTEXPR (Xpr::MaxSizeAtCompileTime != Dynamic) {
124 if (size > Xpr::MaxSizeAtCompileTime) {
125 eigen_internal_assert(false && "invalid dense object size");
126 return;
127 }
128 }
129 const std::ptrdiff_t num_bytes = size * static_cast<std::ptrdiff_t>(sizeof(Scalar));
130 if (num_bytes <= 0) return;
131 void* dst_ptr = static_cast<void*>(dst.data());
132#ifndef EIGEN_NO_DEBUG
133 eigen_assert((dst_ptr != nullptr) && "null pointer dereference error!");
134#endif
135 EIGEN_USING_STD(memset);
136 memset(dst_ptr, 0, static_cast<std::size_t>(num_bytes));
137 }
138 template <typename SrcXpr>
139 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void run(Xpr& dst, const SrcXpr& src) {
140 resize_if_allowed(dst, src, assign_op<Scalar, Scalar>());
141 run(dst);
142 }
143};
144
145} // namespace internal
146} // namespace Eigen
147
148#endif // EIGEN_FILL_H