You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
5.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package common
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strings"
  6. "sync"
  7. )
  8. type BitArray struct {
  9. mtx sync.Mutex
  10. Bits int `json:"bits"` // NOTE: persisted via reflect, must be exported
  11. Elems []uint64 `json:"elems"` // NOTE: persisted via reflect, must be exported
  12. }
  13. // There is no BitArray whose Size is 0. Use nil instead.
  14. func NewBitArray(bits int) *BitArray {
  15. if bits == 0 {
  16. return nil
  17. }
  18. return &BitArray{
  19. Bits: bits,
  20. Elems: make([]uint64, (bits+63)/64),
  21. }
  22. }
  23. func (bA *BitArray) Size() int {
  24. if bA == nil {
  25. return 0
  26. }
  27. return bA.Bits
  28. }
  29. // NOTE: behavior is undefined if i >= bA.Bits
  30. func (bA *BitArray) GetIndex(i int) bool {
  31. if bA == nil {
  32. return false
  33. }
  34. bA.mtx.Lock()
  35. defer bA.mtx.Unlock()
  36. return bA.getIndex(i)
  37. }
  38. func (bA *BitArray) getIndex(i int) bool {
  39. if i >= bA.Bits {
  40. return false
  41. }
  42. return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
  43. }
  44. // NOTE: behavior is undefined if i >= bA.Bits
  45. func (bA *BitArray) SetIndex(i int, v bool) bool {
  46. if bA == nil {
  47. return false
  48. }
  49. bA.mtx.Lock()
  50. defer bA.mtx.Unlock()
  51. return bA.setIndex(i, v)
  52. }
  53. func (bA *BitArray) setIndex(i int, v bool) bool {
  54. if i >= bA.Bits {
  55. return false
  56. }
  57. if v {
  58. bA.Elems[i/64] |= (uint64(1) << uint(i%64))
  59. } else {
  60. bA.Elems[i/64] &= ^(uint64(1) << uint(i%64))
  61. }
  62. return true
  63. }
  64. func (bA *BitArray) Copy() *BitArray {
  65. if bA == nil {
  66. return nil
  67. }
  68. bA.mtx.Lock()
  69. defer bA.mtx.Unlock()
  70. return bA.copy()
  71. }
  72. func (bA *BitArray) copy() *BitArray {
  73. c := make([]uint64, len(bA.Elems))
  74. copy(c, bA.Elems)
  75. return &BitArray{
  76. Bits: bA.Bits,
  77. Elems: c,
  78. }
  79. }
  80. func (bA *BitArray) copyBits(bits int) *BitArray {
  81. c := make([]uint64, (bits+63)/64)
  82. copy(c, bA.Elems)
  83. return &BitArray{
  84. Bits: bits,
  85. Elems: c,
  86. }
  87. }
  88. // Returns a BitArray of larger bits size.
  89. func (bA *BitArray) Or(o *BitArray) *BitArray {
  90. if bA == nil {
  91. o.Copy()
  92. }
  93. bA.mtx.Lock()
  94. defer bA.mtx.Unlock()
  95. c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
  96. for i := 0; i < len(c.Elems); i++ {
  97. c.Elems[i] |= o.Elems[i]
  98. }
  99. return c
  100. }
  101. // Returns a BitArray of smaller bit size.
  102. func (bA *BitArray) And(o *BitArray) *BitArray {
  103. if bA == nil {
  104. return nil
  105. }
  106. bA.mtx.Lock()
  107. defer bA.mtx.Unlock()
  108. return bA.and(o)
  109. }
  110. func (bA *BitArray) and(o *BitArray) *BitArray {
  111. c := bA.copyBits(MinInt(bA.Bits, o.Bits))
  112. for i := 0; i < len(c.Elems); i++ {
  113. c.Elems[i] &= o.Elems[i]
  114. }
  115. return c
  116. }
  117. func (bA *BitArray) Not() *BitArray {
  118. if bA == nil {
  119. return nil // Degenerate
  120. }
  121. bA.mtx.Lock()
  122. defer bA.mtx.Unlock()
  123. c := bA.copy()
  124. for i := 0; i < len(c.Elems); i++ {
  125. c.Elems[i] = ^c.Elems[i]
  126. }
  127. return c
  128. }
  129. func (bA *BitArray) Sub(o *BitArray) *BitArray {
  130. if bA == nil {
  131. return nil
  132. }
  133. bA.mtx.Lock()
  134. defer bA.mtx.Unlock()
  135. if bA.Bits > o.Bits {
  136. c := bA.copy()
  137. for i := 0; i < len(o.Elems)-1; i++ {
  138. c.Elems[i] &= ^c.Elems[i]
  139. }
  140. i := len(o.Elems) - 1
  141. if i >= 0 {
  142. for idx := i * 64; idx < o.Bits; idx++ {
  143. // NOTE: each individual GetIndex() call to o is safe.
  144. c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
  145. }
  146. }
  147. return c
  148. } else {
  149. return bA.and(o.Not()) // Note degenerate case where o == nil
  150. }
  151. }
  152. func (bA *BitArray) IsFull() bool {
  153. if bA == nil {
  154. return true
  155. }
  156. bA.mtx.Lock()
  157. defer bA.mtx.Unlock()
  158. // Check all elements except the last
  159. for _, elem := range bA.Elems[:len(bA.Elems)-1] {
  160. if (^elem) != 0 {
  161. return false
  162. }
  163. }
  164. // Check that the last element has (lastElemBits) 1's
  165. lastElemBits := (bA.Bits+63)%64 + 1
  166. lastElem := bA.Elems[len(bA.Elems)-1]
  167. return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
  168. }
  169. func (bA *BitArray) PickRandom() (int, bool) {
  170. if bA == nil {
  171. return 0, false
  172. }
  173. bA.mtx.Lock()
  174. defer bA.mtx.Unlock()
  175. length := len(bA.Elems)
  176. if length == 0 {
  177. return 0, false
  178. }
  179. randElemStart := rand.Intn(length)
  180. for i := 0; i < length; i++ {
  181. elemIdx := ((i + randElemStart) % length)
  182. if elemIdx < length-1 {
  183. if bA.Elems[elemIdx] > 0 {
  184. randBitStart := rand.Intn(64)
  185. for j := 0; j < 64; j++ {
  186. bitIdx := ((j + randBitStart) % 64)
  187. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  188. return 64*elemIdx + bitIdx, true
  189. }
  190. }
  191. PanicSanity("should not happen")
  192. }
  193. } else {
  194. // Special case for last elem, to ignore straggler bits
  195. elemBits := bA.Bits % 64
  196. if elemBits == 0 {
  197. elemBits = 64
  198. }
  199. randBitStart := rand.Intn(elemBits)
  200. for j := 0; j < elemBits; j++ {
  201. bitIdx := ((j + randBitStart) % elemBits)
  202. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  203. return 64*elemIdx + bitIdx, true
  204. }
  205. }
  206. }
  207. }
  208. return 0, false
  209. }
  210. func (bA *BitArray) String() string {
  211. if bA == nil {
  212. return "nil-BitArray"
  213. }
  214. bA.mtx.Lock()
  215. defer bA.mtx.Unlock()
  216. return bA.stringIndented("")
  217. }
  218. func (bA *BitArray) StringIndented(indent string) string {
  219. if bA == nil {
  220. return "nil-BitArray"
  221. }
  222. bA.mtx.Lock()
  223. defer bA.mtx.Unlock()
  224. return bA.stringIndented(indent)
  225. }
  226. func (bA *BitArray) stringIndented(indent string) string {
  227. lines := []string{}
  228. bits := ""
  229. for i := 0; i < bA.Bits; i++ {
  230. if bA.getIndex(i) {
  231. bits += "X"
  232. } else {
  233. bits += "_"
  234. }
  235. if i%100 == 99 {
  236. lines = append(lines, bits)
  237. bits = ""
  238. }
  239. if i%10 == 9 {
  240. bits += " "
  241. }
  242. if i%50 == 49 {
  243. bits += " "
  244. }
  245. }
  246. if len(bits) > 0 {
  247. lines = append(lines, bits)
  248. }
  249. return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
  250. }