1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
/*
Copyright (C) 2020 Fredrik Johansson
This file is part of Calcium.
Calcium is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "ca_ext.h"
ca_ext_ptr ca_ext_cache_insert(ca_ext_cache_t cache, const ca_ext_t x, ca_ctx_t ctx)
{
ulong xhash;
slong i, loc;
xhash = ca_ext_hash(x, ctx);
/* make room for inserting entry if needed */
if (cache->length == cache->alloc)
{
slong new_alloc;
new_alloc = FLINT_MAX(1, cache->alloc * 2);
cache->items = flint_realloc(cache->items, sizeof(ca_ext_struct *) * new_alloc);
for (i = cache->alloc; i < new_alloc; i++)
cache->items[i] = flint_malloc(sizeof(ca_ext_struct));
cache->alloc = new_alloc;
}
/* rehash if needed */
if (cache->length >= 0.5 * cache->hash_size)
{
slong new_size, j;
slong * new_table;
ulong thash;
new_size = cache->hash_size * 2;
new_table = flint_malloc(sizeof(slong) * new_size);
for (i = 0; i < new_size; i++)
new_table[i] = -1;
for (i = 0; i < cache->length; i++)
{
thash = ca_ext_hash(cache->items[i], ctx);
j = thash % new_size;
while (new_table[j] != -1)
{
j++;
if (j == new_size)
j = 0;
}
new_table[j] = i;
}
flint_free(cache->hash_table);
cache->hash_size = new_size;
cache->hash_table = new_table;
}
loc = xhash % ((ulong) cache->hash_size);
for (i = 0; i < cache->hash_size; i++)
{
/* not found, so insert */
if (cache->hash_table[loc] == -1)
{
ca_ext_init_set(cache->items[cache->length], x, ctx);
cache->hash_table[loc] = cache->length;
cache->length++;
return cache->items[cache->length - 1];
}
/* found */
if (ca_ext_equal_repr(cache->items[cache->hash_table[loc]], x, ctx))
return cache->items[cache->hash_table[loc]];
loc++;
if (loc == cache->hash_size)
loc = 0;
}
/* cannot happen */
flint_abort();
}
|