diff --git a/Eigen/src/Core/functors/BinaryFunctors.h b/Eigen/src/Core/functors/BinaryFunctors.h index 3c7601963de3b0519dd4e250f15dfd1c0c19f612..dd8f4d04ed560cd0be215842eb14e2aa5c6638b9 100644 --- a/Eigen/src/Core/functors/BinaryFunctors.h +++ b/Eigen/src/Core/functors/BinaryFunctors.h @@ -278,6 +278,90 @@ struct scalar_cmp_op : binary_op_base struct scalar_typed_cmp_op; + +template +struct functor_traits > { + enum { + Cost = (NumTraits::AddCost+NumTraits::AddCost)/2, + PacketAccess = is_same::value && + packet_traits::HasCmp + }; +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a==b;} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_eq(a,b); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_lt(a,b); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a<=b;} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_le(a,b); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a>b;} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_lt(b,a); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a>=b;} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_le(b,a); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return !(a<=b || b<=a);} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_eq(internal::por(internal::pcmp_le(a, b), internal::pcmp_le(b, a)), internal::pzero(a)); } +}; + +template +struct scalar_typed_cmp_op : binary_op_base +{ + typedef typename ScalarBinaryOpTraits >::ReturnType result_type; + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(const LhsScalar& a, const RhsScalar& b) const {return a!=b;} + template + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const + { return internal::pcmp_eq(internal::pcmp_eq(a, b), internal::pzero(a)); } +}; + /** \internal * \brief Template functor to compute the hypot of two \b positive \b and \b real scalars * diff --git a/bench/benchSelect.cpp b/bench/benchSelect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b638f9f5458bf9a0b2a0d8552f5ce0c7786ee984 --- /dev/null +++ b/bench/benchSelect.cpp @@ -0,0 +1,68 @@ +// Build with: g++ -O3 -DNDEBUG benchSelect.cpp -I ../ -o benchSelect + +#include + +#include + +#include "BenchUtil.h" + +namespace impl { +template +const Eigen::CwiseBinaryOp< + Eigen::internal::scalar_typed_cmp_op, + const LhsExpr, + const RhsExpr> +equal(const LhsExpr& A, const RhsExpr& B) { + return Eigen::CwiseBinaryOp< + Eigen::internal::scalar_typed_cmp_op, + const LhsExpr, + const RhsExpr>(A, B); +} +} // namespace impl + +template +double BenchmarkSelect(int rows, int cols, int iterations) { + typedef Eigen::Array Array; + Array x = Array::Random(rows, cols); + Array x_transpose = x.transpose(); + + Array zero = Array::Zero(rows, cols); + Array ones = Array::Ones(rows, cols); + + BenchTimer timer; + timer.reset(); + timer.start(); + for (int i = 0; i < iterations; i++) { + Array result = impl::equal(x, x_transpose).select(ones, zero); + } + timer.stop(); + + return timer.value(); +} + +int main(int argc, char *argv[]) +{ + constexpr int rows = 512; + constexpr int cols = 512; + constexpr int iterations = 10000; + + #define RUN_BENCHMARK(TYPE) \ + { \ + double runtime = BenchmarkSelect(rows, cols, iterations); \ + std::cout << #TYPE << ": Ran " << iterations << " in " << runtime \ + << " seconds.\n"; \ + } + + RUN_BENCHMARK(int8_t); + RUN_BENCHMARK(int16_t); + RUN_BENCHMARK(int32_t); + RUN_BENCHMARK(int64_t); + RUN_BENCHMARK(uint8_t); + RUN_BENCHMARK(uint16_t); + RUN_BENCHMARK(uint32_t); + RUN_BENCHMARK(uint64_t); + RUN_BENCHMARK(float); + RUN_BENCHMARK(double); + + return 0; +}