Conflicts:
	src/lib/eina/eina_list.c
	src/lib/eina/eina_types.h
This commit is contained in:
Jérémy Zurcher 2013-03-20 11:45:57 +01:00
parent b71a17b9db
commit d0f3357f77
3 changed files with 151 additions and 0 deletions

View File

@ -1094,6 +1094,85 @@ eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func)
return list;
}
EAPI Eina_List *
eina_list_shuffle(Eina_List *list, Eina_Random_Cb func)
{
unsigned int n, i, j;
Eina_List_Accounting *accounting;
Eina_List *shuffled_list, *shuffled_last, *li;
if (!list)
return NULL;
EINA_MAGIC_CHECK_LIST(list, NULL);
accounting = list->accounting;
n = accounting->count;
shuffled_list = shuffled_last = NULL;
if (n == 1)
return list;
while (n > 1)
{
if (func)
i = func(0, (n - 1));
else
i = (int) ((float)n*rand()/(RAND_MAX+1.0));
if(i == 0)
{
li = list;
list = list->next;
}
else if (i == (n - 1) || i == n)
{
li = accounting->last;
accounting->last = li->prev;
}
else
{
if (i > (n / 2))
for (j = n - 1,
li = accounting->last;
j!=i;
li = li->prev, j--);
else
for (j = 0,
li = list;
j!=i;
li = li->next, j++);
li->prev->next = li->next;
li->next->prev = li->prev;
}
n--;
if (shuffled_list == NULL)
{
li->prev = NULL;
shuffled_list = li;
shuffled_last = li;
}
else
{
shuffled_last->next = li;
li->prev = shuffled_last;
shuffled_last = li;
}
}
list->next = NULL;
list->prev = shuffled_last;
shuffled_last->next = list;
accounting->last = list;
shuffled_list->accounting = accounting;
return shuffled_list;
}
EAPI Eina_List *
eina_list_merge(Eina_List *left, Eina_List *right)
{

View File

@ -333,6 +333,21 @@ typedef int (*Eina_Compare_Cb)(const void *data1, const void *data2);
*/
#define EINA_COMPARE_CB(function) ((Eina_Compare_Cb)function)
/**
* @typedef Eina_Random_Cb
* Function used in shuffling functions. An integer betwen min and max
* inclusive must be returned.
*
* @since 1.8
*/
typedef int (*Eina_Random_Cb)(const int min, const int max);
/**
* @def EINA_RANDOM_CB
* Macro to cast to Eina_Random_Cb.
*/
#define EINA_RANDOM_CB(function) ((Eina_Random_Cb)function)
/**
* @typedef Eina_Each_Cb
* A callback type used when iterating over a container.

View File

@ -375,6 +375,62 @@ START_TEST(eina_test_list_split)
}
END_TEST
static int uicmp(const void *d1, const void *d2)
{
const unsigned int *a = d1;
const unsigned int *b = d2;
if(*a == *b) return 0;
if(*a > *b) return 1;
return -1;
}
#define SHUFFLE_SZ 100
#define SHUFFLE_N 100000
START_TEST(eina_test_shuffle)
{
double d;
unsigned int *p;
unsigned int i, j;
unsigned int n[SHUFFLE_SZ];
unsigned int rand_count[SHUFFLE_SZ];
Eina_List *list = NULL;
Eina_List *item = NULL;
eina_init();
for(i = 0; i < SHUFFLE_SZ; i++)
{
n[i] = i;
rand_count[i] = 0;
list = eina_list_append(list, &n[i]);
}
for(i = 0; i < SHUFFLE_N; i++)
{
list = eina_list_shuffle(list, NULL);
p = eina_list_nth(list, SHUFFLE_SZ/2);
rand_count[*p]++;
j = 0;
list = eina_list_sort(list, 0, (Eina_Compare_Cb)&uicmp);
EINA_LIST_FOREACH(list, item, p)
fail_if(*p != j++);
fail_if(j != SHUFFLE_SZ);
}
d = SHUFFLE_SZ/(float)(SHUFFLE_N);
for(i = 0; i < SHUFFLE_SZ; i++)
{
fail_if(rand_count[i]*d > 1.20f);
fail_if(rand_count[i]*d < 0.80f);
}
eina_shutdown();
}
END_TEST
void
eina_test_list(TCase *tc)
{
@ -382,4 +438,5 @@ eina_test_list(TCase *tc)
tcase_add_test(tc, eina_test_merge);
tcase_add_test(tc, eina_test_sorted_insert);
tcase_add_test(tc, eina_test_list_split);
tcase_add_test(tc, eina_test_shuffle);
}