bitops.h 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef VPX_PORTS_BITOPS_H_
  11. #define VPX_PORTS_BITOPS_H_
  12. #include <assert.h>
  13. #include "vpx_ports/msvc.h"
  14. #ifdef _MSC_VER
  15. # include <math.h> // the ceil() definition must precede intrin.h
  16. # if _MSC_VER > 1310 && (defined(_M_X64) || defined(_M_IX86))
  17. # include <intrin.h>
  18. # define USE_MSC_INTRINSICS
  19. # endif
  20. #endif
  21. #ifdef __cplusplus
  22. extern "C" {
  23. #endif
  24. // These versions of get_msb() are only valid when n != 0 because all
  25. // of the optimized versions are undefined when n == 0:
  26. // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
  27. // use GNU builtins where available.
  28. #if defined(__GNUC__) && \
  29. ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
  30. static INLINE int get_msb(unsigned int n) {
  31. assert(n != 0);
  32. return 31 ^ __builtin_clz(n);
  33. }
  34. #elif defined(USE_MSC_INTRINSICS)
  35. #pragma intrinsic(_BitScanReverse)
  36. static INLINE int get_msb(unsigned int n) {
  37. unsigned long first_set_bit;
  38. assert(n != 0);
  39. _BitScanReverse(&first_set_bit, n);
  40. return first_set_bit;
  41. }
  42. #undef USE_MSC_INTRINSICS
  43. #else
  44. // Returns (int)floor(log2(n)). n must be > 0.
  45. static INLINE int get_msb(unsigned int n) {
  46. int log = 0;
  47. unsigned int value = n;
  48. int i;
  49. assert(n != 0);
  50. for (i = 4; i >= 0; --i) {
  51. const int shift = (1 << i);
  52. const unsigned int x = value >> shift;
  53. if (x != 0) {
  54. value = x;
  55. log += shift;
  56. }
  57. }
  58. return log;
  59. }
  60. #endif
  61. #ifdef __cplusplus
  62. } // extern "C"
  63. #endif
  64. #endif // VPX_PORTS_BITOPS_H_