21 static inline void tanh(
float *
RESTRICT x,
const size_t n)
noexcept
23 assert(n != 0 &&
"n must not be 0.");
24 assert(x !=
nullptr &&
"x must not be null.");
28#if defined(__AVX512F__)
30 simd_end = n & ~(size_t)15;
32#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
33 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(simd_end); i += 16)
35 __m512 v = _mm512_loadu_ps(x + i);
36 v = Sleef_tanhf16_u10avx512f(v);
37 _mm512_storeu_ps(x + i, v);
40#elif defined(__AVX2__)
42 simd_end = n & ~(size_t)7;
44#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
45 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(simd_end); i += 8)
47 __m256 v = _mm256_loadu_ps(x + i);
48 v = Sleef_tanhf8_u10avx2(v);
49 _mm256_storeu_ps(x + i, v);
54 simd_end = n & ~(size_t)7;
56#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
57 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(simd_end); i += 8)
59 __m256 v = _mm256_loadu_ps(x + i);
60 v = Sleef_tanhf8_u10avx(v);
61 _mm256_storeu_ps(x + i, v);
64#elif defined(__SSE4_1__) || defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)
66 simd_end = n & ~(size_t)3;
68#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
69 for (ptrdiff_t i = 0; i < static_cast<ptrdiff_t>(simd_end); i += 4)
71 __m128 v = _mm_loadu_ps(x + i);
73#if defined(__SSE4_1__)
74 v = Sleef_tanhf4_u10sse4(v);
76 v = Sleef_tanhf4_u10sse2(v);
79 _mm_storeu_ps(x + i, v);
84 for (
size_t i = simd_end; i < n; ++i)
86 x[i] = Sleef_tanhf_u10(x[i]);
97 const bool activated =
false) noexcept
99 assert(n != 0 &&
"n must not be 0.");
100 assert(x !=
nullptr &&
"x must not be null.");
106#if defined(__AVX512F__)
108 const __m512 ones = _mm512_set1_ps(1.0f);
109 const size_t simd_end = n & ~(size_t)15;
111 for (; i < simd_end; i += 16)
113 const __m512 t = _mm512_loadu_ps(x + i);
116 const __m512 res = _mm512_fnmadd_ps(t, t, ones);
118 const __m512 res = _mm512_sub_ps(
120 _mm512_mul_ps(t, t));
123 _mm512_storeu_ps(x + i, res);
126#elif defined(__AVX2__)
128 const __m256 ones = _mm256_set1_ps(1.0f);
129 const size_t simd_end = n & ~(size_t)7;
131 for (; i < simd_end; i += 8)
133 const __m256 t = _mm256_loadu_ps(x + i);
136 const __m256 res = _mm256_fnmadd_ps(t, t, ones);
138 const __m256 res = _mm256_sub_ps(
140 _mm256_mul_ps(t, t));
143 _mm256_storeu_ps(x + i, res);
146#elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)
148 const __m128 ones = _mm_set1_ps(1.0f);
149 const size_t simd_end = n & ~(size_t)3;
151 for (; i < simd_end; i += 4)
153 const __m128 t = _mm_loadu_ps(x + i);
156 const __m128 res = _mm_fnmadd_ps(t, t, ones);
158 const __m128 res = _mm_sub_ps(
163 _mm_storeu_ps(x + i, res);
170 const float t = x[i];
177#if defined(__AVX512F__)
180 const __m512 ones = _mm512_set1_ps(1.0f);
181 const size_t simd_end = n & ~(size_t)15;
183#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
184 for (ptrdiff_t j = 0;
185 j < static_cast<ptrdiff_t>(simd_end);
188 __m512 t = _mm512_loadu_ps(x + j);
189 t = Sleef_tanhf16_u10avx512f(t);
192 t = _mm512_fnmadd_ps(t, t, ones);
196 _mm512_mul_ps(t, t));
199 _mm512_storeu_ps(x + j, t);
205#elif defined(__AVX2__)
208 const __m256 ones = _mm256_set1_ps(1.0f);
209 const size_t simd_end = n & ~(size_t)7;
211#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
212 for (ptrdiff_t j = 0;
213 j < static_cast<ptrdiff_t>(simd_end);
216 __m256 t = _mm256_loadu_ps(x + j);
217 t = Sleef_tanhf8_u10avx2(t);
220 t = _mm256_fnmadd_ps(t, t, ones);
224 _mm256_mul_ps(t, t));
227 _mm256_storeu_ps(x + j, t);
233#elif defined(__AVX__)
236 const __m256 ones = _mm256_set1_ps(1.0f);
237 const size_t simd_end = n & ~(size_t)7;
239#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
240 for (ptrdiff_t j = 0;
241 j < static_cast<ptrdiff_t>(simd_end);
244 __m256 t = _mm256_loadu_ps(x + j);
245 t = Sleef_tanhf8_u10avx(t);
248 t = _mm256_fnmadd_ps(t, t, ones);
252 _mm256_mul_ps(t, t));
255 _mm256_storeu_ps(x + j, t);
261#elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)
264 const __m128 ones = _mm_set1_ps(1.0f);
265 const size_t simd_end = n & ~(size_t)3;
267#pragma omp parallel for schedule(static) if (n > 16384 && !omp_in_parallel())
268 for (ptrdiff_t j = 0;
269 j < static_cast<ptrdiff_t>(simd_end);
272 __m128 t = _mm_loadu_ps(x + j);
274#if defined(__SSE4_1__)
275 t = Sleef_tanhf4_u10sse4(t);
277 t = Sleef_tanhf4_u10sse2(t);
281 t = _mm_fnmadd_ps(t, t, ones);
288 _mm_storeu_ps(x + j, t);
305 const float t = Sleef_tanhf_u10(x[i]);
319 assert(n != 0 &&
"n must not be 0.");
320 assert(dst !=
nullptr &&
"dst must not be null.");
321 assert(src !=
nullptr &&
"src must not be null.");
325#if defined(__AVX512F__)
326 __m512 ones = _mm512_set1_ps(1.0f);
327 size_t simd_end = n - (n % 16);
328#pragma omp parallel for schedule(static) if (n > 65536 && !omp_in_parallel())
329 for (ptrdiff_t j = 0; j < (ptrdiff_t)simd_end; j += 16)
331 __m512 s = _mm512_loadu_ps(src + j);
332 __m512 t = Sleef_tanhf16_u10avx512f(s);
334 __m512 res = _mm512_fnmadd_ps(t, t, ones);
336 __m512 res = _mm512_sub_ps(ones, _mm512_mul_ps(t, t));
338 _mm512_storeu_ps(dst + j, res);
341#elif defined(__AVX2__)
342 __m256 ones = _mm256_set1_ps(1.0f);
343 size_t simd_end = n - (n % 8);
344#pragma omp parallel for schedule(static) if (n > 65536 && !omp_in_parallel())
345 for (ptrdiff_t j = 0; j < (ptrdiff_t)simd_end; j += 8)
347 __m256 s = _mm256_loadu_ps(src + j);
348 __m256 t = Sleef_tanhf8_u10avx2(s);
350 __m256 res = _mm256_fnmadd_ps(t, t, ones);
352 __m256 res = _mm256_sub_ps(ones, _mm256_mul_ps(t, t));
354 _mm256_storeu_ps(dst + j, res);
357#elif defined(__SSE4_1__) || defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64)
358 __m128 ones = _mm_set1_ps(1.0f);
359 size_t simd_end = n - (n % 4);
360#pragma omp parallel for schedule(static) if (n > 65536 && !omp_in_parallel())
361 for (ptrdiff_t j = 0; j < (ptrdiff_t)simd_end; j += 4)
363 __m128 s = _mm_loadu_ps(src + j);
364#if defined(__SSE4_1__)
365 __m128 t = Sleef_tanhf4_u10sse4(s);
367 __m128 t = Sleef_tanhf4_u10sse2(s);
370 __m128 res = _mm_fnmadd_ps(t, t, ones);
372 __m128 res = _mm_sub_ps(ones, _mm_mul_ps(t, t));
374 _mm_storeu_ps(dst + j, res);
381 float t = Sleef_tanhf_u10(src[i]);
382 dst[i] = 1.0f - t * t;