1377 const size_t nl,
const size_t nr,
1378 const uint8_t* RESTRICT bits) {
1379 const uint8_t* L = src;
1380 const uint8_t* R = src + nl;
1381 const size_t n = nl + nr;
1385#if defined(ZXC_USE_NEON64)
1388 while (i + 16 <= n) {
1389 const uint8_t b0 = bits[i >> 3];
1390 const uint8_t b1 = bits[(i >> 3) + 1];
1392 tb.val[0] = vld1q_u8(L + lp);
1393 tb.val[1] = vld1q_u8(R + rp);
1394 const int pc0 = zxc_pivco_popcnt32(b0);
1395 const uint8x8_t ia = vld1_u8(zxc_pivco_idxa_u8[b0]);
1396 const uint8x8_t ib = vld1_u8(zxc_pivco_idxb_pre[pc0][b1]);
1397 vst1q_u8(out + i, vqtbl2q_u8(tb, vcombine_u8(ia, ib)));
1398 const int pc = pc0 + zxc_pivco_popcnt32(b1);
1402#if defined(ZXC_USE_AVX512) && defined(__AVX512VBMI2__)
1407 const __m512i zero = _mm512_setzero_si512();
1408 while (i + 64 <= n) {
1410 ZXC_MEMCPY(&ctrl, bits + (i >> 3), 8);
1412 _mm512_mask_expandloadu_epi8(zero, (__mmask64)~ctrl, (
const void*)(L + lp));
1413 const __m512i outv =
1414 _mm512_mask_expandloadu_epi8(vl, (__mmask64)ctrl, (
const void*)(R + rp));
1415 _mm512_storeu_si512((
void*)(out + i), outv);
1416 const int pc = zxc_pivco_popcnt64(ctrl);
1420#if defined(ZXC_USE_AVX512) || defined(ZXC_USE_AVX2) || \
1421 (defined(ZXC_USE_SSE2) && defined(__SSSE3__))
1424#if defined(ZXC_USE_AVX2)
1430 while (i + 32 <= n) {
1431 const uint8_t* cb = bits + (i >> 3);
1432 const int pcA0 = zxc_pivco_popcnt32(cb[0]);
1433 const int pcA = pcA0 + zxc_pivco_popcnt32(cb[1]);
1434 const int pcB0 = zxc_pivco_popcnt32(cb[2]);
1435 const int pcB = pcB0 + zxc_pivco_popcnt32(cb[3]);
1436 const size_t lpB = lp + (size_t)(16 - pcA);
1437 const size_t rpB = rp + (size_t)pcA;
1438 const __m256i vl = _mm256_inserti128_si256(
1439 _mm256_castsi128_si256(_mm_loadu_si128((
const __m128i*)(
const void*)(L + lp))),
1440 _mm_loadu_si128((
const __m128i*)(
const void*)(L + lpB)), 1);
1441 const __m256i vr = _mm256_inserti128_si256(
1442 _mm256_castsi128_si256(_mm_loadu_si128((
const __m128i*)(
const void*)(R + rp))),
1443 _mm_loadu_si128((
const __m128i*)(
const void*)(R + rpB)), 1);
1444 const __m128i ixA = _mm_unpacklo_epi64(
1445 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxa_u8[cb[0]]),
1446 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxb_pre[pcA0][cb[1]]));
1447 const __m128i ixB = _mm_unpacklo_epi64(
1448 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxa_u8[cb[2]]),
1449 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxb_pre[pcB0][cb[3]]));
1450 const __m256i ix = _mm256_inserti128_si256(_mm256_castsi128_si256(ixA), ixB, 1);
1451 _mm256_storeu_si256(
1452 (__m256i*)(
void*)(out + i),
1453 _mm256_blendv_epi8(_mm256_shuffle_epi8(vl, ix), _mm256_shuffle_epi8(vr, ix),
1454 _mm256_slli_epi16(ix, 3)));
1455 lp = lpB + (size_t)(16 - pcB);
1456 rp = rpB + (size_t)pcB;
1460 while (i + 32 <= n) {
1461 const uint8_t* cb = bits + (i >> 3);
1462 const int pcA0 = zxc_pivco_popcnt32(cb[0]);
1463 const int pcA = pcA0 + zxc_pivco_popcnt32(cb[1]);
1464 const int pcB0 = zxc_pivco_popcnt32(cb[2]);
1465 const int pcB = pcB0 + zxc_pivco_popcnt32(cb[3]);
1466 const size_t lpB = lp + (size_t)(16 - pcA);
1467 const size_t rpB = rp + (size_t)pcA;
1468 const __m128i vlA = _mm_loadu_si128((
const __m128i*)(
const void*)(L + lp));
1469 const __m128i vrA = _mm_loadu_si128((
const __m128i*)(
const void*)(R + rp));
1470 const __m128i vlB = _mm_loadu_si128((
const __m128i*)(
const void*)(L + lpB));
1471 const __m128i vrB = _mm_loadu_si128((
const __m128i*)(
const void*)(R + rpB));
1472 const __m128i iaA = _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxa_u8[cb[0]]);
1474 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxb_pre[pcA0][cb[1]]);
1475 const __m128i iaB = _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxa_u8[cb[2]]);
1477 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxb_pre[pcB0][cb[3]]);
1478 const __m128i ixA = _mm_unpacklo_epi64(iaA, ibA);
1479 const __m128i ixB = _mm_unpacklo_epi64(iaB, ibB);
1480 const __m128i selA =
1481 _mm_or_si128(_mm_shuffle_epi8(vlA, _mm_add_epi8(ixA, _mm_set1_epi8(0x70))),
1482 _mm_shuffle_epi8(vrA, _mm_sub_epi8(ixA, _mm_set1_epi8(16))));
1483 const __m128i selB =
1484 _mm_or_si128(_mm_shuffle_epi8(vlB, _mm_add_epi8(ixB, _mm_set1_epi8(0x70))),
1485 _mm_shuffle_epi8(vrB, _mm_sub_epi8(ixB, _mm_set1_epi8(16))));
1486 _mm_storeu_si128((__m128i*)(
void*)(out + i), selA);
1487 _mm_storeu_si128((__m128i*)(
void*)(out + i + 16), selB);
1488 lp = lpB + (size_t)(16 - pcB);
1489 rp = rpB + (size_t)pcB;
1493 while (i + 16 <= n) {
1494 const uint8_t b0 = bits[i >> 3];
1495 const uint8_t b1 = bits[(i >> 3) + 1];
1496 const __m128i vl = _mm_loadu_si128((
const __m128i*)(
const void*)(L + lp));
1497 const __m128i vr = _mm_loadu_si128((
const __m128i*)(
const void*)(R + rp));
1498 const int pc0 = zxc_pivco_popcnt32(b0);
1499 const __m128i ia = _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxa_u8[b0]);
1501 _mm_loadl_epi64((
const __m128i*)(
const void*)zxc_pivco_idxb_pre[pc0][b1]);
1502 const __m128i ix = _mm_unpacklo_epi64(ia, ib);
1503 const __m128i sell = _mm_shuffle_epi8(vl, _mm_add_epi8(ix, _mm_set1_epi8(0x70)));
1504 const __m128i selr = _mm_shuffle_epi8(vr, _mm_sub_epi8(ix, _mm_set1_epi8(16)));
1505 _mm_storeu_si128((__m128i*)(
void*)(out + i), _mm_or_si128(sell, selr));
1506 const int pc = pc0 + zxc_pivco_popcnt32(b1);
1509#elif defined(ZXC_USE_NEON32)
1513 while (i + 8 <= n) {
1514 const uint8_t b = bits[i >> 3];
1516 tb.val[0] = vld1_u8(L + lp);
1517 tb.val[1] = vdup_n_u8(0);
1518 tb.val[2] = vld1_u8(R + rp);
1519 tb.val[3] = vdup_n_u8(0);
1520 vst1_u8(out + i, vtbl4_u8(tb, vld1_u8(zxc_pivco_idxa_u8[b])));
1521 const int pc = zxc_pivco_popcnt32(b);
1529 while (i + 8 <= n) {
1530 const uint8_t b = bits[i >> 3];
1532 ZXC_MEMCPY(comb, L + lp, 8);
1533 ZXC_MEMCPY(comb + 16, R + rp, 8);
1534 const uint8_t* ix = zxc_pivco_idxa_u8[b];
1535 for (
int j = 0; j < 8; j++) out[i + (
size_t)j] = comb[ix[j]];
1536 const int pc = zxc_pivco_popcnt32(b);
1540 const int bit = (bits[i >> 3] >> (i & 7)) & 1;
1541 out[i++] = bit ? R[rp++] : L[lp++];
1556 const uint8_t* RESTRICT bits,
const uint8_t* RESTRICT c2s) {
1558#if defined(ZXC_USE_NEON64)
1561 for (
int k = 0; k < 16; k++) c2s16[k] = c2s[k & 3];
1562 const uint8x16_t vc2s = vld1q_u8(c2s16);
1563 static const uint8_t rep4[16] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3};
1564 static const int8_t sh2[16] = {0, -2, -4, -6, 0, -2, -4, -6, 0, -2, -4, -6, 0, -2, -4, -6};
1565 const uint8x16_t vrep = vld1q_u8(rep4);
1566 const int8x16_t vsh = vld1q_s8(sh2);
1567 const uint8x16_t vmask = vdupq_n_u8(0x03);
1568 while (i + 16 <= n) {
1569 uint8x16_t raw = vdupq_n_u8(0);
1570 raw = vreinterpretq_u8_u32(
1571 vsetq_lane_u32(
zxc_le32(bits + ((i * 2) >> 3)), vreinterpretq_u32_u8(raw), 0));
1572 const uint8x16_t rep = vqtbl1q_u8(raw, vrep);
1573 const uint8x16_t codes = vandq_u8(vshlq_u8(rep, vsh), vmask);
1574 vst1q_u8(out + i, vqtbl1q_u8(vc2s, codes));
1577 }
else if (D == 3) {
1582 for (
int k = 0; k < 16; k++) c2s16[k] = c2s[k & 7];
1583 const uint8x16_t vc2s = vld1q_u8(c2s16);
1584 static const uint8_t idxA[16] = {0, 1, 0, 1, 0, 1, 1, 2, 1, 2, 1, 2, 2, 3, 2, 3};
1585 static const uint8_t idxB[16] = {3, 4, 3, 4, 3, 4, 4, 5, 4, 5, 4, 5, 5, 6, 5, 6};
1586 static const int16_t sh8[8] = {0, -3, -6, -1, -4, -7, -2, -5};
1587 const uint8x16_t vidxA = vld1q_u8(idxA);
1588 const uint8x16_t vidxB = vld1q_u8(idxB);
1589 const int16x8_t vsh = vld1q_s16(sh8);
1590 const uint16x8_t vmask = vdupq_n_u16(0x07);
1591 while (i + 16 <= n) {
1592 const size_t off = (i * 3) >> 3;
1595 ZXC_MEMCPY(&w0, bits + off, 4);
1596 ZXC_MEMCPY(&w1, bits + off + 4, 2);
1597 uint8x16_t raw = vdupq_n_u8(0);
1598 raw = vreinterpretq_u8_u32(vsetq_lane_u32(w0, vreinterpretq_u32_u8(raw), 0));
1599 raw = vreinterpretq_u8_u16(vsetq_lane_u16(w1, vreinterpretq_u16_u8(raw), 2));
1600 const uint16x8_t winA = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxA));
1601 const uint16x8_t winB = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxB));
1602 const uint8x8_t cA = vmovn_u16(vandq_u16(vshlq_u16(winA, vsh), vmask));
1603 const uint8x8_t cB = vmovn_u16(vandq_u16(vshlq_u16(winB, vsh), vmask));
1604 vst1q_u8(out + i, vqtbl1q_u8(vc2s, vcombine_u8(cA, cB)));
1607 }
else if (D == 4) {
1608 const uint8x16_t vc2s = vld1q_u8(c2s);
1609 static const uint8_t rep2[16] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7};
1610 static const int8_t sh4[16] = {0, -4, 0, -4, 0, -4, 0, -4, 0, -4, 0, -4, 0, -4, 0, -4};
1611 const uint8x16_t vrep = vld1q_u8(rep2);
1612 const int8x16_t vsh = vld1q_s8(sh4);
1613 const uint8x16_t vmask = vdupq_n_u8(0x0F);
1614 while (i + 16 <= n) {
1615 uint8x16_t raw = vdupq_n_u8(0);
1616 raw = vreinterpretq_u8_u64(
1617 vsetq_lane_u64(
zxc_le64(bits + ((i * 4) >> 3)), vreinterpretq_u64_u8(raw), 0));
1618 const uint8x16_t rep = vqtbl1q_u8(raw, vrep);
1619 const uint8x16_t codes = vandq_u8(vshlq_u8(rep, vsh), vmask);
1620 vst1q_u8(out + i, vqtbl1q_u8(vc2s, codes));
1623 }
else if (D == 5) {
1625 const uint8x16x2_t vc2s = vld1q_u8_x2(c2s);
1626 static const uint8_t idxA[16] = {0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 3, 4, 3, 4, 4, 5};
1627 static const uint8_t idxB[16] = {5, 6, 5, 6, 6, 7, 6, 7, 7, 8, 8, 9, 8, 9, 9, 10};
1628 static const int16_t sh8[8] = {0, -5, -2, -7, -4, -1, -6, -3};
1629 const uint8x16_t vidxA = vld1q_u8(idxA);
1630 const uint8x16_t vidxB = vld1q_u8(idxB);
1631 const int16x8_t vsh = vld1q_s16(sh8);
1632 const uint16x8_t vmask = vdupq_n_u16(0x1F);
1633 while (i + 16 <= n) {
1634 const size_t off = (i * 5) >> 3;
1637 ZXC_MEMCPY(&w0, bits + off, 8);
1638 ZXC_MEMCPY(&w1, bits + off + 8, 2);
1639 uint8x16_t raw = vdupq_n_u8(0);
1640 raw = vreinterpretq_u8_u64(vsetq_lane_u64(w0, vreinterpretq_u64_u8(raw), 0));
1641 raw = vreinterpretq_u8_u16(vsetq_lane_u16(w1, vreinterpretq_u16_u8(raw), 4));
1642 const uint16x8_t winA = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxA));
1643 const uint16x8_t winB = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxB));
1644 const uint8x8_t cA = vmovn_u16(vandq_u16(vshlq_u16(winA, vsh), vmask));
1645 const uint8x8_t cB = vmovn_u16(vandq_u16(vshlq_u16(winB, vsh), vmask));
1646 vst1q_u8(out + i, vqtbl2q_u8(vc2s, vcombine_u8(cA, cB)));
1649 }
else if (D == 6) {
1651 const uint8x16x4_t vc2s = vld1q_u8_x4(c2s);
1652 static const uint8_t idxA[16] = {0, 1, 0, 1, 1, 2, 2, 3, 3, 4, 3, 4, 4, 5, 5, 6};
1653 static const uint8_t idxB[16] = {6, 7, 6, 7, 7, 8, 8, 9, 9, 10, 9, 10, 10, 11, 11, 12};
1654 static const int16_t sh8[8] = {0, -6, -4, -2, 0, -6, -4, -2};
1655 const uint8x16_t vidxA = vld1q_u8(idxA);
1656 const uint8x16_t vidxB = vld1q_u8(idxB);
1657 const int16x8_t vsh = vld1q_s16(sh8);
1658 const uint16x8_t vmask = vdupq_n_u16(0x3F);
1659 while (i + 16 <= n) {
1660 const size_t off = (i * 6) >> 3;
1663 ZXC_MEMCPY(&w0, bits + off, 8);
1664 ZXC_MEMCPY(&w1, bits + off + 8, 4);
1665 uint8x16_t raw = vdupq_n_u8(0);
1666 raw = vreinterpretq_u8_u64(vsetq_lane_u64(w0, vreinterpretq_u64_u8(raw), 0));
1667 raw = vreinterpretq_u8_u32(vsetq_lane_u32(w1, vreinterpretq_u32_u8(raw), 2));
1668 const uint16x8_t winA = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxA));
1669 const uint16x8_t winB = vreinterpretq_u16_u8(vqtbl1q_u8(raw, vidxB));
1670 const uint8x8_t cA = vmovn_u16(vandq_u16(vshlq_u16(winA, vsh), vmask));
1671 const uint8x8_t cB = vmovn_u16(vandq_u16(vshlq_u16(winB, vsh), vmask));
1672 vst1q_u8(out + i, vqtbl4q_u8(vc2s, vcombine_u8(cA, cB)));
1676#elif defined(ZXC_USE_NEON32)
1681 for (
int k = 0; k < 8; k++) c2s8[k] = c2s[k & 3];
1682 const uint8x8_t vc2s = vld1_u8(c2s8);
1683 static const uint8_t rep4[8] = {0, 0, 0, 0, 1, 1, 1, 1};
1684 static const int8_t sh2[8] = {0, -2, -4, -6, 0, -2, -4, -6};
1685 const uint8x8_t vrep = vld1_u8(rep4);
1686 const int8x8_t vsh = vld1_s8(sh2);
1687 const uint8x8_t vmask = vdup_n_u8(0x03);
1688 while (i + 8 <= n) {
1689 const uint16_t w = (uint16_t)((uint16_t)bits[(i * 2) >> 3] |
1690 ((uint16_t)bits[((i * 2) >> 3) + 1] << 8));
1691 const uint8x8_t raw = vreinterpret_u8_u16(vdup_n_u16(w));
1692 const uint8x8_t rep = vtbl1_u8(raw, vrep);
1693 const uint8x8_t codes = vand_u8(vshl_u8(rep, vsh), vmask);
1694 vst1_u8(out + i, vtbl1_u8(vc2s, codes));
1697 }
else if (D == 3) {
1702 const uint8x8_t vc2s = vld1_u8(c2s);
1703 static const uint8_t idxlo[8] = {0, 1, 0, 1, 0, 1, 1, 2};
1704 static const uint8_t idxhi[8] = {1, 2, 1, 2, 2, 3, 2, 3};
1705 static const uint16_t mul8[8] = {8192, 1024, 128, 4096, 512, 64, 2048, 256};
1706 const uint8x8_t vidxlo = vld1_u8(idxlo);
1707 const uint8x8_t vidxhi = vld1_u8(idxhi);
1708 const uint16x8_t vmul = vld1q_u16(mul8);
1709 const uint16x8_t vmask = vdupq_n_u16(0x07);
1710 while (i + 8 <= n) {
1711 const size_t off = (i * 3) >> 3;
1712 const uint32_t w = (uint32_t)bits[off] | ((uint32_t)bits[off + 1] << 8) |
1713 ((uint32_t)bits[off + 2] << 16);
1714 const uint8x8_t raw = vreinterpret_u8_u32(vdup_n_u32(w));
1715 const uint8x8_t wlo = vtbl1_u8(raw, vidxlo);
1716 const uint8x8_t whi = vtbl1_u8(raw, vidxhi);
1717 const uint16x8_t win = vreinterpretq_u16_u8(vcombine_u8(wlo, whi));
1718 const uint16x8_t codes16 = vandq_u16(vshrq_n_u16(vmulq_u16(win, vmul), 13), vmask);
1719 vst1_u8(out + i, vtbl1_u8(vc2s, vmovn_u16(codes16)));
1722 }
else if (D == 4) {
1726 vc2s.val[0] = vld1_u8(c2s);
1727 vc2s.val[1] = vld1_u8(c2s + 8);
1728 static const uint8_t rep2[8] = {0, 0, 1, 1, 2, 2, 3, 3};
1729 static const int8_t sh4[8] = {0, -4, 0, -4, 0, -4, 0, -4};
1730 const uint8x8_t vrep = vld1_u8(rep2);
1731 const int8x8_t vsh = vld1_s8(sh4);
1732 const uint8x8_t vmask = vdup_n_u8(0x0F);
1733 while (i + 8 <= n) {
1735 ZXC_MEMCPY(&w, bits + ((i * 4) >> 3), 4);
1736 const uint8x8_t raw = vreinterpret_u8_u32(vdup_n_u32(w));
1737 const uint8x8_t rep = vtbl1_u8(raw, vrep);
1738 const uint8x8_t codes = vand_u8(vshl_u8(rep, vsh), vmask);
1739 vst1_u8(out + i, vtbl2_u8(vc2s, codes));
1742 }
else if (D == 5) {
1746 vc2s.val[0] = vld1_u8(c2s);
1747 vc2s.val[1] = vld1_u8(c2s + 8);
1748 vc2s.val[2] = vld1_u8(c2s + 16);
1749 vc2s.val[3] = vld1_u8(c2s + 24);
1750 static const uint8_t idxlo[8] = {0, 1, 0, 1, 1, 2, 1, 2};
1751 static const uint8_t idxhi[8] = {2, 3, 3, 4, 3, 4, 4, 5};
1752 static const uint16_t mul8[8] = {2048, 64, 512, 16, 128, 1024, 32, 256};
1753 const uint8x8_t vidxlo = vld1_u8(idxlo);
1754 const uint8x8_t vidxhi = vld1_u8(idxhi);
1755 const uint16x8_t vmul = vld1q_u16(mul8);
1756 const uint16x8_t vmask = vdupq_n_u16(0x1F);
1757 while (i + 8 <= n) {
1759 ZXC_MEMCPY(&w, bits + ((i * 5) >> 3), 5);
1760 const uint8x8_t raw = vcreate_u8(w);
1761 const uint16x8_t win =
1762 vreinterpretq_u16_u8(vcombine_u8(vtbl1_u8(raw, vidxlo), vtbl1_u8(raw, vidxhi)));
1763 const uint8x8_t codes =
1764 vmovn_u16(vandq_u16(vshrq_n_u16(vmulq_u16(win, vmul), 11), vmask));
1765 vst1_u8(out + i, vtbl4_u8(vc2s, codes));
1768 }
else if (D == 6) {
1772 lo.val[0] = vld1_u8(c2s);
1773 lo.val[1] = vld1_u8(c2s + 8);
1774 lo.val[2] = vld1_u8(c2s + 16);
1775 lo.val[3] = vld1_u8(c2s + 24);
1776 hi.val[0] = vld1_u8(c2s + 32);
1777 hi.val[1] = vld1_u8(c2s + 40);
1778 hi.val[2] = vld1_u8(c2s + 48);
1779 hi.val[3] = vld1_u8(c2s + 56);
1780 static const uint8_t idxlo[8] = {0, 1, 0, 1, 1, 2, 2, 3};
1781 static const uint8_t idxhi[8] = {3, 4, 3, 4, 4, 5, 5, 6};
1782 static const uint16_t mul8[8] = {1024, 16, 64, 256, 1024, 16, 64, 256};
1783 const uint8x8_t vidxlo = vld1_u8(idxlo);
1784 const uint8x8_t vidxhi = vld1_u8(idxhi);
1785 const uint16x8_t vmul = vld1q_u16(mul8);
1786 const uint16x8_t vmask = vdupq_n_u16(0x3F);
1787 while (i + 8 <= n) {
1789 ZXC_MEMCPY(&w, bits + ((i * 6) >> 3), 6);
1790 const uint8x8_t raw = vcreate_u8(w);
1791 const uint16x8_t win =
1792 vreinterpretq_u16_u8(vcombine_u8(vtbl1_u8(raw, vidxlo), vtbl1_u8(raw, vidxhi)));
1793 const uint8x8_t codes =
1794 vmovn_u16(vandq_u16(vshrq_n_u16(vmulq_u16(win, vmul), 10), vmask));
1795 const uint8x8_t sel =
1796 vbsl_u8(vcge_u8(codes, vdup_n_u8(32)), vtbl4_u8(hi, vsub_u8(codes, vdup_n_u8(32))),
1797 vtbl4_u8(lo, codes));
1798 vst1_u8(out + i, sel);
1802#elif defined(ZXC_USE_AVX512) || defined(ZXC_USE_AVX2) || \
1803 (defined(ZXC_USE_SSE2) && defined(__SSE4_1__))
1804#if defined(ZXC_USE_AVX512) && defined(__AVX512VBMI__)
1811 if (D >= 2 && D <= 6) {
1814 for (
int k = 0; k < 8; k++) {
1815 for (
int j = 0; j < 8; j++) {
1816 arr[k * 8 + j] = (uint8_t)(k * D + j);
1817 shf[k * 8 + j] = (uint8_t)(j * D);
1820 const __m512i varr = _mm512_loadu_si512((
const void*)arr);
1821 const __m512i vshf = _mm512_loadu_si512((
const void*)shf);
1822 const __m512i vand = _mm512_set1_epi8((
char)((1 << D) - 1));
1824 const __mmask64 tm = (D == 6) ? ~(__mmask64)0 : (((__mmask64)1 << (1 << D)) - 1);
1825 const __m512i vc2s = _mm512_maskz_loadu_epi8(tm, (
const void*)c2s);
1828 const size_t off = ((size_t)i * (
size_t)D) >> 3;
1829 const size_t avail = nbytes - off;
1830 const size_t left = n - i;
1831 const __mmask64 lm = (avail >= 64) ? ~(__mmask64)0 : (((__mmask64)1 << avail) - 1);
1832 const __mmask64 sm = (left >= 64) ? ~(__mmask64)0 : (((__mmask64)1 << left) - 1);
1833 const __m512i raw = _mm512_maskz_loadu_epi8(lm, (
const void*)(bits + off));
1834 const __m512i q = _mm512_permutexvar_epi8(varr, raw);
1835 const __m512i codes = _mm512_and_si512(_mm512_multishift_epi64_epi8(vshf, q), vand);
1836 _mm512_mask_storeu_epi8((
void*)(out + i), sm, _mm512_permutexvar_epi8(codes, vc2s));
1842#if defined(ZXC_USE_AVX2)
1848 if (D >= 2 && D <= 6) {
1852 for (
int q = 0; q < 8; q++) {
1853 const int ba = (q * D) >> 3;
1854 sa[2 * q] = (uint8_t)ba;
1855 sa[2 * q + 1] = (uint8_t)(ba + 1);
1856 sb[2 * q] = (uint8_t)(ba + D);
1857 sb[2 * q + 1] = (uint8_t)(ba + D + 1);
1858 mu[q] = (uint16_t)(1U << (16 - D - ((q * D) & 7)));
1860 const __m256i vsa = _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)sa));
1861 const __m256i vsb = _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)sb));
1862 const __m256i vmu = _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)mu));
1863 const __m256i vand = _mm256_set1_epi8((
char)((1 << D) - 1));
1865 for (
int e = 0; e < 64; e++) tab[e] = c2s[e & ((1 << D) - 1)];
1866 const __m256i t0 = _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)tab));
1868 _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)(tab + 16)));
1870 _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)(tab + 32)));
1872 _mm256_broadcastsi128_si256(_mm_loadu_si128((
const __m128i*)(
void*)(tab + 48)));
1874 while (i + 32 <= n && ((
size_t)i * (
size_t)D >> 3) + (
size_t)(2 * D) + 16 <= nbytes) {
1875 const uint8_t* src = bits + ((size_t)i * (
size_t)D >> 3);
1876 const __m256i raw = _mm256_inserti128_si256(
1877 _mm256_castsi128_si256(_mm_loadu_si128((
const __m128i*)(
const void*)src)),
1878 _mm_loadu_si128((
const __m128i*)(
const void*)(src + 2 * D)), 1);
1880 _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(raw, vsa), vmu), 16 - D);
1882 _mm256_srli_epi16(_mm256_mullo_epi16(_mm256_shuffle_epi8(raw, vsb), vmu), 16 - D);
1883 const __m256i codes = _mm256_and_si256(_mm256_packus_epi16(ca, cb), vand);
1886 sym = _mm256_shuffle_epi8(t0, codes);
1888 const __m256i b4 = _mm256_slli_epi16(codes, 3);
1889 const __m256i lo = _mm256_blendv_epi8(_mm256_shuffle_epi8(t0, codes),
1890 _mm256_shuffle_epi8(t1, codes), b4);
1894 const __m256i hi = _mm256_blendv_epi8(_mm256_shuffle_epi8(t2, codes),
1895 _mm256_shuffle_epi8(t3, codes), b4);
1896 sym = _mm256_blendv_epi8(lo, hi, _mm256_slli_epi16(codes, 2));
1899 _mm256_storeu_si256((__m256i*)(
void*)(out + i), sym);
1905 const __m128i vc2s = _mm_loadu_si128((
const __m128i*)(
const void*)c2s);
1906 const __m128i vrep = _mm_setr_epi8(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7);
1907 const __m128i vmask = _mm_set1_epi8(0x0F);
1910 const __m128i vodd = _mm_set1_epi16(0x0F00 - 0x0F00 + (
short)0xFF00);
1911 while (i + 16 <= n) {
1913 _mm_loadl_epi64((
const __m128i*)(
const void*)(bits + ((i * 4) >> 3)));
1914 const __m128i rep = _mm_shuffle_epi8(raw, vrep);
1915 const __m128i hi = _mm_and_si128(_mm_srli_epi16(rep, 4), _mm_set1_epi8(0x0F));
1916 const __m128i lo = _mm_and_si128(rep, vmask);
1917 const __m128i codes = _mm_blendv_epi8(lo, hi, vodd);
1918 _mm_storeu_si128((__m128i*)(
void*)(out + i), _mm_shuffle_epi8(vc2s, codes));
1921 }
else if (D == 2) {
1926 for (
int k = 0; k < 16; k++) c2s16[k] = c2s[k & 3];
1927 const __m128i vc2s = _mm_loadu_si128((
const __m128i*)(
const void*)c2s16);
1928 const __m128i vspreadA =
1929 _mm_setr_epi8(0, (
char)0x80, 0, (
char)0x80, 0, (
char)0x80, 0, (
char)0x80, 1, (
char)0x80,
1930 1, (
char)0x80, 1, (
char)0x80, 1, (
char)0x80);
1931 const __m128i vspreadB =
1932 _mm_setr_epi8(2, (
char)0x80, 2, (
char)0x80, 2, (
char)0x80, 2, (
char)0x80, 3, (
char)0x80,
1933 3, (
char)0x80, 3, (
char)0x80, 3, (
char)0x80);
1934 const __m128i vmul = _mm_setr_epi16(64, 16, 4, 1, 64, 16, 4, 1);
1935 while (i + 16 <= n) {
1936 const __m128i raw = _mm_cvtsi32_si128(
1937 (
int)((uint32_t)bits[(i * 2) >> 3] | ((uint32_t)bits[((i * 2) >> 3) + 1] << 8) |
1938 ((uint32_t)bits[((i * 2) >> 3) + 2] << 16) |
1939 ((uint32_t)bits[((i * 2) >> 3) + 3] << 24)));
1941 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, vspreadA), vmul), 6);
1943 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, vspreadB), vmul), 6);
1944 const __m128i codes = _mm_and_si128(_mm_packus_epi16(a16, b16), _mm_set1_epi8(3));
1945 _mm_storeu_si128((__m128i*)(
void*)(out + i), _mm_shuffle_epi8(vc2s, codes));
1948 }
else if (D == 3) {
1953 for (
int k = 0; k < 16; k++) c2s16[k] = c2s[k & 7];
1954 const __m128i vc2s = _mm_loadu_si128((
const __m128i*)(
const void*)c2s16);
1955 const __m128i shufA = _mm_setr_epi8(0, 1, 0, 1, 0, 1, 1, 2, 1, 2, 1, 2, 2, 3, 2, 3);
1956 const __m128i shufB = _mm_setr_epi8(3, 4, 3, 4, 3, 4, 4, 5, 4, 5, 4, 5, 5, 6, 5, 6);
1957 const __m128i vmul = _mm_setr_epi16(8192, 1024, 128, 4096, 512, 64, 2048, 256);
1958 while (i + 16 <= n) {
1959 const size_t off = (i * 3) >> 3;
1962 ZXC_MEMCPY(&w0, bits + off, 4);
1963 ZXC_MEMCPY(&w1, bits + off + 4, 2);
1964 const __m128i raw = _mm_insert_epi16(_mm_cvtsi32_si128((
int)w0), w1, 2);
1966 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufA), vmul), 13);
1968 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufB), vmul), 13);
1969 const __m128i codes = _mm_and_si128(_mm_packus_epi16(cA, cB), _mm_set1_epi8(7));
1970 _mm_storeu_si128((__m128i*)(
void*)(out + i), _mm_shuffle_epi8(vc2s, codes));
1973 }
else if (D == 5) {
1975 const __m128i vlo = _mm_loadu_si128((
const __m128i*)(
const void*)c2s);
1976 const __m128i vhi = _mm_loadu_si128((
const __m128i*)(
const void*)(c2s + 16));
1977 const __m128i shufA = _mm_setr_epi8(0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 3, 4, 3, 4, 4, 5);
1978 const __m128i shufB = _mm_setr_epi8(5, 6, 5, 6, 6, 7, 6, 7, 7, 8, 8, 9, 8, 9, 9, 10);
1979 const __m128i vmul = _mm_setr_epi16(2048, 64, 512, 16, 128, 1024, 32, 256);
1980 while (i + 16 <= n) {
1981 const size_t off = (i * 5) >> 3;
1983 ZXC_MEMCPY(&w1, bits + off + 8, 2);
1985 _mm_insert_epi16(_mm_loadl_epi64((
const __m128i*)(
const void*)(bits + off)), w1, 4);
1987 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufA), vmul), 11);
1989 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufB), vmul), 11);
1990 const __m128i codes = _mm_and_si128(_mm_packus_epi16(cA, cB), _mm_set1_epi8(0x1F));
1992 _mm_blendv_epi8(_mm_shuffle_epi8(vlo, codes), _mm_shuffle_epi8(vhi, codes),
1993 _mm_slli_epi16(codes, 3));
1994 _mm_storeu_si128((__m128i*)(
void*)(out + i), sel);
1997 }
else if (D == 6) {
1999 const __m128i t0 = _mm_loadu_si128((
const __m128i*)(
const void*)c2s);
2000 const __m128i t1 = _mm_loadu_si128((
const __m128i*)(
const void*)(c2s + 16));
2001 const __m128i t2 = _mm_loadu_si128((
const __m128i*)(
const void*)(c2s + 32));
2002 const __m128i t3 = _mm_loadu_si128((
const __m128i*)(
const void*)(c2s + 48));
2003 const __m128i shufA = _mm_setr_epi8(0, 1, 0, 1, 1, 2, 2, 3, 3, 4, 3, 4, 4, 5, 5, 6);
2004 const __m128i shufB = _mm_setr_epi8(6, 7, 6, 7, 7, 8, 8, 9, 9, 10, 9, 10, 10, 11, 11, 12);
2005 const __m128i vmul = _mm_setr_epi16(1024, 16, 64, 256, 1024, 16, 64, 256);
2006 while (i + 16 <= n) {
2007 const size_t off = (i * 6) >> 3;
2009 ZXC_MEMCPY(&w1, bits + off + 8, 4);
2010 const __m128i raw = _mm_insert_epi32(
2011 _mm_loadl_epi64((
const __m128i*)(
const void*)(bits + off)), (
int)w1, 2);
2013 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufA), vmul), 10);
2015 _mm_srli_epi16(_mm_mullo_epi16(_mm_shuffle_epi8(raw, shufB), vmul), 10);
2016 const __m128i codes = _mm_and_si128(_mm_packus_epi16(cA, cB), _mm_set1_epi8(0x3F));
2017 const __m128i m4 = _mm_slli_epi16(codes, 3);
2019 _mm_blendv_epi8(_mm_shuffle_epi8(t0, codes), _mm_shuffle_epi8(t1, codes), m4);
2021 _mm_blendv_epi8(_mm_shuffle_epi8(t2, codes), _mm_shuffle_epi8(t3, codes), m4);
2022 _mm_storeu_si128((__m128i*)(
void*)(out + i),
2023 _mm_blendv_epi8(lo, hi, _mm_slli_epi16(codes, 2)));
2031 uint64_t bitpos = i * (uint64_t)D;
2032 const uint32_t m = (1U << D) - 1U;
2033 const size_t fbytes = (size_t)(((uint64_t)n * (uint64_t)D + 7U) >> 3);
2035 const size_t byte = (size_t)(bitpos >> 3);
2036 uint32_t w = bits[byte];
2037 if (
byte + 1 < fbytes) w |= (uint32_t)bits[
byte + 1] << 8;
2038 if (D > 8 &&
byte + 2 < fbytes) w |= (uint32_t)bits[
byte + 2] << 16;
2039 out[i++] = c2s[(w >> (bitpos & 7U)) & m];
2040 bitpos += (uint64_t)D;
2054 const uint8_t sym0,
const uint8_t sym1,
2055 const uint8_t* RESTRICT bits) {
2057#if defined(ZXC_USE_NEON64)
2058 const uint8x16_t vsym0 = vdupq_n_u8(sym0);
2059 const uint8x16_t vdelta = vdupq_n_u8((uint8_t)(sym0 ^ sym1));
2060 static const uint8_t rep_idx[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1};
2061 static const uint8_t bit_sel[16] = {1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128};
2062 const uint8x16_t vrep = vld1q_u8(rep_idx);
2063 const uint8x16_t vsel = vld1q_u8(bit_sel);
2064 while (i + 16 <= n) {
2065 uint8x16_t ctrl = vdupq_n_u8(0);
2066 ctrl = vsetq_lane_u8(bits[i >> 3], ctrl, 0);
2067 ctrl = vsetq_lane_u8(bits[(i >> 3) + 1], ctrl, 1);
2068 const uint8x16_t rep = vqtbl1q_u8(ctrl, vrep);
2069 const uint8x16_t mask = vtstq_u8(rep, vsel);
2070 vst1q_u8(out + i, veorq_u8(vsym0, vandq_u8(vdelta, mask)));
2073#elif defined(ZXC_USE_NEON32)
2074 const uint8x8_t vsym0 = vdup_n_u8(sym0);
2075 const uint8x8_t vdelta = vdup_n_u8((uint8_t)(sym0 ^ sym1));
2076 static const uint8_t bit_sel8[8] = {1, 2, 4, 8, 16, 32, 64, 128};
2077 const uint8x8_t vsel = vld1_u8(bit_sel8);
2078 while (i + 8 <= n) {
2079 const uint8x8_t mask = vtst_u8(vdup_n_u8(bits[i >> 3]), vsel);
2080 vst1_u8(out + i, veor_u8(vsym0, vand_u8(vdelta, mask)));
2083#elif defined(ZXC_USE_AVX512) || defined(ZXC_USE_AVX2) || \
2084 (defined(ZXC_USE_SSE2) && defined(__SSSE3__))
2085#if defined(ZXC_USE_AVX512)
2089 const __m512i z0 = _mm512_set1_epi8((
char)sym0);
2090 const __m512i z1 = _mm512_set1_epi8((
char)sym1);
2092 const size_t left = n - i;
2093 const size_t cb = (left + 7) >> 3;
2095 ZXC_MEMCPY(&ctrl, bits + (i >> 3), cb < 8 ? cb : 8);
2096 const __mmask64 sm = (left >= 64) ? ~(__mmask64)0 : (((__mmask64)1 << left) - 1);
2097 _mm512_mask_storeu_epi8((
void*)(out + i), sm,
2098 _mm512_mask_blend_epi8((__mmask64)ctrl, z0, z1));
2104#if defined(ZXC_USE_AVX2)
2108 const __m256i y0 = _mm256_set1_epi8((
char)sym0);
2109 const __m256i ydelta = _mm256_set1_epi8((
char)(uint8_t)(sym0 ^ sym1));
2110 const __m256i yrep = _mm256_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2111 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3);
2112 const __m256i ysel =
2113 _mm256_setr_epi8(1, 2, 4, 8, 16, 32, 64, (
char)128, 1, 2, 4, 8, 16, 32, 64, (
char)128,
2114 1, 2, 4, 8, 16, 32, 64, (
char)128, 1, 2, 4, 8, 16, 32, 64, (
char)128);
2115 while (i + 32 <= n) {
2117 ZXC_MEMCPY(&c4, bits + (i >> 3), 4);
2118 const __m256i rep = _mm256_shuffle_epi8(_mm256_set1_epi32((
int)c4), yrep);
2119 const __m256i mask = _mm256_cmpeq_epi8(_mm256_and_si256(rep, ysel), ysel);
2120 _mm256_storeu_si256((__m256i*)(
void*)(out + i),
2121 _mm256_xor_si256(y0, _mm256_and_si256(ydelta, mask)));
2126 const __m128i vsym0 = _mm_set1_epi8((
char)sym0);
2127 const __m128i vdelta = _mm_set1_epi8((
char)(uint8_t)(sym0 ^ sym1));
2128 const __m128i vrep = _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1);
2129 const __m128i vsel =
2130 _mm_setr_epi8(1, 2, 4, 8, 16, 32, 64, (
char)128, 1, 2, 4, 8, 16, 32, 64, (
char)128);
2131 while (i + 16 <= n) {
2132 const __m128i ctrl = _mm_cvtsi32_si128(bits[i >> 3] | ((
int)bits[(i >> 3) + 1] << 8));
2133 const __m128i rep = _mm_shuffle_epi8(ctrl, vrep);
2135 const __m128i mask = _mm_cmpeq_epi8(_mm_and_si128(rep, vsel), vsel);
2136 _mm_storeu_si128((__m128i*)(
void*)(out + i),
2137 _mm_xor_si128(vsym0, _mm_and_si128(vdelta, mask)));
2143 const int bit = (bits[i >> 3] >> (i & 7)) & 1;
2144 out[i++] = bit ? sym1 : sym0;