vector_math_unittest.cc (6356B)
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 <algorithm> 14 #include <array> 15 #include <cmath> 16 #include <cstddef> 17 18 #include "modules/audio_processing/aec3/aec3_common.h" 19 #include "rtc_base/cpu_info.h" 20 #include "rtc_base/system/arch.h" 21 #include "test/gtest.h" 22 23 namespace webrtc { 24 25 #if defined(WEBRTC_HAS_NEON) 26 27 TEST(VectorMath, Sqrt) { 28 std::array<float, kFftLengthBy2Plus1> x; 29 std::array<float, kFftLengthBy2Plus1> z; 30 std::array<float, kFftLengthBy2Plus1> z_neon; 31 32 for (size_t k = 0; k < x.size(); ++k) { 33 x[k] = (2.f / 3.f) * k; 34 } 35 36 std::copy(x.begin(), x.end(), z.begin()); 37 aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z); 38 std::copy(x.begin(), x.end(), z_neon.begin()); 39 aec3::VectorMath(Aec3Optimization::kNeon).Sqrt(z_neon); 40 for (size_t k = 0; k < z.size(); ++k) { 41 EXPECT_NEAR(z[k], z_neon[k], 0.0001f); 42 EXPECT_NEAR(sqrtf(x[k]), z_neon[k], 0.0001f); 43 } 44 } 45 46 TEST(VectorMath, Multiply) { 47 std::array<float, kFftLengthBy2Plus1> x; 48 std::array<float, kFftLengthBy2Plus1> y; 49 std::array<float, kFftLengthBy2Plus1> z; 50 std::array<float, kFftLengthBy2Plus1> z_neon; 51 52 for (size_t k = 0; k < x.size(); ++k) { 53 x[k] = k; 54 y[k] = (2.f / 3.f) * k; 55 } 56 57 aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z); 58 aec3::VectorMath(Aec3Optimization::kNeon).Multiply(x, y, z_neon); 59 for (size_t k = 0; k < z.size(); ++k) { 60 EXPECT_FLOAT_EQ(z[k], z_neon[k]); 61 EXPECT_FLOAT_EQ(x[k] * y[k], z_neon[k]); 62 } 63 } 64 65 TEST(VectorMath, Accumulate) { 66 std::array<float, kFftLengthBy2Plus1> x; 67 std::array<float, kFftLengthBy2Plus1> z; 68 std::array<float, kFftLengthBy2Plus1> z_neon; 69 70 for (size_t k = 0; k < x.size(); ++k) { 71 x[k] = k; 72 z[k] = z_neon[k] = 2.f * k; 73 } 74 75 aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z); 76 aec3::VectorMath(Aec3Optimization::kNeon).Accumulate(x, z_neon); 77 for (size_t k = 0; k < z.size(); ++k) { 78 EXPECT_FLOAT_EQ(z[k], z_neon[k]); 79 EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_neon[k]); 80 } 81 } 82 #endif 83 84 #if defined(WEBRTC_ARCH_X86_FAMILY) 85 86 TEST(VectorMath, Sse2Sqrt) { 87 if (cpu_info::Supports(cpu_info::ISA::kSSE2)) { 88 std::array<float, kFftLengthBy2Plus1> x; 89 std::array<float, kFftLengthBy2Plus1> z; 90 std::array<float, kFftLengthBy2Plus1> z_sse2; 91 92 for (size_t k = 0; k < x.size(); ++k) { 93 x[k] = (2.f / 3.f) * k; 94 } 95 96 std::copy(x.begin(), x.end(), z.begin()); 97 aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z); 98 std::copy(x.begin(), x.end(), z_sse2.begin()); 99 aec3::VectorMath(Aec3Optimization::kSse2).Sqrt(z_sse2); 100 EXPECT_EQ(z, z_sse2); 101 for (size_t k = 0; k < z.size(); ++k) { 102 EXPECT_FLOAT_EQ(z[k], z_sse2[k]); 103 EXPECT_FLOAT_EQ(sqrtf(x[k]), z_sse2[k]); 104 } 105 } 106 } 107 108 TEST(VectorMath, Avx2Sqrt) { 109 if (cpu_info::Supports(cpu_info::ISA::kAVX2)) { 110 std::array<float, kFftLengthBy2Plus1> x; 111 std::array<float, kFftLengthBy2Plus1> z; 112 std::array<float, kFftLengthBy2Plus1> z_avx2; 113 114 for (size_t k = 0; k < x.size(); ++k) { 115 x[k] = (2.f / 3.f) * k; 116 } 117 118 std::copy(x.begin(), x.end(), z.begin()); 119 aec3::VectorMath(Aec3Optimization::kNone).Sqrt(z); 120 std::copy(x.begin(), x.end(), z_avx2.begin()); 121 aec3::VectorMath(Aec3Optimization::kAvx2).Sqrt(z_avx2); 122 EXPECT_EQ(z, z_avx2); 123 for (size_t k = 0; k < z.size(); ++k) { 124 EXPECT_FLOAT_EQ(z[k], z_avx2[k]); 125 EXPECT_FLOAT_EQ(sqrtf(x[k]), z_avx2[k]); 126 } 127 } 128 } 129 130 TEST(VectorMath, Sse2Multiply) { 131 if (cpu_info::Supports(cpu_info::ISA::kSSE2)) { 132 std::array<float, kFftLengthBy2Plus1> x; 133 std::array<float, kFftLengthBy2Plus1> y; 134 std::array<float, kFftLengthBy2Plus1> z; 135 std::array<float, kFftLengthBy2Plus1> z_sse2; 136 137 for (size_t k = 0; k < x.size(); ++k) { 138 x[k] = k; 139 y[k] = (2.f / 3.f) * k; 140 } 141 142 aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z); 143 aec3::VectorMath(Aec3Optimization::kSse2).Multiply(x, y, z_sse2); 144 for (size_t k = 0; k < z.size(); ++k) { 145 EXPECT_FLOAT_EQ(z[k], z_sse2[k]); 146 EXPECT_FLOAT_EQ(x[k] * y[k], z_sse2[k]); 147 } 148 } 149 } 150 151 TEST(VectorMath, Avx2Multiply) { 152 if (cpu_info::Supports(cpu_info::ISA::kAVX2)) { 153 std::array<float, kFftLengthBy2Plus1> x; 154 std::array<float, kFftLengthBy2Plus1> y; 155 std::array<float, kFftLengthBy2Plus1> z; 156 std::array<float, kFftLengthBy2Plus1> z_avx2; 157 158 for (size_t k = 0; k < x.size(); ++k) { 159 x[k] = k; 160 y[k] = (2.f / 3.f) * k; 161 } 162 163 aec3::VectorMath(Aec3Optimization::kNone).Multiply(x, y, z); 164 aec3::VectorMath(Aec3Optimization::kAvx2).Multiply(x, y, z_avx2); 165 for (size_t k = 0; k < z.size(); ++k) { 166 EXPECT_FLOAT_EQ(z[k], z_avx2[k]); 167 EXPECT_FLOAT_EQ(x[k] * y[k], z_avx2[k]); 168 } 169 } 170 } 171 172 TEST(VectorMath, Sse2Accumulate) { 173 if (cpu_info::Supports(cpu_info::ISA::kSSE2)) { 174 std::array<float, kFftLengthBy2Plus1> x; 175 std::array<float, kFftLengthBy2Plus1> z; 176 std::array<float, kFftLengthBy2Plus1> z_sse2; 177 178 for (size_t k = 0; k < x.size(); ++k) { 179 x[k] = k; 180 z[k] = z_sse2[k] = 2.f * k; 181 } 182 183 aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z); 184 aec3::VectorMath(Aec3Optimization::kSse2).Accumulate(x, z_sse2); 185 for (size_t k = 0; k < z.size(); ++k) { 186 EXPECT_FLOAT_EQ(z[k], z_sse2[k]); 187 EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_sse2[k]); 188 } 189 } 190 } 191 192 TEST(VectorMath, Avx2Accumulate) { 193 if (cpu_info::Supports(cpu_info::ISA::kAVX2)) { 194 std::array<float, kFftLengthBy2Plus1> x; 195 std::array<float, kFftLengthBy2Plus1> z; 196 std::array<float, kFftLengthBy2Plus1> z_avx2; 197 198 for (size_t k = 0; k < x.size(); ++k) { 199 x[k] = k; 200 z[k] = z_avx2[k] = 2.f * k; 201 } 202 203 aec3::VectorMath(Aec3Optimization::kNone).Accumulate(x, z); 204 aec3::VectorMath(Aec3Optimization::kAvx2).Accumulate(x, z_avx2); 205 for (size_t k = 0; k < z.size(); ++k) { 206 EXPECT_FLOAT_EQ(z[k], z_avx2[k]); 207 EXPECT_FLOAT_EQ(x[k] + 2.f * x[k], z_avx2[k]); 208 } 209 } 210 } 211 #endif 212 213 } // namespace webrtc