SparseByteSet.h 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright 2015-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <cstdint>
  18. #include <glog/logging.h>
  19. namespace folly {
  20. /***
  21. * SparseByteSet
  22. *
  23. * A special-purpose data structure representing an insert-only set of bytes.
  24. * May have better performance than std::bitset<256>, depending on workload.
  25. *
  26. * Operations:
  27. * - add(byte)
  28. * - contains(byte)
  29. *
  30. * Performance:
  31. * - The entire capacity of the set is inline; the set never allocates.
  32. * - The constructor zeros only the first two bytes of the object.
  33. * - add and contains both run in constant time w.r.t. the size of the set.
  34. * Constant time - not amortized constant - and with small constant factor.
  35. *
  36. * This data structure is ideal for on-stack use.
  37. *
  38. * Aho, Hopcroft, and Ullman refer to this trick in "The Design and Analysis
  39. * of Computer Algorithms" (1974), but the best description is here:
  40. * http://research.swtch.com/sparse
  41. * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.30.7319
  42. */
  43. class SparseByteSet {
  44. public:
  45. // There are this many possible values:
  46. static constexpr uint16_t kCapacity = 256;
  47. // No init of byte-arrays required!
  48. SparseByteSet() : size_(0) {}
  49. /***
  50. * add(byte)
  51. *
  52. * O(1), non-amortized.
  53. */
  54. inline bool add(uint8_t i) {
  55. bool r = !contains(i);
  56. if (r) {
  57. DCHECK_LT(size_, kCapacity);
  58. dense_[size_] = i;
  59. sparse_[i] = uint8_t(size_);
  60. size_++;
  61. }
  62. return r;
  63. }
  64. /***
  65. * contains(byte)
  66. *
  67. * O(1), non-amortized.
  68. */
  69. inline bool contains(uint8_t i) const {
  70. return sparse_[i] < size_ && dense_[sparse_[i]] == i;
  71. }
  72. private:
  73. uint16_t size_; // can't use uint8_t because it would overflow if all
  74. // possible values were inserted.
  75. uint8_t sparse_[kCapacity];
  76. uint8_t dense_[kCapacity];
  77. };
  78. } // namespace folly