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