algorithm.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include "pocketpy/common/algorithm.h"
  2. #include "pocketpy/config.h"
  3. #include <string.h>
  4. static bool _stable_sort_merge(char* a,
  5. char* a_end,
  6. char* b,
  7. char* b_end,
  8. char* r,
  9. int elem_size,
  10. int (*f_lt)(const void* a, const void* b, void* extra),
  11. void* extra) {
  12. while(a < a_end && b < b_end) {
  13. int res = f_lt(b, a, extra);
  14. // check error
  15. if(res == -1) return false;
  16. if(res == 0) { // !(b<a) -> (b>=a) -> (a<=b)
  17. memcpy(r, a, elem_size);
  18. a += elem_size;
  19. } else {
  20. memcpy(r, b, elem_size);
  21. b += elem_size;
  22. }
  23. r += elem_size;
  24. }
  25. // one of the arrays is empty
  26. for(; a < a_end; a += elem_size, r += elem_size)
  27. memcpy(r, a, elem_size);
  28. for(; b < b_end; b += elem_size, r += elem_size)
  29. memcpy(r, b, elem_size);
  30. return true;
  31. }
  32. bool c11__stable_sort(void* ptr_,
  33. int length,
  34. int elem_size,
  35. int (*f_lt)(const void* a, const void* b, void* extra),
  36. void* extra) {
  37. // merge sort
  38. char *ptr = ptr_, *tmp = PK_MALLOC(length * elem_size);
  39. for(int seg = 1; seg < length; seg *= 2) {
  40. for(char* a = ptr; a < ptr + (length - seg) * elem_size; a += 2 * seg * elem_size) {
  41. char *b = a + seg * elem_size, *a_end = b, *b_end = b + seg * elem_size;
  42. if(b_end > ptr + length * elem_size) b_end = ptr + length * elem_size;
  43. bool ok = _stable_sort_merge(a, a_end, b, b_end, tmp, elem_size, f_lt, extra);
  44. if(!ok) {
  45. PK_FREE(tmp);
  46. return false;
  47. }
  48. memcpy(a, tmp, b_end - a);
  49. }
  50. }
  51. PK_FREE(tmp);
  52. return true;
  53. }