#include "semq_dispatch.h"
#include "semq_bits.h"
#include "semq_quant_packing.h"
#include <stdint.h>
#include <math.h>
#include <string.h>
static uint32_t quant_bits_per_dim(uint32_t n_bins) {
return semq_bits_per_symbol_quant(n_bins);
}
static uint32_t quant_output_bytes(uint32_t dim, uint32_t n_bins) {
uint32_t bpd = quant_bits_per_dim(n_bins);
uint64_t total_bits = (uint64_t)dim * (uint64_t)bpd;
return (uint32_t)((total_bits + 7u) / 8u);
}
uint32_t semq_quant_bin_of_magnitude(float mag, float scale_max, uint32_t n_bins) {
if (mag >= scale_max) {
return n_bins - 1u;
}
const float t = (mag * (float)n_bins) / scale_max;
uint32_t b = (uint32_t)floorf(t);
if (b >= n_bins) b = n_bins - 1u;
return b;
}
static uint32_t quant_symbol(float x, float scale_max, uint32_t n_bins) {
uint32_t b = semq_quant_bin_of_magnitude(fabsf(x), scale_max, n_bins);
uint32_t sign_flag = (x < 0.0f) ? 0u : 1u;
return sign_flag * n_bins + b;
}
static double quant_centre(uint32_t symbol, float scale_max, uint32_t n_bins) {
uint32_t sign_flag = symbol / n_bins;
uint32_t b = symbol % n_bins;
double centre = ((double)b + 0.5) * (double)scale_max / (double)n_bins;
return sign_flag ? centre : -centre;
}
static uint32_t unpack_bits(const semq_code_t* in, uint64_t* bit_pos,
uint32_t bits) {
return semq_unpack_bits(in, bit_pos, bits);
}
static semq_status_t quant_encode_scalar(
const float* input,
uint32_t dim,
uint32_t n_bins,
float scale_max,
semq_code_t* output)
{
if (n_bins < 2u || scale_max <= 0.0f) {
return SEMQ_ERR_INVALID_INPUT;
}
uint32_t bpd = quant_bits_per_dim(n_bins);
uint32_t bytes = quant_output_bytes(dim, n_bins);
memset(output, 0, bytes);
uint64_t pos = 0;
for (uint32_t i = 0; i < dim; i++) {
uint32_t sym = quant_symbol(input[i], scale_max, n_bins);
semqi_quant_pack_symbol(output, &pos, sym, bpd);
}
return SEMQ_OK;
}
static semq_status_t quant_reconstruct_scalar(
const semq_code_t* codes,
uint32_t dim,
uint32_t n_bins,
float scale_max,
double* output)
{
if (n_bins < 2u || scale_max <= 0.0f) {
return SEMQ_ERR_INVALID_INPUT;
}
uint32_t bpd = quant_bits_per_dim(n_bins);
uint64_t pos = 0;
for (uint32_t i = 0; i < dim; i++) {
uint32_t sym = unpack_bits(codes, &pos, bpd);
output[i] = quant_centre(sym, scale_max, n_bins);
}
return SEMQ_OK;
}
const semq_quant_backend_t SEMQ_QUANT_SCALAR_BACKEND = {
.encode = quant_encode_scalar,
.reconstruct = quant_reconstruct_scalar,
};