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 d_min = _mm256_set1_ps(rec->fd_min);
373 __m256 d_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, d_min);
392 t = _mm256_min_ps(t, d_max);
393 __m256i k = _mm256_cvttps_epi32(
394 _mm256_mul_ps(_mm256_sub_ps(t, d_min), inv_delta));
395 __m256 d_k = _mm256_add_ps(d_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, d_min);
421 t = _mm256_min_ps(t, d_max);
422 __m256i k = _mm256_cvttps_epi32(
423 _mm256_mul_ps(_mm256_sub_ps(t, d_min), inv_delta));
424 __m256 d_k = _mm256_add_ps(d_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,
535 assert(bit_depth <= 32);
536 __m256 mul = _mm256_set1_ps((
float)(1.0 / (
double)(1ULL << bit_depth)));
537 __m256 d_min = _mm256_set1_ps(rec->ft_min);
538 __m256 d_max = _mm256_set1_ps(rec->ft_max);
539 __m256 delta = _mm256_set1_ps(rec->delta);
540 __m256 inv_delta = _mm256_set1_ps(rec->inv_delta);
541 const float* lut = rec->enc_points;
543 __m256 half_ps = _mm256_set1_ps(0.5f);
544 __m256i one = _mm256_set1_epi32(1);
546 const si32* sp = src_line->i32 + src_line_offset;
547 float* dp = dst_line->f32;
548 if (rec->is_signed())
551 _mm256_set1_epi32(-(
si32)((1ULL << (rec->get_bit_depth() - 1)) + 1));
552 __m256i zero = _mm256_setzero_si256();
553 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
554 __m256i v = _mm256_loadu_si256((__m256i*)sp);
557 __m256i c = _mm256_cmpgt_epi32(zero, v);
558 __m256i neg = _mm256_sub_epi32(bias, v);
559 neg = _mm256_and_si256(c, neg);
560 v = _mm256_andnot_si256(c, v);
561 v = _mm256_or_si256(neg, v);
563 __m256 t = _mm256_add_ps(
564 _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul), half_ps);
565 t = _mm256_max_ps(t, d_min);
566 t = _mm256_min_ps(t, d_max);
567 __m256i k = _mm256_cvttps_epi32(
568 _mm256_mul_ps(_mm256_sub_ps(t, d_min), inv_delta));
569 __m256 d_k = _mm256_add_ps(d_min,
570 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
571 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
573 _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
574 __m256 y = _mm256_add_ps(t_k,
575 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
576 _mm256_sub_ps(t_kp1, t_k)));
577 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
582 for (
int i = (
int)width; i > 0; i -= 8, sp += 8, dp += 8) {
583 __m256i v = _mm256_loadu_si256((__m256i*)sp);
584 __m256 t = _mm256_mul_ps(_mm256_cvtepi32_ps(v), mul);
585 t = _mm256_max_ps(t, d_min);
586 t = _mm256_min_ps(t, d_max);
587 __m256i k = _mm256_cvttps_epi32(
588 _mm256_mul_ps(_mm256_sub_ps(t, d_min), inv_delta));
589 __m256 d_k = _mm256_add_ps(d_min,
590 _mm256_mul_ps(_mm256_cvtepi32_ps(k), delta));
591 __m256 t_k = _mm256_i32gather_ps(lut, k, 4);
593 _mm256_i32gather_ps(lut, _mm256_add_epi32(k, one), 4);
594 __m256 y = _mm256_add_ps(t_k,
595 _mm256_mul_ps(_mm256_mul_ps(_mm256_sub_ps(t, d_k), inv_delta),
596 _mm256_sub_ps(t_kp1, t_k)));
597 _mm256_storeu_ps(dp, _mm256_sub_ps(y, half_ps));
604 ui32 src_line_offset, line_buf *dst_line,
608 if (rec->get_type() == nl::OJPH_NLT_LUT_STYLE_NLT)
609 local_avx2_irv_convert_to_float_nlt2or4<2>(src_line,
610 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
611 else if (rec->get_type() == nl::OJPH_NLT_BINARY_COMPLEMENT_PLUS_LUT)
612 local_avx2_irv_convert_to_float_nlt2or4<4>(src_line,
613 src_line_offset, dst_line, bit_depth, is_signed, width, rec);
623 line_buf *y, line_buf *cb, line_buf *cr,
641 const si32 *rp = r->i32, * gp = g->i32, * bp = b->i32;
642 si32 *yp = y->i32, * cbp = cb->i32, * crp = cr->i32;
643 for (
int i = (repeat + 7) >> 3; i > 0; --i)
645 __m256i mr = _mm256_load_si256((__m256i*)rp);
646 __m256i mg = _mm256_load_si256((__m256i*)gp);
647 __m256i mb = _mm256_load_si256((__m256i*)bp);
648 __m256i t = _mm256_add_epi32(mr, mb);
649 t = _mm256_add_epi32(t, _mm256_slli_epi32(mg, 1));
650 _mm256_store_si256((__m256i*)yp, _mm256_srai_epi32(t, 2));
651 t = _mm256_sub_epi32(mb, mg);
652 _mm256_store_si256((__m256i*)cbp, t);
653 t = _mm256_sub_epi32(mr, mg);
654 _mm256_store_si256((__m256i*)crp, t);
656 rp += 8; gp += 8; bp += 8;
657 yp += 8; cbp += 8; crp += 8;
668 __m256i v2 = _mm256_set1_epi64x(1ULL << (63 - 2));
669 const si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
670 si64 *yp = y->i64, *cbp = cb->i64, *crp = cr->i64;
671 for (
int i = (repeat + 7) >> 3; i > 0; --i)
673 __m256i mr32 = _mm256_load_si256((__m256i*)rp);
674 __m256i mg32 = _mm256_load_si256((__m256i*)gp);
675 __m256i mb32 = _mm256_load_si256((__m256i*)bp);
676 __m256i mr, mg, mb, t;
677 mr = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mr32, 0));
678 mg = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mg32, 0));
679 mb = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mb32, 0));
681 t = _mm256_add_epi64(mr, mb);
682 t = _mm256_add_epi64(t, _mm256_slli_epi64(mg, 1));
683 _mm256_store_si256((__m256i*)yp, avx2_mm256_srai_epi64(t, 2, v2));
684 t = _mm256_sub_epi64(mb, mg);
685 _mm256_store_si256((__m256i*)cbp, t);
686 t = _mm256_sub_epi64(mr, mg);
687 _mm256_store_si256((__m256i*)crp, t);
689 yp += 4; cbp += 4; crp += 4;
691 mr = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mr32, 1));
692 mg = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mg32, 1));
693 mb = _mm256_cvtepi32_epi64(_mm256_extracti128_si256(mb32, 1));
695 t = _mm256_add_epi64(mr, mb);
696 t = _mm256_add_epi64(t, _mm256_slli_epi64(mg, 1));
697 _mm256_store_si256((__m256i*)yp, avx2_mm256_srai_epi64(t, 2, v2));
698 t = _mm256_sub_epi64(mb, mg);
699 _mm256_store_si256((__m256i*)cbp, t);
700 t = _mm256_sub_epi64(mr, mg);
701 _mm256_store_si256((__m256i*)crp, t);
703 rp += 8; gp += 8; bp += 8;
704 yp += 4; cbp += 4; crp += 4;
713 line_buf *r, line_buf *g, line_buf *b,
731 const si32 *yp = y->i32, *cbp = cb->i32, *crp = cr->i32;
732 si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
733 for (
int i = (repeat + 7) >> 3; i > 0; --i)
735 __m256i my = _mm256_load_si256((__m256i*)yp);
736 __m256i mcb = _mm256_load_si256((__m256i*)cbp);
737 __m256i mcr = _mm256_load_si256((__m256i*)crp);
739 __m256i t = _mm256_add_epi32(mcb, mcr);
740 t = _mm256_sub_epi32(my, _mm256_srai_epi32(t, 2));
741 _mm256_store_si256((__m256i*)gp, t);
742 __m256i u = _mm256_add_epi32(mcb, t);
743 _mm256_store_si256((__m256i*)bp, u);
744 u = _mm256_add_epi32(mcr, t);
745 _mm256_store_si256((__m256i*)rp, u);
747 yp += 8; cbp += 8; crp += 8;
748 rp += 8; gp += 8; bp += 8;
759 __m256i v2 = _mm256_set1_epi64x(1ULL << (63 - 2));
760 __m256i low_bits = _mm256_set_epi64x(0, (
si64)ULLONG_MAX,
761 0, (
si64)ULLONG_MAX);
762 const si64 *yp = y->i64, *cbp = cb->i64, *crp = cr->i64;
763 si32 *rp = r->i32, *gp = g->i32, *bp = b->i32;
764 for (
int i = (repeat + 7) >> 3; i > 0; --i)
766 __m256i my, mcb, mcr, tr, tg, tb;
767 my = _mm256_load_si256((__m256i*)yp);
768 mcb = _mm256_load_si256((__m256i*)cbp);
769 mcr = _mm256_load_si256((__m256i*)crp);
771 tg = _mm256_add_epi64(mcb, mcr);
772 tg = _mm256_sub_epi64(my, avx2_mm256_srai_epi64(tg, 2, v2));
773 tb = _mm256_add_epi64(mcb, tg);
774 tr = _mm256_add_epi64(mcr, tg);
777 mr = _mm256_shuffle_epi32(tr, _MM_SHUFFLE(0, 0, 2, 0));
778 mr = _mm256_and_si256(low_bits, mr);
779 mg = _mm256_shuffle_epi32(tg, _MM_SHUFFLE(0, 0, 2, 0));
780 mg = _mm256_and_si256(low_bits, mg);
781 mb = _mm256_shuffle_epi32(tb, _MM_SHUFFLE(0, 0, 2, 0));
782 mb = _mm256_and_si256(low_bits, mb);
784 yp += 4; cbp += 4; crp += 4;
786 my = _mm256_load_si256((__m256i*)yp);
787 mcb = _mm256_load_si256((__m256i*)cbp);
788 mcr = _mm256_load_si256((__m256i*)crp);
790 tg = _mm256_add_epi64(mcb, mcr);
791 tg = _mm256_sub_epi64(my, avx2_mm256_srai_epi64(tg, 2, v2));
792 tb = _mm256_add_epi64(mcb, tg);
793 tr = _mm256_add_epi64(mcr, tg);
795 tr = _mm256_shuffle_epi32(tr, _MM_SHUFFLE(2, 0, 0, 0));
796 tr = _mm256_andnot_si256(low_bits, tr);
797 mr = _mm256_or_si256(mr, tr);
798 mr = _mm256_permute4x64_epi64(mr, _MM_SHUFFLE(3, 1, 2, 0));
800 tg = _mm256_shuffle_epi32(tg, _MM_SHUFFLE(2, 0, 0, 0));
801 tg = _mm256_andnot_si256(low_bits, tg);
802 mg = _mm256_or_si256(mg, tg);
803 mg = _mm256_permute4x64_epi64(mg, _MM_SHUFFLE(3, 1, 2, 0));
805 tb = _mm256_shuffle_epi32(tb, _MM_SHUFFLE(2, 0, 0, 0));
806 tb = _mm256_andnot_si256(low_bits, tb);
807 mb = _mm256_or_si256(mb, tb);
808 mb = _mm256_permute4x64_epi64(mb, _MM_SHUFFLE(3, 1, 2, 0));
810 _mm256_store_si256((__m256i*)rp, mr);
811 _mm256_store_si256((__m256i*)gp, mg);
812 _mm256_store_si256((__m256i*)bp, mb);
814 yp += 4; cbp += 4; crp += 4;
815 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