/* See {group_sort_uint32.h}. */ /* Last edited on 2016-04-17 10:02:23 by stolfilocal */ #define _GNU_SOURCE #include #include #include #include #include void group_sort_uint32 ( uint32_t ni, /* Number of integers to sort. */ uint32_t ng, /* Number of groups. */ uint32_t group[], /* Group assigned to each integer. */ uint32_t isort[], /* (OUT) Integers {0..ni-1} sorted by group. */ uint32_t gstart[] /* (OUT) Beg and end of each group in {isort}. */ ) { /* Determine the number of integers {gsize[ig]} in each group {ig}: */ uint32_t *gsize = notnull(malloc(ng*sizeof(uint32_t)), "no mem"); /* Num of integers in each group. */ uint32_t ig; for (ig = 0; ig < ng; ig++) { gsize[ig] = 0; } uint32_t it; for (it = 0; it < ni; it++) { ig = group[it]; assert(ig < ng); gsize[ig]++; } /* Compute the start {gstart[ig]} of each group in the {ix} list: */ gstart[0] = 0; for (ig = 0; ig < ng; ig++) { gstart[ig+1] = gstart[ig] + gsize[ig]; } /* Distribute each integer {0..ni-1} into the proper group {ig}, decrementing {gsize[ig]}. */ for (it = 0; it < ni; it++) { /* Get the group of integer {it}: */ ig = group[it]; /* At this point, {gsize[ig]} is how many faces are still missing in group {ig}. */ /* Store integer {it} in group {ig}, decrement {gsize}: */ assert((0 < gsize[ig]) && (gsize[ig] <= gstart[ig+1])); uint32_t k = gstart[ig+1] - gsize[ig]; /* First free {ix} slot in group {ig}. */ assert(k >= gstart[ig]); assert(k < ni); isort[k] = it; gsize[ig]--; } /* Paranoia check (should be in tests directory): */ for (ig = 0; ig < ng; ig++) { assert(gsize[ig] == 0); for (uint32_t k = gstart[ig]; k < gstart[ig+1]; k++) { assert(group[isort[k]] == ig); } } assert(gstart[ng] == ni); /* Cleanup: */ free(gsize); }