#ifndef RAY_ENC_H
#define RAY_ENC_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "store/fsst.h"
#define RAY_ENC_VEC 1024
#define RAY_ENC_CHUNK 65536
#define RAY_ENC_DEPTH_MAX 3
size_t ray_enc_packed_bytes(int w);
void ray_enc_pack(const uint64_t* u, int T, int w, uint8_t* out);
void ray_enc_unpack(const uint8_t* in, int T, int w, uint64_t* u);
int ray_enc_bitlen(uint64_t x);
typedef struct { uint8_t T; bool is_signed; bool is_float; } ray_enc_kind_t;
bool ray_enc_kind_of(int8_t type, uint8_t attrs, ray_enc_kind_t* k);
bool ray_enc_value_kind(int8_t type, uint8_t attrs, ray_enc_kind_t* k);
bool ray_enc_has_bitmap(int8_t type);
static inline double ray_enc_fval(uint64_t b, int T) {
if (T == 32) { uint32_t u = (uint32_t)b; float f; memcpy(&f, &u, 4); return (double)f; }
double d; memcpy(&d, &b, 8); return d;
}
int64_t ray_enc_logical(uint64_t bits, ray_enc_kind_t k);
bool ray_enc_lt(uint64_t a, uint64_t b, ray_enc_kind_t k);
typedef struct {
uint64_t bits[RAY_ENC_VEC];
uint8_t nullmap[RAY_ENC_VEC / 8];
int n;
int n_nulls;
ray_enc_kind_t k;
bool bitmap;
} ray_enc_input_t;
bool ray_enc_load(const void* data, int8_t type, uint8_t attrs,
int64_t start, int n, ray_enc_input_t* in);
typedef struct { uint64_t min, max; int runs; bool all_equal; } ray_enc_stats_t;
void ray_enc_stats(const uint64_t* v, int n, ray_enc_kind_t k, ray_enc_stats_t* s);
typedef enum {
RAY_ENC_RAW = 0, RAY_ENC_CONST = 1, RAY_ENC_FOR_BP = 2, RAY_ENC_DELTA_BP = 3,
RAY_ENC_RLE = 4, RAY_ENC_DICT = 5, RAY_ENC_ALP = 6, RAY_ENC_ALP_RD = 7,
RAY_ENC_STR_DICT = 8, RAY_ENC_FSST = 9
} ray_enc_code_t;
typedef struct { uint8_t* p; size_t len, cap; bool oom; } ray_enc_buf_t;
void ray_enc_buf_free(ray_enc_buf_t* b);
bool ray_enc_buf_put(ray_enc_buf_t* b, const void* src, size_t n);
bool ray_enc_buf_pad8(ray_enc_buf_t* b);
int64_t ray_enc_size_raw(int n, int T);
int64_t ray_enc_size_const(void);
int ray_enc_for_width(const uint64_t* v, int n, ray_enc_kind_t k, uint64_t* base);
int64_t ray_enc_size_for(int w);
int ray_enc_delta_width(const uint64_t* v, int n, ray_enc_kind_t k, uint64_t* dbase);
int64_t ray_enc_size_delta(int T, int w);
typedef enum {
RAY_ENC_SLOT_TOP = 0,
RAY_ENC_SLOT_RLE_VALUES,
RAY_ENC_SLOT_RLE_ENDS,
RAY_ENC_SLOT_CODES,
RAY_ENC_SLOT_ALP_INTS,
RAY_ENC_SLOT_ALP_RD_LEFT,
RAY_ENC_SLOT_FSST_LENGTHS
} ray_enc_slot_t;
typedef struct { const uint64_t* v; uint32_t n; } ray_enc_dict_t;
typedef struct { uint8_t enc, width; int64_t bytes; } ray_enc_choice_t;
ray_enc_choice_t ray_enc_choose(const uint64_t* v, int n, ray_enc_kind_t k,
ray_enc_slot_t slot, int depth,
const ray_enc_dict_t* dict);
bool ray_enc_write(const uint64_t* v, int n, ray_enc_kind_t k,
ray_enc_slot_t slot, int depth, const ray_enc_dict_t* dict,
ray_enc_buf_t* out, ray_enc_choice_t* chosen);
bool ray_enc_write_as(uint8_t enc, const uint64_t* v, int n, ray_enc_kind_t k,
const ray_enc_dict_t* dict, ray_enc_buf_t* out, ray_enc_choice_t* chosen);
int64_t ray_enc_body_size(uint8_t enc, const uint64_t* v, int n, ray_enc_kind_t k,
const ray_enc_dict_t* dict);
int64_t ray_enc_read(const uint8_t* p, size_t avail, uint8_t enc, uint8_t width,
int n, ray_enc_kind_t k, ray_enc_slot_t slot, int depth,
const ray_enc_dict_t* dict, uint64_t* out);
int ray_enc_train_dict(const uint64_t* v, int64_t n, ray_enc_kind_t k,
uint64_t** out, uint32_t* out_n);
bool ray_enc_fp_env_ok(void);
#define RAY_ENC_FPENV_MSG "generation-2 float encoding/decoding requires default FP controls (FE_TONEAREST, masked exceptions, no FTZ/DAZ)"
#define RAY_ENC_ALP_CANDS 5
typedef struct { uint8_t e, f; } ray_enc_alp_ef_t;
typedef struct { ray_enc_alp_ef_t c[RAY_ENC_ALP_CANDS]; int n; } ray_enc_alp_cands_t;
void ray_enc_alp_train(const uint64_t* bits, int64_t n, int T, ray_enc_alp_cands_t* out);
int64_t ray_enc_alp_size(const uint64_t* v, int n, int T, const ray_enc_alp_cands_t* c, int* best);
bool ray_enc_alp_write(const uint64_t* v, int n, int T, uint8_t e, uint8_t f, ray_enc_buf_t* out);
int64_t ray_enc_alp_read(const uint8_t* p, size_t avail, int n, int T, uint64_t* out);
int64_t ray_enc_alprd_size(const uint64_t* v, int n, int T);
bool ray_enc_alprd_write(const uint64_t* v, int n, int T, ray_enc_buf_t* out);
int64_t ray_enc_alprd_read(const uint8_t* p, size_t avail, int n, int T, uint64_t* out);
ray_enc_choice_t ray_enc_float_choose(const uint64_t* v, int n, int T, const ray_enc_dict_t* dict,
const ray_enc_alp_cands_t* c, int64_t extra);
bool ray_enc_float_write(uint8_t enc, const uint64_t* v, int n, int T, const ray_enc_dict_t* dict,
const ray_enc_alp_cands_t* c, ray_enc_buf_t* out, ray_enc_choice_t* chosen);
int64_t ray_enc_float_read(const uint8_t* p, size_t avail, uint8_t enc, int n, int T,
const ray_enc_dict_t* dict, uint64_t* out);
int64_t ray_enc_strdict_size(const uint64_t* codes, int n);
bool ray_enc_strdict_write(const uint64_t* codes, int n, ray_enc_buf_t* out);
void ray_enc_strdict_read(const uint8_t* p, size_t avail, int n, uint64_t* codes);
uint64_t ray_enc_fsst_encode(const ray_fsst_table_t* t, const ray_fsst_index_t* ix,
const char* const* s, const uint32_t* len, int n,
uint8_t* buf, uint64_t* clen);
int64_t ray_enc_fsst_size(const uint64_t* clen, int n, uint64_t total);
bool ray_enc_fsst_write(const uint64_t* clen, int n, const uint8_t* bytes, uint64_t total,
ray_enc_buf_t* out);
void ray_enc_fsst_parse(const uint8_t* p, size_t avail, int n, const ray_fsst_table_t* t,
uint64_t* clen, uint64_t* xlen, const uint8_t** bytes);
#endif