Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / media / base / vector_math_unittest.cc
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.
4
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
7 #include <cmath>
8
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"
17
18 using std::fill;
19
20 namespace media {
21
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;
27
28 class VectorMathTest : public testing::Test {
29  public:
30
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)));
37   }
38
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);
43   }
44
45   void VerifyOutput(float value) {
46     for (int i = 0; i < kVectorSize; ++i)
47       ASSERT_FLOAT_EQ(output_vector_.get()[i], value);
48   }
49
50  protected:
51   scoped_ptr<float, base::AlignedFreeDeleter> input_vector_;
52   scoped_ptr<float, base::AlignedFreeDeleter> output_vector_;
53
54   DISALLOW_COPY_AND_ASSIGN(VectorMathTest);
55 };
56
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;
60
61   {
62     SCOPED_TRACE("FMAC");
63     FillTestVectors(kInputFillValue, kOutputFillValue);
64     vector_math::FMAC(
65         input_vector_.get(), kScale, kVectorSize, output_vector_.get());
66     VerifyOutput(kResult);
67   }
68
69   {
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);
75   }
76
77 #if defined(ARCH_CPU_X86_FAMILY)
78   {
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);
85   }
86 #endif
87
88 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
89   {
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);
95   }
96 #endif
97 }
98
99 // Ensure each optimized vector_math::FMUL() method returns the same value.
100 TEST_F(VectorMathTest, FMUL) {
101   static const float kResult = kInputFillValue * kScale;
102
103   {
104     SCOPED_TRACE("FMUL");
105     FillTestVectors(kInputFillValue, kOutputFillValue);
106     vector_math::FMUL(
107         input_vector_.get(), kScale, kVectorSize, output_vector_.get());
108     VerifyOutput(kResult);
109   }
110
111   {
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);
117   }
118
119 #if defined(ARCH_CPU_X86_FAMILY)
120   {
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);
127   }
128 #endif
129
130 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
131   {
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);
137   }
138 #endif
139 }
140
141 namespace {
142
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));
158   }
159
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));
173     }
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;
178   }
179
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;
187   }
188
189   EWMATestScenario WithImpulse(float value, int offset) const {
190     EWMATestScenario result(*this);
191     result.data_.get()[offset] = value;
192     return result;
193   }
194
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;
201   }
202
203   void RunTest() const {
204     {
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);
210     }
211
212     {
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);
218     }
219
220 #if defined(ARCH_CPU_X86_FAMILY)
221     {
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);
228     }
229 #endif
230
231 #if defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
232     {
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);
238     }
239 #endif
240   }
241
242  private:
243   float initial_value_;
244   scoped_ptr<float, base::AlignedFreeDeleter> data_;
245   int data_len_;
246   float smoothing_factor_;
247   float expected_final_avg_;
248   float expected_max_;
249 };
250
251 }  // namespace
252
253 typedef testing::TestWithParam<EWMATestScenario> VectorMathEWMAAndMaxPowerTest;
254
255 TEST_P(VectorMathEWMAAndMaxPowerTest, Correctness) {
256   GetParam().RunTest();
257 }
258
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
262 };
263
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
267 };
268
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
272 };
273
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
277 };
278
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),
285
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),
289
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),
297
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),
313
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),
328
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),
344
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),
360
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)
383     ));
384
385 }  // namespace media