Bitmask.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. simple bitmask class
  15. */
  16. #pragma once
  17. #include <stdint.h>
  18. #include <string.h>
  19. #include <AP_InternalError/AP_InternalError.h>
  20. template<uint16_t num_bits>
  21. class Bitmask {
  22. public:
  23. Bitmask() :
  24. numbits(num_bits),
  25. numwords((num_bits+31)/32) {
  26. clearall();
  27. }
  28. Bitmask &operator=(const Bitmask&other) {
  29. memcpy(bits, other.bits, sizeof(bits[0])*other.numwords);
  30. return *this;
  31. }
  32. Bitmask(const Bitmask &other) = delete;
  33. // set given bitnumber
  34. void set(uint16_t bit) {
  35. // ignore an invalid bit number
  36. if (bit >= numbits) {
  37. AP::internalerror().error(AP_InternalError::error_t::bitmask_range);
  38. return;
  39. }
  40. uint16_t word = bit/32;
  41. uint8_t ofs = bit & 0x1f;
  42. bits[word] |= (1U << ofs);
  43. }
  44. // set all bits
  45. void setall(void) {
  46. // set all words to 111... except the last one.
  47. for (uint16_t i=0; i<numwords-1; i++) {
  48. bits[i] = 0xffffffff;
  49. }
  50. // set most of the last word to 111.., leaving out-of-range bits to be 0
  51. uint16_t num_valid_bits = numbits % 32;
  52. bits[numwords-1] = (1 << num_valid_bits) - 1;
  53. }
  54. // clear given bitnumber
  55. void clear(uint16_t bit) {
  56. uint16_t word = bit/32;
  57. uint8_t ofs = bit & 0x1f;
  58. bits[word] &= ~(1U << ofs);
  59. }
  60. // clear all bits
  61. void clearall(void) {
  62. memset(bits, 0, numwords*sizeof(bits[0]));
  63. }
  64. // return true if given bitnumber is set
  65. bool get(uint16_t bit) const {
  66. uint16_t word = bit/32;
  67. uint8_t ofs = bit & 0x1f;
  68. #if CONFIG_HAL_BOARD == HAL_BOARD_SITL
  69. if (bit >= numbits) {
  70. AP::internalerror().error(AP_InternalError::error_t::bitmask_range);
  71. return false;
  72. }
  73. #endif
  74. return (bits[word] & (1U << ofs)) != 0;
  75. }
  76. // return true if all bits are clear
  77. bool empty(void) const {
  78. for (uint16_t i=0; i<numwords; i++) {
  79. if (bits[i] != 0) {
  80. return false;
  81. }
  82. }
  83. return true;
  84. }
  85. // return number of bits set
  86. uint16_t count() const {
  87. uint16_t sum = 0;
  88. for (uint16_t i=0; i<numwords; i++) {
  89. if (sizeof(bits[i]) <= sizeof(int)) {
  90. sum += __builtin_popcount(bits[i]);
  91. } else if (sizeof(bits[i]) <= sizeof(long)) {
  92. sum += __builtin_popcountl(bits[i]);
  93. } else {
  94. sum += __builtin_popcountll(bits[i]);
  95. }
  96. }
  97. return sum;
  98. }
  99. // return first bit set, or -1 if none set
  100. int16_t first_set() const {
  101. for (uint16_t i=0; i<numwords; i++) {
  102. if (bits[i] == 0) {
  103. continue;
  104. }
  105. int fs;
  106. if (sizeof(bits[i]) <= sizeof(int)) {
  107. fs = __builtin_ffs(bits[i]);
  108. } else if (sizeof(bits[i]) <= sizeof(long)) {
  109. fs = __builtin_ffsl(bits[i]);
  110. } else {
  111. fs = __builtin_ffsll(bits[i]);
  112. }
  113. return i*32 + fs - 1;
  114. }
  115. return -1;
  116. }
  117. // return number of bits available
  118. uint16_t size() const {
  119. return numbits;
  120. }
  121. private:
  122. uint16_t numbits;
  123. uint16_t numwords;
  124. uint32_t bits[(num_bits+31)/32];
  125. };