From 0c84578f95ddc4468f67fbe47f5084ce99d591e2 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 11 Jan 2026 14:17:45 +0000 Subject: [PATCH] mie: add support for caching float values --- mie/ctx.c | 7 ++ mie/dialect/arith/float-cache.c | 215 ++++++++++++++++++++++++++++++++ mie/include/mie/ctx.h | 1 + mie/include/mie/dialect/arith.h | 9 ++ 4 files changed, 232 insertions(+) create mode 100644 mie/dialect/arith/float-cache.c diff --git a/mie/ctx.c b/mie/ctx.c index 5cb3b03..3ee8487 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -42,6 +42,7 @@ struct mie_ctx *mie_ctx_create(void) mie_id_map_init(&out->ctx_types, &types_ns); out->ctx_ints = mie_int_cache_create(); + out->ctx_floats = mie_float_cache_create(); out->ctx_indices = mie_index_cache_create(); out->ctx_strings = mie_string_cache_create(); @@ -305,6 +306,12 @@ struct mie_value *mie_ctx_get_int(struct mie_ctx *ctx, long long val, size_t nr_ ctx->ctx_ints, ctx, val, nr_bits); } +struct mie_value *mie_ctx_get_float(struct mie_ctx *ctx, double val, size_t nr_bits) +{ + return (struct mie_value *)mie_float_cache_get( + ctx->ctx_floats, ctx, val, nr_bits); +} + struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s) { return (struct mie_value *)mie_string_cache_get(ctx->ctx_strings, ctx, s); diff --git a/mie/dialect/arith/float-cache.c b/mie/dialect/arith/float-cache.c new file mode 100644 index 0000000..91f24ac --- /dev/null +++ b/mie/dialect/arith/float-cache.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include + +typedef union float_key { + double f; + unsigned char i[sizeof(double)]; +} float_key; + +struct float_width_cache_entry { + b_btree_node e_node; + float_key e_key; + struct mie_float e_value; +}; + +struct float_width_cache { + b_btree_node c_node; + size_t c_width; + b_btree c_floats; +}; + +struct mie_float_cache { + b_btree c_widths; +}; + +static int float_key_compare(const float_key *a, const float_key *b) +{ + return memcmp(a->i, b->i, sizeof a->i); +} + +static B_BTREE_DEFINE_SIMPLE_INSERT( + struct float_width_cache, c_node, c_width, put_width_cache); +static B_BTREE_DEFINE_SIMPLE_GET( + struct float_width_cache, size_t, c_node, c_width, get_width_cache); + +void put_float(b_btree *tree, struct float_width_cache_entry *node) +{ + if (!tree->b_root) { + tree->b_root = &node->e_node; + b_btree_insert_fixup(tree, &node->e_node); + return; + } + + b_btree_node *cur = tree->b_root; + while (1) { + struct float_width_cache_entry *cur_node + = b_unbox(struct float_width_cache_entry, cur, e_node); + b_btree_node *next = NULL; + int cmp = float_key_compare(&node->e_key, &cur_node->e_key); + + if (cmp >= 0) { + next = b_btree_right(cur); + + if (!next) { + b_btree_put_right(cur, &node->e_node); + break; + } + } else if (cmp < 0) { + next = b_btree_left(cur); + + if (!next) { + b_btree_put_left(cur, &node->e_node); + break; + } + } else { + return; + } + + cur = next; + } + + b_btree_insert_fixup(tree, &node->e_node); +} + +static struct float_width_cache_entry *get_float(const b_btree *tree, float_key key) +{ + b_btree_node *cur = tree->b_root; + while (cur) { + struct float_width_cache_entry *cur_node + = b_unbox(struct float_width_cache_entry, cur, e_node); + int cmp = float_key_compare(&key, &cur_node->e_key); + if (cmp > 0) { + cur = b_btree_right(cur); + } else if (cmp < 0) { + cur = b_btree_left(cur); + } else { + return cur_node; + } + } + + return NULL; +} + +static struct float_width_cache *float_width_cache_create(size_t width) +{ + struct float_width_cache *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->c_width = width; + + return out; +} + +static void float_width_cache_destroy(struct float_width_cache *cache) +{ + b_btree_node *cur = b_btree_first(&cache->c_floats); + while (cur) { + b_btree_node *next = b_btree_next(cur); + b_btree_delete(&cache->c_floats, cur); + + struct float_width_cache_entry *entry + = b_unbox(struct float_width_cache_entry, cur, e_node); + free(entry); + + cur = next; + } + + free(cache); +} + +static struct float_width_cache_entry *float_width_cache_entry_create( + struct mie_ctx *ctx, size_t width, double value) +{ + struct float_width_cache_entry *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + switch (width) { + case MIE_FLOAT_32: + out->e_value.f_val.v_32 = value; + break; + case MIE_FLOAT_64: + out->e_value.f_val.v_64 = value; + break; + default: + free(out); + return NULL; + } + + out->e_value.f_base.v_type = mie_arith_float_get_type(ctx, width); + if (!out->e_value.f_base.v_type) { + free(out); + return NULL; + } + + return out; +} + +struct mie_float_cache *mie_float_cache_create(void) +{ + struct mie_float_cache *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + return out; +} + +void mie_float_cache_destroy(struct mie_float_cache *cache) +{ + b_btree_node *cur = b_btree_first(&cache->c_widths); + while (cur) { + b_btree_node *next = b_btree_next(cur); + b_btree_delete(&cache->c_widths, cur); + + struct float_width_cache *width_cache + = b_unbox(struct float_width_cache, cur, c_node); + float_width_cache_destroy(width_cache); + + cur = next; + } + + free(cache); +} + +struct mie_float *mie_float_cache_get( + struct mie_float_cache *cache, struct mie_ctx *ctx, double value, + size_t bit_width) +{ + struct float_width_cache *width_cache + = get_width_cache(&cache->c_widths, bit_width); + if (!width_cache) { + width_cache = float_width_cache_create(bit_width); + + if (!width_cache) { + return NULL; + } + + put_width_cache(&cache->c_widths, width_cache); + } + + float_key key = {.f = value}; + struct float_width_cache_entry *entry + = get_float(&width_cache->c_floats, key); + if (!entry) { + entry = float_width_cache_entry_create(ctx, bit_width, value); + + if (!entry) { + return NULL; + } + + put_float(&width_cache->c_floats, entry); + } + + return &entry->e_value; +} diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index 686c16d..6c55404 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -27,6 +27,7 @@ struct mie_ctx { struct mie_id_map ctx_traits; struct mie_int_cache *ctx_ints; + struct mie_float_cache *ctx_floats; struct mie_index_cache *ctx_indices; struct mie_string_cache *ctx_strings; }; diff --git a/mie/include/mie/dialect/arith.h b/mie/include/mie/dialect/arith.h index aa98fba..f70a4b4 100644 --- a/mie/include/mie/dialect/arith.h +++ b/mie/include/mie/dialect/arith.h @@ -44,10 +44,19 @@ MIE_API struct mie_type *mie_arith_int_get_type( MIE_API struct mie_type *mie_arith_float_get_type( struct mie_ctx *ctx, size_t bit_width); +MIE_API size_t mie_arith_int_type_get_width(const struct mie_type *type); +MIE_API size_t mie_arith_float_type_get_width(const struct mie_type *type); + MIE_API struct mie_int_cache *mie_int_cache_create(void); MIE_API void mie_int_cache_destroy(struct mie_int_cache *cache); MIE_API struct mie_int *mie_int_cache_get( struct mie_int_cache *cache, struct mie_ctx *ctx, size_t value, size_t bit_width); +MIE_API struct mie_float_cache *mie_float_cache_create(void); +MIE_API void mie_float_cache_destroy(struct mie_float_cache *cache); +MIE_API struct mie_float *mie_float_cache_get( + struct mie_float_cache *cache, struct mie_ctx *ctx, double value, + size_t bit_width); + #endif