mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
fast_math: add extra perf/unit tests
Add a basic sanity test to verify the rounding functions work as expected. Likewise, extend the rounding performance test to cover the additional float -> int fast math functions.
This commit is contained in:
parent
7295983964
commit
b2135be594
@ -4,42 +4,52 @@ namespace opencv_test
|
||||
{
|
||||
using namespace perf;
|
||||
|
||||
template <typename T>
|
||||
static void CvRoundMat(const cv::Mat & src, cv::Mat & dst)
|
||||
{
|
||||
for (int y = 0; y < dst.rows; ++y)
|
||||
{
|
||||
const T * sptr = src.ptr<T>(y);
|
||||
int * dptr = dst.ptr<int>(y);
|
||||
|
||||
for (int x = 0; x < dst.cols; ++x)
|
||||
dptr[x] = cvRound(sptr[x]);
|
||||
}
|
||||
}
|
||||
|
||||
PERF_TEST_P(Size_MatType, CvRound_Float,
|
||||
testing::Combine(testing::Values(TYPICAL_MAT_SIZES),
|
||||
testing::Values(CV_32FC1, CV_64FC1)))
|
||||
{
|
||||
Size size = get<0>(GetParam());
|
||||
int type = get<1>(GetParam()), depth = CV_MAT_DEPTH(type);
|
||||
|
||||
cv::Mat src(size, type), dst(size, CV_32SC1);
|
||||
|
||||
declare.in(src, WARMUP_RNG).out(dst);
|
||||
|
||||
if (depth == CV_32F)
|
||||
{
|
||||
TEST_CYCLE()
|
||||
CvRoundMat<float>(src, dst);
|
||||
}
|
||||
else if (depth == CV_64F)
|
||||
{
|
||||
TEST_CYCLE()
|
||||
CvRoundMat<double>(src, dst);
|
||||
#define DECL_ROUND_TEST(NAME, OP, EXTRA) \
|
||||
template <typename T> \
|
||||
static void OP ## Mat(const cv::Mat & src, cv::Mat & dst) \
|
||||
{ \
|
||||
for (int y = 0; y < dst.rows; ++y) \
|
||||
{ \
|
||||
const T * sptr = src.ptr<T>(y); \
|
||||
int * dptr = dst.ptr<int>(y); \
|
||||
\
|
||||
for (int x = 0; x < dst.cols; ++x) \
|
||||
dptr[x] = OP(sptr[x]) EXTRA; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
PERF_TEST_P(Size_MatType, CvRound_Float ## NAME, \
|
||||
testing::Combine(testing::Values(TYPICAL_MAT_SIZES), \
|
||||
testing::Values(CV_32FC1, CV_64FC1))) \
|
||||
{ \
|
||||
Size size = get<0>(GetParam()); \
|
||||
int type = get<1>(GetParam()), depth = CV_MAT_DEPTH(type); \
|
||||
\
|
||||
cv::Mat src(size, type), dst(size, CV_32SC1); \
|
||||
\
|
||||
declare.in(src, WARMUP_RNG).out(dst); \
|
||||
\
|
||||
if (depth == CV_32F) \
|
||||
{ \
|
||||
TEST_CYCLE() \
|
||||
OP ## Mat<float>(src, dst); \
|
||||
} \
|
||||
else if (depth == CV_64F) \
|
||||
{ \
|
||||
TEST_CYCLE() \
|
||||
OP ## Mat<double>(src, dst); \
|
||||
} \
|
||||
\
|
||||
SANITY_CHECK_NOTHING(); \
|
||||
}
|
||||
|
||||
SANITY_CHECK_NOTHING();
|
||||
}
|
||||
DECL_ROUND_TEST(,cvRound,)
|
||||
DECL_ROUND_TEST(_Ceil,cvCeil,)
|
||||
DECL_ROUND_TEST(_Floor,cvFloor,)
|
||||
|
||||
/* For FP classification tests, try to test them in way which uses
|
||||
branching logic and avoids extra FP logic. */
|
||||
DECL_ROUND_TEST(_NaN,cvIsNaN, ? 1 : 2)
|
||||
DECL_ROUND_TEST(_Inf,cvIsInf, ? 1 : 2)
|
||||
|
||||
} // namespace
|
||||
|
@ -3923,5 +3923,59 @@ TEST(Core_SoftFloat, CvRound)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void checkRounding(T in, int outCeil, int outFloor)
|
||||
{
|
||||
EXPECT_EQ(outCeil,cvCeil(in));
|
||||
EXPECT_EQ(outFloor,cvFloor(in));
|
||||
|
||||
/* cvRound is not expected to be IEEE compliant. The implementation
|
||||
should round to one of the above. */
|
||||
EXPECT_TRUE((cvRound(in) == outCeil) || (cvRound(in) == outFloor));
|
||||
}
|
||||
|
||||
TEST(Core_FastMath, InlineRoundingOps)
|
||||
{
|
||||
struct
|
||||
{
|
||||
double in;
|
||||
int outCeil;
|
||||
int outFloor;
|
||||
} values[] =
|
||||
{
|
||||
// Values are chosen to convert to binary float 32/64 exactly
|
||||
{ 1.0, 1, 1 },
|
||||
{ 1.5, 2, 1 },
|
||||
{ -1.5, -1, -2}
|
||||
};
|
||||
|
||||
for (int i = 0, maxi = sizeof(values) / sizeof(values[0]); i < maxi; i++)
|
||||
{
|
||||
checkRounding<double>(values[i].in, values[i].outCeil, values[i].outFloor);
|
||||
checkRounding<float>((float)values[i].in, values[i].outCeil, values[i].outFloor);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_FastMath, InlineNaN)
|
||||
{
|
||||
EXPECT_EQ( cvIsNaN((float) NAN), 1);
|
||||
EXPECT_EQ( cvIsNaN((float) -NAN), 1);
|
||||
EXPECT_EQ( cvIsNaN(0.0f), 0);
|
||||
EXPECT_EQ( cvIsNaN((double) NAN), 1);
|
||||
EXPECT_EQ( cvIsNaN((double) -NAN), 1);
|
||||
EXPECT_EQ( cvIsNaN(0.0), 0);
|
||||
}
|
||||
|
||||
TEST(Core_FastMath, InlineIsInf)
|
||||
{
|
||||
// Assume HUGE_VAL is infinity. Strictly speaking, may not always be true.
|
||||
EXPECT_EQ( cvIsInf((float) HUGE_VAL), 1);
|
||||
EXPECT_EQ( cvIsInf((float) -HUGE_VAL), 1);
|
||||
EXPECT_EQ( cvIsInf(0.0f), 0);
|
||||
EXPECT_EQ( cvIsInf((double) HUGE_VAL), 1);
|
||||
EXPECT_EQ( cvIsInf((double) -HUGE_VAL), 1);
|
||||
EXPECT_EQ( cvIsInf(0.0), 0);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
/* End of file. */
|
||||
|
Loading…
Reference in New Issue
Block a user