#if defined(__x86_64__) || defined(_M_X64)
#include "semq_dispatch.h"
#include <immintrin.h>
#include <math.h>
#include <stdint.h>
static int64_t scaled_round_one(float x, uint32_t scale) {
if (!isfinite(x)) {
return 0;
}
double y = nearbyint((double)x * (double)scale);
if (y >= 9.2233720368547748e18) {
return INT64_MAX;
}
if (y <= -9.2233720368547758e18) {
return INT64_MIN;
}
return (int64_t)y;
}
static uint8_t reduce_one(uint64_t a) {
if (a == 0u) return 0u;
return (uint8_t)(1u + (uint32_t)((a - 1u) % 9u));
}
static semq_code_t scalar_op(float x, uint32_t scale) {
int64_t v = scaled_round_one(x, scale);
unsigned int s = (v > 0) ? 2u : ((v < 0) ? 0u : 1u);
uint64_t a;
if (v == INT64_MIN) {
a = (uint64_t)INT64_MAX + 1u;
} else {
a = (v < 0) ? (uint64_t)(-v) : (uint64_t)v;
}
return (semq_code_t)(s * 10u + (unsigned int)reduce_one(a));
}
static double scalar_inverse(semq_code_t code, uint32_t scale) {
int sign = (int)(code / 10u) - 1;
unsigned int g = (unsigned int)(code % 10u);
return ((double)g * (double)sign) / (double)scale;
}
static inline __m512i scale_round_16(__m512 f, __m512d dsc) {
__m512d d_lo = _mm512_mul_pd(_mm512_cvtps_pd(_mm512_castps512_ps256(f)), dsc);
__m256i upper_bits = _mm512_extracti64x4_epi64(_mm512_castps_si512(f), 1);
__m256 f_hi = _mm256_castsi256_ps(upper_bits);
__m512d d_hi = _mm512_mul_pd(_mm512_cvtps_pd(f_hi), dsc);
__m256i v_lo = _mm512_cvtpd_epi32(d_lo);
__m256i v_hi = _mm512_cvtpd_epi32(d_hi);
return _mm512_inserti64x4(_mm512_castsi256_si512(v_lo), v_hi, 1);
}
static inline __m512i mod_9_u32_512(__m512i a) {
const __m512i magic = _mm512_set1_epi32((int)0x38E38E39u);
__m512i prod_even = _mm512_mul_epu32(a, magic);
__m512i a_odd = _mm512_srli_epi64(a, 32);
__m512i m_odd = _mm512_srli_epi64(magic, 32);
__m512i prod_odd = _mm512_mul_epu32(a_odd, m_odd);
__m512i q_even = _mm512_srli_epi64(prod_even, 33);
__m512i q_odd = _mm512_slli_epi64(_mm512_srli_epi64(prod_odd, 33), 32);
__m512i mask_lo32 = _mm512_set1_epi64((long long)0x00000000FFFFFFFFULL);
__m512i q = _mm512_or_si512(_mm512_and_si512(q_even, mask_lo32), q_odd);
return _mm512_sub_epi32(a, _mm512_mullo_epi32(q, _mm512_set1_epi32(9)));
}
static inline __m512i encode_int32_16(__m512i v) {
const __m512i Z = _mm512_setzero_si512();
const __m512i ONE = _mm512_set1_epi32(1);
__mmask16 pos_mask = _mm512_cmpgt_epi32_mask(v, Z);
__mmask16 neg_mask = _mm512_cmpgt_epi32_mask(Z, v);
__m512i s = ONE;
s = _mm512_mask_mov_epi32(s, pos_mask, _mm512_set1_epi32(2));
s = _mm512_mask_mov_epi32(s, neg_mask, _mm512_setzero_si512());
__m512i a = _mm512_abs_epi32(v);
__m512i am1 = _mm512_sub_epi32(a, ONE);
__m512i r = mod_9_u32_512(am1);
__m512i g_pos = _mm512_add_epi32(r, ONE);
__mmask16 nz_mask = _mm512_cmpneq_epi32_mask(a, Z);
__m512i g = _mm512_maskz_mov_epi32(nz_mask, g_pos);
__m512i ten = _mm512_set1_epi32(10);
return _mm512_add_epi32(_mm512_mullo_epi32(s, ten), g);
}
static inline __m512i pack_codes_64(__m512i a, __m512i b, __m512i c, __m512i d) {
__m128i p0 = _mm512_cvtusepi32_epi8(a);
__m128i p1 = _mm512_cvtusepi32_epi8(b);
__m128i p2 = _mm512_cvtusepi32_epi8(c);
__m128i p3 = _mm512_cvtusepi32_epi8(d);
__m512i packed = _mm512_castsi128_si512(p0);
packed = _mm512_inserti32x4(packed, p1, 1);
packed = _mm512_inserti32x4(packed, p2, 2);
packed = _mm512_inserti32x4(packed, p3, 3);
return packed;
}
static semq_status_t avx512_encode(
const float* input,
uint32_t dim,
uint32_t scale,
semq_code_t* output) {
__m512d dsc = _mm512_set1_pd((double)scale);
uint32_t i = 0u;
for (; i + 64u <= dim; i += 64u) {
__m512 f0 = _mm512_loadu_ps(input + i + 0u);
__m512 f1 = _mm512_loadu_ps(input + i + 16u);
__m512 f2 = _mm512_loadu_ps(input + i + 32u);
__m512 f3 = _mm512_loadu_ps(input + i + 48u);
__m512i v0 = scale_round_16(f0, dsc);
__m512i v1 = scale_round_16(f1, dsc);
__m512i v2 = scale_round_16(f2, dsc);
__m512i v3 = scale_round_16(f3, dsc);
__m512i c0 = encode_int32_16(v0);
__m512i c1 = encode_int32_16(v1);
__m512i c2 = encode_int32_16(v2);
__m512i c3 = encode_int32_16(v3);
_mm512_storeu_si512((__m512i*)(output + i),
pack_codes_64(c0, c1, c2, c3));
}
for (; i < dim; ++i) {
output[i] = scalar_op(input[i], scale);
}
return SEMQ_OK;
}
static semq_status_t avx512_reconstruct(
const semq_code_t* codes,
uint32_t dim,
uint32_t scale,
double* output) {
__m512d dsc = _mm512_set1_pd((double)scale);
uint32_t i = 0u;
for (; i + 16u <= dim; i += 16u) {
__m128i c8 = _mm_loadu_si128((const __m128i*)(codes + i));
__m512i c32 = _mm512_cvtepu8_epi32(c8);
__m512i q = _mm512_srli_epi32(_mm512_mullo_epi32(c32, _mm512_set1_epi32(26)), 8);
__m512i r = _mm512_sub_epi32(c32,
_mm512_mullo_epi32(q, _mm512_set1_epi32(10)));
__m512i sign = _mm512_sub_epi32(q, _mm512_set1_epi32(1));
__m512i gs = _mm512_mullo_epi32(r, sign);
__m256i gs_lo = _mm512_castsi512_si256(gs);
__m256i gs_hi = _mm512_extracti64x4_epi64(gs, 1);
__m512d f_lo = _mm512_cvtepi32_pd(gs_lo);
__m512d f_hi = _mm512_cvtepi32_pd(gs_hi);
f_lo = _mm512_div_pd(f_lo, dsc);
f_hi = _mm512_div_pd(f_hi, dsc);
_mm512_storeu_pd(output + i + 0, f_lo);
_mm512_storeu_pd(output + i + 8, f_hi);
}
for (; i < dim; ++i) {
output[i] = scalar_inverse(codes[i], scale);
}
return SEMQ_OK;
}
const semq_backend_t SEMQ_AVX512_BACKEND = {
.encode = avx512_encode,
.reconstruct = avx512_reconstruct
};
#endif