bit_util.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #include "test/jemalloc_test.h"
  2. #include "jemalloc/internal/bit_util.h"
  3. #define TEST_POW2_CEIL(t, suf, pri) do { \
  4. unsigned i, pow2; \
  5. t x; \
  6. \
  7. expect_##suf##_eq(pow2_ceil_##suf(0), 0, "Unexpected result"); \
  8. \
  9. for (i = 0; i < sizeof(t) * 8; i++) { \
  10. expect_##suf##_eq(pow2_ceil_##suf(((t)1) << i), ((t)1) \
  11. << i, "Unexpected result"); \
  12. } \
  13. \
  14. for (i = 2; i < sizeof(t) * 8; i++) { \
  15. expect_##suf##_eq(pow2_ceil_##suf((((t)1) << i) - 1), \
  16. ((t)1) << i, "Unexpected result"); \
  17. } \
  18. \
  19. for (i = 0; i < sizeof(t) * 8 - 1; i++) { \
  20. expect_##suf##_eq(pow2_ceil_##suf((((t)1) << i) + 1), \
  21. ((t)1) << (i+1), "Unexpected result"); \
  22. } \
  23. \
  24. for (pow2 = 1; pow2 < 25; pow2++) { \
  25. for (x = (((t)1) << (pow2-1)) + 1; x <= ((t)1) << pow2; \
  26. x++) { \
  27. expect_##suf##_eq(pow2_ceil_##suf(x), \
  28. ((t)1) << pow2, \
  29. "Unexpected result, x=%"pri, x); \
  30. } \
  31. } \
  32. } while (0)
  33. TEST_BEGIN(test_pow2_ceil_u64) {
  34. TEST_POW2_CEIL(uint64_t, u64, FMTu64);
  35. }
  36. TEST_END
  37. TEST_BEGIN(test_pow2_ceil_u32) {
  38. TEST_POW2_CEIL(uint32_t, u32, FMTu32);
  39. }
  40. TEST_END
  41. TEST_BEGIN(test_pow2_ceil_zu) {
  42. TEST_POW2_CEIL(size_t, zu, "zu");
  43. }
  44. TEST_END
  45. void
  46. expect_lg_ceil_range(size_t input, unsigned answer) {
  47. if (input == 1) {
  48. expect_u_eq(0, answer, "Got %u as lg_ceil of 1", answer);
  49. return;
  50. }
  51. expect_zu_le(input, (ZU(1) << answer),
  52. "Got %u as lg_ceil of %zu", answer, input);
  53. expect_zu_gt(input, (ZU(1) << (answer - 1)),
  54. "Got %u as lg_ceil of %zu", answer, input);
  55. }
  56. void
  57. expect_lg_floor_range(size_t input, unsigned answer) {
  58. if (input == 1) {
  59. expect_u_eq(0, answer, "Got %u as lg_floor of 1", answer);
  60. return;
  61. }
  62. expect_zu_ge(input, (ZU(1) << answer),
  63. "Got %u as lg_floor of %zu", answer, input);
  64. expect_zu_lt(input, (ZU(1) << (answer + 1)),
  65. "Got %u as lg_floor of %zu", answer, input);
  66. }
  67. TEST_BEGIN(test_lg_ceil_floor) {
  68. for (size_t i = 1; i < 10 * 1000 * 1000; i++) {
  69. expect_lg_ceil_range(i, lg_ceil(i));
  70. expect_lg_ceil_range(i, LG_CEIL(i));
  71. expect_lg_floor_range(i, lg_floor(i));
  72. expect_lg_floor_range(i, LG_FLOOR(i));
  73. }
  74. for (int i = 10; i < 8 * (1 << LG_SIZEOF_PTR) - 5; i++) {
  75. for (size_t j = 0; j < (1 << 4); j++) {
  76. size_t num1 = ((size_t)1 << i)
  77. - j * ((size_t)1 << (i - 4));
  78. size_t num2 = ((size_t)1 << i)
  79. + j * ((size_t)1 << (i - 4));
  80. expect_zu_ne(num1, 0, "Invalid lg argument");
  81. expect_zu_ne(num2, 0, "Invalid lg argument");
  82. expect_lg_ceil_range(num1, lg_ceil(num1));
  83. expect_lg_ceil_range(num1, LG_CEIL(num1));
  84. expect_lg_ceil_range(num2, lg_ceil(num2));
  85. expect_lg_ceil_range(num2, LG_CEIL(num2));
  86. expect_lg_floor_range(num1, lg_floor(num1));
  87. expect_lg_floor_range(num1, LG_FLOOR(num1));
  88. expect_lg_floor_range(num2, lg_floor(num2));
  89. expect_lg_floor_range(num2, LG_FLOOR(num2));
  90. }
  91. }
  92. }
  93. TEST_END
  94. #define TEST_FFS(t, suf, test_suf, pri) do { \
  95. for (unsigned i = 0; i < sizeof(t) * 8; i++) { \
  96. for (unsigned j = 0; j <= i; j++) { \
  97. for (unsigned k = 0; k <= j; k++) { \
  98. t x = (t)1 << i; \
  99. x |= (t)1 << j; \
  100. x |= (t)1 << k; \
  101. expect_##test_suf##_eq(ffs_##suf(x), k, \
  102. "Unexpected result, x=%"pri, x); \
  103. } \
  104. } \
  105. } \
  106. } while(0)
  107. TEST_BEGIN(test_ffs_u) {
  108. TEST_FFS(unsigned, u, u,"u");
  109. }
  110. TEST_END
  111. TEST_BEGIN(test_ffs_lu) {
  112. TEST_FFS(unsigned long, lu, lu, "lu");
  113. }
  114. TEST_END
  115. TEST_BEGIN(test_ffs_llu) {
  116. TEST_FFS(unsigned long long, llu, qd, "llu");
  117. }
  118. TEST_END
  119. TEST_BEGIN(test_ffs_u32) {
  120. TEST_FFS(uint32_t, u32, u32, FMTu32);
  121. }
  122. TEST_END
  123. TEST_BEGIN(test_ffs_u64) {
  124. TEST_FFS(uint64_t, u64, u64, FMTu64);
  125. }
  126. TEST_END
  127. TEST_BEGIN(test_ffs_zu) {
  128. TEST_FFS(size_t, zu, zu, "zu");
  129. }
  130. TEST_END
  131. #define TEST_FLS(t, suf, test_suf, pri) do { \
  132. for (unsigned i = 0; i < sizeof(t) * 8; i++) { \
  133. for (unsigned j = 0; j <= i; j++) { \
  134. for (unsigned k = 0; k <= j; k++) { \
  135. t x = (t)1 << i; \
  136. x |= (t)1 << j; \
  137. x |= (t)1 << k; \
  138. expect_##test_suf##_eq(fls_##suf(x), i, \
  139. "Unexpected result, x=%"pri, x); \
  140. } \
  141. } \
  142. } \
  143. } while(0)
  144. TEST_BEGIN(test_fls_u) {
  145. TEST_FLS(unsigned, u, u,"u");
  146. }
  147. TEST_END
  148. TEST_BEGIN(test_fls_lu) {
  149. TEST_FLS(unsigned long, lu, lu, "lu");
  150. }
  151. TEST_END
  152. TEST_BEGIN(test_fls_llu) {
  153. TEST_FLS(unsigned long long, llu, qd, "llu");
  154. }
  155. TEST_END
  156. TEST_BEGIN(test_fls_u32) {
  157. TEST_FLS(uint32_t, u32, u32, FMTu32);
  158. }
  159. TEST_END
  160. TEST_BEGIN(test_fls_u64) {
  161. TEST_FLS(uint64_t, u64, u64, FMTu64);
  162. }
  163. TEST_END
  164. TEST_BEGIN(test_fls_zu) {
  165. TEST_FLS(size_t, zu, zu, "zu");
  166. }
  167. TEST_END
  168. TEST_BEGIN(test_fls_u_slow) {
  169. TEST_FLS(unsigned, u_slow, u,"u");
  170. }
  171. TEST_END
  172. TEST_BEGIN(test_fls_lu_slow) {
  173. TEST_FLS(unsigned long, lu_slow, lu, "lu");
  174. }
  175. TEST_END
  176. TEST_BEGIN(test_fls_llu_slow) {
  177. TEST_FLS(unsigned long long, llu_slow, qd, "llu");
  178. }
  179. TEST_END
  180. static unsigned
  181. popcount_byte(unsigned byte) {
  182. int count = 0;
  183. for (int i = 0; i < 8; i++) {
  184. if ((byte & (1 << i)) != 0) {
  185. count++;
  186. }
  187. }
  188. return count;
  189. }
  190. static uint64_t
  191. expand_byte_to_mask(unsigned byte) {
  192. uint64_t result = 0;
  193. for (int i = 0; i < 8; i++) {
  194. if ((byte & (1 << i)) != 0) {
  195. result |= ((uint64_t)0xFF << (i * 8));
  196. }
  197. }
  198. return result;
  199. }
  200. #define TEST_POPCOUNT(t, suf, pri_hex) do { \
  201. t bmul = (t)0x0101010101010101ULL; \
  202. for (unsigned i = 0; i < (1 << sizeof(t)); i++) { \
  203. for (unsigned j = 0; j < 256; j++) { \
  204. /* \
  205. * Replicate the byte j into various \
  206. * bytes of the integer (as indicated by the \
  207. * mask in i), and ensure that the popcount of \
  208. * the result is popcount(i) * popcount(j) \
  209. */ \
  210. t mask = (t)expand_byte_to_mask(i); \
  211. t x = (bmul * j) & mask; \
  212. expect_u_eq( \
  213. popcount_byte(i) * popcount_byte(j), \
  214. popcount_##suf(x), \
  215. "Unexpected result, x=0x%"pri_hex, x); \
  216. } \
  217. } \
  218. } while (0)
  219. TEST_BEGIN(test_popcount_u) {
  220. TEST_POPCOUNT(unsigned, u, "x");
  221. }
  222. TEST_END
  223. TEST_BEGIN(test_popcount_u_slow) {
  224. TEST_POPCOUNT(unsigned, u_slow, "x");
  225. }
  226. TEST_END
  227. TEST_BEGIN(test_popcount_lu) {
  228. TEST_POPCOUNT(unsigned long, lu, "lx");
  229. }
  230. TEST_END
  231. TEST_BEGIN(test_popcount_lu_slow) {
  232. TEST_POPCOUNT(unsigned long, lu_slow, "lx");
  233. }
  234. TEST_END
  235. TEST_BEGIN(test_popcount_llu) {
  236. TEST_POPCOUNT(unsigned long long, llu, "llx");
  237. }
  238. TEST_END
  239. TEST_BEGIN(test_popcount_llu_slow) {
  240. TEST_POPCOUNT(unsigned long long, llu_slow, "llx");
  241. }
  242. TEST_END
  243. int
  244. main(void) {
  245. return test_no_reentrancy(
  246. test_pow2_ceil_u64,
  247. test_pow2_ceil_u32,
  248. test_pow2_ceil_zu,
  249. test_lg_ceil_floor,
  250. test_ffs_u,
  251. test_ffs_lu,
  252. test_ffs_llu,
  253. test_ffs_u32,
  254. test_ffs_u64,
  255. test_ffs_zu,
  256. test_fls_u,
  257. test_fls_lu,
  258. test_fls_llu,
  259. test_fls_u32,
  260. test_fls_u64,
  261. test_fls_zu,
  262. test_fls_u_slow,
  263. test_fls_lu_slow,
  264. test_fls_llu_slow,
  265. test_popcount_u,
  266. test_popcount_u_slow,
  267. test_popcount_lu,
  268. test_popcount_lu_slow,
  269. test_popcount_llu,
  270. test_popcount_llu_slow);
  271. }