39#if defined(OJPH_ARCH_I386) || defined(OJPH_ARCH_X86_64)
59 __m256i avx2_mm256_srai_epi64(__m256i a,
int amt, __m256i m)
63 __m256i x = _mm256_srli_epi64(a, amt);
64 x = _mm256_xor_si256(x, m);
65 __m256i result = _mm256_sub_epi64(x, m);
71 const ui32 src_line_offset,
73 const ui32 dst_line_offset,
80 const si32 *sp = src_line->i32 + src_line_offset;
81 si32 *dp = dst_line->i32 + dst_line_offset;
82 __m256i sh = _mm256_set1_epi32((
si32)shift);
83 for (
int i = (width + 7) >> 3; i > 0; --i, sp+=8, dp+=8)
85 __m256i s = _mm256_loadu_si256((__m256i*)sp);
86 s = _mm256_add_epi32(s, sh);
87 _mm256_storeu_si256((__m256i*)dp, s);
92 const si32 *sp = src_line->i32 + src_line_offset;
93 si64 *dp = dst_line->i64 + dst_line_offset;
94 __m256i sh = _mm256_set1_epi64x(shift);
95 for (
int i = (width + 7) >> 3; i > 0; --i, sp+=8, dp+=8)
98 s = _mm256_loadu_si256((__m256i*)sp);
100 t = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(s, 0));
101 t = _mm256_add_epi64(t, sh);
102 _mm256_storeu_si256((__m256i*)dp, t);
104 t = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(s, 1));
105 t = _mm256_add_epi64(t, sh);
106 _mm256_storeu_si256((__m256i*)dp + 1, t);
114 const si64 *sp = src_line->i64 + src_line_offset;
115 si32 *dp = dst_line->i32 + dst_line_offset;
116 __m256i low_bits = _mm256_set_epi64x(0, (
si64)ULLONG_MAX,
117 0, (
si64)ULLONG_MAX);
118 __m256i sh = _mm256_set1_epi64x(shift);
119 for (
int i = (width + 7) >> 3; i > 0; --i, sp+=8, dp+=8)
122 s = _mm256_loadu_si256((__m256i*)sp);
123 s = _mm256_add_epi64(s, sh);
125 t = _mm256_shuffle_epi32(s, _MM_SHUFFLE(0, 0, 2, 0));
126 t = _mm256_and_si256(low_bits, t);
128 s = _mm256_loadu_si256((__m256i*)sp + 1);
129 s = _mm256_add_epi64(s, sh);
131 s = _mm256_shuffle_epi32(s, _MM_SHUFFLE(2, 0, 0, 0));
132 s = _mm256_andnot_si256(low_bits, s);
134 t = _mm256_or_si256(s, t);
135 t = _mm256_permute4x64_epi64(t, _MM_SHUFFLE(3, 1, 2, 0));
136 _mm256_storeu_si256((__m256i*)dp, t);
143 const ui32 src_line_offset,
145 const ui32 dst_line_offset,
152 const si32 *sp = src_line->i32 + src_line_offset;
153 si32 *dp = dst_line->i32 + dst_line_offset;
154 __m256i sh = _mm256_set1_epi32((
si32)(-shift));
155 __m256i zero = _mm256_setzero_si256();
156 for (
int i = (width + 7) >> 3; i > 0; --i, sp += 8, dp += 8)
158 __m256i s = _mm256_loadu_si256((__m256i*)sp);
159 __m256i c = _mm256_cmpgt_epi32(zero, s);
160 __m256i v_m_sh = _mm256_sub_epi32(sh, s);
161 v_m_sh = _mm256_and_si256(c, v_m_sh);
162 s = _mm256_andnot_si256(c, s);
163 s = _mm256_or_si256(s, v_m_sh);
164 _mm256_storeu_si256((__m256i*)dp, s);
169 const si32 *sp = src_line->i32 + src_line_offset;
170 si64 *dp = dst_line->i64 + dst_line_offset;
171 __m256i sh = _mm256_set1_epi64x(-shift);
172 __m256i zero = _mm256_setzero_si256();
173 for (
int i = (width + 7) >> 3; i > 0; --i, sp += 8, dp += 8)
175 __m256i s, t, u0, u1, c, v_m_sh;
176 s = _mm256_loadu_si256((__m256i*)sp);
178 t = _mm256_cmpgt_epi32(zero, s);
179 u0 = _mm256_unpacklo_epi32(s, t);
180 c = _mm256_unpacklo_epi32(t, t);
182 v_m_sh = _mm256_sub_epi64(sh, u0);
183 v_m_sh = _mm256_and_si256(c, v_m_sh);
184 u0 = _mm256_andnot_si256(c, u0);
185 u0 = _mm256_or_si256(u0, v_m_sh);
187 u1 = _mm256_unpackhi_epi32(s, t);
188 c = _mm256_unpackhi_epi32(t, t);
190 v_m_sh = _mm256_sub_epi64(sh, u1);
191 v_m_sh = _mm256_and_si256(c, v_m_sh);
192 u1 = _mm256_andnot_si256(c, u1);
193 u1 = _mm256_or_si256(u1, v_m_sh);
195 t = _mm256_permute2x128_si256(u0, u1, (2 << 4) | 0);
196 _mm256_storeu_si256((__m256i*)dp, t);
198 t = _mm256_permute2x128_si256(u0, u1, (3 << 4) | 1);
199 _mm256_storeu_si256((__m256i*)dp + 1, t);
207 const si64 *sp = src_line->i64 + src_line_offset;
208 si32 *dp = dst_line->i32 + dst_line_offset;
209 __m256i sh = _mm256_set1_epi64x(-shift);
210 __m256i zero = _mm256_setzero_si256();
211 __m256i half_mask = _mm256_set_epi64x(0, (
si64)ULLONG_MAX,
212 0, (
si64)ULLONG_MAX);
213 for (
int i = (width + 7) >> 3; i > 0; --i, sp += 8, dp += 8)
217 __m256i s, t, p, n, m, tm;
218 s = _mm256_loadu_si256((__m256i*)sp);
220 m = _mm256_cmpgt_epi64(zero, s);
221 tm = _mm256_sub_epi64(sh, s);
222 n = _mm256_and_si256(m, tm);
223 p = _mm256_andnot_si256(m, s);
224 tm = _mm256_or_si256(n, p);
225 tm = _mm256_shuffle_epi32(tm, _MM_SHUFFLE(0, 0, 2, 0));
226 t = _mm256_and_si256(half_mask, tm);
228 s = _mm256_loadu_si256((__m256i*)sp + 1);
229 m = _mm256_cmpgt_epi64(zero, s);
230 tm = _mm256_sub_epi64(sh, s);
231 n = _mm256_and_si256(m, tm);
232 p = _mm256_andnot_si256(m, s);
233 tm = _mm256_or_si256(n, p);
234 tm = _mm256_shuffle_epi32(tm, _MM_SHUFFLE(2, 0, 0, 0));
235 tm = _mm256_andnot_si256(half_mask, tm);
237 t = _mm256_or_si256(t, tm);
238 t = _mm256_permute4x64_epi64(t, _MM_SHUFFLE(3, 1, 2, 0));
239 _mm256_storeu_si256((__m256i*)dp, t);
246 __m256i ojph_mm256_max_ge_epi32(__m256i a, __m256i b, __m256 x, __m256 y)
250 __m256 ct = _mm256_cmp_ps(x, y, _CMP_NLT_UQ);
251 __m256i c = _mm256_castps_si256(ct);
252 __m256i d = _mm256_and_si256(c, a);
253 __m256i e = _mm256_andnot_si256(c, b);
254 return _mm256_or_si256(d, e);
259 __m256i ojph_mm256_min_lt_epi32(__m256i a, __m256i b, __m256 x, __m256 y)
263 __m256 ct = _mm256_cmp_ps(x, y, _CMP_NGE_UQ);
264 __m256i c = _mm256_castps_si256(ct);
265 __m256i d = _mm256_and_si256(c, a);
266 __m256i e = _mm256_andnot_si256(c, b);
267 return _mm256_or_si256(d, e);
271 template<
bool NLT_TYPE3>
273 void local_avx2_irv_convert_to_integer(
const line_buf *src_line,
274 line_buf *dst_line,
ui32 dst_line_offset,
275 ui32 bit_depth,
bool is_signed,
ui32 width)
282 assert(bit_depth <= 32);
283 const float* sp = src_line->f32;
284 si32* dp = dst_line->i32 + dst_line_offset;
291 si32 neg_limit = (
si32)INT_MIN >> (32 - bit_depth);
292 __m256 mul = _mm256_set1_ps((
float)(1ull << bit_depth));
293 __m256 fl_up_lim = _mm256_set1_ps(-(
float)neg_limit);
294 __m256 fl_low_lim = _mm256_set1_ps((
float)neg_limit);
295 __m256i s32_up_lim = _mm256_set1_epi32(INT_MAX >> (32 - bit_depth));
296 __m256i s32_low_lim = _mm256_set1_epi32(INT_MIN >> (32 - bit_depth));
300 __m256i zero = _mm256_setzero_si256();
302 _mm256_set1_epi32(-(
si32)((1ULL << (bit_depth - 1)) + 1));
303 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
304 __m256 t = _mm256_loadu_ps(sp);
305 t = _mm256_mul_ps(t, mul);
306 __m256i u = _mm256_cvtps_epi32(t);
307 u = ojph_mm256_max_ge_epi32(u, s32_low_lim, t, fl_low_lim);
308 u = ojph_mm256_min_lt_epi32(u, s32_up_lim, t, fl_up_lim);
311 __m256i c = _mm256_cmpgt_epi32(zero, u);
312 __m256i neg = _mm256_sub_epi32(bias, u);
313 neg = _mm256_and_si256(c, neg);
314 u = _mm256_andnot_si256(c, u);
315 u = _mm256_or_si256(neg, u);
317 _mm256_storeu_si256((__m256i*)dp, u);
322 __m256i half = _mm256_set1_epi32((
si32)(1ULL << (bit_depth - 1)));
323 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
324 __m256 t = _mm256_loadu_ps(sp);
325 t = _mm256_mul_ps(t, mul);
326 __m256i u = _mm256_cvtps_epi32(t);
327 u = ojph_mm256_max_ge_epi32(u, s32_low_lim, t, fl_low_lim);
328 u = ojph_mm256_min_lt_epi32(u, s32_up_lim, t, fl_up_lim);
329 u = _mm256_add_epi32(u, half);
330 _mm256_storeu_si256((__m256i*)dp, u);
337 line_buf *dst_line,
ui32 dst_line_offset,
338 ui32 bit_depth,
bool is_signed,
ui32 width)
340 local_avx2_irv_convert_to_integer<false>(src_line, dst_line,
341 dst_line_offset, bit_depth, is_signed, width);
346 line_buf *dst_line,
ui32 dst_line_offset,
347 ui32 bit_depth,
bool is_signed,
ui32 width)
349 local_avx2_irv_convert_to_integer<true>(src_line, dst_line,
350 dst_line_offset, bit_depth, is_signed, width);
354 template<
int NLT_TYPE>
356 void local_avx2_irv_convert_to_integer_nlt2or4(
const line_buf *src_line,
357 line_buf *dst_line,
ui32 dst_line_offset,
367 assert(rec->get_bit_depth() <= 32);
368 const float* sp = src_line->f32;
369 si32* dp = dst_line->i32 + dst_line_offset;
371 __m256 mul = _mm256_set1_ps(rec->multiplier);
372 __m256 fd_min = _mm256_set1_ps(rec->fd_min);
373 __m256 fd_max = _mm256_set1_ps(rec->fd_max);
374 __m256 delta = _mm256_set1_ps(rec->delta);
375 __m256 inv_delta = _mm256_set1_ps(rec->inv_delta);
376 const float* lut = rec->dec_points;
378 __m256 half_ps = _mm256_set1_ps(0.5f);
379 __m256i one = _mm256_set1_epi32(1);
381 if (rec->is_signed())
384 _mm256_set1_ps((
float)(1ULL << (rec->get_bit_depth() - 1)));
386 _mm256_set1_epi32(-(
si32)((1ULL << (rec->get_bit_depth() - 1)) + 1));
387 __m256i zero = _mm256_setzero_si256();
388 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
389 __m256 t = _mm256_loadu_ps(sp);
390 t = _mm256_add_ps(t, half_ps);
391 t = _mm256_max_ps(t, fd_min);
392 t = _mm256_min_ps(t, fd_max);
393 __m256i k = _mm256_cvttps_epi32(
394 _mm256_mul_ps(_mm256_sub_ps(t, fd_min), inv_delta));
395 __m256 d_k = _mm256_add_ps(fd_min,
396 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
397 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
398 __m256 t_kp1 = _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
399 __m256 z = _mm256_add_ps(t_k,
400 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
401 _mm256_sub_ps(t_kp1, t_k)));
403 _mm256_cvtps_epi32(_mm256_sub_ps(_mm256_mul_ps(z, mul), half));
406 __m256i c = _mm256_cmpgt_epi32(zero, v);
407 __m256i neg = _mm256_sub_epi32(bias, v);
408 neg = _mm256_and_si256(c, neg);
409 v = _mm256_andnot_si256(c, v);
410 v = _mm256_or_si256(neg, v);
412 _mm256_storeu_si256((__m256i*)dp, v);
417 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
418 __m256 t = _mm256_loadu_ps(sp);
419 t = _mm256_add_ps(t, half_ps);
420 t = _mm256_max_ps(t, fd_min);
421 t = _mm256_min_ps(t, fd_max);
422 __m256i k = _mm256_cvttps_epi32(
423 _mm256_mul_ps(_mm256_sub_ps(t, fd_min), inv_delta));
424 __m256 d_k = _mm256_add_ps(fd_min,
425 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
426 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
428 _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
429 __m256 z = _mm256_add_ps(t_k,
430 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
431 _mm256_sub_ps(t_kp1, t_k)));
432 __m256i v = _mm256_cvtps_epi32(_mm256_mul_ps(z, mul));
433 _mm256_storeu_si256((__m256i*)dp, v);
440 line_buf *dst_line,
ui32 dst_line_offset,
444 if (rec->get_type() == nl::OJPH_NLT_LUT_STYLE_NLT)
445 local_avx2_irv_convert_to_integer_nlt2or4<2>(src_line, dst_line,
446 dst_line_offset, bit_depth, is_signed, width, rec);
447 else if (rec->get_type() == nl::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
448 local_avx2_irv_convert_to_integer_nlt2or4<4>(src_line, dst_line,
449 dst_line_offset, bit_depth, is_signed, width, rec);
455 template<
bool NLT_TYPE3>
457 void local_avx2_irv_convert_to_float(
const line_buf *src_line,
458 ui32 src_line_offset, line_buf *dst_line,
459 ui32 bit_depth,
bool is_signed,
ui32 width)
466 assert(bit_depth <= 32);
467 __m256 mul = _mm256_set1_ps((
float)(1.0 / (
double)(1ULL << bit_depth)));
469 const si32* sp = src_line->i32 + src_line_offset;
470 float* dp = dst_line->f32;
473 __m256i zero = _mm256_setzero_si256();
475 _mm256_set1_epi32(-(
si32)((1ULL << (bit_depth - 1)) + 1));
476 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
477 __m256i t = _mm256_loadu_si256((__m256i*)sp);
480 __m256i c = _mm256_cmpgt_epi32(zero, t);
481 __m256i neg = _mm256_sub_epi32(bias, t);
482 neg = _mm256_and_si256(c, neg);
483 c = _mm256_andnot_si256(c, t);
484 t = _mm256_or_si256(neg, c);
486 __m256 v = _mm256_cvtepi32_ps(t);
487 v = _mm256_mul_ps(v, mul);
488 _mm256_storeu_ps(dp, v);
493 __m256i half = _mm256_set1_epi32((
si32)(1ULL << (bit_depth - 1)));
494 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
495 __m256i t = _mm256_loadu_si256((__m256i*)sp);
496 t = _mm256_sub_epi32(t, half);
497 __m256 v = _mm256_cvtepi32_ps(t);
498 v = _mm256_mul_ps(v, mul);
499 _mm256_storeu_ps(dp, v);
506 ui32 src_line_offset, line_buf *dst_line,
507 ui32 bit_depth,
bool is_signed,
ui32 width)
509 local_avx2_irv_convert_to_float<false>(src_line, src_line_offset,
510 dst_line, bit_depth, is_signed, width);
515 ui32 src_line_offset, line_buf *dst_line,
516 ui32 bit_depth,
bool is_signed,
ui32 width)
518 local_avx2_irv_convert_to_float<true>(src_line, src_line_offset,
519 dst_line, bit_depth, is_signed, width);
523 template<
int NLT_TYPE>
525 void local_avx2_irv_convert_to_float_nlt2or4(
const line_buf *src_line,
526 ui32 src_line_offset, line_buf *dst_line,
537 assert(bit_depth <= 32);
538 __m256 mul = _mm256_set1_ps(rec->multiplier);
539 __m256 ft_min = _mm256_set1_ps(rec->ft_min);
540 __m256 ft_max = _mm256_set1_ps(rec->ft_max);
541 __m256 delta = _mm256_set1_ps(rec->delta);
542 __m256 inv_delta = _mm256_set1_ps(rec->inv_delta);
543 const float* lut = rec->approx_enc_points;
545 __m256 half_ps = _mm256_set1_ps(0.5f);
546 __m256i one = _mm256_set1_epi32(1);
548 const si32* sp = src_line->i32 + src_line_offset;
549 float* dp = dst_line->f32;
550 if (rec->is_signed())
553 _mm256_set1_epi32(-(
si32)((1ULL << (rec->get_bit_depth() - 1)) + 1));
554 __m256i zero = _mm256_setzero_si256();
555 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
556 __m256i v = _mm256_loadu_si256((__m256i*)sp);
559 __m256i c = _mm256_cmpgt_epi32(zero, v);
560 __m256i neg = _mm256_sub_epi32(bias, v);
561 neg = _mm256_and_si256(c, neg);
562 v = _mm256_andnot_si256(c, v);
563 v = _mm256_or_si256(neg, v);
565 __m256 t = _mm256_add_ps(
566 _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul), half_ps);
567 t = _mm256_max_ps(t, ft_min);
568 t = _mm256_min_ps(t, ft_max);
569 __m256i k = _mm256_cvttps_epi32(
570 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
571 __m256 d_k = _mm256_add_ps(ft_min,
572 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
573 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
575 _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
576 __m256 y = _mm256_add_ps(t_k,
577 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
578 _mm256_sub_ps(t_kp1, t_k)));
579 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
584 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
585 __m256i v = _mm256_loadu_si256((__m256i*)sp);
586 __m256 t = _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul);
587 t = _mm256_max_ps(t, ft_min);
588 t = _mm256_min_ps(t, ft_max);
589 __m256i k = _mm256_cvttps_epi32(
590 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
591 __m256 d_k = _mm256_add_ps(ft_min,
592 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
593 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
595 _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
596 __m256 y = _mm256_add_ps(t_k,
597 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
598 _mm256_sub_ps(t_kp1, t_k)));
599 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
612 template<
int NLT_TYPE>
614 void local_avx2_irv_convert_to_float_nlt2or4_precise_1step(
615 const line_buf *src_line,
ui32 src_line_offset, line_buf *dst_line,
626 assert(bit_depth <= 32);
627 __m256 mul = _mm256_set1_ps(rec->multiplier);
628 __m256 ft_min = _mm256_set1_ps(rec->ft_min);
629 __m256 ft_max = _mm256_set1_ps(rec->ft_max);
630 __m256 fd_min = _mm256_set1_ps(rec->fd_min);
631 __m256 delta = _mm256_set1_ps(rec->delta);
632 __m256 inv_delta = _mm256_set1_ps(rec->inv_delta);
633 const float* lut = rec->precise_dec_lut;
634 const ui16* indices = rec->precise_enc_dec_indices;
636 __m256 half_ps = _mm256_set1_ps(0.5f);
637 __m256 one_ps = _mm256_set1_ps(1.0f);
638 __m256 zero_ps = _mm256_setzero_ps();
639 __m256i one = _mm256_set1_epi32(1);
640 __m256i two = _mm256_set1_epi32(2);
641 __m256i low16 = _mm256_set1_epi32(0xFFFF);
643 const si32* sp = src_line->i32 + src_line_offset;
644 float* dp = dst_line->f32;
645 if (rec->is_signed())
648 _mm256_set1_epi32(-(
si32)((1ULL << (rec->get_bit_depth() - 1)) + 1));
649 __m256i zero = _mm256_setzero_si256();
650 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
651 __m256i v = _mm256_loadu_si256((__m256i*)sp);
654 __m256i c = _mm256_cmpgt_epi32(zero, v);
655 __m256i neg = _mm256_sub_epi32(bias, v);
656 neg = _mm256_and_si256(c, neg);
657 v = _mm256_andnot_si256(c, v);
658 v = _mm256_or_si256(neg, v);
660 __m256 t = _mm256_add_ps(
661 _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul), half_ps);
662 t = _mm256_max_ps(t, ft_min);
663 t = _mm256_min_ps(t, ft_max);
664 __m256i kk = _mm256_cvttps_epi32(
665 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
669 __m256i k = _mm256_and_si256(
670 _mm256_i32gather_epi32((
const int*)indices, kk, 2), low16);
671 __m256 y0 = _mm256_i32gather_ps(lut, k, 4);
672 __m256 y1 = _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
673 __m256 y2 = _mm256_i32gather_ps(lut, _mm256_add_epi32(k, two), 4);
676 __m256 adv = _mm256_cmp_ps(t, y1, _CMP_GT_OQ);
677 y0 = _mm256_blendv_ps(y0, y1, adv);
678 y1 = _mm256_blendv_ps(y1, y2, adv);
679 k = _mm256_add_epi32(k,
680 _mm256_and_si256(_mm256_castps_si256(adv), one));
684 __m256 den = _mm256_sub_ps(y1, y0);
685 __m256 has = _mm256_cmp_ps(den, zero_ps, _CMP_GT_OQ);
686 den = _mm256_blendv_ps(one_ps, den, has);
687 __m256 y = _mm256_add_ps(
688 _mm256_add_ps(fd_min,
689 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta)),
690 _mm256_and_ps(_mm256_div_ps(
691 _mm256_mul_ps(_mm256_sub_ps(t, y0), delta), den), has));
692 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
697 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
698 __m256i v = _mm256_loadu_si256((__m256i*)sp);
699 __m256 t = _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul);
700 t = _mm256_max_ps(t, ft_min);
701 t = _mm256_min_ps(t, ft_max);
702 __m256i kk = _mm256_cvttps_epi32(
703 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
707 __m256i k = _mm256_and_si256(
708 _mm256_i32gather_epi32((
const int*)indices, kk, 2), low16);
709 __m256 y0 = _mm256_i32gather_ps(lut, k, 4);
710 __m256 y1 = _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
711 __m256 y2 = _mm256_i32gather_ps(lut, _mm256_add_epi32(k, two), 4);
714 __m256 adv = _mm256_cmp_ps(t, y1, _CMP_GT_OQ);
715 y0 = _mm256_blendv_ps(y0, y1, adv);
716 y1 = _mm256_blendv_ps(y1, y2, adv);
717 k = _mm256_add_epi32(k,
718 _mm256_and_si256(_mm256_castps_si256(adv), one));
722 __m256 den = _mm256_sub_ps(y1, y0);
723 __m256 has = _mm256_cmp_ps(den, zero_ps, _CMP_GT_OQ);
724 den = _mm256_blendv_ps(one_ps, den, has);
725 __m256 y = _mm256_add_ps(
726 _mm256_add_ps(fd_min,
727 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta)),
728 _mm256_and_ps(_mm256_div_ps(
729 _mm256_mul_ps(_mm256_sub_ps(t, y0), delta), den), has));
730 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
745 template<
int NLT_TYPE>
747 void local_avx2_irv_convert_to_float_nlt2or4_precise_search(
748 const line_buf *src_line,
ui32 src_line_offset, line_buf *dst_line,
759 assert(bit_depth <= 32);
760 assert(rec->precise_max_steps > 1);
761 __m256 mul = _mm256_set1_ps(rec->multiplier);
762 __m256 ft_min = _mm256_set1_ps(rec->ft_min);
763 __m256 ft_max = _mm256_set1_ps(rec->ft_max);
764 __m256 fd_min = _mm256_set1_ps(rec->fd_min);
765 __m256 delta = _mm256_set1_ps(rec->delta);
766 __m256 inv_delta = _mm256_set1_ps(rec->inv_delta);
767 const float* lut = rec->precise_dec_lut;
768 const ui16* indices = rec->precise_enc_dec_indices;
769 ui32 num_points = rec->num_points;
774 ui32 span = rec->precise_max_steps + 1;
775 int steps = 32 - (int)count_leading_zeros(rec->precise_max_steps);
777 __m256 half_ps = _mm256_set1_ps(0.5f);
778 __m256 one_ps = _mm256_set1_ps(1.0f);
779 __m256 zero_ps = _mm256_setzero_ps();
780 __m256i low16 = _mm256_set1_epi32(0xFFFF);
781 __m256i span_epi32 = _mm256_set1_epi32((
si32)span);
782 __m256i num_epi32 = _mm256_set1_epi32((
si32)num_points);
784 const si32* sp = src_line->i32 + src_line_offset;
785 float* dp = dst_line->f32;
786 if (rec->is_signed())
789 _mm256_set1_epi32(-(
si32)((1ULL << (rec->get_bit_depth() - 1)) + 1));
790 __m256i zero = _mm256_setzero_si256();
791 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
792 __m256i v = _mm256_loadu_si256((__m256i*)sp);
795 __m256i c = _mm256_cmpgt_epi32(zero, v);
796 __m256i neg = _mm256_sub_epi32(bias, v);
797 neg = _mm256_and_si256(c, neg);
798 v = _mm256_andnot_si256(c, v);
799 v = _mm256_or_si256(neg, v);
801 __m256 t = _mm256_add_ps(
802 _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul), half_ps);
803 t = _mm256_max_ps(t, ft_min);
804 t = _mm256_min_ps(t, ft_max);
805 __m256i kk = _mm256_cvttps_epi32(
806 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
810 __m256i lo = _mm256_and_si256(
811 _mm256_i32gather_epi32((
const int*)indices, kk, 2), low16);
812 __m256i hi = _mm256_min_epi32(
813 _mm256_add_epi32(lo, span_epi32), num_epi32);
815 for (
int step = 0; step < steps; ++step)
817 __m256i mid = _mm256_srli_epi32(_mm256_add_epi32(lo, hi), 1);
818 __m256 lmid = _mm256_i32gather_ps(lut, mid, 4);
819 __m256 ge = _mm256_cmp_ps(t, lmid, _CMP_GE_OQ);
820 __m256i g = _mm256_castps_si256(ge);
821 lo = _mm256_blendv_epi8(lo, mid, g);
822 hi = _mm256_blendv_epi8(mid, hi, g);
825 __m256 y0 = _mm256_i32gather_ps(lut, lo, 4);
826 __m256 y1 = _mm256_i32gather_ps(lut, hi, 4);
830 __m256 den = _mm256_sub_ps(y1, y0);
831 __m256 has = _mm256_cmp_ps(den, zero_ps, _CMP_GT_OQ);
832 den = _mm256_blendv_ps(one_ps, den, has);
833 __m256 y = _mm256_add_ps(
834 _mm256_add_ps(fd_min,
835 _mm256_mul_ps(_mm256_cvtepi32_ps(lo), delta)),
836 _mm256_and_ps(_mm256_div_ps(
837 _mm256_mul_ps(_mm256_sub_ps(t, y0), delta), den), has));
838 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
843 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
844 __m256i v = _mm256_loadu_si256((__m256i*)sp);
845 __m256 t = _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul);
846 t = _mm256_max_ps(t, ft_min);
847 t = _mm256_min_ps(t, ft_max);
848 __m256i kk = _mm256_cvttps_epi32(
849 _mm256_mul_ps(_mm256_sub_ps(t, ft_min), inv_delta));
853 __m256i lo = _mm256_and_si256(
854 _mm256_i32gather_epi32((
const int*)indices, kk, 2), low16);
855 __m256i hi = _mm256_min_epi32(
856 _mm256_add_epi32(lo, span_epi32), num_epi32);
858 for (
int step = 0; step < steps; ++step)
860 __m256i mid = _mm256_srli_epi32(_mm256_add_epi32(lo, hi), 1);
861 __m256 lmid = _mm256_i32gather_ps(lut, mid, 4);
862 __m256 ge = _mm256_cmp_ps(t, lmid, _CMP_GE_OQ);
863 __m256i g = _mm256_castps_si256(ge);
864 lo = _mm256_blendv_epi8(lo, mid, g);
865 hi = _mm256_blendv_epi8(mid, hi, g);
868 __m256 y0 = _mm256_i32gather_ps(lut, lo, 4);
869 __m256 y1 = _mm256_i32gather_ps(lut, hi, 4);
870 __m256 den = _mm256_sub_ps(y1, y0);
871 __m256 has = _mm256_cmp_ps(den, zero_ps, _CMP_GT_OQ);
872 den = _mm256_blendv_ps(one_ps, den, has);
873 __m256 y = _mm256_add_ps(
874 _mm256_add_ps(fd_min,
875 _mm256_mul_ps(_mm256_cvtepi32_ps(lo), delta)),
876 _mm256_and_ps(_mm256_div_ps(
877 _mm256_mul_ps(_mm256_sub_ps(t, y0), delta), den), has));
878 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
885 ui32 src_line_offset, line_buf *dst_line,
889 if (rec->get_type() == nl::OJPH_NLT_LUT_STYLE_NLT)
891 if (rec->approx_encoding_nlt)
892 local_avx2_irv_convert_to_float_nlt2or4<2>(src_line,
893 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
894 else if (rec->precise_max_steps == 1)
895 local_avx2_irv_convert_to_float_nlt2or4_precise_1step<2>(src_line,
896 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
898 local_avx2_irv_convert_to_float_nlt2or4_precise_search<2>(src_line,
899 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
901 else if (rec->get_type() == nl::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
903 if (rec->approx_encoding_nlt)
904 local_avx2_irv_convert_to_float_nlt2or4<4>(src_line,
905 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
906 else if (rec->precise_max_steps == 1)
907 local_avx2_irv_convert_to_float_nlt2or4_precise_1step<4>(src_line,
908 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
910 local_avx2_irv_convert_to_float_nlt2or4_precise_search<4>(src_line,
911 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
922 line_buf *y, line_buf *cb, line_buf *cr,
940 const si32 *rp = r->i32, * gp = g->i32, * bp = b->i32;
941 si32 *yp = y->i32, * cbp = cb->i32, * crp = cr->i32;
942 for (
int i = (repeat + 7) >> 3; i > 0; --i)
944 __m256i mr = _mm256_load_si256((__m256i*)rp);
945 __m256i mg = _mm256_load_si256((__m256i*)gp);
946 __m256i mb = _mm256_load_si256((__m256i*)bp);
947 __m256i t = _mm256_add_epi32(mr, mb);
948 t = _mm256_add_epi32(t, _mm256_slli_epi32(mg, 1));
949 _mm256_store_si256((__m256i*)yp, _mm256_srai_epi32(t, 2));
950 t = _mm256_sub_epi32(mb, mg);
951 _mm256_store_si256((__m256i*)cbp, t);
952 t = _mm256_sub_epi32(mr, mg);
953 _mm256_store_si256((__m256i*)crp, t);
955 rp += 8; gp += 8; bp += 8;
956 yp += 8; cbp += 8; crp += 8;
967 __m256i v2 = _mm256_set1_epi64x(1ULL << (63 - 2));
968 const si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
969 si64 *yp = y->i64, *cbp = cb->i64, *crp = cr->i64;
970 for (
int i = (repeat + 7) >> 3; i > 0; --i)
972 __m256i mr32 = _mm256_load_si256((__m256i*)rp);
973 __m256i mg32 = _mm256_load_si256((__m256i*)gp);
974 __m256i mb32 = _mm256_load_si256((__m256i*)bp);
975 __m256i mr, mg, mb, t;
976 mr = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mr32, 0));
977 mg = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mg32, 0));
978 mb = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mb32, 0));
980 t = _mm256_add_epi64(mr, mb);
981 t = _mm256_add_epi64(t, _mm256_slli_epi64(mg, 1));
982 _mm256_store_si256((__m256i*)yp, avx2_mm256_srai_epi64(t, 2, v2));
983 t = _mm256_sub_epi64(mb, mg);
984 _mm256_store_si256((__m256i*)cbp, t);
985 t = _mm256_sub_epi64(mr, mg);
986 _mm256_store_si256((__m256i*)crp, t);
988 yp += 4; cbp += 4; crp += 4;
990 mr = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mr32, 1));
991 mg = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mg32, 1));
992 mb = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mb32, 1));
994 t = _mm256_add_epi64(mr, mb);
995 t = _mm256_add_epi64(t, _mm256_slli_epi64(mg, 1));
996 _mm256_store_si256((__m256i*)yp, avx2_mm256_srai_epi64(t, 2, v2));
997 t = _mm256_sub_epi64(mb, mg);
998 _mm256_store_si256((__m256i*)cbp, t);
999 t = _mm256_sub_epi64(mr, mg);
1000 _mm256_store_si256((__m256i*)crp, t);
1002 rp += 8; gp += 8; bp += 8;
1003 yp += 4; cbp += 4; crp += 4;
1012 line_buf *r, line_buf *g, line_buf *b,
1030 const si32 *yp = y->i32, *cbp = cb->i32, *crp = cr->i32;
1031 si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
1032 for (
int i = (repeat + 7) >> 3; i > 0; --i)
1034 __m256i my = _mm256_load_si256((__m256i*)yp);
1035 __m256i mcb = _mm256_load_si256((__m256i*)cbp);
1036 __m256i mcr = _mm256_load_si256((__m256i*)crp);
1038 __m256i t = _mm256_add_epi32(mcb, mcr);
1039 t = _mm256_sub_epi32(my, _mm256_srai_epi32(t, 2));
1040 _mm256_store_si256((__m256i*)gp, t);
1041 __m256i u = _mm256_add_epi32(mcb, t);
1042 _mm256_store_si256((__m256i*)bp, u);
1043 u = _mm256_add_epi32(mcr, t);
1044 _mm256_store_si256((__m256i*)rp, u);
1046 yp += 8; cbp += 8; crp += 8;
1047 rp += 8; gp += 8; bp += 8;
1058 __m256i v2 = _mm256_set1_epi64x(1ULL << (63 - 2));
1059 __m256i low_bits = _mm256_set_epi64x(0, (
si64)ULLONG_MAX,
1060 0, (
si64)ULLONG_MAX);
1061 const si64 *yp = y->i64, *cbp = cb->i64, *crp = cr->i64;
1062 si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
1063 for (
int i = (repeat + 7) >> 3; i > 0; --i)
1065 __m256i my, mcb, mcr, tr, tg, tb;
1066 my = _mm256_load_si256((__m256i*)yp);
1067 mcb = _mm256_load_si256((__m256i*)cbp);
1068 mcr = _mm256_load_si256((__m256i*)crp);
1070 tg = _mm256_add_epi64(mcb, mcr);
1071 tg = _mm256_sub_epi64(my, avx2_mm256_srai_epi64(tg, 2, v2));
1072 tb = _mm256_add_epi64(mcb, tg);
1073 tr = _mm256_add_epi64(mcr, tg);
1076 mr = _mm256_shuffle_epi32(tr, _MM_SHUFFLE(0, 0, 2, 0));
1077 mr = _mm256_and_si256(low_bits, mr);
1078 mg = _mm256_shuffle_epi32(tg, _MM_SHUFFLE(0, 0, 2, 0));
1079 mg = _mm256_and_si256(low_bits, mg);
1080 mb = _mm256_shuffle_epi32(tb, _MM_SHUFFLE(0, 0, 2, 0));
1081 mb = _mm256_and_si256(low_bits, mb);
1083 yp += 4; cbp += 4; crp += 4;
1085 my = _mm256_load_si256((__m256i*)yp);
1086 mcb = _mm256_load_si256((__m256i*)cbp);
1087 mcr = _mm256_load_si256((__m256i*)crp);
1089 tg = _mm256_add_epi64(mcb, mcr);
1090 tg = _mm256_sub_epi64(my, avx2_mm256_srai_epi64(tg, 2, v2));
1091 tb = _mm256_add_epi64(mcb, tg);
1092 tr = _mm256_add_epi64(mcr, tg);
1094 tr = _mm256_shuffle_epi32(tr, _MM_SHUFFLE(2, 0, 0, 0));
1095 tr = _mm256_andnot_si256(low_bits, tr);
1096 mr = _mm256_or_si256(mr, tr);
1097 mr = _mm256_permute4x64_epi64(mr, _MM_SHUFFLE(3, 1, 2, 0));
1099 tg = _mm256_shuffle_epi32(tg, _MM_SHUFFLE(2, 0, 0, 0));
1100 tg = _mm256_andnot_si256(low_bits, tg);
1101 mg = _mm256_or_si256(mg, tg);
1102 mg = _mm256_permute4x64_epi64(mg, _MM_SHUFFLE(3, 1, 2, 0));
1104 tb = _mm256_shuffle_epi32(tb, _MM_SHUFFLE(2, 0, 0, 0));
1105 tb = _mm256_andnot_si256(low_bits, tb);
1106 mb = _mm256_or_si256(mb, tb);
1107 mb = _mm256_permute4x64_epi64(mb, _MM_SHUFFLE(3, 1, 2, 0));
1109 _mm256_store_si256((__m256i*)rp, mr);
1110 _mm256_store_si256((__m256i*)gp, mg);
1111 _mm256_store_si256((__m256i*)bp, mb);
1113 yp += 4; cbp += 4; crp += 4;
1114 rp += 8; gp += 8; bp += 8;
void avx2_rct_forward(const line_buf *r, const line_buf *g, const line_buf *b, line_buf *y, line_buf *cb, line_buf *cr, ui32 repeat)
void avx2_rct_backward(const line_buf *y, const line_buf *cb, const line_buf *cr, line_buf *r, line_buf *g, line_buf *b, ui32 repeat)
void avx2_rev_convert(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, const ui32 dst_line_offset, si64 shift, ui32 width)
void avx2_irv_convert_to_float(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width)
void avx2_irv_convert_to_integer_nlt(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void avx2_rev_convert_nlt_type3(const line_buf *src_line, const ui32 src_line_offset, line_buf *dst_line, const ui32 dst_line_offset, si64 shift, ui32 width)
void avx2_irv_convert_to_float_nlt(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width, const nlt_rec *rec)
void avx2_irv_convert_to_integer(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width)
void avx2_irv_convert_to_float_nlt_type3(const line_buf *src_line, ui32 src_line_offset, line_buf *dst_line, ui32 bit_depth, bool is_signed, ui32 width)
void avx2_irv_convert_to_integer_nlt_type3(const line_buf *src_line, line_buf *dst_line, ui32 dst_line_offset, ui32 bit_depth, bool is_signed, ui32 width)
ojph::param_nlt::nonlinearity nonlinearity