mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Remove CXX11/ directory nesting for Tensor modules
libeigen/eigen!2199 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
422
unsupported/Eigen/src/Tensor/TensorFunctors.h
Normal file
422
unsupported/Eigen/src/Tensor/TensorFunctors.h
Normal file
@@ -0,0 +1,422 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
|
||||
#define EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
|
||||
|
||||
// IWYU pragma: private
|
||||
#include "./InternalHeaderCheck.h"
|
||||
|
||||
namespace Eigen {
|
||||
namespace internal {
|
||||
|
||||
/** \internal
|
||||
* \brief Template functor to compute the modulo between an array and a scalar.
|
||||
*/
|
||||
template <typename Scalar>
|
||||
struct scalar_mod_op {
|
||||
EIGEN_DEVICE_FUNC scalar_mod_op(const Scalar& divisor) : m_divisor(divisor) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const { return a % m_divisor; }
|
||||
const Scalar m_divisor;
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_mod_op<Scalar> > {
|
||||
enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess = false };
|
||||
};
|
||||
|
||||
/** \internal
|
||||
* \brief Template functor to compute the modulo between 2 arrays.
|
||||
*/
|
||||
template <typename Scalar>
|
||||
struct scalar_mod2_op {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const { return a % b; }
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_mod2_op<Scalar> > {
|
||||
enum { Cost = scalar_div_cost<Scalar, false>::value, PacketAccess = false };
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct scalar_fmod_op {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
|
||||
return numext::fmod(a, b);
|
||||
}
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_fmod_op<Scalar> > {
|
||||
enum {
|
||||
Cost = 13, // Reciprocal throughput of FPREM on Haswell.
|
||||
PacketAccess = false
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Reducer, typename Device>
|
||||
struct reducer_traits {
|
||||
enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
|
||||
};
|
||||
|
||||
// Standard reduction functors
|
||||
template <typename T>
|
||||
struct SumReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
|
||||
internal::scalar_sum_op<T> sum_op;
|
||||
*accum = sum_op(*accum, t);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
|
||||
(*accum) = padd<Packet>(*accum, p);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
internal::scalar_cast_op<int, T> conv;
|
||||
return conv(0);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
|
||||
return pset1<Packet>(initialize());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
|
||||
return vaccum;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
|
||||
internal::scalar_sum_op<T> sum_op;
|
||||
return sum_op(saccum, predux(vaccum));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct reducer_traits<SumReducer<T>, Device> {
|
||||
enum {
|
||||
Cost = NumTraits<T>::AddCost,
|
||||
PacketAccess = PacketType<T, Device>::HasAdd,
|
||||
IsStateful = false,
|
||||
IsExactlyAssociative = NumTraits<T>::IsInteger
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct MeanReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MeanReducer() : scalarCount_(0), packetCount_(0) {}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) {
|
||||
internal::scalar_sum_op<T> sum_op;
|
||||
*accum = sum_op(*accum, t);
|
||||
scalarCount_++;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) {
|
||||
(*accum) = padd<Packet>(*accum, p);
|
||||
packetCount_++;
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
internal::scalar_cast_op<int, T> conv;
|
||||
return conv(0);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
|
||||
return pset1<Packet>(initialize());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const {
|
||||
internal::scalar_quotient_op<T> quotient_op;
|
||||
return quotient_op(accum, T(scalarCount_));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
|
||||
return pdiv(vaccum, pset1<Packet>(T(packetCount_)));
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
|
||||
internal::scalar_sum_op<T> sum_op;
|
||||
internal::scalar_quotient_op<T> quotient_op;
|
||||
return quotient_op(sum_op(saccum, predux(vaccum)), T(scalarCount_ + packetCount_ * unpacket_traits<Packet>::size));
|
||||
}
|
||||
|
||||
protected:
|
||||
DenseIndex scalarCount_;
|
||||
DenseIndex packetCount_;
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct reducer_traits<MeanReducer<T>, Device> {
|
||||
enum {
|
||||
Cost = NumTraits<T>::AddCost,
|
||||
PacketAccess = PacketType<T, Device>::HasAdd && PacketType<T, Device>::HasDiv && !NumTraits<T>::IsInteger,
|
||||
IsStateful = true,
|
||||
IsExactlyAssociative = NumTraits<T>::IsInteger
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, bool IsMax = true, bool IsInteger = true>
|
||||
struct MinMaxBottomValue {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::lowest(); }
|
||||
};
|
||||
template <typename T>
|
||||
struct MinMaxBottomValue<T, true, false> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return -Eigen::NumTraits<T>::infinity(); }
|
||||
};
|
||||
template <typename T>
|
||||
struct MinMaxBottomValue<T, false, true> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::highest(); }
|
||||
};
|
||||
template <typename T>
|
||||
struct MinMaxBottomValue<T, false, false> {
|
||||
EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE T bottom_value() { return Eigen::NumTraits<T>::infinity(); }
|
||||
};
|
||||
|
||||
template <typename T, int NaNPropagation = PropagateFast>
|
||||
struct MaxReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
|
||||
scalar_max_op<T, T, NaNPropagation> op;
|
||||
*accum = op(t, *accum);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
|
||||
scalar_max_op<T, T, NaNPropagation> op;
|
||||
(*accum) = op.packetOp(*accum, p);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
return MinMaxBottomValue<T, /*IsMax=*/true, Eigen::NumTraits<T>::IsInteger>::bottom_value();
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
|
||||
return pset1<Packet>(initialize());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
|
||||
return vaccum;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
|
||||
scalar_max_op<T, T, NaNPropagation> op;
|
||||
return op(saccum, op.predux(vaccum));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Device, int NaNPropagation>
|
||||
struct reducer_traits<MaxReducer<T, NaNPropagation>, Device> {
|
||||
enum {
|
||||
Cost = NumTraits<T>::AddCost,
|
||||
PacketAccess = PacketType<T, Device>::HasMax,
|
||||
IsStateful = false,
|
||||
IsExactlyAssociative = (NaNPropagation != PropagateFast)
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, int NaNPropagation = PropagateFast>
|
||||
struct MinReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
|
||||
scalar_min_op<T, T, NaNPropagation> op;
|
||||
*accum = op(t, *accum);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
|
||||
scalar_min_op<T, T, NaNPropagation> op;
|
||||
(*accum) = op.packetOp(*accum, p);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
return MinMaxBottomValue<T, /*IsMax=*/false, Eigen::NumTraits<T>::IsInteger>::bottom_value();
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
|
||||
return pset1<Packet>(initialize());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
|
||||
return vaccum;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
|
||||
scalar_min_op<T, T, NaNPropagation> op;
|
||||
return op(saccum, op.predux(vaccum));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Device, int NaNPropagation>
|
||||
struct reducer_traits<MinReducer<T, NaNPropagation>, Device> {
|
||||
enum {
|
||||
Cost = NumTraits<T>::AddCost,
|
||||
PacketAccess = PacketType<T, Device>::HasMin,
|
||||
IsStateful = false,
|
||||
IsExactlyAssociative = (NaNPropagation != PropagateFast)
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ProdReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
|
||||
internal::scalar_product_op<T> prod_op;
|
||||
(*accum) = prod_op(*accum, t);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reducePacket(const Packet& p, Packet* accum) const {
|
||||
(*accum) = pmul<Packet>(*accum, p);
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
internal::scalar_cast_op<int, T> conv;
|
||||
return conv(1);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet initializePacket() const {
|
||||
return pset1<Packet>(initialize());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T accum) const { return accum; }
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet finalizePacket(const Packet& vaccum) const {
|
||||
return vaccum;
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalizeBoth(const T saccum, const Packet& vaccum) const {
|
||||
internal::scalar_product_op<T> prod_op;
|
||||
return prod_op(saccum, predux_mul(vaccum));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct reducer_traits<ProdReducer<T>, Device> {
|
||||
enum {
|
||||
Cost = NumTraits<T>::MulCost,
|
||||
PacketAccess = PacketType<T, Device>::HasMul,
|
||||
IsStateful = false,
|
||||
IsExactlyAssociative = true
|
||||
};
|
||||
};
|
||||
|
||||
struct AndReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { *accum = *accum && t; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { return true; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { return accum; }
|
||||
};
|
||||
|
||||
template <typename Device>
|
||||
struct reducer_traits<AndReducer, Device> {
|
||||
enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
|
||||
};
|
||||
|
||||
struct OrReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(bool t, bool* accum) const { *accum = *accum || t; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool initialize() const { return false; }
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool finalize(bool accum) const { return accum; }
|
||||
};
|
||||
|
||||
template <typename Device>
|
||||
struct reducer_traits<OrReducer, Device> {
|
||||
enum { Cost = 1, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
|
||||
};
|
||||
|
||||
// Argmin/Argmax reducers. Returns the first occurrence if multiple locations
|
||||
// contain the same min/max value.
|
||||
template <typename T>
|
||||
struct ArgMaxPairReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T t, T* accum) const {
|
||||
if (t.second < accum->second) {
|
||||
return;
|
||||
} else if (t.second > accum->second || accum->first > t.first) {
|
||||
*accum = t;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
return T(0, NumTraits<typename T::second_type>::lowest());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { return accum; }
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct reducer_traits<ArgMaxPairReducer<T>, Device> {
|
||||
enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ArgMinPairReducer {
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void reduce(const T& t, T* accum) const {
|
||||
if (t.second > accum->second) {
|
||||
return;
|
||||
} else if (t.second < accum->second || accum->first > t.first) {
|
||||
*accum = t;
|
||||
}
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T initialize() const {
|
||||
return T(0, NumTraits<typename T::second_type>::highest());
|
||||
}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T finalize(const T& accum) const { return accum; }
|
||||
};
|
||||
|
||||
template <typename T, typename Device>
|
||||
struct reducer_traits<ArgMinPairReducer<T>, Device> {
|
||||
enum { Cost = NumTraits<T>::AddCost, PacketAccess = false, IsStateful = false, IsExactlyAssociative = true };
|
||||
};
|
||||
|
||||
template <typename T, typename Index, size_t NumDims>
|
||||
class GaussianGenerator {
|
||||
public:
|
||||
static constexpr bool PacketAccess = false;
|
||||
|
||||
EIGEN_DEVICE_FUNC GaussianGenerator(const array<T, NumDims>& means, const array<T, NumDims>& std_devs)
|
||||
: m_means(means) {
|
||||
EIGEN_UNROLL_LOOP
|
||||
for (size_t i = 0; i < NumDims; ++i) {
|
||||
m_two_sigmas[i] = std_devs[i] * std_devs[i] * 2;
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC T operator()(const array<Index, NumDims>& coordinates) const {
|
||||
T tmp = T(0);
|
||||
EIGEN_UNROLL_LOOP
|
||||
for (size_t i = 0; i < NumDims; ++i) {
|
||||
T offset = coordinates[i] - m_means[i];
|
||||
tmp += offset * offset / m_two_sigmas[i];
|
||||
}
|
||||
return numext::exp(-tmp);
|
||||
}
|
||||
|
||||
private:
|
||||
array<T, NumDims> m_means;
|
||||
array<T, NumDims> m_two_sigmas;
|
||||
};
|
||||
|
||||
template <typename T, typename Index, size_t NumDims>
|
||||
struct functor_traits<GaussianGenerator<T, Index, NumDims> > {
|
||||
enum {
|
||||
Cost = NumDims *
|
||||
(2 * NumTraits<T>::AddCost + NumTraits<T>::MulCost + functor_traits<scalar_quotient_op<T, T> >::Cost) +
|
||||
functor_traits<scalar_exp_op<T> >::Cost,
|
||||
PacketAccess = GaussianGenerator<T, Index, NumDims>::PacketAccess
|
||||
};
|
||||
};
|
||||
|
||||
template <typename Scalar>
|
||||
struct scalar_clamp_op {
|
||||
EIGEN_DEVICE_FUNC inline scalar_clamp_op(const Scalar& _min, const Scalar& _max) : m_min(_min), m_max(_max) {}
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Scalar operator()(const Scalar& x) const {
|
||||
return numext::mini(numext::maxi(x, m_min), m_max);
|
||||
}
|
||||
template <typename Packet>
|
||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& x) const {
|
||||
return internal::pmin(internal::pmax(x, pset1<Packet>(m_min)), pset1<Packet>(m_max));
|
||||
}
|
||||
const Scalar m_min;
|
||||
const Scalar m_max;
|
||||
};
|
||||
template <typename Scalar>
|
||||
struct functor_traits<scalar_clamp_op<Scalar> > {
|
||||
enum {
|
||||
Cost = 2 * NumTraits<Scalar>::AddCost,
|
||||
PacketAccess = (packet_traits<Scalar>::HasMin && packet_traits<Scalar>::HasMax)
|
||||
};
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_CXX11_TENSOR_TENSOR_FUNCTORS_H
|
||||
Reference in New Issue
Block a user