const void * fc_solve_kaz_tree_alloc_insert(dict_t *dict, const void *key) #endif { dnode_t * from_bin; dnode_t * node; const void * ret; fcs_compact_allocator_t * allocator; allocator = &(dict->dict_allocator); if ((from_bin = dict->dict_recycle_bin) != NULL) { node = dict->dict_recycle_bin; dict->dict_recycle_bin = DNODE_NEXT(node); } else { node = (dnode_t *) fcs_compact_alloc_ptr(allocator, sizeof(*node)) ; } #ifdef NO_FC_SOLVE dnode_init(node, data); #else dnode_init(node); #endif if ((ret = fc_solve_kaz_tree_insert(dict, node, key))) { if (from_bin) { DNODE_NEXT(node) = dict->dict_recycle_bin; dict->dict_recycle_bin = node; } else { fcs_compact_alloc_release(allocator); } } return ret; }
DLLEXPORT int fc_solve_user_INTERNAL_is_fcc_new( enum fcs_dbm_variant_type_t local_variant, const char * init_state_str_proto, const char * start_state_str_proto, /* NULL-terminated */ const char * * min_states, /* NULL-terminated */ const char * * states_in_cache, fcs_bool_t * const out_is_fcc_new ) { fcs_state_keyval_pair_t init_state; fc_solve_delta_stater_t * delta; fcs_encoded_state_buffer_t enc_state; fcs_encoded_state_buffer_t start_enc_state; fcs_meta_compact_allocator_t meta_alloc; fcs_FCC_start_points_list_t start_points_list; dict_t * do_next_fcc_start_points_exist; dict_t * does_min_by_sorting_exist; fcs_compact_allocator_t temp_allocator; fcs_fcc_moves_seq_allocator_t moves_list_allocator; const int max_num_elements_in_cache = 1000000; fcs_lru_cache_t does_state_exist_in_any_FCC_cache; fcs_encoded_state_buffer_t min_by_sorting; fcs_fcc_moves_seq_t init_moves_seq; add_start_point_context_t add_start_point_context; void * tree_recycle_bin = NULL; DECLARE_IND_BUF_T(indirect_stacks_buffer) fc_solve_initial_user_state_to_c( init_state_str_proto, &init_state, FREECELLS_NUM, STACKS_NUM, DECKS_NUM, indirect_stacks_buffer ); delta = fc_solve_delta_stater_alloc( &(init_state.s), STACKS_NUM, FREECELLS_NUM #ifndef FCS_FREECELL_ONLY , FCS_SEQ_BUILT_BY_ALTERNATE_COLOR #endif ); fcs_init_and_encode_state( delta, local_variant, &(init_state), &enc_state ); fc_solve_state_string_to_enc( local_variant, delta, start_state_str_proto, &(start_enc_state) ); fc_solve_meta_compact_allocator_init( &meta_alloc ); start_points_list.list = NULL; start_points_list.recycle_bin = NULL; fc_solve_compact_allocator_init(&(start_points_list.allocator), &meta_alloc); do_next_fcc_start_points_exist = fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin); does_min_by_sorting_exist = fc_solve_kaz_tree_create(fc_solve_compare_encoded_states, NULL, &meta_alloc, &tree_recycle_bin); fc_solve_compact_allocator_init(&(temp_allocator), &meta_alloc); moves_list_allocator.recycle_bin = NULL; moves_list_allocator.allocator = &(temp_allocator); /* Populate does_min_by_sorting_exist from min_states */ { const char * * min_states_iter = min_states; for (; *(min_states_iter) ; min_states_iter++) { fcs_encoded_state_buffer_t * min_enc_state; min_enc_state = (fcs_encoded_state_buffer_t *) fcs_compact_alloc_ptr( &(temp_allocator), sizeof (*min_enc_state) ); fc_solve_state_string_to_enc( local_variant, delta, *(min_states_iter), min_enc_state ); fc_solve_kaz_tree_alloc_insert( does_min_by_sorting_exist, min_enc_state ); } } cache_init(&does_state_exist_in_any_FCC_cache, max_num_elements_in_cache, &meta_alloc); /* Populate does_state_exist_in_any_FCC_cache from states_in_cache */ { const char * * min_states_iter = states_in_cache; for (; *(min_states_iter) ; min_states_iter++) { fcs_encoded_state_buffer_t * min_enc_state; min_enc_state = (fcs_encoded_state_buffer_t *) fcs_compact_alloc_ptr( &(temp_allocator), sizeof (*min_enc_state) ); fc_solve_state_string_to_enc( local_variant, delta, *(min_states_iter), min_enc_state ); cache_insert (&does_state_exist_in_any_FCC_cache, min_enc_state, NULL, '\0'); } } init_moves_seq.moves_list = NULL; init_moves_seq.count = 0; add_start_point_context.do_next_fcc_start_points_exist = do_next_fcc_start_points_exist; add_start_point_context.next_start_points_list = &start_points_list; add_start_point_context.moves_list_allocator = &moves_list_allocator; { long num_new_positions_temp; perform_FCC_brfs( local_variant, &(init_state), start_enc_state, &init_moves_seq, fc_solve_add_start_point_in_mem, &add_start_point_context, out_is_fcc_new, &min_by_sorting, does_min_by_sorting_exist, &does_state_exist_in_any_FCC_cache, &num_new_positions_temp, &moves_list_allocator, &meta_alloc ); } fc_solve_compact_allocator_finish(&(start_points_list.allocator)); fc_solve_compact_allocator_finish(&(temp_allocator)); fc_solve_delta_stater_free (delta); fc_solve_kaz_tree_destroy(do_next_fcc_start_points_exist); fc_solve_kaz_tree_destroy(does_min_by_sorting_exist); cache_destroy(&does_state_exist_in_any_FCC_cache); fc_solve_meta_compact_allocator_finish( &meta_alloc ); return 0; }
static void GCC_INLINE fc_solve_cache_stacks( fc_solve_hard_thread_t * hard_thread, fcs_state_t * new_state_key, fcs_state_extra_info_t * new_state_val ) { int a; #if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE SFO_hash_value_t hash_value_int; #endif #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) PWord_t * PValue; #endif void * cached_stack; char * new_ptr; fc_solve_instance_t * instance = hard_thread->instance; #ifndef HARD_CODED_NUM_STACKS DECLARE_AND_SET_GAME_PARAMS(); #endif fcs_cards_column_t column; register int col_len; fcs_compact_allocator_t * stacks_allocator; stacks_allocator = &(hard_thread->allocator); for(a=0 ; a < LOCAL_STACKS_NUM ; a++) { /* * If the stack is not a copy - it is already cached so skip * to the next stack * */ if (! (new_state_val->stacks_copy_on_write_flags & (1 << a))) { continue; } column = fcs_state_get_col(*new_state_key, a); col_len = (fcs_col_len(column)+1); new_ptr = (char*)fcs_compact_alloc_ptr(stacks_allocator, col_len); memcpy(new_ptr, column, col_len); new_state_key->stacks[a] = new_ptr; #if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE /* Calculate the hash value for the stack */ /* This hash function was ripped from the Perl source code. * (It is not derived work however). */ { const char * s_ptr = (char*)(new_state_key->stacks[a]); const char * s_end = s_ptr+fcs_col_len(s_ptr)+1; hash_value_int = 0; while (s_ptr < s_end) { hash_value_int += (hash_value_int << 5) + *(s_ptr++); } hash_value_int += (hash_value_int >> 5); } if (hash_value_int < 0) { /* * This is a bit mask that nullifies the sign bit of the * number so it will always be positive * */ hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1))); } #endif { void * dummy; int verdict; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_hash_insert( &(instance->stacks_hash), column, column, &cached_stack, &dummy, perl_hash_function( (ub1 *)new_state_key->stacks[a], col_len ) #ifdef FCS_ENABLE_SECONDARY_HASH_VALUE , hash_value_int #endif ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GOOGLE_DENSE_HASH) { int verdict; void * dummy; column = fcs_state_get_col(*new_state_key, a); verdict = fc_solve_columns_google_hash_insert( instance->stacks_hash, column, column, &cached_stack, &dummy ); replace_with_cached(verdict); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL2_TREE) cached_stack = fcs_libavl2_stacks_tree_insert( instance->stacks_tree, new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE) cached_stack = (void *)rbsearch( new_state_key->stacks[a], instance->stacks_tree ); replace_with_cached(cached_stack != new_state_key->stacks[a]); #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE) cached_stack = g_tree_lookup( instance->stacks_tree, (gpointer)new_state_key->stacks[a] ); /* replace_with_cached contains an if statement */ replace_with_cached(cached_stack != NULL) else { g_tree_insert( instance->stacks_tree, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH) cached_stack = g_hash_table_lookup( instance->stacks_hash, (gconstpointer)new_state_key->stacks[a] ); replace_with_cached(cached_stack != NULL) else { g_hash_table_insert( instance->stacks_hash, (gpointer)new_state_key->stacks[a], (gpointer)new_state_key->stacks[a] ); } #elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY) column = fcs_state_get_col(*new_state_key, a); JHSI( PValue, instance->stacks_judy_array, column, (1+fcs_col_len(column)) ); /* later_todo : Handle out-of-memory. */ if (*PValue == 0) { /* A new stack */ *PValue = (PWord_t)column; } else { cached_stack = (void *)(*PValue); replace_with_cached(1); } #else #error FCS_STACK_STORAGE is not set to a good value. #endif } }