zend_bitset.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend OPcache JIT |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | https://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Dmitry Stogov <dmitry@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #ifndef _ZEND_BITSET_H_
  19. #define _ZEND_BITSET_H_
  20. typedef zend_ulong *zend_bitset;
  21. #define ZEND_BITSET_ELM_SIZE sizeof(zend_ulong)
  22. #if SIZEOF_ZEND_LONG == 4
  23. # define ZEND_BITSET_ELM_NUM(n) ((n) >> 5)
  24. # define ZEND_BITSET_BIT_NUM(n) ((zend_ulong)(n) & Z_UL(0x1f))
  25. #elif SIZEOF_ZEND_LONG == 8
  26. # define ZEND_BITSET_ELM_NUM(n) ((n) >> 6)
  27. # define ZEND_BITSET_BIT_NUM(n) ((zend_ulong)(n) & Z_UL(0x3f))
  28. #else
  29. # define ZEND_BITSET_ELM_NUM(n) ((n) / (sizeof(zend_long) * 8))
  30. # define ZEND_BITSET_BIT_NUM(n) ((n) % (sizeof(zend_long) * 8))
  31. #endif
  32. #define ZEND_BITSET_ALLOCA(n, use_heap) \
  33. (zend_bitset)do_alloca((n) * ZEND_BITSET_ELM_SIZE, use_heap)
  34. /* Number of trailing zero bits (0x01 -> 0; 0x40 -> 6; 0x00 -> LEN) */
  35. static zend_always_inline int zend_ulong_ntz(zend_ulong num)
  36. {
  37. #if (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) \
  38. && SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CTZL)
  39. return __builtin_ctzl(num);
  40. #elif (defined(__GNUC__) || __has_builtin(__builtin_ctzll)) && defined(PHP_HAVE_BUILTIN_CTZLL)
  41. return __builtin_ctzll(num);
  42. #elif defined(_WIN32)
  43. unsigned long index;
  44. #if defined(_WIN64)
  45. if (!BitScanForward64(&index, num)) {
  46. #else
  47. if (!BitScanForward(&index, num)) {
  48. #endif
  49. /* undefined behavior */
  50. return SIZEOF_ZEND_LONG * 8;
  51. }
  52. return (int) index;
  53. #else
  54. int n;
  55. if (num == Z_UL(0)) return SIZEOF_ZEND_LONG * 8;
  56. n = 1;
  57. #if SIZEOF_ZEND_LONG == 8
  58. if ((num & 0xffffffff) == 0) {n += 32; num = num >> Z_UL(32);}
  59. #endif
  60. if ((num & 0x0000ffff) == 0) {n += 16; num = num >> 16;}
  61. if ((num & 0x000000ff) == 0) {n += 8; num = num >> 8;}
  62. if ((num & 0x0000000f) == 0) {n += 4; num = num >> 4;}
  63. if ((num & 0x00000003) == 0) {n += 2; num = num >> 2;}
  64. return n - (num & 1);
  65. #endif
  66. }
  67. /* Number of leading zero bits (Undefined for zero) */
  68. static zend_always_inline int zend_ulong_nlz(zend_ulong num)
  69. {
  70. #if (defined(__GNUC__) || __has_builtin(__builtin_clzl)) \
  71. && SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CLZL)
  72. return __builtin_clzl(num);
  73. #elif (defined(__GNUC__) || __has_builtin(__builtin_clzll)) && defined(PHP_HAVE_BUILTIN_CLZLL)
  74. return __builtin_clzll(num);
  75. #elif defined(_WIN32)
  76. unsigned long index;
  77. #if defined(_WIN64)
  78. if (!BitScanReverse64(&index, num)) {
  79. #else
  80. if (!BitScanReverse(&index, num)) {
  81. #endif
  82. /* undefined behavior */
  83. return SIZEOF_ZEND_LONG * 8;
  84. }
  85. return (int) (SIZEOF_ZEND_LONG * 8 - 1)- index;
  86. #else
  87. zend_ulong x;
  88. int n;
  89. #if SIZEOF_ZEND_LONG == 8
  90. n = 64;
  91. x = num >> 32; if (x != 0) {n -= 32; num = x;}
  92. #else
  93. n = 32;
  94. #endif
  95. x = num >> 16; if (x != 0) {n -= 16; num = x;}
  96. x = num >> 8; if (x != 0) {n -= 8; num = x;}
  97. x = num >> 4; if (x != 0) {n -= 4; num = x;}
  98. x = num >> 2; if (x != 0) {n -= 2; num = x;}
  99. x = num >> 1; if (x != 0) return n - 2;
  100. return n - num;
  101. #endif
  102. }
  103. /* Returns the number of zend_ulong words needed to store a bitset that is N
  104. bits long. */
  105. static inline uint32_t zend_bitset_len(uint32_t n)
  106. {
  107. return (n + ((sizeof(zend_long) * 8) - 1)) / (sizeof(zend_long) * 8);
  108. }
  109. static inline bool zend_bitset_in(zend_bitset set, uint32_t n)
  110. {
  111. return ZEND_BIT_TEST(set, n);
  112. }
  113. static inline void zend_bitset_incl(zend_bitset set, uint32_t n)
  114. {
  115. set[ZEND_BITSET_ELM_NUM(n)] |= Z_UL(1) << ZEND_BITSET_BIT_NUM(n);
  116. }
  117. static inline void zend_bitset_excl(zend_bitset set, uint32_t n)
  118. {
  119. set[ZEND_BITSET_ELM_NUM(n)] &= ~(Z_UL(1) << ZEND_BITSET_BIT_NUM(n));
  120. }
  121. static inline void zend_bitset_clear(zend_bitset set, uint32_t len)
  122. {
  123. memset(set, 0, len * ZEND_BITSET_ELM_SIZE);
  124. }
  125. static inline bool zend_bitset_empty(zend_bitset set, uint32_t len)
  126. {
  127. uint32_t i;
  128. for (i = 0; i < len; i++) {
  129. if (set[i]) {
  130. return 0;
  131. }
  132. }
  133. return 1;
  134. }
  135. static inline void zend_bitset_fill(zend_bitset set, uint32_t len)
  136. {
  137. memset(set, 0xff, len * ZEND_BITSET_ELM_SIZE);
  138. }
  139. static inline bool zend_bitset_equal(zend_bitset set1, zend_bitset set2, uint32_t len)
  140. {
  141. return memcmp(set1, set2, len * ZEND_BITSET_ELM_SIZE) == 0;
  142. }
  143. static inline void zend_bitset_copy(zend_bitset set1, zend_bitset set2, uint32_t len)
  144. {
  145. memcpy(set1, set2, len * ZEND_BITSET_ELM_SIZE);
  146. }
  147. static inline void zend_bitset_intersection(zend_bitset set1, zend_bitset set2, uint32_t len)
  148. {
  149. uint32_t i;
  150. for (i = 0; i < len; i++) {
  151. set1[i] &= set2[i];
  152. }
  153. }
  154. static inline void zend_bitset_union(zend_bitset set1, zend_bitset set2, uint32_t len)
  155. {
  156. uint32_t i;
  157. for (i = 0; i < len; i++) {
  158. set1[i] |= set2[i];
  159. }
  160. }
  161. static inline void zend_bitset_difference(zend_bitset set1, zend_bitset set2, uint32_t len)
  162. {
  163. uint32_t i;
  164. for (i = 0; i < len; i++) {
  165. set1[i] = set1[i] & ~set2[i];
  166. }
  167. }
  168. static inline void zend_bitset_union_with_intersection(zend_bitset set1, zend_bitset set2, zend_bitset set3, zend_bitset set4, uint32_t len)
  169. {
  170. uint32_t i;
  171. for (i = 0; i < len; i++) {
  172. set1[i] = set2[i] | (set3[i] & set4[i]);
  173. }
  174. }
  175. static inline void zend_bitset_union_with_difference(zend_bitset set1, zend_bitset set2, zend_bitset set3, zend_bitset set4, uint32_t len)
  176. {
  177. uint32_t i;
  178. for (i = 0; i < len; i++) {
  179. set1[i] = set2[i] | (set3[i] & ~set4[i]);
  180. }
  181. }
  182. static inline bool zend_bitset_subset(zend_bitset set1, zend_bitset set2, uint32_t len)
  183. {
  184. uint32_t i;
  185. for (i = 0; i < len; i++) {
  186. if (set1[i] & ~set2[i]) {
  187. return 0;
  188. }
  189. }
  190. return 1;
  191. }
  192. static inline int zend_bitset_first(zend_bitset set, uint32_t len)
  193. {
  194. uint32_t i;
  195. for (i = 0; i < len; i++) {
  196. if (set[i]) {
  197. return ZEND_BITSET_ELM_SIZE * 8 * i + zend_ulong_ntz(set[i]);
  198. }
  199. }
  200. return -1; /* empty set */
  201. }
  202. static inline int zend_bitset_last(zend_bitset set, uint32_t len)
  203. {
  204. uint32_t i = len;
  205. while (i > 0) {
  206. i--;
  207. if (set[i]) {
  208. int j = ZEND_BITSET_ELM_SIZE * 8 * i - 1;
  209. zend_ulong x = set[i];
  210. while (x != Z_UL(0)) {
  211. x = x >> Z_UL(1);
  212. j++;
  213. }
  214. return j;
  215. }
  216. }
  217. return -1; /* empty set */
  218. }
  219. #define ZEND_BITSET_FOREACH(set, len, bit) do { \
  220. zend_bitset _set = (set); \
  221. uint32_t _i, _len = (len); \
  222. for (_i = 0; _i < _len; _i++) { \
  223. zend_ulong _x = _set[_i]; \
  224. if (_x) { \
  225. (bit) = ZEND_BITSET_ELM_SIZE * 8 * _i; \
  226. for (; _x != 0; _x >>= Z_UL(1), (bit)++) { \
  227. if (!(_x & Z_UL(1))) continue;
  228. #define ZEND_BITSET_REVERSE_FOREACH(set, len, bit) do { \
  229. zend_bitset _set = (set); \
  230. uint32_t _i = (len); \
  231. zend_ulong _test = Z_UL(1) << (ZEND_BITSET_ELM_SIZE * 8 - 1); \
  232. while (_i-- > 0) { \
  233. zend_ulong _x = _set[_i]; \
  234. if (_x) { \
  235. (bit) = ZEND_BITSET_ELM_SIZE * 8 * (_i + 1) - 1; \
  236. for (; _x != 0; _x <<= Z_UL(1), (bit)--) { \
  237. if (!(_x & _test)) continue; \
  238. #define ZEND_BITSET_FOREACH_END() \
  239. } \
  240. } \
  241. } \
  242. } while (0)
  243. static inline int zend_bitset_pop_first(zend_bitset set, uint32_t len) {
  244. int i = zend_bitset_first(set, len);
  245. if (i >= 0) {
  246. zend_bitset_excl(set, i);
  247. }
  248. return i;
  249. }
  250. #endif /* _ZEND_BITSET_H_ */