zend_bitset.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend OPcache JIT |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 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. | http://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. /* Returns the number of zend_ulong words needed to store a bitset that is N
  68. bits long. */
  69. static inline uint32_t zend_bitset_len(uint32_t n)
  70. {
  71. return (n + ((sizeof(zend_long) * 8) - 1)) / (sizeof(zend_long) * 8);
  72. }
  73. static inline zend_bool zend_bitset_in(zend_bitset set, uint32_t n)
  74. {
  75. return ZEND_BIT_TEST(set, n);
  76. }
  77. static inline void zend_bitset_incl(zend_bitset set, uint32_t n)
  78. {
  79. set[ZEND_BITSET_ELM_NUM(n)] |= Z_UL(1) << ZEND_BITSET_BIT_NUM(n);
  80. }
  81. static inline void zend_bitset_excl(zend_bitset set, uint32_t n)
  82. {
  83. set[ZEND_BITSET_ELM_NUM(n)] &= ~(Z_UL(1) << ZEND_BITSET_BIT_NUM(n));
  84. }
  85. static inline void zend_bitset_clear(zend_bitset set, uint32_t len)
  86. {
  87. memset(set, 0, len * ZEND_BITSET_ELM_SIZE);
  88. }
  89. static inline int zend_bitset_empty(zend_bitset set, uint32_t len)
  90. {
  91. uint32_t i;
  92. for (i = 0; i < len; i++) {
  93. if (set[i]) {
  94. return 0;
  95. }
  96. }
  97. return 1;
  98. }
  99. static inline void zend_bitset_fill(zend_bitset set, uint32_t len)
  100. {
  101. memset(set, 0xff, len * ZEND_BITSET_ELM_SIZE);
  102. }
  103. static inline zend_bool zend_bitset_equal(zend_bitset set1, zend_bitset set2, uint32_t len)
  104. {
  105. return memcmp(set1, set2, len * ZEND_BITSET_ELM_SIZE) == 0;
  106. }
  107. static inline void zend_bitset_copy(zend_bitset set1, zend_bitset set2, uint32_t len)
  108. {
  109. memcpy(set1, set2, len * ZEND_BITSET_ELM_SIZE);
  110. }
  111. static inline void zend_bitset_intersection(zend_bitset set1, zend_bitset set2, uint32_t len)
  112. {
  113. uint32_t i;
  114. for (i = 0; i < len; i++) {
  115. set1[i] &= set2[i];
  116. }
  117. }
  118. static inline void zend_bitset_union(zend_bitset set1, zend_bitset set2, uint32_t len)
  119. {
  120. uint32_t i;
  121. for (i = 0; i < len; i++) {
  122. set1[i] |= set2[i];
  123. }
  124. }
  125. static inline void zend_bitset_difference(zend_bitset set1, zend_bitset set2, uint32_t len)
  126. {
  127. uint32_t i;
  128. for (i = 0; i < len; i++) {
  129. set1[i] = set1[i] & ~set2[i];
  130. }
  131. }
  132. static inline void zend_bitset_union_with_intersection(zend_bitset set1, zend_bitset set2, zend_bitset set3, zend_bitset set4, uint32_t len)
  133. {
  134. uint32_t i;
  135. for (i = 0; i < len; i++) {
  136. set1[i] = set2[i] | (set3[i] & set4[i]);
  137. }
  138. }
  139. static inline void zend_bitset_union_with_difference(zend_bitset set1, zend_bitset set2, zend_bitset set3, zend_bitset set4, uint32_t len)
  140. {
  141. uint32_t i;
  142. for (i = 0; i < len; i++) {
  143. set1[i] = set2[i] | (set3[i] & ~set4[i]);
  144. }
  145. }
  146. static inline zend_bool zend_bitset_subset(zend_bitset set1, zend_bitset set2, uint32_t len)
  147. {
  148. uint32_t i;
  149. for (i = 0; i < len; i++) {
  150. if (set1[i] & ~set2[i]) {
  151. return 0;
  152. }
  153. }
  154. return 1;
  155. }
  156. static inline int zend_bitset_first(zend_bitset set, uint32_t len)
  157. {
  158. uint32_t i;
  159. for (i = 0; i < len; i++) {
  160. if (set[i]) {
  161. return ZEND_BITSET_ELM_SIZE * 8 * i + zend_ulong_ntz(set[i]);
  162. }
  163. }
  164. return -1; /* empty set */
  165. }
  166. static inline int zend_bitset_last(zend_bitset set, uint32_t len)
  167. {
  168. uint32_t i = len;
  169. while (i > 0) {
  170. i--;
  171. if (set[i]) {
  172. int j = ZEND_BITSET_ELM_SIZE * 8 * i - 1;
  173. zend_ulong x = set[i];
  174. while (x != Z_UL(0)) {
  175. x = x >> Z_UL(1);
  176. j++;
  177. }
  178. return j;
  179. }
  180. }
  181. return -1; /* empty set */
  182. }
  183. #define ZEND_BITSET_FOREACH(set, len, bit) do { \
  184. zend_bitset _set = (set); \
  185. uint32_t _i, _len = (len); \
  186. for (_i = 0; _i < _len; _i++) { \
  187. zend_ulong _x = _set[_i]; \
  188. if (_x) { \
  189. (bit) = ZEND_BITSET_ELM_SIZE * 8 * _i; \
  190. for (; _x != 0; _x >>= Z_UL(1), (bit)++) { \
  191. if (!(_x & Z_UL(1))) continue;
  192. #define ZEND_BITSET_REVERSE_FOREACH(set, len, bit) do { \
  193. zend_bitset _set = (set); \
  194. uint32_t _i = (len); \
  195. zend_ulong _test = Z_UL(1) << (ZEND_BITSET_ELM_SIZE * 8 - 1); \
  196. while (_i-- > 0) { \
  197. zend_ulong _x = _set[_i]; \
  198. if (_x) { \
  199. (bit) = ZEND_BITSET_ELM_SIZE * 8 * (_i + 1) - 1; \
  200. for (; _x != 0; _x <<= Z_UL(1), (bit)--) { \
  201. if (!(_x & _test)) continue; \
  202. #define ZEND_BITSET_FOREACH_END() \
  203. } \
  204. } \
  205. } \
  206. } while (0)
  207. static inline int zend_bitset_pop_first(zend_bitset set, uint32_t len) {
  208. int i = zend_bitset_first(set, len);
  209. if (i >= 0) {
  210. zend_bitset_excl(set, i);
  211. }
  212. return i;
  213. }
  214. #endif /* _ZEND_BITSET_H_ */
  215. /*
  216. * Local variables:
  217. * tab-width: 4
  218. * c-basic-offset: 4
  219. * indent-tabs-mode: t
  220. * End:
  221. * vim600: sw=4 ts=4 fdm=marker
  222. * vim<600: sw=4 ts=4
  223. */