Add helper method to determine the current application horizontal size classes.
[chromium-blink-merge.git] / media / base / vector_math_unittest.cc
bloba9369231987a1ac030f253d1f5653799524b7982
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/memory/aligned_memory.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringize_macros.h"
13 #include "media/base/vector_math.h"
14 #include "media/base/vector_math_testing.h"
15 #include "testing/gtest/include/gtest/gtest.h"
17 using std::fill;
19 namespace media {
21 // Default test values.
22 static const float kScale = 0.5;
23 static const float kInputFillValue = 1.0;
24 static const float kOutputFillValue = 3.0;
25 static const int kVectorSize = 8192;
27 class VectorMathTest : public testing::Test {
28 public:
30 VectorMathTest() {
31 // Initialize input and output vectors.
32 input_vector_.reset(static_cast<float*>(base::AlignedAlloc(
33 sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
34 output_vector_.reset(static_cast<float*>(base::AlignedAlloc(
35 sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
38 void FillTestVectors(float input, float output) {
39 // Setup input and output vectors.
40 fill(input_vector_.get(), input_vector_.get() + kVectorSize, input);
41 fill(output_vector_.get(), output_vector_.get() + kVectorSize, output);
44 void VerifyOutput(float value) {
45 for (int i = 0; i < kVectorSize; ++i)
46 ASSERT_FLOAT_EQ(output_vector_[i], value);
49 protected:
50 scoped_ptr<float[], base::AlignedFreeDeleter> input_vector_;
51 scoped_ptr<float[], base::AlignedFreeDeleter> output_vector_;
53 DISALLOW_COPY_AND_ASSIGN(VectorMathTest);
56 // Ensure each optimized vector_math::FMAC() method returns the same value.
57 TEST_F(VectorMathTest, FMAC) {
58 static const float kResult = kInputFillValue * kScale + kOutputFillValue;
61 SCOPED_TRACE("FMAC");
62 FillTestVectors(kInputFillValue, kOutputFillValue);
63 vector_math::FMAC(
64 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
65 VerifyOutput(kResult);
69 SCOPED_TRACE("FMAC_C");
70 FillTestVectors(kInputFillValue, kOutputFillValue);
71 vector_math::FMAC_C(
72 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
73 VerifyOutput(kResult);
76 #if defined(ARCH_CPU_X86_FAMILY)
78 SCOPED_TRACE("FMAC_SSE");
79 FillTestVectors(kInputFillValue, kOutputFillValue);
80 vector_math::FMAC_SSE(
81 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
82 VerifyOutput(kResult);
84 #endif
86 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
88 SCOPED_TRACE("FMAC_NEON");
89 FillTestVectors(kInputFillValue, kOutputFillValue);
90 vector_math::FMAC_NEON(
91 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
92 VerifyOutput(kResult);
94 #endif
97 // Ensure each optimized vector_math::FMUL() method returns the same value.
98 TEST_F(VectorMathTest, FMUL) {
99 static const float kResult = kInputFillValue * kScale;
102 SCOPED_TRACE("FMUL");
103 FillTestVectors(kInputFillValue, kOutputFillValue);
104 vector_math::FMUL(
105 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
106 VerifyOutput(kResult);
110 SCOPED_TRACE("FMUL_C");
111 FillTestVectors(kInputFillValue, kOutputFillValue);
112 vector_math::FMUL_C(
113 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
114 VerifyOutput(kResult);
117 #if defined(ARCH_CPU_X86_FAMILY)
119 SCOPED_TRACE("FMUL_SSE");
120 FillTestVectors(kInputFillValue, kOutputFillValue);
121 vector_math::FMUL_SSE(
122 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
123 VerifyOutput(kResult);
125 #endif
127 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
129 SCOPED_TRACE("FMUL_NEON");
130 FillTestVectors(kInputFillValue, kOutputFillValue);
131 vector_math::FMUL_NEON(
132 input_vector_.get(), kScale, kVectorSize, output_vector_.get());
133 VerifyOutput(kResult);
135 #endif
138 TEST_F(VectorMathTest, Crossfade) {
139 FillTestVectors(0, 1);
140 vector_math::Crossfade(
141 input_vector_.get(), kVectorSize, output_vector_.get());
142 for (int i = 0; i < kVectorSize; ++i) {
143 ASSERT_FLOAT_EQ(i / static_cast<float>(kVectorSize), output_vector_[i])
144 << "i=" << i;
148 class EWMATestScenario {
149 public:
150 EWMATestScenario(float initial_value, const float src[], int len,
151 float smoothing_factor)
152 : initial_value_(initial_value),
153 data_(static_cast<float*>(
154 len == 0 ? NULL :
155 base::AlignedAlloc(len * sizeof(float),
156 vector_math::kRequiredAlignment))),
157 data_len_(len),
158 smoothing_factor_(smoothing_factor),
159 expected_final_avg_(initial_value),
160 expected_max_(0.0f) {
161 if (data_len_ > 0)
162 memcpy(data_.get(), src, len * sizeof(float));
165 // Copy constructor and assignment operator for ::testing::Values(...).
166 EWMATestScenario(const EWMATestScenario& other) { *this = other; }
167 EWMATestScenario& operator=(const EWMATestScenario& other) {
168 this->initial_value_ = other.initial_value_;
169 this->smoothing_factor_ = other.smoothing_factor_;
170 if (other.data_len_ == 0) {
171 this->data_.reset();
172 } else {
173 this->data_.reset(static_cast<float*>(
174 base::AlignedAlloc(other.data_len_ * sizeof(float),
175 vector_math::kRequiredAlignment)));
176 memcpy(this->data_.get(), other.data_.get(),
177 other.data_len_ * sizeof(float));
179 this->data_len_ = other.data_len_;
180 this->expected_final_avg_ = other.expected_final_avg_;
181 this->expected_max_ = other.expected_max_;
182 return *this;
185 EWMATestScenario ScaledBy(float scale) const {
186 EWMATestScenario result(*this);
187 float* p = result.data_.get();
188 float* const p_end = p + result.data_len_;
189 for (; p < p_end; ++p)
190 *p *= scale;
191 return result;
194 EWMATestScenario WithImpulse(float value, int offset) const {
195 EWMATestScenario result(*this);
196 result.data_.get()[offset] = value;
197 return result;
200 EWMATestScenario HasExpectedResult(float final_avg_value,
201 float max_value) const {
202 EWMATestScenario result(*this);
203 result.expected_final_avg_ = final_avg_value;
204 result.expected_max_ = max_value;
205 return result;
208 void RunTest() const {
210 SCOPED_TRACE("EWMAAndMaxPower");
211 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower(
212 initial_value_, data_.get(), data_len_, smoothing_factor_);
213 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
214 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
218 SCOPED_TRACE("EWMAAndMaxPower_C");
219 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_C(
220 initial_value_, data_.get(), data_len_, smoothing_factor_);
221 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
222 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
225 #if defined(ARCH_CPU_X86_FAMILY)
227 SCOPED_TRACE("EWMAAndMaxPower_SSE");
228 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_SSE(
229 initial_value_, data_.get(), data_len_, smoothing_factor_);
230 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
231 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
233 #endif
235 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
237 SCOPED_TRACE("EWMAAndMaxPower_NEON");
238 const std::pair<float, float>& result = vector_math::EWMAAndMaxPower_NEON(
239 initial_value_, data_.get(), data_len_, smoothing_factor_);
240 EXPECT_NEAR(expected_final_avg_, result.first, 0.0000001f);
241 EXPECT_NEAR(expected_max_, result.second, 0.0000001f);
243 #endif
246 private:
247 float initial_value_;
248 scoped_ptr<float, base::AlignedFreeDeleter> data_;
249 int data_len_;
250 float smoothing_factor_;
251 float expected_final_avg_;
252 float expected_max_;
255 typedef testing::TestWithParam<EWMATestScenario> VectorMathEWMAAndMaxPowerTest;
257 TEST_P(VectorMathEWMAAndMaxPowerTest, Correctness) {
258 GetParam().RunTest();
261 static const float kZeros[] = { // 32 zeros
262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
266 static const float kOnes[] = { // 32 ones
267 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
268 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
271 static const float kCheckerboard[] = { // 32 alternating 0, 1
272 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
273 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
276 static const float kInverseCheckerboard[] = { // 32 alternating 1, 0
277 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
278 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
281 INSTANTIATE_TEST_CASE_P(
282 Scenarios, VectorMathEWMAAndMaxPowerTest,
283 ::testing::Values(
284 // Zero-length input: Result should equal initial value.
285 EWMATestScenario(0.0f, NULL, 0, 0.0f).HasExpectedResult(0.0f, 0.0f),
286 EWMATestScenario(1.0f, NULL, 0, 0.0f).HasExpectedResult(1.0f, 0.0f),
288 // Smoothing factor of zero: Samples have no effect on result.
289 EWMATestScenario(0.0f, kOnes, 32, 0.0f).HasExpectedResult(0.0f, 1.0f),
290 EWMATestScenario(1.0f, kZeros, 32, 0.0f).HasExpectedResult(1.0f, 0.0f),
292 // Smothing factor of one: Result = last sample squared.
293 EWMATestScenario(0.0f, kCheckerboard, 32, 1.0f)
294 .ScaledBy(2.0f)
295 .HasExpectedResult(4.0f, 4.0f),
296 EWMATestScenario(1.0f, kInverseCheckerboard, 32, 1.0f)
297 .ScaledBy(2.0f)
298 .HasExpectedResult(0.0f, 4.0f),
300 // Smoothing factor of 1/4, muted signal.
301 EWMATestScenario(1.0f, kZeros, 1, 0.25f)
302 .HasExpectedResult(powf(0.75, 1.0f), 0.0f),
303 EWMATestScenario(1.0f, kZeros, 2, 0.25f)
304 .HasExpectedResult(powf(0.75, 2.0f), 0.0f),
305 EWMATestScenario(1.0f, kZeros, 3, 0.25f)
306 .HasExpectedResult(powf(0.75, 3.0f), 0.0f),
307 EWMATestScenario(1.0f, kZeros, 12, 0.25f)
308 .HasExpectedResult(powf(0.75, 12.0f), 0.0f),
309 EWMATestScenario(1.0f, kZeros, 13, 0.25f)
310 .HasExpectedResult(powf(0.75, 13.0f), 0.0f),
311 EWMATestScenario(1.0f, kZeros, 14, 0.25f)
312 .HasExpectedResult(powf(0.75, 14.0f), 0.0f),
313 EWMATestScenario(1.0f, kZeros, 15, 0.25f)
314 .HasExpectedResult(powf(0.75, 15.0f), 0.0f),
316 // Smoothing factor of 1/4, constant full-amplitude signal.
317 EWMATestScenario(0.0f, kOnes, 1, 0.25f).HasExpectedResult(0.25f, 1.0f),
318 EWMATestScenario(0.0f, kOnes, 2, 0.25f)
319 .HasExpectedResult(0.4375f, 1.0f),
320 EWMATestScenario(0.0f, kOnes, 3, 0.25f)
321 .HasExpectedResult(0.578125f, 1.0f),
322 EWMATestScenario(0.0f, kOnes, 12, 0.25f)
323 .HasExpectedResult(0.96832365f, 1.0f),
324 EWMATestScenario(0.0f, kOnes, 13, 0.25f)
325 .HasExpectedResult(0.97624274f, 1.0f),
326 EWMATestScenario(0.0f, kOnes, 14, 0.25f)
327 .HasExpectedResult(0.98218205f, 1.0f),
328 EWMATestScenario(0.0f, kOnes, 15, 0.25f)
329 .HasExpectedResult(0.98663654f, 1.0f),
331 // Smoothing factor of 1/4, checkerboard signal.
332 EWMATestScenario(0.0f, kCheckerboard, 1, 0.25f)
333 .HasExpectedResult(0.0f, 0.0f),
334 EWMATestScenario(0.0f, kCheckerboard, 2, 0.25f)
335 .HasExpectedResult(0.25f, 1.0f),
336 EWMATestScenario(0.0f, kCheckerboard, 3, 0.25f)
337 .HasExpectedResult(0.1875f, 1.0f),
338 EWMATestScenario(0.0f, kCheckerboard, 12, 0.25f)
339 .HasExpectedResult(0.55332780f, 1.0f),
340 EWMATestScenario(0.0f, kCheckerboard, 13, 0.25f)
341 .HasExpectedResult(0.41499585f, 1.0f),
342 EWMATestScenario(0.0f, kCheckerboard, 14, 0.25f)
343 .HasExpectedResult(0.56124689f, 1.0f),
344 EWMATestScenario(0.0f, kCheckerboard, 15, 0.25f)
345 .HasExpectedResult(0.42093517f, 1.0f),
347 // Smoothing factor of 1/4, inverse checkerboard signal.
348 EWMATestScenario(0.0f, kInverseCheckerboard, 1, 0.25f)
349 .HasExpectedResult(0.25f, 1.0f),
350 EWMATestScenario(0.0f, kInverseCheckerboard, 2, 0.25f)
351 .HasExpectedResult(0.1875f, 1.0f),
352 EWMATestScenario(0.0f, kInverseCheckerboard, 3, 0.25f)
353 .HasExpectedResult(0.390625f, 1.0f),
354 EWMATestScenario(0.0f, kInverseCheckerboard, 12, 0.25f)
355 .HasExpectedResult(0.41499585f, 1.0f),
356 EWMATestScenario(0.0f, kInverseCheckerboard, 13, 0.25f)
357 .HasExpectedResult(0.56124689f, 1.0f),
358 EWMATestScenario(0.0f, kInverseCheckerboard, 14, 0.25f)
359 .HasExpectedResult(0.42093517f, 1.0f),
360 EWMATestScenario(0.0f, kInverseCheckerboard, 15, 0.25f)
361 .HasExpectedResult(0.56570137f, 1.0f),
363 // Smoothing factor of 1/4, impluse signal.
364 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
365 .WithImpulse(2.0f, 0)
366 .HasExpectedResult(0.562500f, 4.0f),
367 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
368 .WithImpulse(2.0f, 1)
369 .HasExpectedResult(0.75f, 4.0f),
370 EWMATestScenario(0.0f, kZeros, 3, 0.25f)
371 .WithImpulse(2.0f, 2)
372 .HasExpectedResult(1.0f, 4.0f),
373 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
374 .WithImpulse(2.0f, 0)
375 .HasExpectedResult(0.00013394f, 4.0f),
376 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
377 .WithImpulse(2.0f, 1)
378 .HasExpectedResult(0.00017858f, 4.0f),
379 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
380 .WithImpulse(2.0f, 2)
381 .HasExpectedResult(0.00023811f, 4.0f),
382 EWMATestScenario(0.0f, kZeros, 32, 0.25f)
383 .WithImpulse(2.0f, 3)
384 .HasExpectedResult(0.00031748f, 4.0f)
387 } // namespace media