diff --git a/Makefile.am b/Makefile.am index 67c597de0..9117f57bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,6 +82,7 @@ include example/v4l2/Makefile.am ## include example/warp/Makefile.am include example/testing/Makefile.am include example/camera/Makefile.am +include example/sort/Makefile.am # revision control and ChangeLog ChangeLog: diff --git a/doc/release_notes.txt b/doc/release_notes.txt index a860aa400..cca1c7bd4 100644 --- a/doc/release_notes.txt +++ b/doc/release_notes.txt @@ -18,6 +18,9 @@ ### Functionality + - Rename, redesign and reactivate the priority queue functions. + - Merge new code to define and modify a camera object for graphics. + ## 2.8.7 We expect this to be a drop-in replacement for most use cases, but there are diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 23e68ce96..2708fb2e6 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -29,6 +29,7 @@ sc_example(function function/function.c) sc_example(logging logging/logging.c) sc_example(test_shmem testing/sc_test_shmem.c) sc_example(camera camera/camera.c) +sc_example(sort sort/sort.c) configure_file(options/sc_options_example.ini sc_options_example.ini COPYONLY) configure_file(options/sc_options_example.json sc_options_example.json COPYONLY) diff --git a/example/sort/Makefile.am b/example/sort/Makefile.am new file mode 100644 index 000000000..b83e99ff4 --- /dev/null +++ b/example/sort/Makefile.am @@ -0,0 +1,7 @@ + +# This file is part of the SC Library +# Makefile.am in example/sort +# included non-recursively from toplevel directory + +bin_PROGRAMS += example/sort/sc_sort +example_sort_sc_sort_SOURCES = example/sort/sort.c diff --git a/example/sort/sort.c b/example/sort/sort.c new file mode 100644 index 000000000..53ec45441 --- /dev/null +++ b/example/sort/sort.c @@ -0,0 +1,210 @@ +/* + This file is part of the SC Library. + The SC Library provides support for parallel scientific applications. + + Copyright (C) 2010 The University of Texas System + Additional copyright (C) 2011 individual authors + + The SC 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.1 of the License, or (at your option) any later version. + + The SC 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 the SC Library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +/* + * Demo program to exercise various sorting algorithms + */ + +#include +#include +#include + +typedef struct sc_sort +{ + sc_rand_state_t rstate; + int mpirank; + int mpisize; + int n; + int myself, mynext, myn; + int roundn; + sc_array_t *input; + sc_array_t *tosort; +} +sc_sort_t; + +static void +print_small (sc_sort_t *s, sc_array_t *a, const char *prefi) +{ + int i; + + SC_ASSERT (s != NULL); + SC_ASSERT (a != NULL); + SC_ASSERT (a->elem_size == sizeof (double)); + SC_ASSERT (a->elem_count == (size_t) s->myn); + + if (s->myn <= 10 && s->mpirank == 0) { + for (i = 0; i < s->myn; ++i) { + SC_INFOF ("%8s %d is %8.6f\n", prefi, i, + *(double *) sc_array_index_int (a, i)); + } + } +} + +static void +array_heapsort (sc_array_t *a, int (*compar) (const void *, const void *)) +{ + size_t esize; + size_t snn; + size_t sz; + char *temp; + + SC_ASSERT (a != NULL); + if ((snn = a->elem_count) <= 1) { + return; + } + esize = a->elem_size; + + /* reserve temporary element storage */ + temp = SC_ALLOC (char, esize); + + /* insert input variables into heap */ + for (sz = 1; sz < snn; ++sz) { + memcpy (temp, sc_array_index (a, sz), esize); + sc_array_pqueue_siftup (a, sz, temp, compar); + } + + /* remove maximum value one at a time */ + for (sz = snn - 1; sz > 0; --sz) { + memcpy (temp, sc_array_index (a, sz), esize); + memcpy (sc_array_index (a, sz), sc_array_index (a, 0), esize); + sc_array_pqueue_siftdown (a, sz, 0, temp, compar); + } + + /* free temporary element storage */ + SC_FREE (temp); +} + +static void +run_sort (sc_sort_t *s) +{ + int i; + + /* compute offset and count of elements assigned to rank */ + s->myself = (int) ((s->mpirank * (long) s->n) / s->mpisize); + s->mynext = (int) (((s->mpirank + 1) * (long) s->n) / s->mpisize); + s->myn = s->mynext - s->myself; + + /* initialize storage for items to sort */ + s->input = sc_array_new_count (sizeof (double), s->myn); + for (i = 0; i < s->myn; ++i) { + *(double *) sc_array_index_int (s->input, i) = + floor (s->roundn * sc_rand (&s->rstate)) / s->roundn; + } + + /* print for small output ranges */ + print_small (s, s->input, "Input"); + + /* initialize output array */ + s->tosort = sc_array_new (sizeof (double)); + + /* run quicksort for comparison */ + sc_array_copy (s->tosort, s->input); + sc_array_sort (s->tosort, sc_double_compare); + print_small (s, s->tosort, "Qsort"); + + /* run parallel sort in serial for comparison */ + sc_array_copy (s->tosort, s->input); + sc_psort (sc_MPI_COMM_SELF, + s->tosort->array, &s->tosort->elem_count, s->tosort->elem_size, + sc_double_compare); + print_small (s, s->tosort, "Psort"); + + /* run heapsort for comparison */ + sc_array_copy (s->tosort, s->input); + array_heapsort (s->tosort, sc_double_compare); + print_small (s, s->tosort, "Hsort"); + + /* release memory */ + sc_array_destroy (s->tosort); + sc_array_destroy (s->input); +} + +int +main (int argc, char **argv) +{ + sc_sort_t sort, *s = &sort; + int fail = 0; + int mpiret; + int help; + int first_arg; + size_t seed; + sc_options_t *opt; + + mpiret = sc_MPI_Init (&argc, &argv); + SC_CHECK_MPI (mpiret); + + sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_DEFAULT); + + mpiret = sc_MPI_Comm_size (sc_MPI_COMM_WORLD, &s->mpisize); + SC_CHECK_MPI (mpiret); + mpiret = sc_MPI_Comm_rank (sc_MPI_COMM_WORLD, &s->mpirank); + SC_CHECK_MPI (mpiret); + + opt = sc_options_new (argv[0]); + sc_options_add_int (opt, 'n', NULL, &s->n, 10, "Total number of items"); + sc_options_add_int (opt, 'r', NULL, &s->roundn, 1000, "Random rounded"); + sc_options_add_size_t (opt, 's', "seed", &seed, 0, "Random number seed"); + sc_options_add_switch (opt, 'h', "help", &help, "Show help information"); + + /* process command line options */ + first_arg = sc_options_parse (sc_package_id, SC_LP_INFO, opt, argc, argv); + if (!fail && first_arg < 0) { + SC_GLOBAL_LERROR ("Error in option parsing\n"); + fail = 1; + } + if (!fail && first_arg < argc) { + SC_GLOBAL_LERROR ("This program takes no arguments, just options\n"); + fail = 1; + } + if (!fail && s->n < 0) { + SC_GLOBAL_LERROR ("Parameter n must be non-negative\n"); + fail = 1; + } + if (!fail && s->roundn <= 0) { + SC_GLOBAL_LERROR ("Parameter r must be positive\n"); + fail = 1; + } + s->rstate = (sc_rand_state_t) (seed ^ (size_t) s->mpirank); + + /* execute main program action */ + if (fail) { + sc_options_print_usage (sc_package_id, SC_LP_ERROR, opt, NULL); + } + else { + if (help) { + sc_options_print_usage (sc_package_id, SC_LP_PRODUCTION, opt, NULL); + } + else { + sc_options_print_summary (sc_package_id, SC_LP_PRODUCTION, opt); + run_sort (s); + } + } + + sc_options_destroy (opt); + sc_finalize (); + + mpiret = sc_MPI_Finalize (); + SC_CHECK_MPI (mpiret); + + return fail ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/sc_containers.c b/src/sc_containers.c index 7510d6bac..8e92a1e23 100644 --- a/src/sc_containers.c +++ b/src/sc_containers.c @@ -653,114 +653,131 @@ sc_array_checksum (sc_array_t * array) } size_t -sc_array_pqueue_add (sc_array_t * array, void *temp, - int (*compar) (const void *, const void *)) +sc_array_pqueue_siftup (sc_array_t * array, size_t pos, void *newval, + int (*compar) (const void *, const void *)) { - int comp; - size_t parent, child, swaps; - const size_t size = array->elem_size; - void *p, *c; + size_t esize; + size_t swaps; + size_t parent; + void *Hparent; - /* this works on a pre-allocated array that is not a view */ + SC_ASSERT (array != NULL); SC_ASSERT (SC_ARRAY_IS_OWNER (array)); - SC_ASSERT (array->elem_count > 0); - - /* PQUEUE FUNCTIONS ARE UNTESTED AND CURRENTLY DISABLED. */ - SC_ABORT_NOT_REACHED (); + SC_ASSERT (pos < array->elem_count); + SC_ASSERT (newval != NULL); + SC_ASSERT (compar != NULL); + esize = array->elem_size; swaps = 0; - child = array->elem_count - 1; - c = array->array + (size * child); - while (child > 0) { - parent = (child - 1) / 2; - p = array->array + (size * parent); - - /* compare child to parent */ - comp = compar (p, c); - if (comp <= 0) { - break; + while (pos > 0) { + parent = (pos - 1) >> 1; + Hparent = sc_array_index (array, parent); + if (compar (newval, Hparent) > 0) { + memcpy (sc_array_index (array, pos), Hparent, esize); + pos = parent; + ++swaps; } - - /* swap child and parent */ - memcpy (temp, c, size); - memcpy (c, p, size); - memcpy (p, temp, size); - ++swaps; - - /* walk up the tree */ - child = parent; - c = p; + else + break; } - + memcpy (sc_array_index (array, pos), newval, esize); return swaps; } size_t -sc_array_pqueue_pop (sc_array_t * array, void *result, - int (*compar) (const void *, const void *)) +sc_array_pqueue_insert (sc_array_t * array, void *newval, + int (*compar) (const void *, const void *)) { - int comp; - size_t new_count, swaps; - size_t parent, child, child1; - const size_t size = array->elem_size; - void *p, *c, *c1; - void *temp; + size_t snn; - /* array must not be empty or a view */ + SC_ASSERT (array != NULL); SC_ASSERT (SC_ARRAY_IS_OWNER (array)); - SC_ASSERT (array->elem_count > 0); + SC_ASSERT (newval != NULL); + SC_ASSERT (compar != NULL); - /* PQUEUE FUNCTIONS ARE UNTESTED AND CURRENTLY DISABLED. */ - SC_ABORT_NOT_REACHED (); + snn = array->elem_count; + sc_array_push (array); + return sc_array_pqueue_siftup (array, snn, newval, compar); +} + +size_t +sc_array_pqueue_siftdown (sc_array_t * array, size_t snn, + size_t pos, void *newval, + int (*compar) (const void *, const void *)) +{ + size_t esize; + size_t swaps; + size_t child, child2; + void *Hchild, *Hchild2; + + SC_ASSERT (array != NULL); + SC_ASSERT (SC_ARRAY_IS_OWNER (array)); + SC_ASSERT (snn <= array->elem_count); + SC_ASSERT (pos < snn); + SC_ASSERT (newval != NULL); + SC_ASSERT (compar != NULL); + esize = array->elem_size; swaps = 0; - new_count = array->elem_count - 1; - - /* extract root */ - parent = 0; - p = array->array + (size * parent); - memcpy (result, p, size); - - /* copy the last element to the top and reuse it as temp storage */ - temp = array->array + (size * new_count); - if (new_count > 0) { - memcpy (p, temp, size); - } - - /* sift down the tree */ - while ((child = 2 * parent + 1) < new_count) { - c = array->array + (size * child); - - /* check if child has a sibling and use that one if it is smaller */ - if ((child1 = 2 * parent + 2) < new_count) { - c1 = array->array + (size * child1); - comp = compar (c, c1); - if (comp > 0) { - child = child1; - c = c1; + for (;;) { + child = (pos << 1) + 1; + if (child < snn) { + Hchild = sc_array_index (array, child); + child2 = child + 1; + if (child2 < snn) { + Hchild2 = sc_array_index (array, child2); + if (compar (Hchild, Hchild2) <= 0) { + child = child2; + Hchild = Hchild2; + } + } + if (compar (newval, Hchild) < 0) { + memcpy (sc_array_index (array, pos), Hchild, esize); + pos = child; + ++swaps; } + else + break; } - - /* sift down the parent if it is larger */ - comp = compar (p, c); - if (comp <= 0) { + else break; - } + } + memcpy (sc_array_index (array, pos), newval, esize); + return swaps; +} - /* swap child and parent */ - memcpy (temp, c, size); - memcpy (c, p, size); - memcpy (p, temp, size); - ++swaps; +size_t +sc_array_pqueue_pop (sc_array_t * array, void *newval, + int (*compar) (const void *, const void *)) +{ + size_t esize; + size_t snn; + size_t swaps; - /* walk down the tree */ - parent = child; - p = c; - } + SC_ASSERT (array != NULL); + SC_ASSERT (SC_ARRAY_IS_OWNER (array)); + SC_ASSERT (array->elem_count > 0); + SC_ASSERT (newval != NULL); + SC_ASSERT (compar != NULL); - /* we can resize down here only since we need the temp element above */ - sc_array_resize (array, new_count); + esize = array->elem_size; + snn = array->elem_count; + swaps = 0; + /* remove root from heap */ + memcpy (newval, sc_array_index (array, 0), esize); + if (snn == 1) { + sc_array_resize (array, 0); + } + else { + /* move last leaf to root and sift down */ + --snn; + swaps = sc_array_pqueue_siftdown + (array, snn, 0, sc_array_index (array, snn), compar); + + /* circumvent calling sc_array_pop */ + array->elem_count = snn; + } return swaps; } @@ -1787,15 +1804,16 @@ sc_recycle_array_remove (sc_recycle_array_t * rec_array, size_t position) /* definitions for inline functions */ -void *sc_array_index (sc_array_t * array, size_t iz); -void *sc_array_index_null (sc_array_t * array, size_t iz); -void *sc_array_index_int (sc_array_t * array, int i); -void *sc_array_index_long (sc_array_t * array, long l); -void *sc_array_index_ssize_t (sc_array_t * array, ssize_t is); -void *sc_array_index_int16 (sc_array_t * array, int16_t i16); -size_t sc_array_position (sc_array_t * array, void *element); -void *sc_array_pop (sc_array_t * array); -void *sc_array_push_count (sc_array_t * array, size_t add_count); -void *sc_array_push (sc_array_t * array); -void *sc_mempool_alloc (sc_mempool_t * mempool); -void sc_mempool_free (sc_mempool_t * mempool, void *elem); +void *sc_array_index (sc_array_t * array, size_t iz); +void *sc_array_index_null (sc_array_t * array, size_t iz); +void *sc_array_index_int (sc_array_t * array, int i); +void *sc_array_index_long (sc_array_t * array, long l); +void *sc_array_index_ssize_t (sc_array_t * array, ssize_t is); +void *sc_array_index_int16 (sc_array_t * array, int16_t i16); +size_t sc_array_position (sc_array_t * array, void *element); +void *sc_array_pop (sc_array_t * array); +void *sc_array_push_count (sc_array_t * array, + size_t add_count); +void *sc_array_push (sc_array_t * array); +void *sc_mempool_alloc (sc_mempool_t * mempool); +void sc_mempool_free (sc_mempool_t * mempool, void *elem); diff --git a/src/sc_containers.h b/src/sc_containers.h index 6eaeb74d5..1879a034c 100644 --- a/src/sc_containers.h +++ b/src/sc_containers.h @@ -111,7 +111,8 @@ typedef int (*sc_hash_foreach_t) (void **v, const void *u); * \ref sc_array_resize and \ref sc_array_rewind. * Elements can be sorted with \ref sc_array_sort. * If the array is sorted, it can be searched with \ref sc_array_bsearch. - * A priority queue is implemented with pqueue_add and pqueue_pop (untested). + * A maximum-first priority queue is implemented with \ref + * sc_array_pqueue_insert, \ref sc_array_pqueue_pop and further helpers. */ typedef struct sc_array { @@ -452,37 +453,73 @@ void sc_array_permute (sc_array_t * array, */ unsigned int sc_array_checksum (sc_array_t * array); -/** Adds an element to a priority queue. - * \note PQUEUE FUNCTIONS ARE UNTESTED AND CURRENTLY DISABLED. +/** Replace an element in a priority queue with another and sift up. + * The priority queue is implemented as a binary heap in descending order. + * It is a maximum heap: The largest values have highest priority. + * The new element is inserted at a given position and must not + * be less than the descendants below that position. * This function is not allowed for views. - * The priority queue is implemented as a heap in ascending order. - * A heap is a binary tree where the children are not less than their parent. - * Assumes that elements [0]..[elem_count-2] form a valid heap. - * Then propagates [elem_count-1] upward by swapping if necessary. - * \param [in,out] array Valid priority queue object. - * \param [in] temp Pointer to unused allocated memory of elem_size. - * \param [in] compar The comparison function to be used. - * \return Returns the number of swap operations. - * \note If the return value is zero for all elements in an array, - * the array is sorted linearly and unchanged. - */ -size_t sc_array_pqueue_add (sc_array_t * array, - void *temp, - int (*compar) (const void *, - const void *)); - -/** Pops the smallest element from a priority queue. - * \note PQUEUE FUNCTIONS ARE UNTESTED AND CURRENTLY DISABLED. + * \param [in,out] array Valid priority queue, not a view. + * \param [in] pos Valid position in priority queue. + * \param [in] newval Read-only storage of the new value. + * Must reside outside of the array. + * \param [in] compar A comparison function to be used. + * \return The number of swap operations. + */ +size_t sc_array_pqueue_siftup (sc_array_t * array, + size_t pos, void *newval, + int (*compar) (const void *, + const void *)); + +/** Add an element to a priority queue. + * The priority queue is implemented as a heap in descending order. + * It is a maximum heap: The largest values have highest priority. + * This function augments the priority queue by one element. + * This function is not allowed for views. + * \param [in,out] array Valid priority queue, not a view. + * Enlarged by one element. + * \param [in] newval Read-only storage of the new value. + * \param [in] compar A comparison function to be used. + * \return The number of swap operations. + */ +size_t sc_array_pqueue_insert (sc_array_t * array, void *newval, + int (*compar) (const void *, + const void *)); + +/** Replace an element in a priority queue with another and sift down. + * The priority queue is implemented as a binary heap in descending order. + * It is a maximum heap: The largest values have highest priority. + * The new element is inserted at a given position and must not be greater + * than its ancestors above that position. + * This function is not allowed for views. + * \param [in,out] array Valid priority queue, not a view. + * \param [in] maxcount Less or equal than \a array's element count. + * Work only with this amount of array elements. + * \param [in] pos Valid position less than \a maxcount. + * \param [in] newval Read-only storage of the new value. Must reside + * outside of the first maxcount array positions. + * \param [in] compar A comparison function to be used. + * \return The number of swap operations. + */ +size_t sc_array_pqueue_siftdown (sc_array_t * array, + size_t maxcount, + size_t pos, void *newval, + int (*compar) (const void *, + const void *)); + +/** Pop the largest element from a priority queue. + * The priority queue is implemented as a binary heap in descending order. + * It is a maximum heap: The largest values have highest priority. + * The root of the heap is removed and returned. * This function is not allowed for views. - * This function assumes that the array forms a valid heap in ascending order. - * \param [in,out] array Valid priority queue object. - * \param [out] result Pointer to unused allocated memory of elem_size. - * \param [in] compar The comparison function to be used. - * \return Returns the number of swap operations. - * \note This function resizes the array to elem_count-1. + * \param [in,out] array Valid priority queue, not a view. + * Shrunk by one element. + * \param [in] newval Storage for the maximum value removed. + * \param [in] compar A comparison function to be used. + * \return The number of swap operations. */ size_t sc_array_pqueue_pop (sc_array_t * array, - void *result, + void *newval, int (*compar) (const void *, const void *)); @@ -491,7 +528,7 @@ size_t sc_array_pqueue_pop (sc_array_t * array, * \param [in] iz Needs to be in [0]..[elem_count-1]. * \return Pointer to the indexed array element. */ -inline void * +inline void * sc_array_index (sc_array_t * array, size_t iz) { SC_ASSERT (iz < array->elem_count); @@ -505,7 +542,7 @@ sc_array_index (sc_array_t * array, size_t iz) * \return Pointer to the indexed array element or * NULL if the specified index is elem_count. */ -inline void * +inline void * sc_array_index_null (sc_array_t * array, size_t iz) { SC_ASSERT (iz <= array->elem_count); @@ -518,7 +555,7 @@ sc_array_index_null (sc_array_t * array, size_t iz) * \param [in] array Valid array. * \param [in] i Needs to be in [0]..[elem_count-1]. */ -inline void * +inline void * sc_array_index_int (sc_array_t * array, int i) { SC_ASSERT (i >= 0 && (size_t) i < array->elem_count); @@ -530,7 +567,7 @@ sc_array_index_int (sc_array_t * array, int i) * \param [in] array Valid array. * \param [in] l Needs to be in [0]..[elem_count-1]. */ -inline void * +inline void * sc_array_index_long (sc_array_t * array, long l) { SC_ASSERT (l >= 0 && (size_t) l < array->elem_count); @@ -542,7 +579,7 @@ sc_array_index_long (sc_array_t * array, long l) * \param [in] array Valid array. * \param [in] is Needs to be in [0]..[elem_count-1]. */ -inline void * +inline void * sc_array_index_ssize_t (sc_array_t * array, ssize_t is) { SC_ASSERT (is >= 0 && (size_t) is < array->elem_count); @@ -554,7 +591,7 @@ sc_array_index_ssize_t (sc_array_t * array, ssize_t is) * \param [in] array Valid array. * \param [in] i16 Needs to be in [0]..[elem_count-1]. */ -inline void * +inline void * sc_array_index_int16 (sc_array_t * array, int16_t i16) { SC_ASSERT (i16 >= 0 && (size_t) i16 < array->elem_count); @@ -586,7 +623,7 @@ sc_array_position (sc_array_t * array, void *element) * \return The pointer to the removed object. Will be valid * as long as no other function is called on this array. */ -inline void * +inline void * sc_array_pop (sc_array_t * array) { SC_ASSERT (SC_ARRAY_IS_OWNER (array)); @@ -599,7 +636,7 @@ sc_array_pop (sc_array_t * array) * This function is not allowed for views. * \return Returns a pointer to the uninitialized newly added elements. */ -inline void * +inline void * sc_array_push_count (sc_array_t * array, size_t add_count) { const size_t old_count = array->elem_count; @@ -621,7 +658,7 @@ sc_array_push_count (sc_array_t * array, size_t add_count) * This function is not allowed for views. * \return Returns a pointer to the uninitialized newly added element. */ -inline void * +inline void * sc_array_push (sc_array_t * array) { return sc_array_push_count (array, 1); @@ -775,7 +812,7 @@ void sc_mempool_truncate (sc_mempool_t * mempool); * Elements previously returned to the pool are recycled. * \return Returns a new or recycled element pointer. */ -inline void * +inline void * sc_mempool_alloc (sc_mempool_t * mempool) { void *ret; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ba59edbd3..ddd9a20ac 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,7 +7,7 @@ if(SC_HAVE_RANDOM AND SC_HAVE_SRANDOM) endif() if(SC_HAVE_UNISTD_H) - list(APPEND sc_tests sort) + list(APPEND sc_tests sort pqueue) endif() list(APPEND sc_tests builtin io_sink helpers) diff --git a/test/Makefile.am b/test/Makefile.am index 0ae79a29c..21d7d2762 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -16,14 +16,12 @@ sc_test_programs = \ test/sc_test_search \ test/sc_test_sort \ test/sc_test_sortb \ + test/sc_test_pqueue \ test/sc_test_version \ test/sc_test_helpers \ test/sc_test_mpi_pack \ test/sc_test_scda -## Reenable and properly verify pqueue when it is actually used -## test/sc_test_pqueue \ - check_PROGRAMS += $(sc_test_programs) test_sc_test_allgather_SOURCES = test/test_allgather.c @@ -34,12 +32,11 @@ test_sc_test_io_file_SOURCES = test/test_io_file.c test_sc_test_keyvalue_SOURCES = test/test_keyvalue.c test_sc_test_notify_SOURCES = test/test_notify.c test_sc_test_node_comm_SOURCES = test/test_node_comm.c -## Reenable and properly verify pqueue when it is actually used -## test_sc_test_pqueue_SOURCES = test/test_pqueue.c test_sc_test_reduce_SOURCES = test/test_reduce.c test_sc_test_search_SOURCES = test/test_search.c test_sc_test_sort_SOURCES = test/test_sort.c test_sc_test_sortb_SOURCES = test/test_sortb.c +test_sc_test_pqueue_SOURCES = test/test_pqueue.c test_sc_test_version_SOURCES = test/test_version.c test_sc_test_helpers_SOURCES = test/test_helpers.c test_sc_test_mpi_pack_SOURCES = test/test_mpi_pack.c diff --git a/test/test_pqueue.c b/test/test_pqueue.c index 93b295355..f7cb51281 100644 --- a/test/test_pqueue.c +++ b/test/test_pqueue.c @@ -23,15 +23,17 @@ #include -/* #define THEBIGTEST */ +#if 0 +#define THEBIGTEST +#endif static int -compar (const void *p1, const void *p2) +reverse_compare (const void *v1, const void *v2) { - int i1 = *(int *) p1; - int i2 = *(int *) p2; + const int i1 = *(int *) v1; + const int i2 = *(int *) v2; - return i1 - i2; + return i1 == i2 ? 0 : i1 < i2 ? +1 : -1; } int @@ -67,28 +69,28 @@ main (int argc, char **argv) swaps1 = swaps2 = swaps3 = 0; total1 = total2 = total3 = 0; for (i = 0; i < count; ++i) { - *(int *) sc_array_push (a1) = i; - s = sc_array_pqueue_add (a1, &temp, compar); + i1 = i; + s = sc_array_pqueue_insert (a1, &i1, reverse_compare); swaps1 += ((s > 0) ? 1 : 0); total1 += s; - *(int *) sc_array_push (a2) = count - i - 1; - s = sc_array_pqueue_add (a2, &temp, compar); + i2 = count - i - 1; + s = sc_array_pqueue_insert (a2, &i2, reverse_compare); swaps2 += ((s > 0) ? 1 : 0); total2 += s; - *(int *) sc_array_push (a3) = (15 * i) % 172; - s = sc_array_pqueue_add (a3, &temp, compar); + i3 = (15 * i) % 172; + s = sc_array_pqueue_insert (a3, &i3, reverse_compare); swaps3 += ((s > 0) ? 1 : 0); total3 += s; } - SC_CHECK_ABORT (swaps1 == 0 && total1 == 0, "pqueue_add"); + SC_CHECK_ABORT (swaps1 == 0 && total1 == 0, "pqueue_insert"); SC_VERBOSEF (" Swaps %lld %lld %lld Total %lld %lld %lld\n", (long long) swaps1, (long long) swaps2, (long long) swaps3, (long long) total1, (long long) total2, (long long) total3); temp = 52; - searched = sc_array_bsearch (a1, &temp, compar); + searched = sc_array_bsearch (a1, &temp, sc_int_compare); SC_CHECK_ABORT (searched != -1, "array_bsearch_index"); pi = (int *) sc_array_index_ssize_t (a1, searched); SC_CHECK_ABORT (*pi == temp, "array_bsearch"); @@ -97,15 +99,15 @@ main (int argc, char **argv) swaps1 = swaps2 = swaps3 = 0; total1 = total2 = total3 = 0; for (i = 0; i < count; ++i) { - s = sc_array_pqueue_pop (a1, &i1, compar); + s = sc_array_pqueue_pop (a1, &i1, reverse_compare); swaps1 += ((s > 0) ? 1 : 0); total1 += s; - s = sc_array_pqueue_pop (a2, &i2, compar); + s = sc_array_pqueue_pop (a2, &i2, reverse_compare); swaps2 += ((s > 0) ? 1 : 0); total2 += s; - s = sc_array_pqueue_pop (a3, &i3, compar); + s = sc_array_pqueue_pop (a3, &i3, reverse_compare); swaps3 += ((s > 0) ? 1 : 0); total3 += s; @@ -131,7 +133,7 @@ main (int argc, char **argv) for (i = 0; i < count; ++i) { *(int *) sc_array_push (a4) = (15 * i) % 172; } - sc_array_sort (a4, compar); + sc_array_sort (a4, sc_int_compare); i4last = -1; for (i = 0; i < count; ++i) {