Add typed logicals

This commit is contained in:
Charles Schlosser 2023-02-18 01:23:47 +00:00 committed by Rasmus Munk Larsen
parent e797974689
commit 049a144798
13 changed files with 415 additions and 124 deletions

View File

@ -27,7 +27,7 @@ struct all_unroller
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
{
return all_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) && mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i);
return all_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) && mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i) != typename Derived::CoeffReturnType(0);
}
};
@ -54,7 +54,7 @@ struct any_unroller
EIGEN_DEVICE_FUNC static inline bool run(const Derived &mat)
{
return any_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) || mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i);
return any_unroller<Derived, UnrollCount-1, InnerSize>::run(mat) || mat.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i) != typename Derived::CoeffReturnType(0);
}
};
@ -94,7 +94,7 @@ EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::all() const
{
for(Index i = 0; i < derived().outerSize(); ++i)
for(Index j = 0; j < derived().innerSize(); ++j)
if (!evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i)) return false;
if (evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i) == Scalar(0)) return false;
return true;
}
}
@ -118,7 +118,7 @@ EIGEN_DEVICE_FUNC inline bool DenseBase<Derived>::any() const
{
for(Index i = 0; i < derived().outerSize(); ++i)
for(Index j = 0; j < derived().innerSize(); ++j)
if (evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i)) return true;
if (evaluator.coeff(IsRowMajor ? i : j, IsRowMajor ? j : i) != Scalar(0)) return true;
return false;
}
}

View File

@ -350,8 +350,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
typedef typename ReturnType<internal::member_hypotNorm,RealScalar>::Type HypotNormReturnType;
typedef typename ReturnType<internal::member_sum>::Type SumReturnType;
typedef EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(SumReturnType,Scalar,quotient) MeanReturnType;
typedef typename ReturnType<internal::member_all>::Type AllReturnType;
typedef typename ReturnType<internal::member_any>::Type AnyReturnType;
typedef typename ReturnType<internal::member_all, bool>::Type AllReturnType;
typedef typename ReturnType<internal::member_any, bool>::Type AnyReturnType;
typedef PartialReduxExpr<ExpressionType, internal::member_count<Index,Scalar>, Direction> CountReturnType;
typedef typename ReturnType<internal::member_prod>::Type ProdReturnType;
typedef Reverse<const ExpressionType, Direction> ConstReverseReturnType;

View File

@ -216,6 +216,7 @@ template<> struct packet_traits<bool> : default_packet_traits
HasAdd = 1,
HasSub = 1,
HasCmp = 1, // note -- only pcmp_eq is defined
HasShift = 0,
HasMul = 1,
HasNegate = 1,

View File

@ -428,60 +428,168 @@ struct functor_traits<scalar_quotient_op<LhsScalar,RhsScalar> > {
};
};
/** \internal
* \brief Template functor to compute the and of two booleans
* \brief Template functor to compute the and of two scalars as if they were booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator&&
*/
template <typename Scalar>
struct scalar_boolean_and_op {
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a && b; }
template<typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pand(a,b); }
using result_type = Scalar;
// `false` any value `a` that satisfies `a == Scalar(0)`
// `true` is the complement of `false`
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
return (a != Scalar(0)) && (b != Scalar(0)) ? Scalar(1) : Scalar(0);
}
template <typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
const Packet cst_one = pset1<Packet>(Scalar(1));
// and(a,b) == !or(!a,!b)
Packet not_a = pcmp_eq(a, pzero(a));
Packet not_b = pcmp_eq(b, pzero(b));
Packet a_nand_b = por(not_a, not_b);
return pandnot(cst_one, a_nand_b);
}
};
template<> struct functor_traits<scalar_boolean_and_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = true
};
template <typename Scalar>
struct functor_traits<scalar_boolean_and_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
};
/** \internal
* \brief Template functor to compute the or of two booleans
* \brief Template functor to compute the or of two scalars as if they were booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator||
*/
template <typename Scalar>
struct scalar_boolean_or_op {
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a || b; }
template<typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::por(a,b); }
using result_type = Scalar;
// `false` any value `a` that satisfies `a == Scalar(0)`
// `true` is the complement of `false`
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
return (a != Scalar(0)) || (b != Scalar(0)) ? Scalar(1) : Scalar(0);
}
template <typename Packet>
EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
const Packet cst_one = pset1<Packet>(Scalar(1));
// if or(a,b) == 0, then a == 0 and b == 0
// or(a,b) == !nor(a,b)
Packet a_nor_b = pcmp_eq(por(a, b), pzero(a));
return pandnot(cst_one, a_nor_b);
}
};
template<> struct functor_traits<scalar_boolean_or_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = true
};
template <typename Scalar>
struct functor_traits<scalar_boolean_or_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
};
/** \internal
* \brief Template functor to compute the xor of two booleans
* \brief Template functor to compute the xor of two scalars as if they were booleans
*
* \sa class CwiseBinaryOp, ArrayBase::operator^
*/
template <typename Scalar>
struct scalar_boolean_xor_op {
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a, const bool& b) const { return a ^ b; }
template<typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(const Packet& a, const Packet& b) const
{ return internal::pxor(a,b); }
using result_type = Scalar;
// `false` any value `a` that satisfies `a == Scalar(0)`
// `true` is the complement of `false`
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
return (a != Scalar(0)) != (b != Scalar(0)) ? Scalar(1) : Scalar(0);
}
template <typename Packet>
EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
const Packet cst_one = pset1<Packet>(Scalar(1));
// xor(a,b) == xor(!a,!b)
Packet not_a = pcmp_eq(a, pzero(a));
Packet not_b = pcmp_eq(b, pzero(b));
Packet a_xor_b = pxor(not_a, not_b);
return pand(cst_one, a_xor_b);
}
};
template<> struct functor_traits<scalar_boolean_xor_op> {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = true
};
template <typename Scalar>
struct functor_traits<scalar_boolean_xor_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
};
/** \internal
* \brief Template functor to compute the bitwise and of two scalars
*
* \sa class CwiseBinaryOp, ArrayBase::operator&
*/
template <typename Scalar>
struct scalar_bitwise_and_op {
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization, BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES )
using result_type = Scalar;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
Scalar result;
const uint8_t* a_bytes = reinterpret_cast<const uint8_t*>(&a);
const uint8_t* b_bytes = reinterpret_cast<const uint8_t*>(&b);
uint8_t* r_bytes = reinterpret_cast<uint8_t*>(&result);
for (Index i = 0; i < sizeof(Scalar); i++) r_bytes[i] = a_bytes[i] & b_bytes[i];
return result;
}
template <typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
return pand(a, b);
}
};
template <typename Scalar>
struct functor_traits<scalar_bitwise_and_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
};
/** \internal
* \brief Template functor to compute the bitwise or of two scalars
*
* \sa class CwiseBinaryOp, ArrayBase::operator|
*/
template <typename Scalar>
struct scalar_bitwise_or_op {
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization, BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
using result_type = Scalar;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
Scalar result;
const uint8_t* a_bytes = reinterpret_cast<const uint8_t*>(&a);
const uint8_t* b_bytes = reinterpret_cast<const uint8_t*>(&b);
uint8_t* r_bytes = reinterpret_cast<uint8_t*>(&result);
for (Index i = 0; i < sizeof(Scalar); i++) r_bytes[i] = a_bytes[i] | b_bytes[i];
return result;
}
template <typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
return por(a, b);
}
};
template <typename Scalar>
struct functor_traits<scalar_bitwise_or_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
};
/** \internal
* \brief Template functor to compute the bitwise xor of two scalars
*
* \sa class CwiseBinaryOp, ArrayBase::operator^
*/
template <typename Scalar>
struct scalar_bitwise_xor_op {
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization, BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
using result_type = Scalar;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a, const Scalar& b) const {
Scalar result;
const uint8_t* a_bytes = reinterpret_cast<const uint8_t*>(&a);
const uint8_t* b_bytes = reinterpret_cast<const uint8_t*>(&b);
uint8_t* r_bytes = reinterpret_cast<uint8_t*>(&result);
for (Index i = 0; i < sizeof(Scalar); i++) r_bytes[i] = a_bytes[i] ^ b_bytes[i];
return result;
}
template <typename Packet>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet& a, const Packet& b) const {
return pxor(a, b);
}
};
template <typename Scalar>
struct functor_traits<scalar_bitwise_xor_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
};
/** \internal

View File

@ -913,19 +913,54 @@ struct functor_traits<scalar_isfinite_op<Scalar> >
};
/** \internal
* \brief Template functor to compute the logical not of a boolean
* \brief Template functor to compute the logical not of a scalar as if it were a boolean
*
* \sa class CwiseUnaryOp, ArrayBase::operator!
*/
template<typename Scalar> struct scalar_boolean_not_op {
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool operator() (const bool& a) const { return !a; }
template <typename Scalar>
struct scalar_boolean_not_op {
using result_type = Scalar;
// `false` any value `a` that satisfies `a == Scalar(0)`
// `true` is the complement of `false`
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
return a == Scalar(0) ? Scalar(1) : Scalar(0);
}
template <typename Packet>
EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
const Packet cst_one = pset1<Packet>(Scalar(1));
Packet not_a = pcmp_eq(a, pzero(a));
return pand(not_a, cst_one);
}
};
template<typename Scalar>
struct functor_traits<scalar_boolean_not_op<Scalar> > {
enum {
Cost = NumTraits<bool>::AddCost,
PacketAccess = false
};
template <typename Scalar>
struct functor_traits<scalar_boolean_not_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = packet_traits<Scalar>::HasCmp };
};
/** \internal
* \brief Template functor to compute the bitwise not of a scalar
*
* \sa class CwiseUnaryOp, ArrayBase::operator~
*/
template <typename Scalar>
struct scalar_bitwise_not_op {
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::RequireInitialization, BITWISE OPERATIONS MAY ONLY BE PERFORMED ON PLAIN DATA TYPES)
using result_type = Scalar;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar operator()(const Scalar& a) const {
Scalar result;
const uint8_t* a_bytes = reinterpret_cast<const uint8_t*>(&a);
uint8_t* r_bytes = reinterpret_cast<uint8_t*>(&result);
for (Index i = 0; i < sizeof(Scalar); i++) r_bytes[i] = ~a_bytes[i];
return result;
}
template <typename Packet>
EIGEN_STRONG_INLINE Packet packetOp(const Packet& a) const {
return pandnot(ptrue(a), a);
}
};
template <typename Scalar>
struct functor_traits<scalar_bitwise_not_op<Scalar>> {
enum { Cost = NumTraits<Scalar>::AddCost, PacketAccess = true };
};
/** \internal

View File

@ -210,6 +210,15 @@ struct scalar_unary_pow_op;
template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_hypot_op;
template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_product_op;
template<typename LhsScalar,typename RhsScalar=LhsScalar> struct scalar_quotient_op;
// logical and bitwise operations
template <typename Scalar> struct scalar_boolean_and_op;
template <typename Scalar> struct scalar_boolean_or_op;
template <typename Scalar> struct scalar_boolean_xor_op;
template <typename Scalar> struct scalar_boolean_not_op;
template <typename Scalar> struct scalar_bitwise_and_op;
template <typename Scalar> struct scalar_bitwise_or_op;
template <typename Scalar> struct scalar_bitwise_xor_op;
template <typename Scalar> struct scalar_bitwise_not_op;
// SpecialFunctions module
template<typename Scalar> struct scalar_lgamma_op;

View File

@ -368,28 +368,28 @@ struct binary_evaluator<CwiseBinaryOp<scalar_quotient_op<T1,T2>, Lhs, Rhs>, Iter
// "sparse && sparse"
template<typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IteratorBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IteratorBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
{
typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
typedef sparse_conjunction_evaluator<XprType> Base;
explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "dense && sparse"
template<typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IndexBased, IteratorBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IndexBased, IteratorBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
{
typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
typedef sparse_conjunction_evaluator<XprType> Base;
explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};
// "sparse && dense"
template<typename Lhs, typename Rhs>
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs>, IteratorBased, IndexBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> >
struct binary_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs>, IteratorBased, IndexBased>
: sparse_conjunction_evaluator<CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> >
{
typedef CwiseBinaryOp<scalar_boolean_and_op, Lhs, Rhs> XprType;
typedef CwiseBinaryOp<scalar_boolean_and_op<bool>, Lhs, Rhs> XprType;
typedef sparse_conjunction_evaluator<XprType> Base;
explicit binary_evaluator(const XprType& xpr) : Base(xpr) {}
};

View File

@ -307,25 +307,6 @@ const CwiseBinaryOp<internal::scalar_difference_op<T,Scalar>,Constant<T>,Derived
operator/(const T& s,const StorageBaseType& a);
#endif
/** \returns an expression of the coefficient-wise ^ operator of *this and \a other
*
* \warning this operator is for expression of bool only.
*
* Example: \include Cwise_boolean_xor.cpp
* Output: \verbinclude Cwise_boolean_xor.out
*
* \sa operator&&(), select()
*/
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
inline const CwiseBinaryOp<internal::scalar_boolean_xor_op, const Derived, const OtherDerived>
operator^(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
{
EIGEN_STATIC_ASSERT((internal::is_same<bool,Scalar>::value && internal::is_same<bool,typename OtherDerived::Scalar>::value),
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return CwiseBinaryOp<internal::scalar_boolean_xor_op, const Derived, const OtherDerived>(derived(),other.derived());
}
// NOTE disabled until we agree on argument order
#if 0
/** \cpp11 \returns an expression of the coefficient-wise polygamma function.

View File

@ -9,6 +9,7 @@ typedef CwiseUnaryOp<internal::scalar_rsqrt_op<Scalar>, const Derived> RsqrtRetu
typedef CwiseUnaryOp<internal::scalar_sign_op<Scalar>, const Derived> SignReturnType;
typedef CwiseUnaryOp<internal::scalar_inverse_op<Scalar>, const Derived> InverseReturnType;
typedef CwiseUnaryOp<internal::scalar_boolean_not_op<Scalar>, const Derived> BooleanNotReturnType;
typedef CwiseUnaryOp<internal::scalar_bitwise_not_op<Scalar>, const Derived> BitwiseNotReturnType;
typedef CwiseUnaryOp<internal::scalar_exp_op<Scalar>, const Derived> ExpReturnType;
typedef CwiseUnaryOp<internal::scalar_expm1_op<Scalar>, const Derived> Expm1ReturnType;
@ -580,8 +581,6 @@ isFinite() const
}
/** \returns an expression of the coefficient-wise ! operator of *this
*
* \warning this operator is for expression of bool only.
*
* Example: \include Cwise_boolean_not.cpp
* Output: \verbinclude Cwise_boolean_not.out
@ -592,11 +591,18 @@ EIGEN_DEVICE_FUNC
inline const BooleanNotReturnType
operator!() const
{
EIGEN_STATIC_ASSERT((internal::is_same<bool,Scalar>::value),
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return BooleanNotReturnType(derived());
}
/** \returns an expression of the bitwise ~ operator of *this
*/
EIGEN_DEVICE_FUNC
inline const BitwiseNotReturnType
operator~() const
{
return BitwiseNotReturnType(derived());
}
// --- SpecialFunctions module ---

View File

@ -77,39 +77,61 @@ const CwiseBinaryOp<internal::scalar_quotient_op<Scalar,T>,Derived,Constant<T> >
#endif
/** \returns an expression of the coefficient-wise boolean \b and operator of \c *this and \a other
*
* \warning this operator is for expression of bool only.
*
* Example: \include Cwise_boolean_and.cpp
* Output: \verbinclude Cwise_boolean_and.out
*
* \sa operator||(), select()
*/
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
inline const CwiseBinaryOp<internal::scalar_boolean_and_op, const Derived, const OtherDerived>
operator&&(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
{
EIGEN_STATIC_ASSERT((internal::is_same<bool,Scalar>::value && internal::is_same<bool,typename OtherDerived::Scalar>::value),
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return CwiseBinaryOp<internal::scalar_boolean_and_op, const Derived, const OtherDerived>(derived(),other.derived());
*
* Example: \include Cwise_boolean_and.cpp
* Output: \verbinclude Cwise_boolean_and.out
*
* \sa operator||(), select()
*/
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp<internal::scalar_boolean_and_op<Scalar>, const Derived, const OtherDerived>
operator&&(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived>& other) const {
return CwiseBinaryOp<internal::scalar_boolean_and_op<Scalar>, const Derived, const OtherDerived>(derived(),
other.derived());
}
/** \returns an expression of the coefficient-wise boolean \b or operator of \c *this and \a other
*
* \warning this operator is for expression of bool only.
*
* Example: \include Cwise_boolean_or.cpp
* Output: \verbinclude Cwise_boolean_or.out
*
* \sa operator&&(), select()
*/
template<typename OtherDerived>
EIGEN_DEVICE_FUNC
inline const CwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>
operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived> &other) const
{
EIGEN_STATIC_ASSERT((internal::is_same<bool,Scalar>::value && internal::is_same<bool,typename OtherDerived::Scalar>::value),
THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL);
return CwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>(derived(),other.derived());
*
* Example: \include Cwise_boolean_or.cpp
* Output: \verbinclude Cwise_boolean_or.out
*
* \sa operator&&(), select()
*/
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp<internal::scalar_boolean_or_op<Scalar>, const Derived, const OtherDerived>
operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived>& other) const {
return CwiseBinaryOp<internal::scalar_boolean_or_op<Scalar>, const Derived, const OtherDerived>(derived(),
other.derived());
}
/** \returns an expression of the bitwise \b and operator of \c *this and \a other
*
* \sa operator|(), operator^()
*/
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp<internal::scalar_bitwise_and_op<Scalar>, const Derived, const OtherDerived>
operator&(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived>& other) const {
return CwiseBinaryOp<internal::scalar_bitwise_and_op<Scalar>, const Derived, const OtherDerived>(derived(),
other.derived());
}
/** \returns an expression of the bitwise boolean \b or operator of \c *this and \a other
*
* \sa operator&(), operator^()
*/
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp<internal::scalar_bitwise_or_op<Scalar>, const Derived, const OtherDerived>
operator|(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived>& other) const {
return CwiseBinaryOp<internal::scalar_bitwise_or_op<Scalar>, const Derived, const OtherDerived>(derived(),
other.derived());
}
/** \returns an expression of the bitwise xor operator of *this and \a other
* \sa operator&(), operator|()
*/
template <typename OtherDerived>
EIGEN_DEVICE_FUNC inline const CwiseBinaryOp<internal::scalar_bitwise_xor_op<Scalar>, const Derived, const OtherDerived>
operator^(const EIGEN_CURRENT_STORAGE_BASE_CLASS<OtherDerived>& other) const {
return CwiseBinaryOp<internal::scalar_bitwise_xor_op<Scalar>, const Derived, const OtherDerived>(derived(),
other.derived());
}

View File

@ -1,2 +0,0 @@
Array3d v(-1,2,1), w(-3,2,3);
cout << ((v<w) ^ (v<0)) << endl;

View File

@ -29,7 +29,7 @@ std::vector<Scalar> special_values() {
const Scalar two = Scalar(2);
const Scalar three = Scalar(3);
const Scalar sqrt_half = Scalar(std::sqrt(0.5));
const Scalar sqrt2 = Scalar(std::sqrt(2));
const Scalar sqrt2 = Scalar(std::sqrt(2));
const Scalar inf = Eigen::NumTraits<Scalar>::infinity();
const Scalar nan = Eigen::NumTraits<Scalar>::quiet_NaN();
const Scalar denorm_min = std::numeric_limits<Scalar>::denorm_min();
@ -968,6 +968,104 @@ void signed_shift_test(const ArrayType& m) {
signed_shift_test_impl<ArrayType>::run(m);
}
template <typename ArrayType>
struct typed_logicals_test_impl {
using Scalar = typename ArrayType::Scalar;
static bool scalar_to_bool(const Scalar& x) { return x != Scalar(0); }
static Scalar bool_to_scalar(const bool& x) { return x ? Scalar(1) : Scalar(0); }
static Scalar eval_bool_and(const Scalar& x, const Scalar& y) { return bool_to_scalar(scalar_to_bool(x) && scalar_to_bool(y)); }
static Scalar eval_bool_or(const Scalar& x, const Scalar& y) { return bool_to_scalar(scalar_to_bool(x) || scalar_to_bool(y)); }
static Scalar eval_bool_xor(const Scalar& x, const Scalar& y) { return bool_to_scalar(scalar_to_bool(x) != scalar_to_bool(y)); }
static Scalar eval_bool_not(const Scalar& x) { return bool_to_scalar(!scalar_to_bool(x)); }
static void run(const ArrayType& m) {
Index rows = m.rows();
Index cols = m.cols();
ArrayType m1(rows, cols), m2(rows, cols), m3(rows, cols), m4(rows, cols);
m1.setRandom();
m2.setRandom();
m1 *= ArrayX<bool>::Random(rows, cols).cast<Scalar>();
m2 *= ArrayX<bool>::Random(rows, cols).cast<Scalar>();
// test boolean and
m3 = m1 && m2;
m4 = m1.binaryExpr(m2, [](const Scalar& x, const Scalar& y) { return eval_bool_and(x, y); });
VERIFY_IS_CWISE_EQUAL(m3, m4);
for (const Scalar& val : m3) VERIFY(val == Scalar(0) || val == Scalar(1));
// test boolean or
m3 = m1 || m2;
m4 = m1.binaryExpr(m2, [](const Scalar& x, const Scalar& y) { return eval_bool_or(x, y); });
VERIFY_IS_CWISE_EQUAL(m3, m4);
for (const Scalar& val : m3) VERIFY(val == Scalar(0) || val == Scalar(1));
// test boolean xor
m3 = m1.binaryExpr(m2, internal::scalar_boolean_xor_op<Scalar>());
m4 = m1.binaryExpr(m2, [](const Scalar& x, const Scalar& y) { return eval_bool_xor(x, y); });
VERIFY_IS_CWISE_EQUAL(m3, m4);
for (const Scalar& val : m3) VERIFY(val == Scalar(0) || val == Scalar(1));
// test boolean not
m3 = !m1;
m4 = m1.unaryExpr([](const Scalar& x) { return eval_bool_not(x); });
VERIFY_IS_CWISE_EQUAL(m3, m4);
for (const Scalar& val : m3) VERIFY(val == Scalar(0) || val == Scalar(1));
// test something more complicated
m3 = m1 && m2;
m4 = !(!m1 || !m2);
VERIFY_IS_CWISE_EQUAL(m3, m4);
m3 = m1.binaryExpr(m2, internal::scalar_boolean_xor_op<Scalar>());
m4 = (!m1).binaryExpr((!m2), internal::scalar_boolean_xor_op<Scalar>());
VERIFY_IS_CWISE_EQUAL(m3, m4);
const Index bytes = rows * cols * sizeof(Scalar);
const uint8_t* m1_data = reinterpret_cast<const uint8_t*>(m1.data());
const uint8_t* m2_data = reinterpret_cast<const uint8_t*>(m2.data());
uint8_t* m3_data = reinterpret_cast<uint8_t*>(m3.data());
uint8_t* m4_data = reinterpret_cast<uint8_t*>(m4.data());
// test bitwise and
m3 = m1 & m2;
for (Index i = 0; i < bytes; i++) m4_data[i] = m1_data[i] & m2_data[i];
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
// test bitwise or
m3 = m1 | m2;
for (Index i = 0; i < bytes; i++) m4_data[i] = m1_data[i] | m2_data[i];
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
// test bitwise xor
m3 = m1 ^ m2;
for (Index i = 0; i < bytes; i++) m4_data[i] = m1_data[i] ^ m2_data[i];
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
// test bitwise not
m3 = ~m1;
for (Index i = 0; i < bytes; i++) m4_data[i] = ~m1_data[i];
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
// test something more complicated
m3 = m1 & m2;
m4 = ~(~m1 | ~m2);
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
m3 = m1 ^ m2;
m4 = (~m1) ^ (~m2);
for (Index i = 0; i < bytes; i++) VERIFY_IS_EQUAL(m3_data[i], m4_data[i]);
}
};
template <typename ArrayType>
void typed_logicals_test(const ArrayType& m) {
typed_logicals_test_impl<ArrayType>::run(m);
}
EIGEN_DECLARE_TEST(array_cwise)
{
for(int i = 0; i < g_repeat; i++) {
@ -1016,6 +1114,14 @@ EIGEN_DECLARE_TEST(array_cwise)
CALL_SUBTEST_7( mixed_pow_test() );
CALL_SUBTEST_8( signbit_tests() );
}
for (int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1( typed_logicals_test(ArrayX<bool>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_2( typed_logicals_test(ArrayX<int>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_2( typed_logicals_test(ArrayX<float>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))) );
CALL_SUBTEST_3( typed_logicals_test(ArrayX<double>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_3( typed_logicals_test(ArrayX<std::complex<float>>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
CALL_SUBTEST_3( typed_logicals_test(ArrayX<std::complex<double>>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
}
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));

View File

@ -490,34 +490,59 @@ class TensorBase<Derived, ReadOnlyAccessors>
return binaryExpr(other.derived(), internal::scalar_quotient_op<Scalar>());
}
template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar,Scalar, NaNPropagation>, const Derived, const OtherDerived>
template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_max_op<Scalar,Scalar, NaNPropagation>, const Derived, const OtherDerived>
cwiseMax(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_max_op<Scalar,Scalar, NaNPropagation>());
return binaryExpr(other.derived(), internal::scalar_max_op<Scalar,Scalar, NaNPropagation>());
}
template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
template<int NaNPropagation=PropagateFast, typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_min_op<Scalar,Scalar, NaNPropagation>, const Derived, const OtherDerived>
cwiseMin(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_min_op<Scalar,Scalar, NaNPropagation>());
}
// logical operators
template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_boolean_and_op, const Derived, const OtherDerived>
const TensorCwiseBinaryOp<internal::scalar_boolean_and_op<Scalar>, const Derived, const OtherDerived>
operator&&(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_boolean_and_op());
return binaryExpr(other.derived(), internal::scalar_boolean_and_op<Scalar>());
}
template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_boolean_or_op, const Derived, const OtherDerived>
const TensorCwiseBinaryOp<internal::scalar_boolean_or_op<Scalar>, const Derived, const OtherDerived>
operator||(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_boolean_or_op());
return binaryExpr(other.derived(), internal::scalar_boolean_or_op<Scalar>());
}
template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_boolean_xor_op, const Derived, const OtherDerived>
const TensorCwiseBinaryOp<internal::scalar_bitwise_and_op<Scalar>, const Derived, const OtherDerived>
operator&(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_bitwise_and_op<Scalar>());
}
template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_bitwise_or_op<Scalar>, const Derived, const OtherDerived>
operator|(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_bitwise_or_op<Scalar>());
}
template<typename OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseBinaryOp<internal::scalar_bitwise_xor_op<Scalar>, const Derived, const OtherDerived>
operator^(const OtherDerived& other) const {
return binaryExpr(other.derived(), internal::scalar_boolean_xor_op());
return binaryExpr(other.derived(), internal::scalar_bitwise_xor_op<Scalar>());
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseUnaryOp<internal::scalar_boolean_not_op<Scalar>, const Derived>
operator!() const {
return unaryExpr(internal::scalar_boolean_not_op<Scalar>());
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const TensorCwiseUnaryOp<internal::scalar_bitwise_not_op<Scalar>, const Derived>
operator~() const {
return unaryExpr(internal::scalar_bitwise_not_op<Scalar>());
}
// Comparisons and tests.