michael@0: /* michael@0: * Copyright 2013 The LibYuv Project Authors. All rights reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "libyuv/basic_types.h" michael@0: #include "libyuv/cpu_id.h" michael@0: #include "libyuv/row.h" michael@0: #include "libyuv/scale.h" michael@0: #include "libyuv/scale_row.h" michael@0: #include "../unit_test/unit_test.h" michael@0: michael@0: namespace libyuv { michael@0: michael@0: TEST_F(libyuvTest, TestFixedDiv) { michael@0: int num[1280]; michael@0: int div[1280]; michael@0: int result_opt[1280]; michael@0: int result_c[1280]; michael@0: michael@0: EXPECT_EQ(0x10000, libyuv::FixedDiv(1, 1)); michael@0: EXPECT_EQ(0x7fff0000, libyuv::FixedDiv(0x7fff, 1)); michael@0: // TODO(fbarchard): Avoid the following that throw exceptions. michael@0: // EXPECT_EQ(0x100000000, libyuv::FixedDiv(0x10000, 1)); michael@0: // EXPECT_EQ(0x80000000, libyuv::FixedDiv(0x8000, 1)); michael@0: michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(640 * 2, 640)); michael@0: EXPECT_EQ(0x30000, libyuv::FixedDiv(640 * 3, 640)); michael@0: EXPECT_EQ(0x40000, libyuv::FixedDiv(640 * 4, 640)); michael@0: EXPECT_EQ(0x50000, libyuv::FixedDiv(640 * 5, 640)); michael@0: EXPECT_EQ(0x60000, libyuv::FixedDiv(640 * 6, 640)); michael@0: EXPECT_EQ(0x70000, libyuv::FixedDiv(640 * 7, 640)); michael@0: EXPECT_EQ(0x80000, libyuv::FixedDiv(640 * 8, 640)); michael@0: EXPECT_EQ(0xa0000, libyuv::FixedDiv(640 * 10, 640)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(960 * 2, 960)); michael@0: EXPECT_EQ(0x08000, libyuv::FixedDiv(640 / 2, 640)); michael@0: EXPECT_EQ(0x04000, libyuv::FixedDiv(640 / 4, 640)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(1080 * 2, 1080)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(200000, 100000)); michael@0: EXPECT_EQ(0x18000, libyuv::FixedDiv(150000, 100000)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(40000, 20000)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(-40000, -20000)); michael@0: EXPECT_EQ(-0x20000, libyuv::FixedDiv(40000, -20000)); michael@0: EXPECT_EQ(-0x20000, libyuv::FixedDiv(-40000, 20000)); michael@0: EXPECT_EQ(0x10000, libyuv::FixedDiv(4095, 4095)); michael@0: EXPECT_EQ(0x10000, libyuv::FixedDiv(4096, 4096)); michael@0: EXPECT_EQ(0x10000, libyuv::FixedDiv(4097, 4097)); michael@0: EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1)); michael@0: michael@0: for (int i = 1; i < 4100; ++i) { michael@0: EXPECT_EQ(0x10000, libyuv::FixedDiv(i, i)); michael@0: EXPECT_EQ(0x20000, libyuv::FixedDiv(i * 2, i)); michael@0: EXPECT_EQ(0x30000, libyuv::FixedDiv(i * 3, i)); michael@0: EXPECT_EQ(0x40000, libyuv::FixedDiv(i * 4, i)); michael@0: EXPECT_EQ(0x08000, libyuv::FixedDiv(i, i * 2)); michael@0: EXPECT_NEAR(16384 * 65536 / i, libyuv::FixedDiv(16384, i), 1); michael@0: } michael@0: EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1)); michael@0: michael@0: srandom(time(NULL)); michael@0: MemRandomize(reinterpret_cast(&num[0]), sizeof(num)); michael@0: MemRandomize(reinterpret_cast(&div[0]), sizeof(div)); michael@0: for (int j = 0; j < 1280; ++j) { michael@0: if (div[j] == 0) { michael@0: div[j] = 1280; michael@0: } michael@0: num[j] &= 0xffff; // Clamp to avoid divide overflow. michael@0: } michael@0: for (int i = 0; i < benchmark_pixels_div1280_; ++i) { michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_opt[j] = libyuv::FixedDiv(num[j], div[j]); michael@0: } michael@0: } michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_c[j] = libyuv::FixedDiv_C(num[j], div[j]); michael@0: EXPECT_NEAR(result_c[j], result_opt[j], 1); michael@0: } michael@0: } michael@0: michael@0: TEST_F(libyuvTest, TestFixedDiv_Opt) { michael@0: int num[1280]; michael@0: int div[1280]; michael@0: int result_opt[1280]; michael@0: int result_c[1280]; michael@0: michael@0: srandom(time(NULL)); michael@0: MemRandomize(reinterpret_cast(&num[0]), sizeof(num)); michael@0: MemRandomize(reinterpret_cast(&div[0]), sizeof(div)); michael@0: for (int j = 0; j < 1280; ++j) { michael@0: num[j] &= 4095; // Make numerator smaller. michael@0: div[j] &= 4095; // Make divisor smaller. michael@0: if (div[j] == 0) { michael@0: div[j] = 1280; michael@0: } michael@0: } michael@0: michael@0: int has_x86 = TestCpuFlag(kCpuHasX86); michael@0: for (int i = 0; i < benchmark_pixels_div1280_; ++i) { michael@0: if (has_x86) { michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_opt[j] = libyuv::FixedDiv(num[j], div[j]); michael@0: } michael@0: } else { michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_opt[j] = libyuv::FixedDiv_C(num[j], div[j]); michael@0: } michael@0: } michael@0: } michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_c[j] = libyuv::FixedDiv_C(num[j], div[j]); michael@0: EXPECT_NEAR(result_c[j], result_opt[j], 1); michael@0: } michael@0: } michael@0: michael@0: TEST_F(libyuvTest, TestFixedDiv1_Opt) { michael@0: int num[1280]; michael@0: int div[1280]; michael@0: int result_opt[1280]; michael@0: int result_c[1280]; michael@0: michael@0: srandom(time(NULL)); michael@0: MemRandomize(reinterpret_cast(&num[0]), sizeof(num)); michael@0: MemRandomize(reinterpret_cast(&div[0]), sizeof(div)); michael@0: for (int j = 0; j < 1280; ++j) { michael@0: num[j] &= 4095; // Make numerator smaller. michael@0: div[j] &= 4095; // Make divisor smaller. michael@0: if (div[j] <= 1) { michael@0: div[j] = 1280; michael@0: } michael@0: } michael@0: michael@0: int has_x86 = TestCpuFlag(kCpuHasX86); michael@0: for (int i = 0; i < benchmark_pixels_div1280_; ++i) { michael@0: if (has_x86) { michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_opt[j] = libyuv::FixedDiv1(num[j], div[j]); michael@0: } michael@0: } else { michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_opt[j] = libyuv::FixedDiv1_C(num[j], div[j]); michael@0: } michael@0: } michael@0: } michael@0: for (int j = 0; j < 1280; ++j) { michael@0: result_c[j] = libyuv::FixedDiv1_C(num[j], div[j]); michael@0: EXPECT_NEAR(result_c[j], result_opt[j], 1); michael@0: } michael@0: } michael@0: michael@0: } // namespace libyuv