mie: add support for caching float values
This commit is contained in:
@@ -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);
|
||||
|
||||
215
mie/dialect/arith/float-cache.c
Normal file
215
mie/dialect/arith/float-cache.c
Normal file
@@ -0,0 +1,215 @@
|
||||
#include <blue/core/btree.h>
|
||||
#include <mie/dialect/arith.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user