bits.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright (c) Meta Platforms, Inc. and affiliates.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. * You may select, at your option, one of the above-listed licenses.
  9. */
  10. #ifndef ZSTD_BITS_H
  11. #define ZSTD_BITS_H
  12. #include "mem.h"
  13. MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)
  14. {
  15. assert(val != 0);
  16. {
  17. static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,
  18. 30, 22, 20, 15, 25, 17, 4, 8,
  19. 31, 27, 13, 23, 21, 19, 16, 7,
  20. 26, 12, 18, 6, 11, 5, 10, 9};
  21. return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];
  22. }
  23. }
  24. MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)
  25. {
  26. assert(val != 0);
  27. #if defined(_MSC_VER)
  28. # if STATIC_BMI2
  29. return (unsigned)_tzcnt_u32(val);
  30. # else
  31. if (val != 0) {
  32. unsigned long r;
  33. _BitScanForward(&r, val);
  34. return (unsigned)r;
  35. } else {
  36. __assume(0); /* Should not reach this code path */
  37. }
  38. # endif
  39. #elif defined(__GNUC__) && (__GNUC__ >= 4)
  40. return (unsigned)__builtin_ctz(val);
  41. #elif defined(__ICCARM__)
  42. return (unsigned)__builtin_ctz(val);
  43. #else
  44. return ZSTD_countTrailingZeros32_fallback(val);
  45. #endif
  46. }
  47. MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)
  48. {
  49. assert(val != 0);
  50. {
  51. static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,
  52. 11, 14, 16, 18, 22, 25, 3, 30,
  53. 8, 12, 20, 28, 15, 17, 24, 7,
  54. 19, 27, 23, 6, 26, 5, 4, 31};
  55. val |= val >> 1;
  56. val |= val >> 2;
  57. val |= val >> 4;
  58. val |= val >> 8;
  59. val |= val >> 16;
  60. return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];
  61. }
  62. }
  63. MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)
  64. {
  65. assert(val != 0);
  66. #if defined(_MSC_VER)
  67. # if STATIC_BMI2
  68. return (unsigned)_lzcnt_u32(val);
  69. # else
  70. if (val != 0) {
  71. unsigned long r;
  72. _BitScanReverse(&r, val);
  73. return (unsigned)(31 - r);
  74. } else {
  75. __assume(0); /* Should not reach this code path */
  76. }
  77. # endif
  78. #elif defined(__GNUC__) && (__GNUC__ >= 4)
  79. return (unsigned)__builtin_clz(val);
  80. #elif defined(__ICCARM__)
  81. return (unsigned)__builtin_clz(val);
  82. #else
  83. return ZSTD_countLeadingZeros32_fallback(val);
  84. #endif
  85. }
  86. MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)
  87. {
  88. assert(val != 0);
  89. #if defined(_MSC_VER) && defined(_WIN64)
  90. # if STATIC_BMI2
  91. return (unsigned)_tzcnt_u64(val);
  92. # else
  93. if (val != 0) {
  94. unsigned long r;
  95. _BitScanForward64(&r, val);
  96. return (unsigned)r;
  97. } else {
  98. __assume(0); /* Should not reach this code path */
  99. }
  100. # endif
  101. #elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)
  102. return (unsigned)__builtin_ctzll(val);
  103. #elif defined(__ICCARM__)
  104. return (unsigned)__builtin_ctzll(val);
  105. #else
  106. {
  107. U32 mostSignificantWord = (U32)(val >> 32);
  108. U32 leastSignificantWord = (U32)val;
  109. if (leastSignificantWord == 0) {
  110. return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);
  111. } else {
  112. return ZSTD_countTrailingZeros32(leastSignificantWord);
  113. }
  114. }
  115. #endif
  116. }
  117. MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)
  118. {
  119. assert(val != 0);
  120. #if defined(_MSC_VER) && defined(_WIN64)
  121. # if STATIC_BMI2
  122. return (unsigned)_lzcnt_u64(val);
  123. # else
  124. if (val != 0) {
  125. unsigned long r;
  126. _BitScanReverse64(&r, val);
  127. return (unsigned)(63 - r);
  128. } else {
  129. __assume(0); /* Should not reach this code path */
  130. }
  131. # endif
  132. #elif defined(__GNUC__) && (__GNUC__ >= 4)
  133. return (unsigned)(__builtin_clzll(val));
  134. #elif defined(__ICCARM__)
  135. return (unsigned)(__builtin_clzll(val));
  136. #else
  137. {
  138. U32 mostSignificantWord = (U32)(val >> 32);
  139. U32 leastSignificantWord = (U32)val;
  140. if (mostSignificantWord == 0) {
  141. return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);
  142. } else {
  143. return ZSTD_countLeadingZeros32(mostSignificantWord);
  144. }
  145. }
  146. #endif
  147. }
  148. MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)
  149. {
  150. if (MEM_isLittleEndian()) {
  151. if (MEM_64bits()) {
  152. return ZSTD_countTrailingZeros64((U64)val) >> 3;
  153. } else {
  154. return ZSTD_countTrailingZeros32((U32)val) >> 3;
  155. }
  156. } else { /* Big Endian CPU */
  157. if (MEM_64bits()) {
  158. return ZSTD_countLeadingZeros64((U64)val) >> 3;
  159. } else {
  160. return ZSTD_countLeadingZeros32((U32)val) >> 3;
  161. }
  162. }
  163. }
  164. MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */
  165. {
  166. assert(val != 0);
  167. return 31 - ZSTD_countLeadingZeros32(val);
  168. }
  169. /* ZSTD_rotateRight_*():
  170. * Rotates a bitfield to the right by "count" bits.
  171. * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts
  172. */
  173. MEM_STATIC
  174. U64 ZSTD_rotateRight_U64(U64 const value, U32 count) {
  175. assert(count < 64);
  176. count &= 0x3F; /* for fickle pattern recognition */
  177. return (value >> count) | (U64)(value << ((0U - count) & 0x3F));
  178. }
  179. MEM_STATIC
  180. U32 ZSTD_rotateRight_U32(U32 const value, U32 count) {
  181. assert(count < 32);
  182. count &= 0x1F; /* for fickle pattern recognition */
  183. return (value >> count) | (U32)(value << ((0U - count) & 0x1F));
  184. }
  185. MEM_STATIC
  186. U16 ZSTD_rotateRight_U16(U16 const value, U32 count) {
  187. assert(count < 16);
  188. count &= 0x0F; /* for fickle pattern recognition */
  189. return (value >> count) | (U16)(value << ((0U - count) & 0x0F));
  190. }
  191. #endif /* ZSTD_BITS_H */