Clean-up: Removes gfx::FontList::GetStringWidth(text).
[chromium-blink-merge.git] / media / base / vector_math_unittest.cc
blobf8278ce1b5dfd3b45461eefb60f3626f2b22c640
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
7 #include <cmath>
9 #include "base/cpu.h"
10 #include "base/memory/aligned_memory.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringize_macros.h"
14 #include "media/base/vector_math.h"
15 #include "media/base/vector_math_testing.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 using std::fill;
20 namespace media {
22 // Default test values.
23 static const float kScale = 0.5;
24 static const float kInputFillValue = 1.0;
25 static const float kOutputFillValue = 3.0;
26 static const int kVectorSize = 8192;
28 class VectorMathTest : public testing::Test {
29 public:
31 VectorMathTest() {
32 // Initialize input and output vectors.
33 input_vector_.reset(static_cast<float*>(base::AlignedAlloc(
34 sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
35 output_vector_.reset(static_cast<float*>(base::AlignedAlloc(
36 sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
39 void FillTestVectors(float input, float output) {
40 // Setup input and output vectors.
41 fill(input_vector_.get(), input_vector_.get() + kVectorSize, input);
42 fill(output_vector_.get(), output_vector_.get() + kVectorSize, output);
45 void VerifyOutput(float value) {
46 for (int i = 0; i < kVectorSize; ++i)
47 ASSERT_FLOAT_EQ(output_vector_.get()[i], value);
50 protected:
51 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> input_vector_;
52 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> output_vector_;
54 DISALLOW_COPY_AND_ASSIGN(VectorMathTest);
57 // Ensure each optimized vector_math::FMAC() method returns the same value.
58 TEST_F(VectorMathTest, FMAC) {
59 static const float kResult = kInputFillValue * kScale + kOutputFillValue;
62 SCOPED_TRACE("FMAC");
63 FillTestVectors(kInputFillValue, kOutputFillValue);
64 vector_math::FMAC(
65 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
66 VerifyOutput(kResult);
70 SCOPED_TRACE("FMAC_C");
71 FillTestVectors(kInputFillValue, kOutputFillValue);
72 vector_math::FMAC_C(
73 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
74 VerifyOutput(kResult);
77 #if defined(ARCH_CPU_X86_FAMILY)
79 ASSERT_TRUE(base::CPU().has_sse());
80 SCOPED_TRACE("FMAC_SSE");
81 FillTestVectors(kInputFillValue, kOutputFillValue);
82 vector_math::FMAC_SSE(
83 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
84 VerifyOutput(kResult);
86 #endif
88 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
90 SCOPED_TRACE("FMAC_NEON");
91 FillTestVectors(kInputFillValue, kOutputFillValue);
92 vector_math::FMAC_NEON(
93 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
94 VerifyOutput(kResult);
96 #endif
99 // Ensure each optimized vector_math::FMUL() method returns the same value.
100 TEST_F(VectorMathTest, FMUL) {
101 static const float kResult = kInputFillValue * kScale;
104 SCOPED_TRACE("FMUL");
105 FillTestVectors(kInputFillValue, kOutputFillValue);
106 vector_math::FMUL(
107 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
108 VerifyOutput(kResult);
112 SCOPED_TRACE("FMUL_C");
113 FillTestVectors(kInputFillValue, kOutputFillValue);
114 vector_math::FMUL_C(
115 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
116 VerifyOutput(kResult);
119 #if defined(ARCH_CPU_X86_FAMILY)
121 ASSERT_TRUE(base::CPU().has_sse());
122 SCOPED_TRACE("FMUL_SSE");
123 FillTestVectors(kInputFillValue, kOutputFillValue);
124 vector_math::FMUL_SSE(
125 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
126 VerifyOutput(kResult);
128 #endif
130 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
132 SCOPED_TRACE("FMUL_NEON");
133 FillTestVectors(kInputFillValue, kOutputFillValue);
134 vector_math::FMUL_NEON(
135 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
136 VerifyOutput(kResult);
138 #endif
141 namespace {
143 class EWMATestScenario {
144 public:
145 EWMATestScenario(float initial_value, const float src[], int len,
146 float smoothing_factor)
147 : initial_value_(initial_value),
148 data_(static_cast<float*>(
149 len == 0 ? NULL :
150 base::AlignedAlloc(len * sizeof(float),
151 vector_math::kRequiredAlignment))),
152 data_len_(len),
153 smoothing_factor_(smoothing_factor),
154 expected_final_avg_(initial_value),
155 expected_max_(0.0f) {
156 if (data_len_ > 0)
157 memcpy(data_.get(), src, len * sizeof(float));
160 // Copy constructor and assignment operator for ::testing::Values(...).
161 EWMATestScenario(const EWMATestScenario& other) { *this = other; }
162 EWMATestScenario& operator=(const EWMATestScenario& other) {
163 this->initial_value_ = other.initial_value_;
164 this->smoothing_factor_ = other.smoothing_factor_;
165 if (other.data_len_ == 0) {
166 this->data_.reset();
167 } else {
168 this->data_.reset(static_cast<float*>(
169 base::AlignedAlloc(other.data_len_ * sizeof(float),
170 vector_math::kRequiredAlignment)));
171 memcpy(this->data_.get(), other.data_.get(),
172 other.data_len_ * sizeof(float));
174 this->data_len_ = other.data_len_;
175 this->expected_final_avg_ = other.expected_final_avg_;
176 this->expected_max_ = other.expected_max_;
177 return *this;
180 EWMATestScenario ScaledBy(float scale) const {
181 EWMATestScenario result(*this);
182 float* p = result.data_.get();
183 float* const p_end = p + result.data_len_;
184 for (; p < p_end; ++p)
185 *p *= scale;
186 return result;
189 EWMATestScenario WithImpulse(float value, int offset) const {
190 EWMATestScenario result(*this);
191 result.data_.get()[offset] = value;
192 return result;
195 EWMATestScenario HasExpectedResult(float final_avg_value,
196 float max_value) const {
197 EWMATestScenario result(*this);
198 result.expected_final_avg_ = final_avg_value;
199 result.expected_max_ = max_value;
200 return result;
203 void RunTest() const {
205 SCOPED_TRACE("EWMAAndMaxPower");
206 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower(
207 initial_value_, data_.get(), data_len_, smoothing_factor_);
208 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
209 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
213 SCOPED_TRACE("EWMAAndMaxPower_C");
214 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_C(
215 initial_value_, data_.get(), data_len_, smoothing_factor_);
216 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
217 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
220 #if defined(ARCH_CPU_X86_FAMILY)
222 ASSERT_TRUE(base::CPU().has_sse());
223 SCOPED_TRACE("EWMAAndMaxPower_SSE");
224 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_SSE(
225 initial_value_, data_.get(), data_len_, smoothing_factor_);
226 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
227 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
229 #endif
231 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
233 SCOPED_TRACE("EWMAAndMaxPower_NEON");
234 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_NEON(
235 initial_value_, data_.get(), data_len_, smoothing_factor_);
236 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
237 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
239 #endif
242 private:
243 float initial_value_;
244 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data_;
245 int data_len_;
246 float smoothing_factor_;
247 float expected_final_avg_;
248 float expected_max_;
251 } // namespace
253 typedef testing::TestWithParam<EWMATestScenario> VectorMathEWMAAndMaxPowerTest;
255 TEST_P(VectorMathEWMAAndMaxPowerTest, Correctness) {
256 GetParam().RunTest();
259 static const float kZeros[] = { // 32 zeros
260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
264 static const float kOnes[] = { // 32 ones
265 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
266 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
269 static const float kCheckerboard[] = { // 32 alternating 0, 1
270 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
271 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
274 static const float kInverseCheckerboard[] = { // 32 alternating 1, 0
275 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
276 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
279 INSTANTIATE_TEST_CASE_P(
280 Scenarios, VectorMathEWMAAndMaxPowerTest,
281 ::testing::Values(
282 // Zero-length input: Result should equal initial value.
283 EWMATestScenario(0.0f, NULL, 0, 0.0f).HasExpectedResult(0.0f, 0.0f),
284 EWMATestScenario(1.0f, NULL, 0, 0.0f).HasExpectedResult(1.0f, 0.0f),
286 // Smoothing factor of zero: Samples have no effect on result.
287 EWMATestScenario(0.0f, kOnes, 32, 0.0f).HasExpectedResult(0.0f, 1.0f),
288 EWMATestScenario(1.0f, kZeros, 32, 0.0f).HasExpectedResult(1.0f, 0.0f),
290 // Smothing factor of one: Result = last sample squared.
291 EWMATestScenario(0.0f, kCheckerboard, 32, 1.0f)
292 .ScaledBy(2.0f)
293 .HasExpectedResult(4.0f, 4.0f),
294 EWMATestScenario(1.0f, kInverseCheckerboard, 32, 1.0f)
295 .ScaledBy(2.0f)
296 .HasExpectedResult(0.0f, 4.0f),
298 // Smoothing factor of 1/4, muted signal.
299 EWMATestScenario(1.0f, kZeros, 1, 0.25f)
300 .HasExpectedResult(powf(0.75, 1.0f), 0.0f),
301 EWMATestScenario(1.0f, kZeros, 2, 0.25f)
302 .HasExpectedResult(powf(0.75, 2.0f), 0.0f),
303 EWMATestScenario(1.0f, kZeros, 3, 0.25f)
304 .HasExpectedResult(powf(0.75, 3.0f), 0.0f),
305 EWMATestScenario(1.0f, kZeros, 12, 0.25f)
306 .HasExpectedResult(powf(0.75, 12.0f), 0.0f),
307 EWMATestScenario(1.0f, kZeros, 13, 0.25f)
308 .HasExpectedResult(powf(0.75, 13.0f), 0.0f),
309 EWMATestScenario(1.0f, kZeros, 14, 0.25f)
310 .HasExpectedResult(powf(0.75, 14.0f), 0.0f),
311 EWMATestScenario(1.0f, kZeros, 15, 0.25f)
312 .HasExpectedResult(powf(0.75, 15.0f), 0.0f),
314 // Smoothing factor of 1/4, constant full-amplitude signal.
315 EWMATestScenario(0.0f, kOnes, 1, 0.25f).HasExpectedResult(0.25f, 1.0f),
316 EWMATestScenario(0.0f, kOnes, 2, 0.25f)
317 .HasExpectedResult(0.4375f, 1.0f),
318 EWMATestScenario(0.0f, kOnes, 3, 0.25f)
319 .HasExpectedResult(0.578125f, 1.0f),
320 EWMATestScenario(0.0f, kOnes, 12, 0.25f)
321 .HasExpectedResult(0.96832365f, 1.0f),
322 EWMATestScenario(0.0f, kOnes, 13, 0.25f)
323 .HasExpectedResult(0.97624274f, 1.0f),
324 EWMATestScenario(0.0f, kOnes, 14, 0.25f)
325 .HasExpectedResult(0.98218205f, 1.0f),
326 EWMATestScenario(0.0f, kOnes, 15, 0.25f)
327 .HasExpectedResult(0.98663654f, 1.0f),
329 // Smoothing factor of 1/4, checkerboard signal.
330 EWMATestScenario(0.0f, kCheckerboard, 1, 0.25f)
331 .HasExpectedResult(0.0f, 0.0f),
332 EWMATestScenario(0.0f, kCheckerboard, 2, 0.25f)
333 .HasExpectedResult(0.25f, 1.0f),
334 EWMATestScenario(0.0f, kCheckerboard, 3, 0.25f)
335 .HasExpectedResult(0.1875f, 1.0f),
336 EWMATestScenario(0.0f, kCheckerboard, 12, 0.25f)
337 .HasExpectedResult(0.55332780f, 1.0f),
338 EWMATestScenario(0.0f, kCheckerboard, 13, 0.25f)
339 .HasExpectedResult(0.41499585f, 1.0f),
340 EWMATestScenario(0.0f, kCheckerboard, 14, 0.25f)
341 .HasExpectedResult(0.56124689f, 1.0f),
342 EWMATestScenario(0.0f, kCheckerboard, 15, 0.25f)
343 .HasExpectedResult(0.42093517f, 1.0f),
345 // Smoothing factor of 1/4, inverse checkerboard signal.
346 EWMATestScenario(0.0f, kInverseCheckerboard, 1, 0.25f)
347 .HasExpectedResult(0.25f, 1.0f),
348 EWMATestScenario(0.0f, kInverseCheckerboard, 2, 0.25f)
349 .HasExpectedResult(0.1875f, 1.0f),
350 EWMATestScenario(0.0f, kInverseCheckerboard, 3, 0.25f)
351 .HasExpectedResult(0.390625f, 1.0f),
352 EWMATestScenario(0.0f, kInverseCheckerboard, 12, 0.25f)
353 .HasExpectedResult(0.41499585f, 1.0f),
354 EWMATestScenario(0.0f, kInverseCheckerboard, 13, 0.25f)
355 .HasExpectedResult(0.56124689f, 1.0f),
356 EWMATestScenario(0.0f, kInverseCheckerboard, 14, 0.25f)
357 .HasExpectedResult(0.42093517f, 1.0f),
358 EWMATestScenario(0.0f, kInverseCheckerboard, 15, 0.25f)
359 .HasExpectedResult(0.56570137f, 1.0f),
361 // Smoothing factor of 1/4, impluse signal.
362 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
363 .WithImpulse(2.0f, 0)
364 .HasExpectedResult(0.562500f, 4.0f),
365 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
366 .WithImpulse(2.0f, 1)
367 .HasExpectedResult(0.75f, 4.0f),
368 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
369 .WithImpulse(2.0f, 2)
370 .HasExpectedResult(1.0f, 4.0f),
371 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
372 .WithImpulse(2.0f, 0)
373 .HasExpectedResult(0.00013394f, 4.0f),
374 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
375 .WithImpulse(2.0f, 1)
376 .HasExpectedResult(0.00017858f, 4.0f),
377 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
378 .WithImpulse(2.0f, 2)
379 .HasExpectedResult(0.00023811f, 4.0f),
380 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
381 .WithImpulse(2.0f, 3)
382 .HasExpectedResult(0.00031748f, 4.0f)
385 } // namespace media