1f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang/*
2f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
3f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *
4f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  Use of this source code is governed by a BSD-style license
5f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  that can be found in the LICENSE file in the root of the source
6f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  tree. An additional intellectual property rights grant can be found
7f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  in the file PATENTS. All contributing project authors may
8f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang *  be found in the AUTHORS file in the root of the source tree.
9f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang */
10f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
11f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include <stdlib.h>
12f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include <string.h>
13f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include <time.h>
14f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
15b83bb38f0a92bedeb52baa31e515220927ef53bbFrank Barchard#include "../unit_test/unit_test.h"
16f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/basic_types.h"
17f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/cpu_id.h"
18f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/scale.h"
19f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang#include "libyuv/scale_row.h"
20f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
21f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuangnamespace libyuv {
22f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
23f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_F(LibYUVBaseTest, TestFixedDiv) {
24f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int num[1280];
25f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int div[1280];
26f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_opt[1280];
27f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_c[1280];
28f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
29f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x10000, libyuv::FixedDiv(1, 1));
30f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x7fff0000, libyuv::FixedDiv(0x7fff, 1));
31f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // TODO(fbarchard): Avoid the following that throw exceptions.
32f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // EXPECT_EQ(0x100000000, libyuv::FixedDiv(0x10000, 1));
33f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  // EXPECT_EQ(0x80000000, libyuv::FixedDiv(0x8000, 1));
34f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
35f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(640 * 2, 640));
36f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x30000, libyuv::FixedDiv(640 * 3, 640));
37f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x40000, libyuv::FixedDiv(640 * 4, 640));
38f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x50000, libyuv::FixedDiv(640 * 5, 640));
39f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x60000, libyuv::FixedDiv(640 * 6, 640));
40f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x70000, libyuv::FixedDiv(640 * 7, 640));
41f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x80000, libyuv::FixedDiv(640 * 8, 640));
42f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0xa0000, libyuv::FixedDiv(640 * 10, 640));
43f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(960 * 2, 960));
44f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x08000, libyuv::FixedDiv(640 / 2, 640));
45f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x04000, libyuv::FixedDiv(640 / 4, 640));
46f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(1080 * 2, 1080));
47f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(200000, 100000));
48f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x18000, libyuv::FixedDiv(150000, 100000));
49f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(40000, 20000));
50f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x20000, libyuv::FixedDiv(-40000, -20000));
51f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(-0x20000, libyuv::FixedDiv(40000, -20000));
52f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(-0x20000, libyuv::FixedDiv(-40000, 20000));
53f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x10000, libyuv::FixedDiv(4095, 4095));
54f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x10000, libyuv::FixedDiv(4096, 4096));
55f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(0x10000, libyuv::FixedDiv(4097, 4097));
56f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
57f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
58f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 1; i < 4100; ++i) {
59f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_EQ(0x10000, libyuv::FixedDiv(i, i));
60f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_EQ(0x20000, libyuv::FixedDiv(i * 2, i));
61f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_EQ(0x30000, libyuv::FixedDiv(i * 3, i));
62f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_EQ(0x40000, libyuv::FixedDiv(i * 4, i));
63f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_EQ(0x08000, libyuv::FixedDiv(i, i * 2));
64f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_NEAR(16384 * 65536 / i, libyuv::FixedDiv(16384, i), 1);
65f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
66f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
67f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
68f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
69f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
70f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
71f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (div[j] == 0) {
72f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      div[j] = 1280;
73f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
74f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    num[j] &= 0xffff;  // Clamp to avoid divide overflow.
75f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
76f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
77f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    for (int j = 0; j < 1280; ++j) {
78f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
79f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
80f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
81f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
82f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
83f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_NEAR(result_c[j], result_opt[j], 1);
84f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
85f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
86f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
87f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_F(LibYUVBaseTest, TestFixedDiv_Opt) {
88f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int num[1280];
89f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int div[1280];
90f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_opt[1280];
91f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_c[1280];
92f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
93f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
94f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
95f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
96f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    num[j] &= 4095;  // Make numerator smaller.
97f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    div[j] &= 4095;  // Make divisor smaller.
98f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (div[j] == 0) {
99f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      div[j] = 1280;
100f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
101f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
102f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
103f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int has_x86 = TestCpuFlag(kCpuHasX86);
104f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
105f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (has_x86) {
106f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      for (int j = 0; j < 1280; ++j) {
107f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
108f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
109f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    } else {
110f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      for (int j = 0; j < 1280; ++j) {
111f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        result_opt[j] = libyuv::FixedDiv_C(num[j], div[j]);
112f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
113f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
114f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
115f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
116f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
117f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_NEAR(result_c[j], result_opt[j], 1);
118f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
119f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
120f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
121f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu KuangTEST_F(LibYUVBaseTest, TestFixedDiv1_Opt) {
122f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int num[1280];
123f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int div[1280];
124f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_opt[1280];
125f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int result_c[1280];
126f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
127f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&num[0]), sizeof(num));
128f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  MemRandomize(reinterpret_cast<uint8*>(&div[0]), sizeof(div));
129f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
130f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    num[j] &= 4095;  // Make numerator smaller.
131f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    div[j] &= 4095;  // Make divisor smaller.
132f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (div[j] <= 1) {
133f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      div[j] = 1280;
134f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
135f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
136f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
137f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  int has_x86 = TestCpuFlag(kCpuHasX86);
138f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
139f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    if (has_x86) {
140f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      for (int j = 0; j < 1280; ++j) {
141f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        result_opt[j] = libyuv::FixedDiv1(num[j], div[j]);
142f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
143f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    } else {
144f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      for (int j = 0; j < 1280; ++j) {
145f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang        result_opt[j] = libyuv::FixedDiv1_C(num[j], div[j]);
146f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang      }
147f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    }
148f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
149f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  for (int j = 0; j < 1280; ++j) {
150f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    result_c[j] = libyuv::FixedDiv1_C(num[j], div[j]);
151f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang    EXPECT_NEAR(result_c[j], result_opt[j], 1);
152f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang  }
153f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}
154f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang
155f047e7ca6983218eed7703c7afd51fed7bd3b5c9Hangyu Kuang}  // namespace libyuv
156