mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Fix pfrexp/pldexp for half.
The recent addition of vectorized pow (!330) relies on `pfrexp` and `pldexp`. This was missing for `Eigen::half` and `Eigen::bfloat16`. Adding tests for these packet ops also exposed an issue with handling negative values in `pfrexp`, returning an incorrect exponent. Added the missing implementations, corrected the exponent in `pfrexp1`, and added `packetmath` tests.
This commit is contained in:
committed by
Rasmus Munk Larsen
parent
25d8498f8b
commit
b2126fd6b5
@@ -46,6 +46,21 @@ inline bool REF_MUL(const bool& a, const bool& 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;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T REF_LDEXP(const T& x, const T& exp) {
|
||||
EIGEN_USING_STD(ldexp)
|
||||
return static_cast<T>(ldexp(x, static_cast<int>(exp)));
|
||||
}
|
||||
|
||||
// Uses pcast to cast from one array to another.
|
||||
template <typename SrcPacket, typename TgtPacket, int SrcCoeffRatio, int TgtCoeffRatio>
|
||||
struct pcast_array;
|
||||
@@ -552,6 +567,17 @@ void packetmath_real() {
|
||||
data2[i] = Scalar(internal::random<double>(-87, 88));
|
||||
}
|
||||
CHECK_CWISE1_IF(PacketTraits::HasExp, std::exp, internal::pexp);
|
||||
CHECK_CWISE1_BYREF1_IF(PacketTraits::HasExp, REF_FREXP, internal::pfrexp);
|
||||
for (int i = 0; i < PacketSize; ++i) {
|
||||
data1[i] = Scalar(internal::random<double>(-1, 1));
|
||||
data2[i] = Scalar(internal::random<double>(-1, 1));
|
||||
}
|
||||
for (int i = 0; i < PacketSize; ++i) {
|
||||
data1[i+PacketSize] = Scalar(internal::random<int>(0, 4));
|
||||
data2[i+PacketSize] = Scalar(internal::random<double>(0, 4));
|
||||
}
|
||||
CHECK_CWISE2_IF(PacketTraits::HasExp, REF_LDEXP, internal::pldexp);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
data1[i] = Scalar(internal::random<double>(-1, 1) * std::pow(10., internal::random<double>(-6, 6)));
|
||||
data2[i] = Scalar(internal::random<double>(-1, 1) * std::pow(10., internal::random<double>(-6, 6)));
|
||||
|
||||
@@ -143,6 +143,9 @@ struct packet_helper
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const Packet& x, unsigned long long umask) const { internal::pstoreu(to, x, umask); }
|
||||
|
||||
template<typename T>
|
||||
inline Packet& forward_reference(Packet& packet, T& /*scalar*/) const { return packet; }
|
||||
};
|
||||
|
||||
template<typename Packet>
|
||||
@@ -162,6 +165,9 @@ struct packet_helper<false,Packet>
|
||||
|
||||
template<typename T>
|
||||
inline void store(T* to, const T& x, unsigned long long) const { *to = x; }
|
||||
|
||||
template<typename T>
|
||||
inline T& forward_reference(Packet& /*packet*/, T& scalar) const { return scalar; }
|
||||
};
|
||||
|
||||
#define CHECK_CWISE1_IF(COND, REFOP, POP) if(COND) { \
|
||||
@@ -180,6 +186,18 @@ struct packet_helper<false,Packet>
|
||||
VERIFY(test::areApprox(ref, data2, PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
// One input, one output by reference.
|
||||
#define CHECK_CWISE1_BYREF1_IF(COND, REFOP, POP) if(COND) { \
|
||||
test::packet_helper<COND,Packet> h; \
|
||||
for (int i=0; i<PacketSize; ++i) \
|
||||
ref[i] = Scalar(REFOP(data1[i], ref[i+PacketSize])); \
|
||||
Packet pout; \
|
||||
Scalar sout; \
|
||||
h.store(data2, POP(h.load(data1), h.forward_reference(pout, sout))); \
|
||||
h.store(data2+PacketSize, h.forward_reference(pout, sout)); \
|
||||
VERIFY(test::areApprox(ref, data2, 2 * PacketSize) && #POP); \
|
||||
}
|
||||
|
||||
#define CHECK_CWISE3_IF(COND, REFOP, POP) if (COND) { \
|
||||
test::packet_helper<COND, Packet> h; \
|
||||
for (int i = 0; i < PacketSize; ++i) \
|
||||
|
||||
Reference in New Issue
Block a user