1 /*
2  *  Copyright (c) 2017 The WebRTC 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 "modules/audio_processing/aec3/vector_math.h"
12 
13 #include <math.h>
14 
15 #include "system_wrappers/include/cpu_features_wrapper.h"
16 #include "test/gtest.h"
17 #include "typedefs.h"  // NOLINT(build/include)
18 
19 namespace webrtc {
20 
21 #if defined(WEBRTC_HAS_NEON)
22 
TEST(VectorMath,Sqrt)23 TEST(VectorMath, Sqrt) {
24   std::array<float, kFftLengthBy2Plus1> x;
25   std::array<float, kFftLengthBy2Plus1> z;
26   std::array<float, kFftLengthBy2Plus1> z_neon;
27 
28   for (size_t k = 0; k < x.size(); ++k) {
29     x[k] = (2.f / 3.f) * k;
30   }
31 
32   std::copy(x.begin(), x.end(), z.begin());
33   aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z);
34   std::copy(x.begin(), x.end(), z_neon.begin());
35   aec3::VectorMath(Aec3Optimization::kNeon).Sqrt(z_neon);
36   for (size_t k = 0; k < z.size(); ++k) {
37     EXPECT_NEAR(z[k], z_neon[k], 0.0001f);
38     EXPECT_NEAR(sqrtf(x[k]), z_neon[k], 0.0001f);
39   }
40 }
41 
TEST(VectorMath,Multiply)42 TEST(VectorMath, Multiply) {
43   std::array<float, kFftLengthBy2Plus1> x;
44   std::array<float, kFftLengthBy2Plus1> y;
45   std::array<float, kFftLengthBy2Plus1> z;
46   std::array<float, kFftLengthBy2Plus1> z_neon;
47 
48   for (size_t k = 0; k < x.size(); ++k) {
49     x[k] = k;
50     y[k] = (2.f / 3.f) * k;
51   }
52 
53   aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z);
54   aec3::VectorMath(Aec3Optimization::kNeon).Multiply(x, y, z_neon);
55   for (size_t k = 0; k < z.size(); ++k) {
56     EXPECT_FLOAT_EQ(z[k], z_neon[k]);
57     EXPECT_FLOAT_EQ(x[k] * y[k], z_neon[k]);
58   }
59 }
60 
TEST(VectorMath,Accumulate)61 TEST(VectorMath, Accumulate) {
62   std::array<float, kFftLengthBy2Plus1> x;
63   std::array<float, kFftLengthBy2Plus1> z;
64   std::array<float, kFftLengthBy2Plus1> z_neon;
65 
66   for (size_t k = 0; k < x.size(); ++k) {
67     x[k] = k;
68     z[k] = z_neon[k] = 2.f * k;
69   }
70 
71   aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z);
72   aec3::VectorMath(Aec3Optimization::kNeon).Accumulate(x, z_neon);
73   for (size_t k = 0; k < z.size(); ++k) {
74     EXPECT_FLOAT_EQ(z[k], z_neon[k]);
75     EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_neon[k]);
76   }
77 }
78 #endif
79 
80 #if defined(WEBRTC_ARCH_X86_FAMILY)
81 
TEST(VectorMath,Sqrt)82 TEST(VectorMath, Sqrt) {
83   if (WebRtc_GetCPUInfo(kSSE2) != 0) {
84     std::array<float, kFftLengthBy2Plus1> x;
85     std::array<float, kFftLengthBy2Plus1> z;
86     std::array<float, kFftLengthBy2Plus1> z_sse2;
87 
88     for (size_t k = 0; k < x.size(); ++k) {
89       x[k] = (2.f / 3.f) * k;
90     }
91 
92     std::copy(x.begin(), x.end(), z.begin());
93     aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z);
94     std::copy(x.begin(), x.end(), z_sse2.begin());
95     aec3::VectorMath(Aec3Optimization::kSse2).Sqrt(z_sse2);
96     EXPECT_EQ(z, z_sse2);
97     for (size_t k = 0; k < z.size(); ++k) {
98       EXPECT_FLOAT_EQ(z[k], z_sse2[k]);
99       EXPECT_FLOAT_EQ(sqrtf(x[k]), z_sse2[k]);
100     }
101   }
102 }
103 
TEST(VectorMath,Multiply)104 TEST(VectorMath, Multiply) {
105   if (WebRtc_GetCPUInfo(kSSE2) != 0) {
106     std::array<float, kFftLengthBy2Plus1> x;
107     std::array<float, kFftLengthBy2Plus1> y;
108     std::array<float, kFftLengthBy2Plus1> z;
109     std::array<float, kFftLengthBy2Plus1> z_sse2;
110 
111     for (size_t k = 0; k < x.size(); ++k) {
112       x[k] = k;
113       y[k] = (2.f / 3.f) * k;
114     }
115 
116     aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z);
117     aec3::VectorMath(Aec3Optimization::kSse2).Multiply(x, y, z_sse2);
118     for (size_t k = 0; k < z.size(); ++k) {
119       EXPECT_FLOAT_EQ(z[k], z_sse2[k]);
120       EXPECT_FLOAT_EQ(x[k] * y[k], z_sse2[k]);
121     }
122   }
123 }
124 
TEST(VectorMath,Accumulate)125 TEST(VectorMath, Accumulate) {
126   if (WebRtc_GetCPUInfo(kSSE2) != 0) {
127     std::array<float, kFftLengthBy2Plus1> x;
128     std::array<float, kFftLengthBy2Plus1> z;
129     std::array<float, kFftLengthBy2Plus1> z_sse2;
130 
131     for (size_t k = 0; k < x.size(); ++k) {
132       x[k] = k;
133       z[k] = z_sse2[k] = 2.f * k;
134     }
135 
136     aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z);
137     aec3::VectorMath(Aec3Optimization::kSse2).Accumulate(x, z_sse2);
138     for (size_t k = 0; k < z.size(); ++k) {
139       EXPECT_FLOAT_EQ(z[k], z_sse2[k]);
140       EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_sse2[k]);
141     }
142   }
143 }
144 #endif
145 
146 }  // namespace webrtc
147