mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-16 14:49:39 +08:00
Add typed logicals
This commit is contained in:
parent
e797974689
commit
049a144798
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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 ---
|
||||
|
||||
|
@ -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());
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
Array3d v(-1,2,1), w(-3,2,3);
|
||||
cout << ((v<w) ^ (v<0)) << endl;
|
@ -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));
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user