+#include <limits>
+#include <cstdint>
+
#include "gtest/gtest.h"
#include "nnc/core/linalg/Tensor.h"
#include "nnc/core/linalg/ShapeRange.h"
#include "nncc/core/ADT/tensor/Shape.h"
-
#include "op_info_util.h"
std::shared_ptr<TensorVariant> getTensor(const opinfo::Tensor* t)
/** @brief Custom float comparator.
* It is supposed to be equivalent to GTest's ASSERT_FLOAT_EQ when allowedUlpsDiff is 4.
+ * Reminder: if the integer representations of two same-sign floats are subtracted then
+ * the absolute value of the result is equal to one plus the number of representable floats
+ * between them. This difference tells us how many ULPs the numbers differ by.
+ * @usage This function only works if float implementation conforms to IEEE-754.
*/
static inline ::testing::AssertionResult areFloatsEqual(float f1, float f2, int allowedUlpsDiff)
{
- auto intRepr1 = *reinterpret_cast<int*>(&f1);
- auto intRepr2 = *reinterpret_cast<int*>(&f2);
+ auto intRepr1 = *reinterpret_cast<int32_t*>(&f1);
+ auto intRepr2 = *reinterpret_cast<int32_t*>(&f2);
+
+ if ((intRepr1 < 0) != (intRepr2 < 0))
+ {
+ if (f1 == f2) // Checking for +0 and -0
+ return ::testing::AssertionSuccess();
+ else
+ return ::testing::AssertionFailure() << "Different signs";
+ }
- int ulpsDiff = std::abs(intRepr1 - intRepr2);
+ auto ulpsDiff = std::abs(intRepr1 - intRepr2);
if (ulpsDiff <= allowedUlpsDiff)
return ::testing::AssertionSuccess();
using nncc::contrib::core::data::ShapeRange;
using nncc::contrib::core::data::Tensor;
+ const int GTEST_FLOAT_EQ_ULP = 4;
+
Tensor<float> lhsAccessor(lhs);
Tensor<float> rhsAccessor(rhs);
for(auto& idx : ShapeRange(lhsAccessor.getShape()))
{
- ASSERT_TRUE(areFloatsEqual(lhsAccessor.at(idx), rhsAccessor.at(idx), 4));
+ ASSERT_TRUE(areFloatsEqual(lhsAccessor.at(idx), rhsAccessor.at(idx), GTEST_FLOAT_EQ_ULP));
}
}