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.

322 lines
6.2 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. "encoding/binary"
  4. "fmt"
  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 && o == nil {
  91. return nil
  92. }
  93. if bA == nil && o != nil {
  94. return o.Copy()
  95. }
  96. if o == nil {
  97. return bA.Copy()
  98. }
  99. bA.mtx.Lock()
  100. defer bA.mtx.Unlock()
  101. c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
  102. for i := 0; i < len(c.Elems); i++ {
  103. c.Elems[i] |= o.Elems[i]
  104. }
  105. return c
  106. }
  107. // Returns a BitArray of smaller bit size.
  108. func (bA *BitArray) And(o *BitArray) *BitArray {
  109. if bA == nil || o == nil {
  110. return nil
  111. }
  112. bA.mtx.Lock()
  113. defer bA.mtx.Unlock()
  114. return bA.and(o)
  115. }
  116. func (bA *BitArray) and(o *BitArray) *BitArray {
  117. c := bA.copyBits(MinInt(bA.Bits, o.Bits))
  118. for i := 0; i < len(c.Elems); i++ {
  119. c.Elems[i] &= o.Elems[i]
  120. }
  121. return c
  122. }
  123. func (bA *BitArray) Not() *BitArray {
  124. if bA == nil {
  125. return nil // Degenerate
  126. }
  127. bA.mtx.Lock()
  128. defer bA.mtx.Unlock()
  129. c := bA.copy()
  130. for i := 0; i < len(c.Elems); i++ {
  131. c.Elems[i] = ^c.Elems[i]
  132. }
  133. return c
  134. }
  135. func (bA *BitArray) Sub(o *BitArray) *BitArray {
  136. if bA == nil || o == nil {
  137. // TODO: Decide if we should do 1's complement here?
  138. return nil
  139. }
  140. bA.mtx.Lock()
  141. defer bA.mtx.Unlock()
  142. if bA.Bits > o.Bits {
  143. c := bA.copy()
  144. for i := 0; i < len(o.Elems)-1; i++ {
  145. c.Elems[i] &= ^c.Elems[i]
  146. }
  147. i := len(o.Elems) - 1
  148. if i >= 0 {
  149. for idx := i * 64; idx < o.Bits; idx++ {
  150. // NOTE: each individual GetIndex() call to o is safe.
  151. c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
  152. }
  153. }
  154. return c
  155. }
  156. return bA.and(o.Not()) // Note degenerate case where o == nil
  157. }
  158. func (bA *BitArray) IsEmpty() bool {
  159. if bA == nil {
  160. return true // should this be opposite?
  161. }
  162. bA.mtx.Lock()
  163. defer bA.mtx.Unlock()
  164. for _, e := range bA.Elems {
  165. if e > 0 {
  166. return false
  167. }
  168. }
  169. return true
  170. }
  171. func (bA *BitArray) IsFull() bool {
  172. if bA == nil {
  173. return true
  174. }
  175. bA.mtx.Lock()
  176. defer bA.mtx.Unlock()
  177. // Check all elements except the last
  178. for _, elem := range bA.Elems[:len(bA.Elems)-1] {
  179. if (^elem) != 0 {
  180. return false
  181. }
  182. }
  183. // Check that the last element has (lastElemBits) 1's
  184. lastElemBits := (bA.Bits+63)%64 + 1
  185. lastElem := bA.Elems[len(bA.Elems)-1]
  186. return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
  187. }
  188. func (bA *BitArray) PickRandom() (int, bool) {
  189. if bA == nil {
  190. return 0, false
  191. }
  192. bA.mtx.Lock()
  193. defer bA.mtx.Unlock()
  194. length := len(bA.Elems)
  195. if length == 0 {
  196. return 0, false
  197. }
  198. randElemStart := RandIntn(length)
  199. for i := 0; i < length; i++ {
  200. elemIdx := ((i + randElemStart) % length)
  201. if elemIdx < length-1 {
  202. if bA.Elems[elemIdx] > 0 {
  203. randBitStart := RandIntn(64)
  204. for j := 0; j < 64; j++ {
  205. bitIdx := ((j + randBitStart) % 64)
  206. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  207. return 64*elemIdx + bitIdx, true
  208. }
  209. }
  210. PanicSanity("should not happen")
  211. }
  212. } else {
  213. // Special case for last elem, to ignore straggler bits
  214. elemBits := bA.Bits % 64
  215. if elemBits == 0 {
  216. elemBits = 64
  217. }
  218. randBitStart := RandIntn(elemBits)
  219. for j := 0; j < elemBits; j++ {
  220. bitIdx := ((j + randBitStart) % elemBits)
  221. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  222. return 64*elemIdx + bitIdx, true
  223. }
  224. }
  225. }
  226. }
  227. return 0, false
  228. }
  229. func (bA *BitArray) String() string {
  230. if bA == nil {
  231. return "nil-BitArray"
  232. }
  233. bA.mtx.Lock()
  234. defer bA.mtx.Unlock()
  235. return bA.stringIndented("")
  236. }
  237. func (bA *BitArray) StringIndented(indent string) string {
  238. if bA == nil {
  239. return "nil-BitArray"
  240. }
  241. bA.mtx.Lock()
  242. defer bA.mtx.Unlock()
  243. return bA.stringIndented(indent)
  244. }
  245. func (bA *BitArray) stringIndented(indent string) string {
  246. lines := []string{}
  247. bits := ""
  248. for i := 0; i < bA.Bits; i++ {
  249. if bA.getIndex(i) {
  250. bits += "X"
  251. } else {
  252. bits += "_"
  253. }
  254. if i%100 == 99 {
  255. lines = append(lines, bits)
  256. bits = ""
  257. }
  258. if i%10 == 9 {
  259. bits += " "
  260. }
  261. if i%50 == 49 {
  262. bits += " "
  263. }
  264. }
  265. if len(bits) > 0 {
  266. lines = append(lines, bits)
  267. }
  268. return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
  269. }
  270. func (bA *BitArray) Bytes() []byte {
  271. bA.mtx.Lock()
  272. defer bA.mtx.Unlock()
  273. numBytes := (bA.Bits + 7) / 8
  274. bytes := make([]byte, numBytes)
  275. for i := 0; i < len(bA.Elems); i++ {
  276. elemBytes := [8]byte{}
  277. binary.LittleEndian.PutUint64(elemBytes[:], bA.Elems[i])
  278. copy(bytes[i*8:], elemBytes[:])
  279. }
  280. return bytes
  281. }
  282. // NOTE: other bitarray o is not locked when reading,
  283. // so if necessary, caller must copy or lock o prior to calling Update.
  284. // If bA is nil, does nothing.
  285. func (bA *BitArray) Update(o *BitArray) {
  286. if bA == nil || o == nil {
  287. return
  288. }
  289. bA.mtx.Lock()
  290. defer bA.mtx.Unlock()
  291. copy(bA.Elems, o.Elems)
  292. }