1f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com/*
2f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
3f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *
4f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  Use of this source code is governed by a BSD-style license
5f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  that can be found in the LICENSE file in the root of the source
6f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  tree. An additional intellectual property rights grant can be found
7f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  in the file PATENTS. All contributing project authors may
8f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com *  be found in the AUTHORS file in the root of the source tree.
9f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com */
10f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
11f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com#include <stdlib.h>
12f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com#include <string.h>
13f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
14f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com#include "libyuv/basic_types.h"
15747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com#include "libyuv/cpu_id.h"
16a18ba50d2338a847d60ec69c00cab8d0f8002cc6fbarchard@google.com#include "libyuv/row.h"
175dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com#include "libyuv/scale.h"
185dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com#include "libyuv/scale_row.h"
19f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com#include "../unit_test/unit_test.h"
20f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
21f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.comnamespace libyuv {
22f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
23f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.comTEST_F(libyuvTest, TestFixedDiv) {
2448ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int num[1280];
2548ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int div[1280];
2648ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int result_opt[1280];
2748ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int result_c[1280];
2848ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com
2948ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  EXPECT_EQ(0x10000, libyuv::FixedDiv(1, 1));
3048ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  EXPECT_EQ(0x7fff0000, libyuv::FixedDiv(0x7fff, 1));
3148ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  // TODO(fbarchard): Avoid the following that throw exceptions.
325dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  // EXPECT_EQ(0x100000000, libyuv::FixedDiv(0x10000, 1));
3348ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  // EXPECT_EQ(0x80000000, libyuv::FixedDiv(0x8000, 1));
34f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
35c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(640 * 2, 640));
36c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x30000, libyuv::FixedDiv(640 * 3, 640));
37c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x40000, libyuv::FixedDiv(640 * 4, 640));
38c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x50000, libyuv::FixedDiv(640 * 5, 640));
39c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x60000, libyuv::FixedDiv(640 * 6, 640));
40c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x70000, libyuv::FixedDiv(640 * 7, 640));
41c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x80000, libyuv::FixedDiv(640 * 8, 640));
42c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0xa0000, libyuv::FixedDiv(640 * 10, 640));
43c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(960 * 2, 960));
44c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x08000, libyuv::FixedDiv(640 / 2, 640));
45c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x04000, libyuv::FixedDiv(640 / 4, 640));
46c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(1080 * 2, 1080));
47c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(200000, 100000));
48c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x18000, libyuv::FixedDiv(150000, 100000));
49c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(40000, 20000));
50c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x20000, libyuv::FixedDiv(-40000, -20000));
51c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(-0x20000, libyuv::FixedDiv(40000, -20000));
52c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(-0x20000, libyuv::FixedDiv(-40000, 20000));
53e5d3e10ee88210f8290e6d62765e7f0f532b3cbcfbarchard@google.com  EXPECT_EQ(0x10000, libyuv::FixedDiv(4095, 4095));
54c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x10000, libyuv::FixedDiv(4096, 4096));
55c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com  EXPECT_EQ(0x10000, libyuv::FixedDiv(4097, 4097));
56e5d3e10ee88210f8290e6d62765e7f0f532b3cbcfbarchard@google.com  EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
57c9f0d966edfb8247d0408daa63c599e20fc63ac7fbarchard@google.com
58595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com  for (int i = 1; i < 4100; ++i) {
59595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_EQ(0x10000, libyuv::FixedDiv(i, i));
60595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_EQ(0x20000, libyuv::FixedDiv(i * 2, i));
61595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_EQ(0x30000, libyuv::FixedDiv(i * 3, i));
62595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_EQ(0x40000, libyuv::FixedDiv(i * 4, i));
63595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_EQ(0x08000, libyuv::FixedDiv(i, i * 2));
64595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com    EXPECT_NEAR(16384 * 65536 / i, libyuv::FixedDiv(16384, i), 1);
65595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com  }
66595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com  EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
67595c2427e8543f5a4c1b73e6b2ec4973a5fa5970fbarchard@google.com
68f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  srandom(time(NULL));
69f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
70f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
7148ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
72f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    if (div[j] == 0) {
73f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com      div[j] = 1280;
74f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    }
7548ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com    num[j] &= 0xffff;  // Clamp to avoid divide overflow.
76f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
7748ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
7848ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com    for (int j = 0; j < 1280; ++j) {
79f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com      result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
80f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    }
81f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
8248ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
83f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
84747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com    EXPECT_NEAR(result_c[j], result_opt[j], 1);
85f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
86f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com}
87f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
88f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.comTEST_F(libyuvTest, TestFixedDiv_Opt) {
8948ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int num[1280];
9048ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int div[1280];
9148ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int result_opt[1280];
9248ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  int result_c[1280];
93f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
94f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  srandom(time(NULL));
95f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
96f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
9748ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
98f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    num[j] &= 4095;  // Make numerator smaller.
99f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    div[j] &= 4095;  // Make divisor smaller.
100f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    if (div[j] == 0) {
101f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com      div[j] = 1280;
102f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    }
103f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
104747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com
105747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com  int has_x86 = TestCpuFlag(kCpuHasX86);
10648ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
107747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com    if (has_x86) {
10848ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com      for (int j = 0; j < 1280; ++j) {
109747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com        result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
110747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com      }
111747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com    } else {
11248ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com      for (int j = 0; j < 1280; ++j) {
113747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com        result_opt[j] = libyuv::FixedDiv_C(num[j], div[j]);
114747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com      }
115f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    }
116f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
11748ab3cf3f4c712daad439a271b4cc516d912b191fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
118f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com    result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
119747ceb9fa5cea5c923d4b08acbb7f1cfa39f138efbarchard@google.com    EXPECT_NEAR(result_c[j], result_opt[j], 1);
120f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com  }
121f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com}
122f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com
1235dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.comTEST_F(libyuvTest, TestFixedDiv1_Opt) {
1245dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  int num[1280];
1255dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  int div[1280];
1265dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  int result_opt[1280];
1275dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  int result_c[1280];
1285dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com
1295dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  srandom(time(NULL));
1305dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
1315dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
1325dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
1335dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    num[j] &= 4095;  // Make numerator smaller.
1345dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    div[j] &= 4095;  // Make divisor smaller.
1355dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    if (div[j] <= 1) {
1365dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      div[j] = 1280;
1375dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    }
1385dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  }
1395dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com
1405dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  int has_x86 = TestCpuFlag(kCpuHasX86);
1415dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
1425dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    if (has_x86) {
1435dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      for (int j = 0; j < 1280; ++j) {
1445dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com        result_opt[j] = libyuv::FixedDiv1(num[j], div[j]);
1455dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      }
1465dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    } else {
1475dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      for (int j = 0; j < 1280; ++j) {
1485dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com        result_opt[j] = libyuv::FixedDiv1_C(num[j], div[j]);
1495dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com      }
1505dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    }
1515dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  }
1525dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  for (int j = 0; j < 1280; ++j) {
1535dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    result_c[j] = libyuv::FixedDiv1_C(num[j], div[j]);
1545dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com    EXPECT_NEAR(result_c[j], result_opt[j], 1);
1555dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com  }
1565dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com}
1575dba58cb1ed4117f491267f68351a6079eaed667fbarchard@google.com
158f2f9dbb644626349de54d00caf68ef2290c91f91fbarchard@google.com}  // namespace libyuv
159