X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/ba773d1d2583d6907c3f28ea0c7fa035524cae87..3f8469006c8a8486904d2870733afabfb0d968a7:/src/xbt/dynar.c diff --git a/src/xbt/dynar.c b/src/xbt/dynar.c index 7e6f0152c6..2b6a2873d7 100644 --- a/src/xbt/dynar.c +++ b/src/xbt/dynar.c @@ -720,6 +720,53 @@ XBT_INLINE void xbt_dynar_sort(xbt_dynar_t dynar, _dynar_unlock(dynar); } +/** @brief Sorts a dynar according to their color assuming elements can have only three colors. + * Since there are only three colors, it is linear and much faster than a classical sort. + * See for example http://en.wikipedia.org/wiki/Dutch_national_flag_problem + * + * \param dynar the dynar to sort + * \param color the color function of type (int (compar_fn*) (void*) (void*)). The return value of color is assumed to be 0, 1, or 2. + * + * At the end of the call, elements with color 0 are at the beginning of the dynar, elements with color 2 are at the end and elements with color 1 are in the middle. + * + * Remark: if the elements stored in the dynar are structures, the color + * function has to retrieve the field to sort first. + */ +XBT_PUBLIC(void) xbt_dynar_three_way_partition(xbt_dynar_t const dynar, + int_f_pvoid_t color) +{ + _dynar_lock(dynar); + unsigned long int i; + unsigned long int p = -1; + unsigned long int q = dynar->used; + const unsigned long elmsize = dynar->elmsize; + void *tmp = xbt_malloc(elmsize); + void *elm; + + for (i = 0; i < q;) { + void *elmi = _xbt_dynar_elm(dynar, i); + int colori = color(elmi); + + if (colori == 1) { + ++i; + } else { + if (colori == 0) { + elm = _xbt_dynar_elm(dynar, ++p); + ++i; + } else { /* colori == 2 */ + elm = _xbt_dynar_elm(dynar, --q); + } + if (elm != elmi) { + memcpy(tmp, elm, elmsize); + memcpy(elm, elmi, elmsize); + memcpy(elmi, tmp, elmsize); + } + } + } + _dynar_unlock(dynar); + xbt_free(tmp); +} + /** @brief Transform a dynar into a NULL terminated array * * \param dynar the dynar to transform