You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kpat/freecell-solver/fcs_dm.c

147 lines
3.3 KiB

/*
fcs_dm.c - Freecell Solver's data management routines.
Written by Shlomi Fish, 2000
This file is distributed under the public domain.
(It's not copyrighted)
*/
#include <stddef.h>
#include <string.h>
#include "fcs_dm.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/*
freecell_solver_bsearch - an improved binary search function. Highlights:
* The comparison function accepts a common context argument that
is passed to SFO_bsearch.
* If the item was not found the function returns the place in which
it should be placed, while setting *found to 0. If it was found
(*found) is set to 1.
*/
void * freecell_solver_bsearch
(
void * key,
void * void_array,
size_t len,
size_t width,
int (* compare)(const void *, const void *, void *),
void * context,
int * found
)
{
int low = 0;
int high = len-1;
int mid;
int result;
char * array = void_array;
while (low <= high)
{
mid = ((low+high)>>1);
result = compare(key, (void*)(array+mid*width), context);
if (result < 0)
{
high = mid-1;
}
else if (result > 0)
{
low = mid+1;
}
else
{
*found = 1;
return (void*)(array+mid*width);
}
}
*found = 0;
return ((void*)(array+(high+1)*width));
}
/*
freecell_solver_merge_large_and_small_sorted_array - merges a large sorted
array with a small sorted array. The arrays could be of any length
whatsoever, but it works faster if the first is significantly bigger
than the second.
This function assumes that big_array is allocated with enough
space to hold the extra elements.
The array should be distinct or else there would be unexpected
results.
*/
int freecell_solver_merge_large_and_small_sorted_arrays
(
void * void_big_array,
size_t size_big_array,
void * void_small_array,
size_t size_small_array,
size_t width,
int (*compare) (const void *, const void *, void *),
void * context
)
{
int item_to_move, num_big_items_moved, pos;
char * pos_ptr;
char * big_array;
char * small_array;
int found;
int start_offset, end_offset;
big_array = (char*)void_big_array;
small_array = (char*)void_small_array;
num_big_items_moved = 0;
for(item_to_move = size_small_array-1 ; item_to_move>=0; item_to_move--)
{
pos_ptr = freecell_solver_bsearch (
small_array+item_to_move*width,
big_array,
size_big_array-num_big_items_moved,
width,
compare,
context,
&found
);
pos = (pos_ptr-big_array)/width;
end_offset = size_big_array + size_small_array -
num_big_items_moved -
(size_small_array-item_to_move-1);
start_offset = end_offset + pos -
(size_big_array - num_big_items_moved);
memmove(
big_array+start_offset*width,
big_array+pos*width,
(end_offset-start_offset)*width
);
memcpy(
big_array+(start_offset-1)*width,
small_array+item_to_move*width,
width
);
num_big_items_moved += (end_offset - start_offset);
}
return 1;
}