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.

317 lines
6.1 KiB

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