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.

378 lines
7.8 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
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. "regexp"
  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 && o == nil {
  92. return nil
  93. }
  94. if bA == nil && o != nil {
  95. return o.Copy()
  96. }
  97. if o == nil {
  98. return bA.Copy()
  99. }
  100. bA.mtx.Lock()
  101. defer bA.mtx.Unlock()
  102. c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
  103. for i := 0; i < len(c.Elems); i++ {
  104. c.Elems[i] |= o.Elems[i]
  105. }
  106. return c
  107. }
  108. // Returns a BitArray of smaller bit size.
  109. func (bA *BitArray) And(o *BitArray) *BitArray {
  110. if bA == nil || o == nil {
  111. return nil
  112. }
  113. bA.mtx.Lock()
  114. defer bA.mtx.Unlock()
  115. return bA.and(o)
  116. }
  117. func (bA *BitArray) and(o *BitArray) *BitArray {
  118. c := bA.copyBits(MinInt(bA.Bits, o.Bits))
  119. for i := 0; i < len(c.Elems); i++ {
  120. c.Elems[i] &= o.Elems[i]
  121. }
  122. return c
  123. }
  124. func (bA *BitArray) Not() *BitArray {
  125. if bA == nil {
  126. return nil // Degenerate
  127. }
  128. bA.mtx.Lock()
  129. defer bA.mtx.Unlock()
  130. c := bA.copy()
  131. for i := 0; i < len(c.Elems); i++ {
  132. c.Elems[i] = ^c.Elems[i]
  133. }
  134. return c
  135. }
  136. func (bA *BitArray) Sub(o *BitArray) *BitArray {
  137. if bA == nil || o == nil {
  138. // TODO: Decide if we should do 1's complement here?
  139. return nil
  140. }
  141. bA.mtx.Lock()
  142. defer bA.mtx.Unlock()
  143. if bA.Bits > o.Bits {
  144. c := bA.copy()
  145. for i := 0; i < len(o.Elems)-1; i++ {
  146. c.Elems[i] &= ^c.Elems[i]
  147. }
  148. i := len(o.Elems) - 1
  149. if i >= 0 {
  150. for idx := i * 64; idx < o.Bits; idx++ {
  151. // NOTE: each individual GetIndex() call to o is safe.
  152. c.setIndex(idx, c.getIndex(idx) && !o.GetIndex(idx))
  153. }
  154. }
  155. return c
  156. }
  157. return bA.and(o.Not()) // Note degenerate case where o == nil
  158. }
  159. func (bA *BitArray) IsEmpty() bool {
  160. if bA == nil {
  161. return true // should this be opposite?
  162. }
  163. bA.mtx.Lock()
  164. defer bA.mtx.Unlock()
  165. for _, e := range bA.Elems {
  166. if e > 0 {
  167. return false
  168. }
  169. }
  170. return true
  171. }
  172. func (bA *BitArray) IsFull() bool {
  173. if bA == nil {
  174. return true
  175. }
  176. bA.mtx.Lock()
  177. defer bA.mtx.Unlock()
  178. // Check all elements except the last
  179. for _, elem := range bA.Elems[:len(bA.Elems)-1] {
  180. if (^elem) != 0 {
  181. return false
  182. }
  183. }
  184. // Check that the last element has (lastElemBits) 1's
  185. lastElemBits := (bA.Bits+63)%64 + 1
  186. lastElem := bA.Elems[len(bA.Elems)-1]
  187. return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
  188. }
  189. func (bA *BitArray) PickRandom() (int, bool) {
  190. if bA == nil {
  191. return 0, false
  192. }
  193. bA.mtx.Lock()
  194. defer bA.mtx.Unlock()
  195. length := len(bA.Elems)
  196. if length == 0 {
  197. return 0, false
  198. }
  199. randElemStart := RandIntn(length)
  200. for i := 0; i < length; i++ {
  201. elemIdx := ((i + randElemStart) % length)
  202. if elemIdx < length-1 {
  203. if bA.Elems[elemIdx] > 0 {
  204. randBitStart := RandIntn(64)
  205. for j := 0; j < 64; j++ {
  206. bitIdx := ((j + randBitStart) % 64)
  207. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  208. return 64*elemIdx + bitIdx, true
  209. }
  210. }
  211. PanicSanity("should not happen")
  212. }
  213. } else {
  214. // Special case for last elem, to ignore straggler bits
  215. elemBits := bA.Bits % 64
  216. if elemBits == 0 {
  217. elemBits = 64
  218. }
  219. randBitStart := RandIntn(elemBits)
  220. for j := 0; j < elemBits; j++ {
  221. bitIdx := ((j + randBitStart) % elemBits)
  222. if (bA.Elems[elemIdx] & (uint64(1) << uint(bitIdx))) > 0 {
  223. return 64*elemIdx + bitIdx, true
  224. }
  225. }
  226. }
  227. }
  228. return 0, false
  229. }
  230. // String returns a string representation of BitArray: BA{<bit-string>},
  231. // where <bit-string> is a sequence of 'x' (1) and '_' (0).
  232. // The <bit-string> includes spaces and newlines to help people.
  233. // For a simple sequence of 'x' and '_' characters with no spaces or newlines,
  234. // see the MarshalJSON() method.
  235. // Example: "BA{_x_}" or "nil-BitArray" for nil.
  236. func (bA *BitArray) String() string {
  237. return bA.StringIndented("")
  238. }
  239. func (bA *BitArray) StringIndented(indent string) string {
  240. if bA == nil {
  241. return "nil-BitArray"
  242. }
  243. bA.mtx.Lock()
  244. defer bA.mtx.Unlock()
  245. return bA.stringIndented(indent)
  246. }
  247. func (bA *BitArray) stringIndented(indent string) string {
  248. lines := []string{}
  249. bits := ""
  250. for i := 0; i < bA.Bits; i++ {
  251. if bA.getIndex(i) {
  252. bits += "x"
  253. } else {
  254. bits += "_"
  255. }
  256. if i%100 == 99 {
  257. lines = append(lines, bits)
  258. bits = ""
  259. }
  260. if i%10 == 9 {
  261. bits += indent
  262. }
  263. if i%50 == 49 {
  264. bits += indent
  265. }
  266. }
  267. if len(bits) > 0 {
  268. lines = append(lines, bits)
  269. }
  270. return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
  271. }
  272. func (bA *BitArray) Bytes() []byte {
  273. bA.mtx.Lock()
  274. defer bA.mtx.Unlock()
  275. numBytes := (bA.Bits + 7) / 8
  276. bytes := make([]byte, numBytes)
  277. for i := 0; i < len(bA.Elems); i++ {
  278. elemBytes := [8]byte{}
  279. binary.LittleEndian.PutUint64(elemBytes[:], bA.Elems[i])
  280. copy(bytes[i*8:], elemBytes[:])
  281. }
  282. return bytes
  283. }
  284. // NOTE: other bitarray o is not locked when reading,
  285. // so if necessary, caller must copy or lock o prior to calling Update.
  286. // If bA is nil, does nothing.
  287. func (bA *BitArray) Update(o *BitArray) {
  288. if bA == nil || o == nil {
  289. return
  290. }
  291. bA.mtx.Lock()
  292. defer bA.mtx.Unlock()
  293. copy(bA.Elems, o.Elems)
  294. }
  295. // MarshalJSON implements json.Marshaler interface by marshaling bit array
  296. // using a custom format: a string of '-' or 'x' where 'x' denotes the 1 bit.
  297. func (bA *BitArray) MarshalJSON() ([]byte, error) {
  298. if bA == nil {
  299. return []byte("null"), nil
  300. }
  301. bA.mtx.Lock()
  302. defer bA.mtx.Unlock()
  303. bits := `"`
  304. for i := 0; i < bA.Bits; i++ {
  305. if bA.getIndex(i) {
  306. bits += `x`
  307. } else {
  308. bits += `_`
  309. }
  310. }
  311. bits += `"`
  312. return []byte(bits), nil
  313. }
  314. var bitArrayJSONRegexp = regexp.MustCompile(`\A"([_x]*)"\z`)
  315. // UnmarshalJSON implements json.Unmarshaler interface by unmarshaling a custom
  316. // JSON description.
  317. func (bA *BitArray) UnmarshalJSON(bz []byte) error {
  318. b := string(bz)
  319. if b == "null" {
  320. // This is required e.g. for encoding/json when decoding
  321. // into a pointer with pre-allocated BitArray.
  322. bA.Bits = 0
  323. bA.Elems = nil
  324. return nil
  325. }
  326. // Validate 'b'.
  327. match := bitArrayJSONRegexp.FindStringSubmatch(b)
  328. if match == nil {
  329. return fmt.Errorf("BitArray in JSON should be a string of format %q but got %s", bitArrayJSONRegexp.String(), b)
  330. }
  331. bits := match[1]
  332. // Construct new BitArray and copy over.
  333. numBits := len(bits)
  334. bA2 := NewBitArray(numBits)
  335. for i := 0; i < numBits; i++ {
  336. if bits[i] == 'x' {
  337. bA2.SetIndex(i, true)
  338. }
  339. }
  340. *bA = *bA2
  341. return nil
  342. }