From 1734712a6faea21f867acca4eddc64ac26d55333 Mon Sep 17 00:00:00 2001 From: Frank Barchard Date: Wed, 4 Oct 2017 14:23:20 -0700 Subject: [PATCH] Fix odd length HammingDistance If length of HammingDistance was not a multiple of 4, the result was incorrect. The old tests did not catch this so a new test is done to count 1s. Bug: libyuv:740 Test: LibYUVCompareTest.TestHammingDistance Change-Id: I93db5437821c597f1f162ac263d4a594bb83231f Reviewed-on: https://chromium-review.googlesource.com/699614 Reviewed-by: richard winterton Reviewed-by: Cheng Wang Reviewed-by: Frank Barchard Commit-Queue: Frank Barchard --- README.chromium | 2 +- include/libyuv/version.h | 2 +- source/compare.cc | 5 +++-- source/compare_common.cc | 12 +++++++++++- unit_test/compare_test.cc | 17 +++++++++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.chromium b/README.chromium index 9d05c559e..2c97ef119 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 1672 +Version: 1673 License: BSD License File: LICENSE diff --git a/include/libyuv/version.h b/include/libyuv/version.h index 2314ef0a0..ea589a0c0 100644 --- a/include/libyuv/version.h +++ b/include/libyuv/version.h @@ -11,6 +11,6 @@ #ifndef INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_ -#define LIBYUV_VERSION 1672 +#define LIBYUV_VERSION 1673 #endif // INCLUDE_LIBYUV_VERSION_H_ diff --git a/source/compare.cc b/source/compare.cc index 63ec526e4..986b097c0 100644 --- a/source/compare.cc +++ b/source/compare.cc @@ -115,8 +115,9 @@ uint64 ComputeHammingDistance(const uint8* src_a, const uint8* src_b, int count) { const int kBlockSize = 65536; + const int kSimdSize = 64; // SIMD for multiple of 64, and C for remainder - int remainder = count & (kBlockSize - 1) & ~63; + int remainder = count & (kBlockSize - 1) & ~(kSimdSize - 1); uint64 diff = 0; int i; uint32 (*HammingDistance)(const uint8* src_a, const uint8* src_b, int count) = @@ -159,7 +160,7 @@ uint64 ComputeHammingDistance(const uint8* src_a, src_a += remainder; src_b += remainder; } - remainder = count & 31; + remainder = count & (kSimdSize - 1); if (remainder) { diff += HammingDistance_C(src_a, src_b, remainder); } diff --git a/source/compare_common.cc b/source/compare_common.cc index d3e46fb50..83564a1bc 100644 --- a/source/compare_common.cc +++ b/source/compare_common.cc @@ -18,7 +18,7 @@ extern "C" { #endif #if ORIGINAL_OPT -uint32 HammingDistance_C(const uint8* src_a, const uint8* src_b, int count) { +uint32 HammingDistance_C1(const uint8* src_a, const uint8* src_b, int count) { uint32 diff = 0u; int i; @@ -58,6 +58,16 @@ uint32 HammingDistance_C(const uint8* src_a, const uint8* src_b, int count) { src_a += 4; src_b += 4; } + + for (; i < count; ++i) { + uint32 x = *src_a ^ *src_b; + uint32 u = x - ((x >> 1) & 0x55); + u = ((u >> 2) & 0x33) + (u & 0x33); + diff += (u + (u >> 4)) & 0x0f; + src_a += 1; + src_b += 1; + } + return diff; } diff --git a/unit_test/compare_test.cc b/unit_test/compare_test.cc index 74e155008..55f5ffde4 100644 --- a/unit_test/compare_test.cc +++ b/unit_test/compare_test.cc @@ -316,6 +316,23 @@ TEST_F(LibYUVCompareTest, BenchmarkHammingDistance) { free_aligned_buffer_page_end(src_b); } +TEST_F(LibYUVCompareTest, TestHammingDistance) { + align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_); + align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_); + memset(src_a, 255u, benchmark_width_ * benchmark_height_); + memset(src_b, 0, benchmark_width_ * benchmark_height_); + + uint64 h1 = 0; + for (int i = 0; i < benchmark_iterations_; ++i) { + h1 = ComputeHammingDistance(src_a, src_b, + benchmark_width_ * benchmark_height_); + } + EXPECT_EQ(benchmark_width_ * benchmark_height_ * 8ULL, h1); + + free_aligned_buffer_page_end(src_a); + free_aligned_buffer_page_end(src_b); +} + TEST_F(LibYUVCompareTest, BenchmarkSumSquareError_Opt) { const int kMaxWidth = 4096 * 3; align_buffer_page_end(src_a, kMaxWidth);