sort.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. *
  3. * Copyright (c) 2011, Jue Ruan <ruanjue@gmail.com>
  4. *
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef __SORT_RJ_H
  20. #define __SORT_RJ_H
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #define cmp_2nums_proc(a, b) if((a) < (b)) return -1; else if((a) > (b)) return 1;
  24. #define num_cmp_script(e1, e2, obj, val_macro) ((val_macro(e1, obj) == val_macro(e2, obj))? 0 : ((val_macro(e1, obj) < val_macro(e2, obj))? -1 : 1))
  25. #define cmpgt_2nums_proc(a, b) if((a) < (b)) return 0; else if((a) > (b)) return 1;
  26. #define define_bubble_sort(name, e_type, is_greater_func) \
  27. static inline void name(e_type* list, size_t size, void *ref){ \
  28. size_t i, j, n; \
  29. e_type t; \
  30. i = 0; \
  31. while(i < size){ \
  32. n = 0; \
  33. for(j=size-1;j>i;j--){ \
  34. if(is_greater_func(list[j-1], list[j], ref) > 0){ \
  35. t = list[j-1]; list[j-1] = list[j]; list[j] = t; \
  36. n = 1; \
  37. } \
  38. } \
  39. if(n == 0) break; \
  40. i ++; \
  41. } \
  42. if(ref == ref) return; \
  43. }
  44. #define bubble_sort_array(rs, size, e_type, is_a_greater_than_b) \
  45. do { \
  46. size_t bubble_i, bubble_j, bubble_n, bubble_size; \
  47. e_type a, b; \
  48. bubble_size = size; \
  49. for(bubble_i=0;bubble_i<bubble_size;bubble_i++){ \
  50. bubble_n = 0; \
  51. for(bubble_j=bubble_size-1;bubble_j>bubble_i;bubble_j--){ \
  52. a = (rs)[bubble_j - 1]; \
  53. b = (rs)[bubble_j]; \
  54. if((int)(is_a_greater_than_b) > 0){ \
  55. (rs)[bubble_j] = a; (rs)[bubble_j - 1] = b; \
  56. bubble_n = 1; \
  57. } \
  58. } \
  59. if(bubble_n == 0) break; \
  60. } \
  61. } while(0)
  62. #define divide_array(rs_ary, rs_size, e_type, is_a_greater_than_b, ret_val) \
  63. do { \
  64. e_type *_rs; \
  65. _rs = (e_type*)(rs_ary); \
  66. size_t s, e, i, j, m; \
  67. e_type p, t, a, b; \
  68. if((rs_size) < 2){ (ret_val) = 0; break; } \
  69. { \
  70. s = 0; \
  71. e = (rs_size) - 1; \
  72. m = s + (e - s) / 2; \
  73. a = _rs[s]; b = _rs[m]; \
  74. if(is_a_greater_than_b){ t = _rs[s]; _rs[s] = _rs[m]; _rs[m] = t; } \
  75. a = _rs[m]; b = _rs[e]; \
  76. if(is_a_greater_than_b){ \
  77. t = _rs[e]; _rs[e] = _rs[m]; _rs[m] = t; \
  78. a = _rs[s]; b = _rs[m]; \
  79. if(is_a_greater_than_b){ t = _rs[s]; _rs[s] = _rs[m]; _rs[m] = t; } \
  80. } \
  81. p = _rs[m]; \
  82. i = s + 1; j = e - 1; \
  83. while(1){ \
  84. a = p; \
  85. while(b = _rs[i], (is_a_greater_than_b)) i ++; \
  86. b = p; \
  87. while(a = _rs[j], (is_a_greater_than_b)) j --; \
  88. if(i < j){ \
  89. t = _rs[i]; _rs[i] = _rs[j]; _rs[j] = t; \
  90. i ++; j --; \
  91. } else break; \
  92. } \
  93. if(i == j){ i ++; j --; } \
  94. (ret_val) = i; \
  95. } \
  96. } while(0)
  97. #define sort_array(rs_ary, rs_size, e_type, is_a_greater_than_b) \
  98. do { \
  99. e_type *_rs; \
  100. _rs = (e_type*)(rs_ary); \
  101. size_t _qsort_n; \
  102. _qsort_n = rs_size; \
  103. size_t s, e, i, j, m, stack[64][2], x; \
  104. e_type p, t, a, b; \
  105. if(_qsort_n < 2) break; \
  106. x = 0; \
  107. stack[x][0] = 0; stack[x][1] = _qsort_n - 1; x ++; \
  108. while(x){ \
  109. x --; s = stack[x][0]; e = stack[x][1]; \
  110. m = s + (e - s) / 2; \
  111. a = _rs[s]; b = _rs[m]; \
  112. if(is_a_greater_than_b){ t = _rs[s]; _rs[s] = _rs[m]; _rs[m] = t; } \
  113. a = _rs[m]; b = _rs[e]; \
  114. if(is_a_greater_than_b){ \
  115. t = _rs[e]; _rs[e] = _rs[m]; _rs[m] = t; \
  116. a = _rs[s]; b = _rs[m]; \
  117. if(is_a_greater_than_b){ t = _rs[s]; _rs[s] = _rs[m]; _rs[m] = t; } \
  118. } \
  119. p = _rs[m]; \
  120. i = s + 1; j = e - 1; \
  121. while(1){ \
  122. a = p; \
  123. while(b = _rs[i], (is_a_greater_than_b)) i ++; \
  124. b = p; \
  125. while(a = _rs[j], (is_a_greater_than_b)) j --; \
  126. if(i < j){ \
  127. t = _rs[i]; _rs[i] = _rs[j]; _rs[j] = t; \
  128. i ++; j --; \
  129. } else break; \
  130. } \
  131. if(i == j){ i ++; j --; } \
  132. if(j - s > e - i){ \
  133. if(s + 4 < j){ stack[x][0] = s; stack[x][1] = j; x ++; } \
  134. if(i + 4 < e){ stack[x][0] = i; stack[x][1] = e; x ++; } \
  135. } else { \
  136. if(i + 4 < e){ stack[x][0] = i; stack[x][1] = e; x ++; } \
  137. if(s + 4 < j){ stack[x][0] = s; stack[x][1] = j; x ++; } \
  138. } \
  139. } \
  140. for(i=0;i<_qsort_n;i++){ \
  141. x = 0; \
  142. for(j=_qsort_n-1;j>i;j--){ \
  143. a = _rs[j - 1]; b = _rs[j]; \
  144. if(is_a_greater_than_b){ t = _rs[j - 1]; _rs[j - 1] = _rs[j]; _rs[j] = t; x = 1; } \
  145. } \
  146. if(x == 0) break; \
  147. } \
  148. } while(0)
  149. #define sort_array_adv(rs_size, is_a_greater_than_b, swap_expr) \
  150. do { \
  151. size_t _qsort_n; \
  152. _qsort_n = rs_size; \
  153. size_t s, e, i, j, m, stack[64][2], x, a, b; \
  154. if(_qsort_n < 2) break; \
  155. x = 0; \
  156. stack[x][0] = 0; stack[x][1] = _qsort_n - 1; x ++; \
  157. while(x){ \
  158. x --; s = stack[x][0]; e = stack[x][1]; \
  159. m = s + (e - s) / 2; \
  160. a = s; b = m; \
  161. if(is_a_greater_than_b){ swap_expr; } \
  162. a = m; b = e; \
  163. if(is_a_greater_than_b){ \
  164. swap_expr; \
  165. a = s; b = m; \
  166. if(is_a_greater_than_b){ swap_expr; } \
  167. } \
  168. i = s + 1; j = e - 1; \
  169. while(1){ \
  170. a = m; \
  171. while(b = i, (is_a_greater_than_b)) i ++; \
  172. b = m; \
  173. while(a = j, (is_a_greater_than_b)) j --; \
  174. if(i < j){ \
  175. if(m == i) m = j; \
  176. else if(m == j) m = i; \
  177. a = i; b = j; \
  178. swap_expr; \
  179. i ++; j --; \
  180. } else break; \
  181. } \
  182. if(i == j){ i ++; j --; } \
  183. if(s + 4 < j){ stack[x][0] = s; stack[x][1] = j; x ++; } \
  184. if(i + 4 < e){ stack[x][0] = i; stack[x][1] = e; x ++; } \
  185. } \
  186. for(i=0;i<_qsort_n;i++){ \
  187. x = 0; \
  188. for(j=_qsort_n-1;j>i;j--){ \
  189. a = j - 1; b = j; \
  190. if(is_a_greater_than_b){ swap_expr; x = 1; } \
  191. } \
  192. if(x == 0) break; \
  193. } \
  194. } while(0)
  195. // Must #include "thread.h" and "list.h"
  196. #define psort_array(rs_ary, rs_size, e_type, ncpu, is_a_greater_than_b) \
  197. do { \
  198. thread_beg_def(psrt); \
  199. e_type *rs; \
  200. size_t beg, end, div; \
  201. int divide; \
  202. thread_end_def(psrt); \
  203. thread_beg_func_inline(psrt); \
  204. thread_beg_loop(psrt); \
  205. if(psrt->divide){ \
  206. divide_array(psrt->rs + psrt->beg, psrt->end - psrt->beg, e_type, is_a_greater_than_b, psrt->div); \
  207. psrt->div += psrt->beg; \
  208. } else { \
  209. sort_array(psrt->rs + psrt->beg, psrt->end - psrt->beg, e_type, is_a_greater_than_b); \
  210. } \
  211. thread_end_loop(psrt); \
  212. thread_end_func(psrt); \
  213. thread_preprocess(psrt); \
  214. e_type *_rs; \
  215. _rs = (e_type*)(rs_ary); \
  216. size_t _qsort_n, _min_blk_size; \
  217. _qsort_n = rs_size; \
  218. _min_blk_size = _qsort_n / ncpu / 8; \
  219. if(_min_blk_size < 1024) _min_blk_size = 1024; \
  220. if(_qsort_n < ((uint32_t)(ncpu)) * 32){ \
  221. sort_array(rs_ary, rs_size, e_type, is_a_greater_than_b); \
  222. break; \
  223. } \
  224. thread_beg_init(psrt, (int)(ncpu)); \
  225. psrt->rs = _rs; psrt->beg = psrt->end = psrt->div = 0; psrt->divide = 0; \
  226. thread_end_init(psrt); \
  227. u64list *stacks[2]; \
  228. int x; \
  229. stacks[0] = init_u64list(32); \
  230. stacks[1] = init_u64list(32); \
  231. push_u64list(stacks[0], 0); \
  232. push_u64list(stacks[1], _qsort_n); \
  233. x = 0; \
  234. while(stacks[0]->size || x > 0){ \
  235. thread_waitfor_one_idle(psrt); \
  236. if(psrt->divide){ \
  237. if(psrt->div - psrt->beg <= psrt->end - psrt->div){ \
  238. push_u64list(stacks[0], psrt->beg); \
  239. push_u64list(stacks[1], psrt->div); \
  240. push_u64list(stacks[0], psrt->div); \
  241. push_u64list(stacks[1], psrt->end); \
  242. } else { \
  243. push_u64list(stacks[0], psrt->div); \
  244. push_u64list(stacks[1], psrt->end); \
  245. push_u64list(stacks[0], psrt->beg); \
  246. push_u64list(stacks[1], psrt->div); \
  247. } \
  248. x --; \
  249. psrt->divide = 0; \
  250. } else if(stacks[0]->size){ \
  251. psrt->beg = stacks[0]->buffer[--stacks[0]->size]; \
  252. psrt->end = stacks[1]->buffer[--stacks[1]->size]; \
  253. psrt->divide = (psrt->end - psrt->beg > _min_blk_size); \
  254. if(psrt->divide) x ++; \
  255. thread_wake(psrt); \
  256. } \
  257. } \
  258. thread_waitfor_all_idle(psrt); \
  259. thread_beg_close(psrt); \
  260. thread_end_close(psrt); \
  261. free_u64list(stacks[0]); \
  262. free_u64list(stacks[1]); \
  263. } while(0)
  264. #define quick_median_array(_rs, _rs_size, e_type, expr) \
  265. ({ \
  266. e_type key; \
  267. do { \
  268. e_type *rs; \
  269. rs = (e_type*)(_rs); \
  270. size_t size; \
  271. size = (size_t)(_rs_size); \
  272. size_t i, j, beg, mid, end; \
  273. if(size == 0){ \
  274. memset(&key, 0, sizeof(e_type)); \
  275. break; \
  276. } \
  277. beg = 0; \
  278. end = size - 1; \
  279. e_type tmp, a, b; \
  280. while(beg < end){ \
  281. mid = beg + (end - beg) / 2; \
  282. a = rs[beg]; b = rs[mid]; \
  283. if(expr){ tmp = rs[beg]; rs[beg] = rs[mid]; rs[mid] = tmp; } \
  284. a = rs[mid]; b = rs[end]; \
  285. if(expr){ \
  286. tmp = rs[end]; rs[end] = rs[mid]; rs[mid] = tmp; \
  287. a = rs[beg]; b = rs[mid]; \
  288. if(expr){ tmp = rs[beg]; rs[beg] = rs[mid]; rs[mid] = tmp; } \
  289. } \
  290. key = rs[mid]; \
  291. i = beg + 1; j = end - 1; \
  292. while(1){ \
  293. a = key; \
  294. while(b = rs[i], (expr)) i ++; \
  295. b = key; \
  296. while(a = rs[j], (expr)) j --; \
  297. if(i < j){ \
  298. tmp = rs[i]; rs[i] = rs[j]; rs[j] = tmp; \
  299. i ++; j --; \
  300. } else break; \
  301. } \
  302. if(i == j){ i ++; j --; } \
  303. if(i <= size / 2) beg = i; \
  304. else end = j; \
  305. } \
  306. key = rs[size/2]; \
  307. } while(0); \
  308. key; \
  309. })
  310. #define apply_array(rs, rs_size, e_type, expression) \
  311. do { \
  312. size_t _i, _rs_size; \
  313. e_type a; \
  314. _rs_size = rs_size; \
  315. for(_i=0;_i<_rs_size;_i++){ \
  316. a = (rs)[_i]; \
  317. expression; \
  318. } \
  319. } while(0)
  320. #define ref_apply_array(rs, rs_size, e_type, expression) \
  321. do { \
  322. size_t _i, _rs_size; \
  323. e_type *a; \
  324. _rs_size = rs_size; \
  325. for(_i=0;_i<_rs_size;_i++){ \
  326. a = (rs) + _i; \
  327. (expression); \
  328. } \
  329. } while(0)
  330. #define locate_array(rs, rs_size, e_type, expr) \
  331. ({ \
  332. size_t _i, _size; \
  333. e_type a; \
  334. _size = rs_size; \
  335. for(_i=0;_i<_size;_i++){ \
  336. a = rs[_i]; \
  337. if(expr) break; \
  338. }; \
  339. _i; \
  340. })
  341. // sort the array according to bool value (true then flase), and return the size of trues
  342. #define apply_xchg_array(rs, rs_size, e_type, expr) \
  343. ({ \
  344. size_t _i, _j, _size; \
  345. e_type a; \
  346. _size = rs_size; \
  347. for(_i=_j=0;_i<_size;_i++){ \
  348. a = (rs)[_i]; \
  349. if(!(expr)) continue; \
  350. if(_j < _i){ \
  351. a = (rs)[_j]; \
  352. (rs)[_j] = (rs)[_i]; \
  353. (rs)[_i] = a; \
  354. } \
  355. _j ++; \
  356. } \
  357. _j; \
  358. })
  359. #define define_quick_sort(name, e_type, is_greater_func) \
  360. static inline void name(e_type *rs, size_t n, void *obj){ \
  361. size_t s, e, i, j, m, stack[64][2], x; \
  362. e_type p, t; \
  363. if(n < 2) return; \
  364. x = 0; \
  365. stack[x][0] = 0; stack[x][1] = n - 1; x ++; \
  366. while(x){ \
  367. x --; s = stack[x][0]; e = stack[x][1]; \
  368. m = s + (e - s) / 2; \
  369. if(is_greater_func(rs[s], rs[m], obj) > 0){ t = rs[s]; rs[s] = rs[m]; rs[m] = t; } \
  370. if(is_greater_func(rs[m], rs[e], obj) > 0){ \
  371. t = rs[e]; rs[e] = rs[m]; rs[m] = t; \
  372. if(is_greater_func(rs[s], rs[m], obj) > 0){ t = rs[s]; rs[s] = rs[m]; rs[m] = t; } \
  373. } \
  374. p = rs[m]; \
  375. i = s + 1; j = e - 1; \
  376. while(1){ \
  377. while(is_greater_func(p, rs[i], obj) > 0) i ++; \
  378. while(is_greater_func(rs[j], p, obj) > 0) j --; \
  379. if(i < j){ \
  380. t = rs[i]; rs[i] = rs[j]; rs[j] = t; \
  381. i ++; j --; \
  382. } else break; \
  383. } \
  384. if(i == j){ i ++; j --; } \
  385. if(j - s > e - i){ \
  386. if(s + 4 < j){ stack[x][0] = s; stack[x][1] = j; x ++; } \
  387. if(i + 4 < e){ stack[x][0] = i; stack[x][1] = e; x ++; } \
  388. } else { \
  389. if(i + 4 < e){ stack[x][0] = i; stack[x][1] = e; x ++; } \
  390. if(s + 4 < j){ stack[x][0] = s; stack[x][1] = j; x ++; } \
  391. } \
  392. } \
  393. for(i=0;i<n;i++){ \
  394. x = 0; \
  395. for(j=n-1;j>i;j--){ \
  396. if(is_greater_func(rs[j - 1], rs[j], obj) > 0){ t = rs[j - 1]; rs[j - 1] = rs[j]; rs[j] = t; x = 1; } \
  397. } \
  398. if(x == 0) break; \
  399. } \
  400. if(obj == obj) return; \
  401. }
  402. #define define_merge(name, e_type, cmp_func, output_func) \
  403. static inline void name(e_type *list1, size_t size1, e_type *list2, size_t size2, void *ref){ \
  404. size_t i, j; \
  405. i = j = 0; \
  406. while(i < size1 && j < size2){ \
  407. if(cmp_func(list1[i], list2[j], ref) <= 0){ \
  408. output_func(list1[i], ref); \
  409. i ++; \
  410. } else { \
  411. output_func(list2[j], ref); \
  412. j ++; \
  413. } \
  414. } \
  415. while(i < size1){ output_func(list1[i++], ref); } \
  416. while(j < size2){ output_func(list2[j++], ref); } \
  417. } \
  418. \
  419. static inline size_t name##_files(FILE **files, int n, void *ref){ \
  420. e_type *es; \
  421. int *flags, i, min; \
  422. size_t ret; \
  423. ret = 0; \
  424. es = malloc(sizeof(e_type) * n); \
  425. flags = malloc(sizeof(int) * n); \
  426. for(i=0;i<n;i++) flags[i] = 0; \
  427. while(1){ \
  428. min = -1; \
  429. for(i=0;i<n;i++){ \
  430. if(flags[i] == 0){ \
  431. flags[i] = (fread(es + i, sizeof(e_type), 1, files[i]) == 1)? 1 : 2; \
  432. } \
  433. if(flags[i] == 1){ \
  434. if(min == -1){ \
  435. min = i; \
  436. } else if(cmp_func(es[i], es[min], ref) <= 0){ \
  437. min = i; \
  438. } \
  439. } \
  440. } \
  441. if(min == -1) break; \
  442. output_func(es[min], ref); \
  443. flags[min] = 0; \
  444. ret ++; \
  445. } \
  446. free(es); \
  447. free(flags); \
  448. return ret; \
  449. }
  450. #define define_unique_merge(name, e_type, cmp_func, output_func) \
  451. static inline void name(e_type *list1, size_t size1, e_type *list2, size_t size2, void *ref){ \
  452. size_t i, j; \
  453. i = j = 0; \
  454. while(i < size1 && j < size2){ \
  455. switch(cmp_func(list1[i], list2[j])){ \
  456. case 0: output_func(list1[i++], ref); j ++; break; \
  457. case -1: output_func(list1[i++], ref); break; \
  458. default: output_func(list2[j++], ref); \
  459. } \
  460. } \
  461. while(i < size1){ output_func(list1[i++], ref); } \
  462. while(j < size2){ output_func(list2[j++], ref); } \
  463. }
  464. #define reverse_array(_rs, _rs_size, e_type) \
  465. do { \
  466. size_t i, n; \
  467. n = (_rs_size); \
  468. e_type* __rs = (_rs); \
  469. e_type e; \
  470. for(i=0;i<n>>1;i++){ \
  471. e = __rs[i]; __rs[i] = __rs[n-1-i]; __rs[n-1-i] = e; \
  472. } \
  473. } while(0)
  474. #define define_reverse_array(name, e_type) \
  475. static inline void name(e_type *list, size_t size){ \
  476. size_t i, j; \
  477. e_type t; \
  478. if(size == 0) return; \
  479. i = 0; \
  480. j = size - 1; \
  481. while(i < j){ \
  482. t = list[i]; list[i] = list[j]; list[j] = t; \
  483. i ++; j --; \
  484. } \
  485. }
  486. #define define_apply_array(name, e_type, apply_func) \
  487. static inline size_t name(e_type *list, size_t size, void *ref){ \
  488. size_t i, ret; \
  489. ret = 0; \
  490. for(i=0;i<size;i++){ \
  491. ret += apply_func(list[i], ref); \
  492. } \
  493. return ret; \
  494. ref = NULL; \
  495. }
  496. #define define_search_array(name, e_type, cmp_func) \
  497. static inline long long name(e_type *array, long long size, e_type key, void *ref){ \
  498. long long i, j, m; \
  499. i = 0; \
  500. j = size; \
  501. while(i < j){ \
  502. m = i + (j - i) / 2; \
  503. if(cmp_func(array[m], key, ref) < 0){ \
  504. i = m + 1; \
  505. } else { \
  506. j = m; \
  507. } \
  508. } \
  509. if(i < size && cmp_func(array[i], key, ref) == 0) return i; \
  510. else return - (i + 1); \
  511. if(ref) return 0; \
  512. }
  513. #define bsearch_array(_rs_array, _rs_size, e_type, _bs_ret, is_a_less_than_your) \
  514. \
  515. do { \
  516. e_type*_bs_rs; \
  517. e_type a; \
  518. _bs_rs = (e_type*)(_rs_array); \
  519. size_t _bs_size; \
  520. _bs_size = _rs_size; \
  521. size_t _bs_i, _bs_j, _bs_m; \
  522. _bs_i = 0; \
  523. _bs_j = _bs_size; \
  524. while(_bs_i < _bs_j){ \
  525. _bs_m = _bs_i + (_bs_j - _bs_i) / 2; \
  526. a = _bs_rs[_bs_m]; \
  527. if(is_a_less_than_your){ \
  528. _bs_i = _bs_m + 1; \
  529. } else { \
  530. _bs_j = _bs_m; \
  531. } \
  532. } \
  533. _bs_ret = _bs_i; \
  534. } while(0)
  535. #endif