• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "rtc_base/system/arch.h"
16 #include "system_wrappers/include/cpu_features_wrapper.h"
17 #include "test/gtest.h"
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,Sse2Sqrt)82 TEST(VectorMath, Sse2Sqrt) {
83   if (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,Avx2Sqrt)104 TEST(VectorMath, Avx2Sqrt) {
105   if (GetCPUInfo(kAVX2) != 0) {
106     std::array<float, kFftLengthBy2Plus1> x;
107     std::array<float, kFftLengthBy2Plus1> z;
108     std::array<float, kFftLengthBy2Plus1> z_avx2;
109 
110     for (size_t k = 0; k < x.size(); ++k) {
111       x[k] = (2.f / 3.f) * k;
112     }
113 
114     std::copy(x.begin(), x.end(), z.begin());
115     aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z);
116     std::copy(x.begin(), x.end(), z_avx2.begin());
117     aec3::VectorMath(Aec3Optimization::kAvx2).Sqrt(z_avx2);
118     EXPECT_EQ(z, z_avx2);
119     for (size_t k = 0; k < z.size(); ++k) {
120       EXPECT_FLOAT_EQ(z[k], z_avx2[k]);
121       EXPECT_FLOAT_EQ(sqrtf(x[k]), z_avx2[k]);
122     }
123   }
124 }
125 
TEST(VectorMath,Sse2Multiply)126 TEST(VectorMath, Sse2Multiply) {
127   if (GetCPUInfo(kSSE2) != 0) {
128     std::array<float, kFftLengthBy2Plus1> x;
129     std::array<float, kFftLengthBy2Plus1> y;
130     std::array<float, kFftLengthBy2Plus1> z;
131     std::array<float, kFftLengthBy2Plus1> z_sse2;
132 
133     for (size_t k = 0; k < x.size(); ++k) {
134       x[k] = k;
135       y[k] = (2.f / 3.f) * k;
136     }
137 
138     aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z);
139     aec3::VectorMath(Aec3Optimization::kSse2).Multiply(x, y, z_sse2);
140     for (size_t k = 0; k < z.size(); ++k) {
141       EXPECT_FLOAT_EQ(z[k], z_sse2[k]);
142       EXPECT_FLOAT_EQ(x[k] * y[k], z_sse2[k]);
143     }
144   }
145 }
146 
TEST(VectorMath,Avx2Multiply)147 TEST(VectorMath, Avx2Multiply) {
148   if (GetCPUInfo(kAVX2) != 0) {
149     std::array<float, kFftLengthBy2Plus1> x;
150     std::array<float, kFftLengthBy2Plus1> y;
151     std::array<float, kFftLengthBy2Plus1> z;
152     std::array<float, kFftLengthBy2Plus1> z_avx2;
153 
154     for (size_t k = 0; k < x.size(); ++k) {
155       x[k] = k;
156       y[k] = (2.f / 3.f) * k;
157     }
158 
159     aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z);
160     aec3::VectorMath(Aec3Optimization::kAvx2).Multiply(x, y, z_avx2);
161     for (size_t k = 0; k < z.size(); ++k) {
162       EXPECT_FLOAT_EQ(z[k], z_avx2[k]);
163       EXPECT_FLOAT_EQ(x[k] * y[k], z_avx2[k]);
164     }
165   }
166 }
167 
TEST(VectorMath,Sse2Accumulate)168 TEST(VectorMath, Sse2Accumulate) {
169   if (GetCPUInfo(kSSE2) != 0) {
170     std::array<float, kFftLengthBy2Plus1> x;
171     std::array<float, kFftLengthBy2Plus1> z;
172     std::array<float, kFftLengthBy2Plus1> z_sse2;
173 
174     for (size_t k = 0; k < x.size(); ++k) {
175       x[k] = k;
176       z[k] = z_sse2[k] = 2.f * k;
177     }
178 
179     aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z);
180     aec3::VectorMath(Aec3Optimization::kSse2).Accumulate(x, z_sse2);
181     for (size_t k = 0; k < z.size(); ++k) {
182       EXPECT_FLOAT_EQ(z[k], z_sse2[k]);
183       EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_sse2[k]);
184     }
185   }
186 }
187 
TEST(VectorMath,Avx2Accumulate)188 TEST(VectorMath, Avx2Accumulate) {
189   if (GetCPUInfo(kAVX2) != 0) {
190     std::array<float, kFftLengthBy2Plus1> x;
191     std::array<float, kFftLengthBy2Plus1> z;
192     std::array<float, kFftLengthBy2Plus1> z_avx2;
193 
194     for (size_t k = 0; k < x.size(); ++k) {
195       x[k] = k;
196       z[k] = z_avx2[k] = 2.f * k;
197     }
198 
199     aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z);
200     aec3::VectorMath(Aec3Optimization::kAvx2).Accumulate(x, z_avx2);
201     for (size_t k = 0; k < z.size(); ++k) {
202       EXPECT_FLOAT_EQ(z[k], z_avx2[k]);
203       EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_avx2[k]);
204     }
205   }
206 }
207 #endif
208 
209 }  // namespace webrtc
210