X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/779fa3b8b270f1e62f58dfeb093e2b390d9c84b0..dd7a7135b956a02f4deed321d54b54d0a3f7844f:/src/xbt/dynar.c diff --git a/src/xbt/dynar.c b/src/xbt/dynar.c index 3e9cb2c2ec..7e7512bee2 100644 --- a/src/xbt/dynar.c +++ b/src/xbt/dynar.c @@ -238,6 +238,28 @@ XBT_INLINE void xbt_dynar_reset(xbt_dynar_t const dynar) _dynar_unlock(dynar); } +/** @brief Merge dynar d2 into d1 + * + * \param d1 dynar to keep + * \param d2 dynar to merge into d1. This dynar is free at end. + */ +void xbt_dynar_merge(xbt_dynar_t *d1, xbt_dynar_t *d2) +{ + if((*d1)->elmsize != (*d2)->elmsize) + xbt_die("Element size must are not equal"); + + const unsigned long elmsize = (*d1)->elmsize; + + void *ptr = _xbt_dynar_elm((*d2), 0); + _xbt_dynar_resize(*d1, (*d1)->size + (*d2)->size); + void *elm = _xbt_dynar_elm((*d1), (*d1)->used); + + memcpy(elm, ptr, ((*d2)->size)*elmsize); + (*d1)->used += (*d2)->used; + (*d2)->used = 0; + xbt_dynar_free(d2); +} + /** * \brief Shrink the dynar by removing empty slots at the end of the internal array * \param dynar a dynar @@ -291,7 +313,7 @@ XBT_INLINE unsigned long xbt_dynar_length(const xbt_dynar_t dynar) return (dynar ? (unsigned long) dynar->used : (unsigned long) 0); } -/**@brief check if a dynar is empty + /**@brief check if a dynar is empty * *\param dynar the dynat we want to check */ @@ -698,6 +720,54 @@ 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 size = xbt_dynar_length(dynar); + void *data = dynar->data; + unsigned long int i; + unsigned long int p = -1; + unsigned long int q = size; + unsigned long elmsize = dynar->elmsize; + void *tmp = xbt_malloc(elmsize); + +#define swap(a,b) do { \ + memcpy(tmp, a , elmsize); \ + memcpy( a , b , elmsize); \ + memcpy( b , tmp, elmsize); \ + } while(0) + + for (i = 0; i < q;) { + unsigned long int datai = ((unsigned long int) data) + i*elmsize; + int colori = color((void *) datai); + + if(colori==0) { + unsigned long int datap = ((unsigned long int) data) + (++p)*elmsize; + swap((void *) datai, (void *) datap); + ++i; + } else if (colori==2) { + unsigned long int dataq = ((unsigned long int) data) + (--q)*elmsize; + swap((void *) datai, (void *) dataq); + } else { + ++i; + } + } + _dynar_unlock(dynar); +} + /** @brief Transform a dynar into a NULL terminated array * * \param dynar the dynar to transform @@ -731,13 +801,13 @@ XBT_INLINE int xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2, } if((d1->elmsize)!=(d2->elmsize)) { - XBT_DEBUG("Size of elmsize d1=%ld d2=%ld",d1->elmsize,d2->elmsize); + XBT_DEBUG("Size of elmsize d1=%lu d2=%lu",d1->elmsize,d2->elmsize); xbt_dynar_free(&d2); return 1; // xbt_die } if(xbt_dynar_length(d1) != xbt_dynar_length(d2)) { - XBT_DEBUG("Size of dynar d1=%ld d2=%ld",xbt_dynar_length(d1),xbt_dynar_length(d2)); + XBT_DEBUG("Size of dynar d1=%lu d2=%lu",xbt_dynar_length(d1),xbt_dynar_length(d2)); xbt_dynar_free(&d2); return 1; } @@ -762,8 +832,7 @@ XBT_INLINE int xbt_dynar_compare(xbt_dynar_t d1, xbt_dynar_t d2, #define NB_ELEM 5000 XBT_TEST_SUITE("dynar", "Dynar data container"); -XBT_LOG_EXTERNAL_CATEGORY(xbt_dyn); -XBT_LOG_DEFAULT_CATEGORY(xbt_dyn); +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(xbt_dyn); XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers") { @@ -798,14 +867,14 @@ XBT_TEST_UNIT("int", test_dynar_int, "Dynars of integers") for (cursor = 0; cursor < NB_ELEM; cursor++) { iptr = xbt_dynar_get_ptr(d, cursor); xbt_test_assert(cursor == *iptr, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } /* 3. Traverse the dynar using the neat macro to that extend */ xbt_dynar_foreach(d, cursor, cpt) { xbt_test_assert(cursor == cpt, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } /* end_of_traversal */ @@ -937,7 +1006,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn /* 3. Traverse the dynar */ xbt_dynar_foreach(d, cursor, cpt) { xbt_test_assert(cursor == cpt, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } /* end_of_traversal */ @@ -947,14 +1016,14 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn xbt_dynar_set_as(d, cpt, int, cpt); xbt_dynar_foreach(d, cursor, cpt) xbt_test_assert(cursor == cpt, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); for (cpt = 0; cpt < NB_ELEM; cpt++) { int val; xbt_dynar_remove_at(d,0,&val); xbt_test_assert(cpt == val, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } xbt_test_assert(xbt_dynar_is_empty(d), @@ -973,7 +1042,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn /* 3. Traverse the dynar */ xbt_dynar_foreach(d, cursor, cpt) { xbt_test_assert(cursor == cpt, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } /* end_of_traversal */ @@ -982,7 +1051,7 @@ XBT_TEST_UNIT("insert",test_dynar_insert,"Using the xbt_dynar_insert and xbt_dyn int val; xbt_dynar_remove_at(d,xbt_dynar_length(d)-1,&val); xbt_test_assert(cpt == val, - "The retrieved value is not the same than the injected one (%d!=%d)", + "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt); } xbt_test_assert(xbt_dynar_is_empty(d), @@ -1179,7 +1248,7 @@ XBT_TEST_UNIT("string", test_dynar_string, "Dynars of strings") } /* 2. Traverse the dynar with the macro */ xbt_dynar_foreach(d, iter, s1) { - sprintf(buf, "%d", NB_ELEM - iter - 1); + sprintf(buf, "%u", NB_ELEM - iter - 1); xbt_test_assert(!strcmp(buf, s1), "The retrieved value is not the same than the injected one (%s!=%s)", buf, s1);