/*
* Copyright © 2020 Benjamin Otte
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library . If not , see < http : //www.gnu.org/licenses/>.
*/
#include <locale.h>
#include <gtk/gtk.h>
#include "gtk/timsort/gtktimsortprivate.h"
#define assert_sort_equal(a, b, size, n) \
g_assert_cmpmem (a, sizeof (size) * n, b, sizeof (size) * n)
static int
compare_int (gconstpointer a,
gconstpointer b,
gpointer unused)
{
int ia = *(const int *) a;
int ib = *(const int *) b;
return ia < ib ? -1 : (ia > ib);
}
static int
compare_pointer (gconstpointer a,
gconstpointer b,
gpointer unused)
{
gpointer pa = *(const gpointer *) a;
gpointer pb = *(const gpointer *) b;
return pa < pb ? -1 : (pa > pb);
}
G_GNUC_UNUSED static void
dump (int *a,
gsize n)
{
gsize i;
for (i = 0 ; i < n; i++)
{
if (i)
g_print(", " );
g_print ("%d" , a[i]);
}
g_print ("\n" );
}
static void
run_comparison (gpointer a,
gsize n,
gsize element_size,
GCompareDataFunc compare_func,
gpointer data)
{
gint64 start, mid, end;
gpointer b;
g_assert_cmpint (n, <=, G_MAXSIZE / element_size);
b = g_memdup2 (a, element_size * n);
start = g_get_monotonic_time ();
gtk_tim_sort (a, n, element_size, compare_func, data);
mid = g_get_monotonic_time ();
g_sort_array (b, n, element_size, compare_func, data);
end = g_get_monotonic_time ();
g_test_message ("%zu items in %uus vs %uus (%u%%)" ,
n,
(guint) (mid - start),
(guint) (end - mid),
(guint) (100 * (mid - start) / MAX (1 , end - mid)));
assert_sort_equal (a, b, int , n);
g_free (b);
}
static void
test_integers (void )
{
int *a;
gsize i, n, run;
a = g_new (int , 1000 );
for (run = 0 ; run < 10 ; run++)
{
n = g_test_rand_int_range (0 , 1000 );
for (i = 0 ; i < n; i++)
a[i] = g_test_rand_int ();
run_comparison (a, n, sizeof (int ), compare_int, NULL);
}
g_free (a);
}
static void
test_integers_runs (void )
{
int *a;
gsize i, j, n, run;
a = g_new (int , 1000 );
for (run = 0 ; run < 10 ; run++)
{
n = g_test_rand_int_range (0 , 1000 );
for (i = 0 ; i < n; i++)
{
a[i] = g_test_rand_int ();
j = i + g_test_rand_int_range (0 , 20 );
j = MIN (n, j);
if (g_test_rand_bit ())
{
for (i++; i < j; i++)
a[i] = a[i - 1 ] + 1 ;
}
else
{
for (i++; i < j; i++)
a[i] = a[i - 1 ] - 1 ;
}
}
run_comparison (a, n, sizeof (int ), compare_int, NULL);
}
g_free (a);
}
static void
test_integers_huge (void )
{
int *a;
gsize i, n;
n = g_test_rand_int_range (2 * 1000 * 1000 , 5 * 1000 * 1000 );
a = g_new (int , n);
for (i = 0 ; i < n; i++)
a[i] = g_test_rand_int ();
run_comparison (a, n, sizeof (int ), compare_int, NULL);
g_free (a);
}
static void
test_pointers (void )
{
gpointer *a;
gsize i, n, run;
a = g_new (gpointer, 1000 );
for (run = 0 ; run < 10 ; run++)
{
n = g_test_rand_int_range (0 , 1000 );
for (i = 0 ; i < n; i++)
a[i] = GINT_TO_POINTER (g_test_rand_int ());
run_comparison (a, n, sizeof (gpointer), compare_pointer, NULL);
}
g_free (a);
}
static void
test_pointers_huge (void )
{
gpointer *a;
gsize i, n;
n = g_test_rand_int_range (2 * 1000 * 1000 , 5 * 1000 * 1000 );
a = g_new (gpointer, n);
for (i = 0 ; i < n; i++)
a[i] = GINT_TO_POINTER (g_test_rand_int ());
run_comparison (a, n, sizeof (gpointer), compare_pointer, NULL);
g_free (a);
}
static void
test_steps (void )
{
GtkTimSortRun change;
GtkTimSort sort;
int *a, *b;
gsize i, n;
n = g_test_rand_int_range (20 * 1000 , 50 * 1000 );
a = g_new (int , n);
for (i = 0 ; i < n; i++)
a[i] = g_test_rand_int ();
b = g_memdup2 (a, sizeof (int ) * n);
gtk_tim_sort_init (&sort, a, n, sizeof (int ), compare_int, NULL);
gtk_tim_sort_set_max_merge_size (&sort, g_test_rand_int_range (512 , 2048 ));
while (gtk_tim_sort_step (&sort, &change))
{
if (change.len)
{
int *a_start = change.base;
int *b_start = b + ((int *) change.base - a);
g_assert_cmpint (a_start[0 ], !=, b_start[0 ]);
g_assert_cmpint (a_start[change.len - 1 ], !=, b_start[change.len - 1 ]);
memcpy (b_start, a_start, change.len * sizeof (int ));
}
assert_sort_equal (a, b, int , n);
}
g_sort_array (b, n, sizeof (int ), compare_int, NULL);
assert_sort_equal (a, b, int , n);
gtk_tim_sort_finish (&sort);
g_free (b);
g_free (a);
}
int
main (int argc, char *argv[])
{
(g_test_init) (&argc, &argv, NULL);
setlocale (LC_ALL, "C" );
g_test_add_func ("/timsort/integers" , test_integers);
g_test_add_func ("/timsort/integers/runs" , test_integers_runs);
g_test_add_func ("/timsort/integers/huge" , test_integers_huge);
g_test_add_func ("/timsort/pointers" , test_pointers);
g_test_add_func ("/timsort/pointers/huge" , test_pointers_huge);
g_test_add_func ("/timsort/steps" , test_steps);
return g_test_run ();
}
Messung V0.5 in Prozent C=99 H=89 G=94
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet am 2026-07-03)
¤
*© Formatika GbR, Deutschland