utils.h 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #pragma once
  2. #if defined(__GNUC__) || defined(__clang__)
  3. static inline uint32_t clz32(unsigned long val)
  4. {
  5. return __builtin_clz(val);
  6. }
  7. static inline uint32_t ctz32(unsigned long val)
  8. {
  9. return __builtin_ctz(val);
  10. }
  11. #elif defined(_MSC_VER) && _MSC_VER >= 1400
  12. static inline uint32_t clz32(unsigned long val)
  13. {
  14. /* __lzcnt() / _lzcnt_u32() do not work correctly on older Intel CPUs,
  15. * so use BSR instead for better compatibility. */
  16. uint32_t zeros = 0;
  17. _BitScanReverse(&zeros, val);
  18. return 31 - zeros;
  19. }
  20. static inline uint32_t ctz32(unsigned long val)
  21. {
  22. #if defined(_M_ARM64)
  23. return _CountTrailingZeros(val);
  24. #else
  25. return _tzcnt_u32(val);
  26. #endif
  27. }
  28. #else
  29. static uint32_t popcnt(uint32_t x)
  30. {
  31. x -= ((x >> 1) & 0x55555555);
  32. x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
  33. x = (((x >> 4) + x) & 0x0f0f0f0f);
  34. x += (x >> 8);
  35. x += (x >> 16);
  36. return x & 0x0000003f;
  37. }
  38. static uint32_t clz32(uint32_t x)
  39. {
  40. x |= (x >> 1);
  41. x |= (x >> 2);
  42. x |= (x >> 4);
  43. x |= (x >> 8);
  44. x |= (x >> 16);
  45. return 32 - popcnt(x);
  46. }
  47. static uint32_t ctz32(uint32_t x)
  48. {
  49. return popcnt((x & -x) - 1);
  50. }
  51. #endif
  52. static inline uint32_t min_u32(uint32_t a, uint32_t b)
  53. {
  54. return (a < b) ? a : b;
  55. }
  56. static inline uint16_t min_u16(uint16_t a, uint16_t b)
  57. {
  58. return (a < b) ? a : b;
  59. }
  60. static inline int32_t min_i32(int32_t a, int32_t b)
  61. {
  62. return (a < b) ? a : b;
  63. }
  64. static inline uint8_t max_u8(uint8_t a, uint8_t b)
  65. {
  66. return (a > b) ? a : b;
  67. }