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