1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 18 нояб. 2018 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #include <dsp/dsp.h> 23 #include <test/utest.h> 24 #include <test/FloatBuffer.h> 25 26 namespace native 27 { 28 void limit_saturate1(float *dst, size_t count); 29 void limit_saturate2(float *dst, const float *src, size_t count); 30 } 31 32 IF_ARCH_X86( 33 namespace sse2 34 { 35 void limit_saturate1(float *dst, size_t count); 36 void limit_saturate2(float *dst, const float *src, size_t count); 37 } 38 39 namespace avx2 40 { 41 void limit_saturate1(float *dst, size_t count); 42 void limit_saturate2(float *dst, const float *src, size_t count); 43 } 44 ) 45 46 IF_ARCH_ARM( 47 namespace neon_d32 48 { 49 void limit_saturate1(float *dst, size_t count); 50 void limit_saturate2(float *dst, const float *src, size_t count); 51 } 52 ) 53 54 IF_ARCH_AARCH64( 55 namespace asimd 56 { 57 void limit_saturate1(float *dst, size_t count); 58 void limit_saturate2(float *dst, const float *src, size_t count); 59 } 60 ) 61 62 typedef void (* limit_saturate1_t)(float *dst, size_t count); 63 typedef void (* limit_saturate2_t)(float *dst, const float *src, size_t count); 64 65 UTEST_BEGIN("dsp.float", limit_saturate) 66 init_buf(FloatBuffer & buf)67 void init_buf(FloatBuffer &buf) 68 { 69 for (size_t i=0; i<buf.size(); ++i) 70 { 71 switch (i%6) 72 { 73 case 0: 74 buf[i] = +INFINITY; 75 break; 76 case 1: 77 buf[i] = (rand() * 2.0f) / RAND_MAX; 78 break; 79 case 2: 80 buf[i] = -INFINITY; 81 break; 82 case 3: 83 buf[i] = - (rand() * 2.0f) / RAND_MAX; 84 break; 85 case 4: 86 buf[i] = -NAN; 87 break; 88 default: 89 buf[i] = NAN; 90 break; 91 } 92 } 93 } 94 check_buffer(const char * label,FloatBuffer & buf)95 void check_buffer(const char *label, FloatBuffer & buf) 96 { 97 UTEST_ASSERT_MSG(buf.valid(), "Destination buffer '%s' corrupted", label); 98 for (size_t i=0, n=buf.size(); i<n; ++i) 99 { 100 float s = buf.get(i); 101 UTEST_ASSERT_MSG((s >= -1.0f) && (s <= 1.0f), "Invalid buffer contents: %.5f", s); 102 } 103 } 104 call(const char * label,size_t align,limit_saturate2_t func)105 void call(const char *label, size_t align, limit_saturate2_t func) 106 { 107 if (!UTEST_SUPPORTED(func)) 108 return; 109 110 UTEST_FOREACH(count, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 111 32, 64, 65, 100, 768, 999, 1024, 0x1fff) 112 { 113 for (size_t mask=0; mask <= 0x03; ++mask) 114 { 115 printf("Testing %s on input buffer of %d numbers, mask=0x%x...\n", label, int(count), int(mask)); 116 117 FloatBuffer src(count, align, mask & 0x01); 118 init_buf(src); 119 FloatBuffer dst1(count, align, mask & 0x02); 120 FloatBuffer dst2(dst1); 121 122 // Call functions 123 native::limit_saturate2(dst1, src, count); 124 func(dst2, src, count); 125 126 UTEST_ASSERT_MSG(src.valid(), "Source buffer corrupted"); 127 128 check_buffer("dst1", dst1); 129 check_buffer("dst2", dst2); 130 131 // Compare buffers 132 if (!dst1.equals_relative(dst2, 1e-5)) 133 { 134 src.dump("src "); 135 dst1.dump("dst1"); 136 dst2.dump("dst2"); 137 UTEST_FAIL_MSG("Output of functions for test '%s' differs", label); 138 } 139 } 140 } 141 } 142 call(const char * label,size_t align,limit_saturate1_t func)143 void call(const char *label, size_t align, limit_saturate1_t func) 144 { 145 if (!UTEST_SUPPORTED(func)) 146 return; 147 148 UTEST_FOREACH(count, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 149 32, 64, 65, 100, 768, 999, 1024, 0x1fff) 150 { 151 for (size_t mask=0; mask <= 0x01; ++mask) 152 { 153 printf("Testing %s on input buffer of %d numbers, mask=0x%x...\n", label, int(count), int(mask)); 154 155 FloatBuffer dst1(count, align, mask & 0x02); 156 init_buf(dst1); 157 FloatBuffer dst2(dst1); 158 FloatBuffer src(dst1); 159 160 // Call functions 161 native::limit_saturate1(dst1, count); 162 func(dst2, count); 163 164 check_buffer("dst1", dst1); 165 check_buffer("dst2", dst2); 166 167 // Compare buffers 168 if (!dst1.equals_relative(dst2, 1e-5)) 169 { 170 src.dump("src "); 171 dst1.dump("dst1"); 172 dst2.dump("dst2"); 173 UTEST_FAIL_MSG("Output of functions for test '%s' differs", label); 174 } 175 } 176 } 177 } 178 179 UTEST_MAIN 180 { 181 #define CALL(func, align) \ 182 call(#func, align, func) 183 184 IF_ARCH_X86(CALL(sse2::limit_saturate1, 16)); 185 IF_ARCH_X86(CALL(sse2::limit_saturate2, 16)); 186 187 IF_ARCH_X86(CALL(avx2::limit_saturate1, 32)); 188 IF_ARCH_X86(CALL(avx2::limit_saturate2, 32)); 189 190 IF_ARCH_ARM(CALL(neon_d32::limit_saturate1, 16)); 191 IF_ARCH_ARM(CALL(neon_d32::limit_saturate2, 16)); 192 193 IF_ARCH_AARCH64(CALL(asimd::limit_saturate1, 16)); 194 IF_ARCH_AARCH64(CALL(asimd::limit_saturate2, 16)); 195 } 196 197 UTEST_END; 198 199 200