// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@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/.
template <typename T> inline T REF_ADD(const T& a, const T& b) { return a + b;
} template <typename T> inline T REF_SUB(const T& a, const T& b) { return a - b;
} template <typename T> inline T REF_MUL(const T& a, const T& b) { return a * b;
} template <typename T> inline T REF_DIV(const T& a, const T& b) { return a / b;
} template <typename T> inline T REF_ABS_DIFF(const T& a, const T& b) { return a > b ? a - b : b - a;
}
// Specializations for bool. template <> inlinebool REF_ADD(constbool& a, constbool& b) { return a || b;
} template <> inlinebool REF_SUB(constbool& a, constbool& b) { return a ^ b;
} template <> inlinebool REF_MUL(constbool& a, constbool& b) { return a && b;
}
template <typename T> inline T REF_FREXP(const T& x, T& exp) { int iexp;
EIGEN_USING_STD(frexp) const T out = static_cast<T>(frexp(x, &iexp));
exp = static_cast<T>(iexp); return out;
}
// Uses pcast to cast from one array to another. template <typename SrcPacket, typename TgtPacket, int SrcCoeffRatio, int TgtCoeffRatio> struct pcast_array;
template <typename SrcPacket, typename TgtPacket, int TgtCoeffRatio> struct pcast_array<SrcPacket, TgtPacket, 1, TgtCoeffRatio> { typedeftypename internal::unpacket_traits<SrcPacket>::type SrcScalar; typedeftypename internal::unpacket_traits<TgtPacket>::type TgtScalar; staticvoid cast(const SrcScalar* src, size_t size, TgtScalar* dst) { staticconstint SrcPacketSize = internal::unpacket_traits<SrcPacket>::size; staticconstint TgtPacketSize = internal::unpacket_traits<TgtPacket>::size;
size_t i; for (i = 0; i < size && i + SrcPacketSize <= size; i += TgtPacketSize) {
internal::pstoreu(dst + i, internal::pcast<SrcPacket, TgtPacket>(internal::ploadu<SrcPacket>(src + i)));
} // Leftovers that cannot be loaded into a packet. for (; i < size; ++i) {
dst[i] = static_cast<TgtScalar>(src[i]);
}
}
};
template <typename SrcPacket, typename TgtPacket> struct pcast_array<SrcPacket, TgtPacket, 2, 1> { staticvoid cast(consttypename internal::unpacket_traits<SrcPacket>::type* src, size_t size, typename internal::unpacket_traits<TgtPacket>::type* dst) { staticconstint SrcPacketSize = internal::unpacket_traits<SrcPacket>::size; staticconstint TgtPacketSize = internal::unpacket_traits<TgtPacket>::size; for (size_t i = 0; i < size; i += TgtPacketSize) {
SrcPacket a = internal::ploadu<SrcPacket>(src + i);
SrcPacket b = internal::ploadu<SrcPacket>(src + i + SrcPacketSize);
internal::pstoreu(dst + i, internal::pcast<SrcPacket, TgtPacket>(a, b));
}
}
};
template <typename SrcPacket, typename TgtPacket> struct pcast_array<SrcPacket, TgtPacket, 4, 1> { staticvoid cast(consttypename internal::unpacket_traits<SrcPacket>::type* src, size_t size, typename internal::unpacket_traits<TgtPacket>::type* dst) { staticconstint SrcPacketSize = internal::unpacket_traits<SrcPacket>::size; staticconstint TgtPacketSize = internal::unpacket_traits<TgtPacket>::size; for (size_t i = 0; i < size; i += TgtPacketSize) {
SrcPacket a = internal::ploadu<SrcPacket>(src + i);
SrcPacket b = internal::ploadu<SrcPacket>(src + i + SrcPacketSize);
SrcPacket c = internal::ploadu<SrcPacket>(src + i + 2 * SrcPacketSize);
SrcPacket d = internal::ploadu<SrcPacket>(src + i + 3 * SrcPacketSize);
internal::pstoreu(dst + i, internal::pcast<SrcPacket, TgtPacket>(a, b, c, d));
}
}
};
template <typename SrcPacket, typename TgtPacket> struct pcast_array<SrcPacket, TgtPacket, 8, 1> { staticvoid cast(consttypename internal::unpacket_traits<SrcPacket>::type* src, size_t size, typename internal::unpacket_traits<TgtPacket>::type* dst) { staticconstint SrcPacketSize = internal::unpacket_traits<SrcPacket>::size; staticconstint TgtPacketSize = internal::unpacket_traits<TgtPacket>::size; for (size_t i = 0; i < size; i += TgtPacketSize) {
SrcPacket a = internal::ploadu<SrcPacket>(src + i);
SrcPacket b = internal::ploadu<SrcPacket>(src + i + SrcPacketSize);
SrcPacket c = internal::ploadu<SrcPacket>(src + i + 2 * SrcPacketSize);
SrcPacket d = internal::ploadu<SrcPacket>(src + i + 3 * SrcPacketSize);
SrcPacket e = internal::ploadu<SrcPacket>(src + i + 4 * SrcPacketSize);
SrcPacket f = internal::ploadu<SrcPacket>(src + i + 5 * SrcPacketSize);
SrcPacket g = internal::ploadu<SrcPacket>(src + i + 6 * SrcPacketSize);
SrcPacket h = internal::ploadu<SrcPacket>(src + i + 7 * SrcPacketSize);
internal::pstoreu(dst + i, internal::pcast<SrcPacket, TgtPacket>(a, b, c, d, e, f, g, h));
}
}
};
template <typename SrcPacket, typename TgtPacket, int SrcCoeffRatio, int TgtCoeffRatio, bool CanCast = false> struct test_cast_helper;
template <typename SrcPacket, typename TgtPacket, int SrcCoeffRatio, int TgtCoeffRatio> struct test_cast_helper<SrcPacket, TgtPacket, SrcCoeffRatio, TgtCoeffRatio, false> { staticvoid run() {}
};
// Construct a packet of scalars that will not overflow when casting for (int i = 0; i < DataSize; ++i) {
data1[i] = internal::random_without_cast_overflow<SrcScalar, TgtScalar>::value();
}
for (int i = 0; i < DataSize; ++i) {
ref[i] = static_cast<const TgtScalar>(data1[i]);
}
//Test (-0) <=/< (0) for signed operations for (int i = 0; i < PacketSize; ++i) {
data1[i] = Scalar(-0.0);
data1[i + PacketSize] = internal::random<bool>() ? data1[i] : Scalar(0);
}
CHECK_CWISE2_IF(true, internal::pcmp_le, internal::pcmp_le);
CHECK_CWISE2_IF(true, internal::pcmp_lt, internal::pcmp_lt);
//Test NaN for (int i = 0; i < PacketSize; ++i) {
data1[i] = NumTraits<Scalar>::quiet_NaN();
data1[i + PacketSize] = internal::random<bool>() ? data1[i] : Scalar(0);
}
CHECK_CWISE2_IF(true, internal::pcmp_le, internal::pcmp_le);
CHECK_CWISE2_IF(true, internal::pcmp_lt, internal::pcmp_lt);
}
// Packet16b representing bool does not support ptrue, pandnot or pcmp_eq, since the scalar path // (for some compilers) compute the bitwise and with 0x1 of the results to keep the value in [0,1]. template<> void packetmath_boolean_mask_ops<bool, internal::packet_traits<bool>::type>() {} template<> void packetmath_boolean_mask_ops_notcomplex<bool, internal::packet_traits<bool>::type>() {}
for (int i = 0; i < PacketSize; ++i) {
data1[i] = Scalar(-0.0);
data1[i + PacketSize] = Scalar(-0.0);
}
CHECK_CWISE2_IF(internal::packet_traits<Scalar>::HasAdd, REF_ADD, internal::padd);
}
// Ensure optimization barrier compiles and doesn't modify contents. // Only applies to raw types, so will not work for std::complex, Eigen::half // or Eigen::bfloat16. For those you would need to refer to an underlying // storage element. template<typename Packet, typename EnableIf = void> struct eigen_optimization_barrier_test { staticvoid run() {}
};
if (g_first_pass)
std::cerr << "=== Testing packet of type '" << typeid(Packet).name() << "' and scalar type '"
<< typeid(Scalar).name() << "' and size '" << PacketSize << "' ===\n";
for (int i = 0; i < size; ++i) {
data1[i] = numext::abs(internal::random<Scalar>());
}
CHECK_CWISE1_IF(PacketTraits::HasSqrt, numext::sqrt, internal::psqrt);
CHECK_CWISE1_IF(PacketTraits::HasRsqrt, numext::rsqrt, internal::prsqrt);
}
// Notice that this definition works for complex types as well. // c++11 has std::log2 for real, but not for complex types. template <typename Scalar>
Scalar log2(Scalar x) { return Scalar(EIGEN_LOG2E) * std::log(x);
}
if (PacketTraits::HasTanh) { // NOTE this test migh fail with GCC prior to 6.3, see MathFunctionsImpl.h for details.
data1[0] = NumTraits<Scalar>::quiet_NaN();
test::packet_helper<internal::packet_traits<Scalar>::HasTanh, Packet> h;
h.store(data2, internal::ptanh(h.load(data1)));
VERIFY((numext::isnan)(data2[0]));
}
if (PacketTraits::HasExp) {
internal::scalar_logistic_op<Scalar> logistic; for (int i = 0; i < size; ++i) {
data1[i] = Scalar(internal::random<double>(-20, 20));
}
test::packet_helper<PacketTraits::HasExp, Packet> h;
h.store(data2, logistic.packetOp(h.load(data1))); for (int i = 0; i < PacketSize; ++i) {
VERIFY_IS_APPROX(data2[i], logistic(data1[i]));
}
}
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmin(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_min(internal::pload<Packet>(data1))) && "internal::predux_min");
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmax(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_max(internal::pload<Packet>(data1))) && "internal::predux_max");
for (int i = 0; i < PacketSize; ++i) ref[i] = data1[0] + Scalar(i);
internal::pstore(data2, internal::plset<Packet>(data1[0]));
VERIFY(test::areApprox(ref, data2, PacketSize) && "internal::plset");
{ unsignedchar* data1_bits = reinterpret_cast<unsignedchar*>(data1); // predux_all - not needed yet // for (unsigned int i=0; i<PacketSize*sizeof(Scalar); ++i) data1_bits[i] = 0xff; // VERIFY(internal::predux_all(internal::pload<Packet>(data1)) && "internal::predux_all(1111)"); // for(int k=0; k<PacketSize; ++k) // { // for (unsigned int i=0; i<sizeof(Scalar); ++i) data1_bits[k*sizeof(Scalar)+i] = 0x0; // VERIFY( (!internal::predux_all(internal::pload<Packet>(data1))) && "internal::predux_all(0101)"); // for (unsigned int i=0; i<sizeof(Scalar); ++i) data1_bits[k*sizeof(Scalar)+i] = 0xff; // }
// predux_any for (unsignedint i = 0; i < PacketSize * sizeof(Scalar); ++i) data1_bits[i] = 0x0;
VERIFY((!internal::predux_any(internal::pload<Packet>(data1))) && "internal::predux_any(0000)"); for (int k = 0; k < PacketSize; ++k) { for (unsignedint i = 0; i < sizeof(Scalar); ++i) data1_bits[k * sizeof(Scalar) + i] = 0xff;
VERIFY(internal::predux_any(internal::pload<Packet>(data1)) && "internal::predux_any(0101)"); for (unsignedint i = 0; i < sizeof(Scalar); ++i) data1_bits[k * sizeof(Scalar) + i] = 0x00;
}
}
// Test NaN propagation. if (!NumTraits<Scalar>::IsInteger) { // Test reductions with no NaNs.
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmin<PropagateNumbers>(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_min<PropagateNumbers>(internal::pload<Packet>(data1))) && "internal::predux_min");
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmin<PropagateNaN>(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_min<PropagateNaN>(internal::pload<Packet>(data1))) && "internal::predux_min");
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmax<PropagateNumbers>(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_max<PropagateNumbers>(internal::pload<Packet>(data1))) && "internal::predux_max");
ref[0] = data1[0]; for (int i = 0; i < PacketSize; ++i) ref[0] = internal::pmax<PropagateNaN>(ref[0], data1[i]);
VERIFY(internal::isApprox(ref[0], internal::predux_max<PropagateNaN>(internal::pload<Packet>(data1))) && "internal::predux_max"); // A single NaN. const size_t index = std::numeric_limits<size_t>::quiet_NaN() % PacketSize;
data1[index] = NumTraits<Scalar>::quiet_NaN();
VERIFY(PacketSize==1 || !(numext::isnan)(internal::predux_min<PropagateNumbers>(internal::pload<Packet>(data1))));
VERIFY((numext::isnan)(internal::predux_min<PropagateNaN>(internal::pload<Packet>(data1))));
VERIFY(PacketSize==1 || !(numext::isnan)(internal::predux_max<PropagateNumbers>(internal::pload<Packet>(data1))));
VERIFY((numext::isnan)(internal::predux_max<PropagateNaN>(internal::pload<Packet>(data1)))); // All NaNs. for (int i = 0; i < 4 * PacketSize; ++i) data1[i] = NumTraits<Scalar>::quiet_NaN();
VERIFY((numext::isnan)(internal::predux_min<PropagateNumbers>(internal::pload<Packet>(data1))));
VERIFY((numext::isnan)(internal::predux_min<PropagateNaN>(internal::pload<Packet>(data1))));
VERIFY((numext::isnan)(internal::predux_max<PropagateNumbers>(internal::pload<Packet>(data1))));
VERIFY((numext::isnan)(internal::predux_max<PropagateNaN>(internal::pload<Packet>(data1))));
// Test NaN propagation for coefficient-wise min and max. for (int i = 0; i < PacketSize; ++i) {
data1[i] = internal::random<bool>() ? NumTraits<Scalar>::quiet_NaN() : Scalar(0);
data1[i + PacketSize] = internal::random<bool>() ? NumTraits<Scalar>::quiet_NaN() : Scalar(0);
} // Note: NaN propagation is implementation defined for pmin/pmax, so we do not test it here.
CHECK_CWISE2_IF(PacketTraits::HasMin, propagate_number_min, (internal::pmin<PropagateNumbers>));
CHECK_CWISE2_IF(PacketTraits::HasMax, propagate_number_max, internal::pmax<PropagateNumbers>);
CHECK_CWISE2_IF(PacketTraits::HasMin, propagate_nan_min, (internal::pmin<PropagateNaN>));
CHECK_CWISE2_IF(PacketTraits::HasMax, propagate_nan_max, internal::pmax<PropagateNaN>);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.