Eigen  5.0.1-dev+60122df6
 
Loading...
Searching...
No Matches
NullaryFunctors.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-2016 Gael Guennebaud <gael.guennebaud@inria.fr>
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
10#ifndef EIGEN_NULLARY_FUNCTORS_H
11#define EIGEN_NULLARY_FUNCTORS_H
12
13// IWYU pragma: private
14#include "../InternalHeaderCheck.h"
15
16namespace Eigen {
17
18namespace internal {
19
20template <typename Scalar>
21struct scalar_constant_op {
22 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_constant_op(const Scalar& other) : m_other(other) {}
23 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()() const { return m_other; }
24 template <typename PacketType>
25 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp() const {
26 return internal::pset1<PacketType>(m_other);
27 }
28 const Scalar m_other;
29};
30template <typename Scalar>
31struct functor_traits<scalar_constant_op<Scalar>> {
32 enum {
33 Cost = 0 /* as the constant value should be loaded in register only once for the whole expression */,
34 PacketAccess = packet_traits<Scalar>::Vectorizable,
35 IsRepeatable = true
36 };
37};
38
39template <typename Scalar>
40struct scalar_zero_op {
41 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE scalar_zero_op() = default;
42 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()() const { return Scalar(0); }
43 template <typename PacketType>
44 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const PacketType packetOp() const {
45 return internal::pzero<PacketType>(PacketType());
46 }
47};
48template <typename Scalar>
49struct functor_traits<scalar_zero_op<Scalar>> : functor_traits<scalar_constant_op<Scalar>> {};
50
51template <typename Scalar>
52struct scalar_identity_op {
53 template <typename IndexType>
54 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(IndexType row, IndexType col) const {
55 return row == col ? Scalar(1) : Scalar(0);
56 }
57};
58template <typename Scalar>
59struct functor_traits<scalar_identity_op<Scalar>> {
60 enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = false, IsRepeatable = true };
61};
62
63template <typename Scalar, bool IsInteger>
64struct linspaced_op_impl;
65
66template <typename Scalar>
67struct linspaced_op_impl<Scalar, /*IsInteger*/ false> {
68 typedef typename NumTraits<Scalar>::Real RealScalar;
69
70 EIGEN_DEVICE_FUNC linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps)
71 : m_low(low),
72 m_high(high),
73 m_size1(num_steps == 1 ? 1 : num_steps - 1),
74 m_step(num_steps == 1 ? Scalar() : Scalar((high - low) / RealScalar(num_steps - 1))),
75 m_flip(numext::abs(high) < numext::abs(low)) {}
76
77 template <typename IndexType>
78 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(IndexType i) const {
79 if (m_flip)
80 return (i == 0) ? m_low : Scalar(m_high - RealScalar(m_size1 - i) * m_step);
81 else
82 return (i == m_size1) ? m_high : Scalar(m_low + RealScalar(i) * m_step);
83 }
84
85 template <typename Packet, typename IndexType>
86 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const {
87 // Principle:
88 // [low, ..., low] + ( [step, ..., step] * ( [i, ..., i] + [0, ..., size] ) )
89 Packet low = pset1<Packet>(m_low);
90 Packet high = pset1<Packet>(m_high);
91 Packet step = pset1<Packet>(m_step);
92 if (m_flip) {
93 Packet pi = plset<Packet>(Scalar(i - m_size1));
94 Packet res = pmadd(step, pi, high);
95 Packet mask = pcmp_lt(pzero(res), plset<Packet>(Scalar(i)));
96 return pselect<Packet>(mask, res, low);
97 } else {
98 Packet pi = plset<Packet>(Scalar(i));
99 Packet res = pmadd(step, pi, low);
100 Packet mask = pcmp_lt(pi, pset1<Packet>(Scalar(m_size1)));
101 return pselect<Packet>(mask, res, high);
102 }
103 }
104
105 const Scalar m_low;
106 const Scalar m_high;
107 const Index m_size1;
108 const Scalar m_step;
109 const bool m_flip;
110};
111
112template <typename Scalar>
113struct linspaced_op_impl<Scalar, /*IsInteger*/ true> {
114 EIGEN_DEVICE_FUNC linspaced_op_impl(const Scalar& low, const Scalar& high, Index num_steps)
115 : m_low(low),
116 m_multiplier((high - low) / convert_index<Scalar>(num_steps <= 1 ? 1 : num_steps - 1)),
117 m_divisor(convert_index<Scalar>((high >= low ? num_steps : -num_steps) + (high - low)) /
118 ((numext::abs(high - low) + 1) == 0 ? 1 : (numext::abs(high - low) + 1))),
119 m_use_divisor(num_steps > 1 && (numext::abs(high - low) + 1) < num_steps) {}
120
121 template <typename IndexType>
122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(IndexType i) const {
123 if (m_use_divisor)
124 return m_low + convert_index<Scalar>(i) / m_divisor;
125 else
126 return m_low + convert_index<Scalar>(i) * m_multiplier;
127 }
128
129 const Scalar m_low;
130 const Scalar m_multiplier;
131 const Scalar m_divisor;
132 const bool m_use_divisor;
133};
134
135// ----- Linspace functor ----------------------------------------------------------------
136
137// Forward declaration (we default to random access which does not really give
138// us a speed gain when using packet access but it allows to use the functor in
139// nested expressions).
140template <typename Scalar>
141struct linspaced_op;
142template <typename Scalar>
143struct functor_traits<linspaced_op<Scalar>> {
144 enum {
145 Cost = 1,
146 PacketAccess = (!NumTraits<Scalar>::IsInteger) && packet_traits<Scalar>::HasSetLinear,
147 /*&& ((!NumTraits<Scalar>::IsInteger) || packet_traits<Scalar>::HasDiv),*/ // <- vectorization for integer is
148 // currently disabled
149 IsRepeatable = true
150 };
151};
152template <typename Scalar>
153struct linspaced_op {
154 EIGEN_DEVICE_FUNC linspaced_op(const Scalar& low, const Scalar& high, Index num_steps)
155 : impl((num_steps == 1 ? high : low), high, num_steps) {}
156
157 template <typename IndexType>
158 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(IndexType i) const {
159 return impl(i);
160 }
161
162 template <typename Packet, typename IndexType>
163 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(IndexType i) const {
164 return impl.template packetOp<Packet>(i);
165 }
166
167 // This proxy object handles the actual required temporaries and the different
168 // implementations (integer vs. floating point).
169 const linspaced_op_impl<Scalar, NumTraits<Scalar>::IsInteger> impl;
170};
171
172template <typename Scalar>
173struct equalspaced_op {
174 typedef typename NumTraits<Scalar>::Real RealScalar;
175
176 EIGEN_DEVICE_FUNC equalspaced_op(const Scalar& start, const Scalar& step) : m_start(start), m_step(step) {}
177 template <typename IndexType>
178 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(IndexType i) const {
179 return m_start + m_step * static_cast<Scalar>(i);
180 }
181 template <typename Packet, typename IndexType>
182 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(IndexType i) const {
183 const Packet cst_start = pset1<Packet>(m_start);
184 const Packet cst_step = pset1<Packet>(m_step);
185 const Packet cst_lin0 = plset<Packet>(Scalar(0));
186 const Packet cst_offset = pmadd(cst_lin0, cst_step, cst_start);
187
188 Packet i_packet = pset1<Packet>(static_cast<Scalar>(i));
189 return pmadd(i_packet, cst_step, cst_offset);
190 }
191 const Scalar m_start;
192 const Scalar m_step;
193};
194
195template <typename Scalar>
196struct functor_traits<equalspaced_op<Scalar>> {
197 enum {
198 Cost = NumTraits<Scalar>::AddCost + NumTraits<Scalar>::MulCost,
199 PacketAccess =
200 packet_traits<Scalar>::HasSetLinear && packet_traits<Scalar>::HasMul && packet_traits<Scalar>::HasAdd,
201 IsRepeatable = true
202 };
203};
204
205// Linear access is automatically determined from the operator() prototypes available for the given functor.
206// If it exposes an operator()(i,j), then we assume the i and j coefficients are required independently
207// and linear access is not possible. In all other cases, linear access is enabled.
208// Users should not have to deal with this structure.
209template <typename Functor>
210struct functor_has_linear_access {
211 enum { ret = !has_binary_operator<Functor>::value };
212};
213
214// For unreliable compilers, let's specialize the has_*ary_operator
215// helpers so that at least built-in nullary functors work fine.
216#if !(EIGEN_COMP_MSVC || EIGEN_COMP_GNUC || (EIGEN_COMP_ICC >= 1600))
217template <typename Scalar, typename IndexType>
218struct has_nullary_operator<scalar_constant_op<Scalar>, IndexType> {
219 enum { value = 1 };
220};
221template <typename Scalar, typename IndexType>
222struct has_unary_operator<scalar_constant_op<Scalar>, IndexType> {
223 enum { value = 0 };
224};
225template <typename Scalar, typename IndexType>
226struct has_binary_operator<scalar_constant_op<Scalar>, IndexType> {
227 enum { value = 0 };
228};
229
230template <typename Scalar, typename IndexType>
231struct has_nullary_operator<scalar_identity_op<Scalar>, IndexType> {
232 enum { value = 0 };
233};
234template <typename Scalar, typename IndexType>
235struct has_unary_operator<scalar_identity_op<Scalar>, IndexType> {
236 enum { value = 0 };
237};
238template <typename Scalar, typename IndexType>
239struct has_binary_operator<scalar_identity_op<Scalar>, IndexType> {
240 enum { value = 1 };
241};
242
243template <typename Scalar, typename IndexType>
244struct has_nullary_operator<linspaced_op<Scalar>, IndexType> {
245 enum { value = 0 };
246};
247template <typename Scalar, typename IndexType>
248struct has_unary_operator<linspaced_op<Scalar>, IndexType> {
249 enum { value = 1 };
250};
251template <typename Scalar, typename IndexType>
252struct has_binary_operator<linspaced_op<Scalar>, IndexType> {
253 enum { value = 0 };
254};
255
256template <typename Scalar, typename IndexType>
257struct has_nullary_operator<scalar_random_op<Scalar>, IndexType> {
258 enum { value = 1 };
259};
260template <typename Scalar, typename IndexType>
261struct has_unary_operator<scalar_random_op<Scalar>, IndexType> {
262 enum { value = 0 };
263};
264template <typename Scalar, typename IndexType>
265struct has_binary_operator<scalar_random_op<Scalar>, IndexType> {
266 enum { value = 0 };
267};
268#endif
269
270} // end namespace internal
271
272} // end namespace Eigen
273
274#endif // EIGEN_NULLARY_FUNCTORS_H
Namespace containing all symbols from the Eigen library.
Definition B01_Experimental.dox:1
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition Meta.h:82