melder_sort.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* NUMsort.cpp
  2. *
  3. * Copyright (C) 1992-2011,2015,2017,2018 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "melder.h"
  19. /*
  20. NUMsort uses heapsort.
  21. J.W.J. Williams (1964). 'xx.'
  22. Communications of the Association for Computing Machinery 7: 347-348.
  23. R.W. Floyd (1964). 'xx.'
  24. Communications of the Association for Computing Machinery 7: 701.
  25. Algorithm follows p. 145 of:
  26. Donald E. Knuth (1998): The art of computer programming. Third edition. Vol. 3: sorting and searching.
  27. Boston: Addison-Wesley.
  28. Modification: there is no distinction between record and key.
  29. */
  30. #define MACRO_NUMsort(DataType, dataExpression, CounterType, sizeExpression) \
  31. {/* scope */ \
  32. DataType *_x = dataExpression; \
  33. CounterType _n = sizeExpression; \
  34. if (_n < 2) return; /* Already sorted. */ \
  35. /* This `n < 2` step is absent from Press et al.'s implementation, */ \
  36. /* which will therefore not terminate on `if (_r == 1)`. */ \
  37. /* Knuth's initial assumption is now fulfilled: n >= 2. */ \
  38. if (_n == 2) { \
  39. if (_x [1] > _x [2]) { DataType _min = _x [2]; _x [2] = _x [1]; _x [1] = _min; } \
  40. } else if (_n <= 44) { \
  41. for (CounterType _i = 1; _i < _n; _i ++) { \
  42. DataType _min = _x [_i]; \
  43. CounterType _pmin = _i; \
  44. for (CounterType _j = _i + 1; _j <= _n; _j ++) if (_x [_j] < _min) { \
  45. _min = _x [_j]; \
  46. _pmin = _j; \
  47. } \
  48. _x [_pmin] = _x [_i]; \
  49. _x [_i] = _min; \
  50. } \
  51. } else { \
  52. CounterType _l = (_n >> 1) + 1; \
  53. CounterType _r = _n; \
  54. for (;;) { \
  55. DataType _k; \
  56. if (_l > 1) { \
  57. _l --; \
  58. _k = _x [_l]; \
  59. } else /* _l == 1 */ { \
  60. _k = _x [_r]; \
  61. _x [_r] = _x [1]; \
  62. _r --; \
  63. if (_r == 1) { _x [1] = _k; return; } \
  64. } \
  65. CounterType _j = _l; \
  66. CounterType _i; \
  67. for (;;) { \
  68. _i = _j; \
  69. _j = _j << 1; \
  70. if (_j > _r) break; \
  71. if (_j < _r && _x [_j] < _x [_j + 1]) _j ++; \
  72. if (_k >= _x [_j]) break; \
  73. _x [_i] = _x [_j]; \
  74. } \
  75. _x [_i] = _k; \
  76. } \
  77. } \
  78. }
  79. void VECsort_inplace (const VEC& x) noexcept {
  80. MACRO_NUMsort (double, x.at, integer, x.size)
  81. }
  82. void NUMsort_integer (integer n, integer a []) {
  83. MACRO_NUMsort (integer, a, integer, n)
  84. }
  85. void NUMsort_str (string32vector array) {
  86. char32 **a = array.at;
  87. integer n = array.size;
  88. integer l, r, j, i;
  89. char32 *k;
  90. if (n < 2) return;
  91. l = (n >> 1) + 1;
  92. r = n;
  93. for (;;) {
  94. if (l > 1) {
  95. l --;
  96. k = a [l];
  97. } else {
  98. k = a [r];
  99. a [r] = a [1];
  100. r --;
  101. if (r == 1) { a [1] = k; return; }
  102. }
  103. j = l;
  104. for (;;) {
  105. i = j;
  106. j = j << 1;
  107. if (j > r) break;
  108. if (j < r && str32cmp (a [j], a [j + 1]) < 0) j ++;
  109. if (str32cmp (k, a [j]) >= 0) break;
  110. a [i] = a [j];
  111. }
  112. a [i] = k;
  113. }
  114. }
  115. void NUMsort_p (integer n, void *a [], int (*compare) (const void *, const void *)) {
  116. integer l, r, j, i;
  117. void *k;
  118. if (n < 2) return;
  119. l = (n >> 1) + 1;
  120. r = n;
  121. for (;;) {
  122. if (l > 1) {
  123. l --;
  124. k = a [l];
  125. } else {
  126. k = a [r];
  127. a [r] = a [1];
  128. r --;
  129. if (r == 1) { a [1] = k; return; }
  130. }
  131. j = l;
  132. for (;;) {
  133. i = j;
  134. j = j << 1;
  135. if (j > r) break;
  136. if (j < r && compare (a [j], a [j + 1]) < 0) j ++;
  137. if (compare (k, a [j]) >= 0) break;
  138. a [i] = a [j];
  139. }
  140. a [i] = k;
  141. }
  142. }
  143. double NUMquantile (integer n, double a [], double factor) {
  144. double place = factor * n + 0.5;
  145. integer left = (integer) floor (place);
  146. if (n < 1) return 0.0;
  147. if (n == 1) return a [1];
  148. if (left < 1) left = 1;
  149. if (left >= n) left = n - 1;
  150. if (a [left + 1] == a [left]) return a [left];
  151. return a [left] + (place - left) * (a [left + 1] - a [left]);
  152. }
  153. double NUMquantile (const constVEC& a, double factor) noexcept {
  154. double place = factor * a.size + 0.5;
  155. integer left = (integer) floor (place);
  156. if (a.size < 1) return 0.0;
  157. if (a.size == 1) return a [1];
  158. if (left < 1) left = 1;
  159. if (left >= a.size) left = a.size - 1;
  160. if (a [left + 1] == a [left]) return a [left];
  161. return a [left] + (place - left) * (a [left + 1] - a [left]);
  162. }
  163. /* End of file NUMsort.cpp */