From ef371d9c3cbd97d2dbc2df2b2a59e722f4e82886 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Thu, 24 Nov 2016 23:23:55 -0500 Subject: [PATCH] mlhmmv reorg --- c/containers/mlhmmv.c | 202 +++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/c/containers/mlhmmv.c b/c/containers/mlhmmv.c index 55aac1307..31d405fe2 100644 --- a/c/containers/mlhmmv.c +++ b/c/containers/mlhmmv.c @@ -380,6 +380,43 @@ void mlhmmv_level_clear(mlhmmv_level_t* plevel) { memset(plevel->states, EMPTY, plevel->array_length); } +// ---------------------------------------------------------------- +// Returns >=0 for where the key is *or* should go (end of chain). + +static int mlhmmv_level_find_index_for_key(mlhmmv_level_t* plevel, mv_t* plevel_key, int* pideal_index) { + int hash = mlhmmv_hash_func(plevel_key); + int index = mlr_canonical_mod(hash, plevel->array_length); + *pideal_index = index; + int num_tries = 0; + + while (TRUE) { + mlhmmv_level_entry_t* pentry = &plevel->entries[index]; + if (plevel->states[index] == OCCUPIED) { + mv_t* ekey = &pentry->level_key; + // Existing key found in chain. + if (mv_equals_si(plevel_key, ekey)) + return index; + } else if (plevel->states[index] == EMPTY) { + return index; + } + + // If the current entry has been freed, i.e. previously occupied, + // the sought index may be further down the chain. So we must + // continue looking. + if (++num_tries >= plevel->array_length) { + fprintf(stderr, + "%s: Coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0); + exit(1); + } + + // Linear probing. + if (++index >= plevel->array_length) + index = 0; + } + MLR_INTERNAL_CODING_ERROR(); + return -1; // not reached +} + // ---------------------------------------------------------------- static mlhmmv_level_entry_t* mlhmmv_level_look_up_and_ref_entry(mlhmmv_level_t* plevel, sllmve_t* prestkeys, int* perror) @@ -609,6 +646,70 @@ void mlhmmv_level_put_terminal(mlhmmv_level_t* plevel, sllmve_t* prest_keys, mv_ mlhmmv_level_put_terminal_no_enlarge(plevel, prest_keys, pterminal_value); } +// ---------------------------------------------------------------- +static void mlhmmv_level_put_terminal_no_enlarge(mlhmmv_level_t* plevel, sllmve_t* prest_keys, mv_t* pterminal_value) { + mv_t* plevel_key = &prest_keys->value; + int ideal_index = 0; + int index = mlhmmv_level_find_index_for_key(plevel, plevel_key, &ideal_index); + mlhmmv_level_entry_t* pentry = &plevel->entries[index]; + + if (plevel->states[index] == EMPTY) { // End of chain. + pentry->ideal_index = ideal_index; + pentry->level_key = mv_copy(plevel_key); + + if (prest_keys->pnext == NULL) { + pentry->level_value.is_terminal = TRUE; + pentry->level_value.terminal_mlrval = mv_copy(pterminal_value); + } else { + pentry->level_value.is_terminal = FALSE; + pentry->level_value.pnext_level = mlhmmv_level_alloc(); + } + plevel->states[index] = OCCUPIED; + + if (plevel->phead == NULL) { // First entry at this level + pentry->pprev = NULL; + pentry->pnext = NULL; + plevel->phead = pentry; + plevel->ptail = pentry; + } else { // Subsequent entry at this level + pentry->pprev = plevel->ptail; + pentry->pnext = NULL; + plevel->ptail->pnext = pentry; + plevel->ptail = pentry; + } + + plevel->num_occupied++; + if (prest_keys->pnext != NULL) { + // RECURSE + mlhmmv_level_put_terminal(pentry->level_value.pnext_level, prest_keys->pnext, pterminal_value); + } + + } else if (plevel->states[index] == OCCUPIED) { // Existing key found in chain + if (prest_keys->pnext == NULL) { // Place the terminal at this level + if (pentry->level_value.is_terminal) { + mv_free(&pentry->level_value.terminal_mlrval); + } else { + mlhmmv_level_free(pentry->level_value.pnext_level); + } + pentry->level_value.is_terminal = TRUE; + pentry->level_value.terminal_mlrval = mv_copy(pterminal_value); + + } else { // The terminal will be placed at a deeper level + if (pentry->level_value.is_terminal) { + mv_free(&pentry->level_value.terminal_mlrval); + pentry->level_value.is_terminal = FALSE; + pentry->level_value.pnext_level = mlhmmv_level_alloc(); + } + // RECURSE + mlhmmv_level_put_terminal(pentry->level_value.pnext_level, prest_keys->pnext, pterminal_value); + } + + } else { + fprintf(stderr, "%s: mlhmmv_level_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0); + exit(1); + } +} + // ---------------------------------------------------------------- // xxx code-dup w/ mlhmmv_root_partial_to_lrecs and mlhmmv_root_all_to_lrecs void mlhmmv_level_to_lrecs(mlhmmv_level_t* plevel, sllmv_t* pkeys, sllmv_t* pnames, sllv_t* poutrecs, @@ -1376,107 +1477,6 @@ void mlhmmv_root_print_json_single_lines(mlhmmv_root_t* pmap, int quote_values_a static mlhmmv_level_t* mlhmmv_get_or_create_level_aux_no_enlarge(mlhmmv_level_t* plevel, sllmve_t* prest_keys); -// ---------------------------------------------------------------- -// Used by get() and remove(). -// Returns >=0 for where the key is *or* should go (end of chain). -static int mlhmmv_level_find_index_for_key(mlhmmv_level_t* plevel, mv_t* plevel_key, int* pideal_index) { - int hash = mlhmmv_hash_func(plevel_key); - int index = mlr_canonical_mod(hash, plevel->array_length); - *pideal_index = index; - int num_tries = 0; - - while (TRUE) { - mlhmmv_level_entry_t* pentry = &plevel->entries[index]; - if (plevel->states[index] == OCCUPIED) { - mv_t* ekey = &pentry->level_key; - // Existing key found in chain. - if (mv_equals_si(plevel_key, ekey)) - return index; - } else if (plevel->states[index] == EMPTY) { - return index; - } - - // If the current entry has been freed, i.e. previously occupied, - // the sought index may be further down the chain. So we must - // continue looking. - if (++num_tries >= plevel->array_length) { - fprintf(stderr, - "%s: Coding error: table full even after enlargement.\n", MLR_GLOBALS.bargv0); - exit(1); - } - - // Linear probing. - if (++index >= plevel->array_length) - index = 0; - } - MLR_INTERNAL_CODING_ERROR(); - return -1; // not reached -} - -// ---------------------------------------------------------------- -static void mlhmmv_level_put_terminal_no_enlarge(mlhmmv_level_t* plevel, sllmve_t* prest_keys, mv_t* pterminal_value) { - mv_t* plevel_key = &prest_keys->value; - int ideal_index = 0; - int index = mlhmmv_level_find_index_for_key(plevel, plevel_key, &ideal_index); - mlhmmv_level_entry_t* pentry = &plevel->entries[index]; - - if (plevel->states[index] == EMPTY) { // End of chain. - pentry->ideal_index = ideal_index; - pentry->level_key = mv_copy(plevel_key); - - if (prest_keys->pnext == NULL) { - pentry->level_value.is_terminal = TRUE; - pentry->level_value.terminal_mlrval = mv_copy(pterminal_value); - } else { - pentry->level_value.is_terminal = FALSE; - pentry->level_value.pnext_level = mlhmmv_level_alloc(); - } - plevel->states[index] = OCCUPIED; - - if (plevel->phead == NULL) { // First entry at this level - pentry->pprev = NULL; - pentry->pnext = NULL; - plevel->phead = pentry; - plevel->ptail = pentry; - } else { // Subsequent entry at this level - pentry->pprev = plevel->ptail; - pentry->pnext = NULL; - plevel->ptail->pnext = pentry; - plevel->ptail = pentry; - } - - plevel->num_occupied++; - if (prest_keys->pnext != NULL) { - // RECURSE - mlhmmv_level_put_terminal(pentry->level_value.pnext_level, prest_keys->pnext, pterminal_value); - } - - } else if (plevel->states[index] == OCCUPIED) { // Existing key found in chain - if (prest_keys->pnext == NULL) { // Place the terminal at this level - if (pentry->level_value.is_terminal) { - mv_free(&pentry->level_value.terminal_mlrval); - } else { - mlhmmv_level_free(pentry->level_value.pnext_level); - } - pentry->level_value.is_terminal = TRUE; - pentry->level_value.terminal_mlrval = mv_copy(pterminal_value); - - } else { // The terminal will be placed at a deeper level - if (pentry->level_value.is_terminal) { - mv_free(&pentry->level_value.terminal_mlrval); - pentry->level_value.is_terminal = FALSE; - pentry->level_value.pnext_level = mlhmmv_level_alloc(); - } - // RECURSE - mlhmmv_level_put_terminal(pentry->level_value.pnext_level, prest_keys->pnext, pterminal_value); - } - - } else { - fprintf(stderr, "%s: mlhmmv_level_find_index_for_key did not find end of chain\n", MLR_GLOBALS.bargv0); - exit(1); - } -} - // ---------------------------------------------------------------- static mlhmmv_level_t* mlhmmv_level_ref_or_create(mlhmmv_level_t* plevel, sllmve_t* prest_keys) { if ((plevel->num_occupied + plevel->num_freed) >= (plevel->array_length * LOAD_FACTOR))