}
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)
{
unsigned int n_left, n_right;
#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.
*/
}
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)
{
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);
}