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.

417 lines
9.5 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
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
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. // BitArray is a thread-safe implementation of a bit array.
  10. type BitArray struct {
  11. mtx sync.Mutex
  12. Bits int `json:"bits"` // NOTE: persisted via reflect, must be exported
  13. Elems []uint64 `json:"elems"` // NOTE: persisted via reflect, must be exported
  14. }
  15. // NewBitArray returns a new bit array.
  16. // It returns nil if the number of bits is zero.
  17. func NewBitArray(bits int) *BitArray {
  18. if bits <= 0 {
  19. return nil
  20. }
  21. return &BitArray{
  22. Bits: bits,
  23. Elems: make([]uint64, (bits+63)/64),
  24. }
  25. }
  26. // Size returns the number of bits in the bitarray
  27. func (bA *BitArray) Size() int {
  28. if bA == nil {
  29. return 0
  30. }
  31. return bA.Bits
  32. }
  33. // GetIndex returns the bit at index i within the bit array.
  34. // The behavior is undefined if i >= bA.Bits
  35. func (bA *BitArray) GetIndex(i int) bool {
  36. if bA == nil {
  37. return false
  38. }
  39. bA.mtx.Lock()
  40. defer bA.mtx.Unlock()
  41. return bA.getIndex(i)
  42. }
  43. func (bA *BitArray) getIndex(i int) bool {
  44. if i >= bA.Bits {
  45. return false
  46. }
  47. return bA.Elems[i/64]&(uint64(1)<<uint(i%64)) > 0
  48. }
  49. // SetIndex sets the bit at index i within the bit array.
  50. // The behavior is undefined if i >= bA.Bits
  51. func (bA *BitArray) SetIndex(i int, v bool) bool {
  52. if bA == nil {
  53. return false
  54. }
  55. bA.mtx.Lock()
  56. defer bA.mtx.Unlock()
  57. return bA.setIndex(i, v)
  58. }
  59. func (bA *BitArray) setIndex(i int, v bool) bool {
  60. if i >= bA.Bits {
  61. return false
  62. }
  63. if v {
  64. bA.Elems[i/64] |= (uint64(1) << uint(i%64))
  65. } else {
  66. bA.Elems[i/64] &= ^(uint64(1) << uint(i%64))
  67. }
  68. return true
  69. }
  70. // Copy returns a copy of the provided bit array.
  71. func (bA *BitArray) Copy() *BitArray {
  72. if bA == nil {
  73. return nil
  74. }
  75. bA.mtx.Lock()
  76. defer bA.mtx.Unlock()
  77. return bA.copy()
  78. }
  79. func (bA *BitArray) copy() *BitArray {
  80. c := make([]uint64, len(bA.Elems))
  81. copy(c, bA.Elems)
  82. return &BitArray{
  83. Bits: bA.Bits,
  84. Elems: c,
  85. }
  86. }
  87. func (bA *BitArray) copyBits(bits int) *BitArray {
  88. c := make([]uint64, (bits+63)/64)
  89. copy(c, bA.Elems)
  90. return &BitArray{
  91. Bits: bits,
  92. Elems: c,
  93. }
  94. }
  95. // Or returns a bit array resulting from a bitwise OR of the two bit arrays.
  96. // If the two bit-arrys have different lengths, Or right-pads the smaller of the two bit-arrays with zeroes.
  97. // Thus the size of the return value is the maximum of the two provided bit arrays.
  98. func (bA *BitArray) Or(o *BitArray) *BitArray {
  99. if bA == nil && o == nil {
  100. return nil
  101. }
  102. if bA == nil && o != nil {
  103. return o.Copy()
  104. }
  105. if o == nil {
  106. return bA.Copy()
  107. }
  108. bA.mtx.Lock()
  109. o.mtx.Lock()
  110. c := bA.copyBits(MaxInt(bA.Bits, o.Bits))
  111. smaller := MinInt(len(bA.Elems), len(o.Elems))
  112. for i := 0; i < smaller; i++ {
  113. c.Elems[i] |= o.Elems[i]
  114. }
  115. bA.mtx.Unlock()
  116. o.mtx.Unlock()
  117. return c
  118. }
  119. // And returns a bit array resulting from a bitwise AND of the two bit arrays.
  120. // If the two bit-arrys have different lengths, this truncates the larger of the two bit-arrays from the right.
  121. // Thus the size of the return value is the minimum of the two provided bit arrays.
  122. func (bA *BitArray) And(o *BitArray) *BitArray {
  123. if bA == nil || o == nil {
  124. return nil
  125. }
  126. bA.mtx.Lock()
  127. o.mtx.Lock()
  128. defer func() {
  129. bA.mtx.Unlock()
  130. o.mtx.Unlock()
  131. }()
  132. return bA.and(o)
  133. }
  134. func (bA *BitArray) and(o *BitArray) *BitArray {
  135. c := bA.copyBits(MinInt(bA.Bits, o.Bits))
  136. for i := 0; i < len(c.Elems); i++ {
  137. c.Elems[i] &= o.Elems[i]
  138. }
  139. return c
  140. }
  141. // Not returns a bit array resulting from a bitwise Not of the provided bit array.
  142. func (bA *BitArray) Not() *BitArray {
  143. if bA == nil {
  144. return nil // Degenerate
  145. }
  146. bA.mtx.Lock()
  147. defer bA.mtx.Unlock()
  148. return bA.not()
  149. }
  150. func (bA *BitArray) not() *BitArray {
  151. c := bA.copy()
  152. for i := 0; i < len(c.Elems); i++ {
  153. c.Elems[i] = ^c.Elems[i]
  154. }
  155. return c
  156. }
  157. // Sub subtracts the two bit-arrays bitwise, without carrying the bits.
  158. // Note that carryless subtraction of a - b is (a and not b).
  159. // The output is the same as bA, regardless of o's size.
  160. // If bA is longer than o, o is right padded with zeroes
  161. func (bA *BitArray) Sub(o *BitArray) *BitArray {
  162. if bA == nil || o == nil {
  163. // TODO: Decide if we should do 1's complement here?
  164. return nil
  165. }
  166. bA.mtx.Lock()
  167. o.mtx.Lock()
  168. // output is the same size as bA
  169. c := bA.copyBits(bA.Bits)
  170. // Only iterate to the minimum size between the two.
  171. // If o is longer, those bits are ignored.
  172. // If bA is longer, then skipping those iterations is equivalent
  173. // to right padding with 0's
  174. smaller := MinInt(len(bA.Elems), len(o.Elems))
  175. for i := 0; i < smaller; i++ {
  176. // &^ is and not in golang
  177. c.Elems[i] &^= o.Elems[i]
  178. }
  179. bA.mtx.Unlock()
  180. o.mtx.Unlock()
  181. return c
  182. }
  183. // IsEmpty returns true iff all bits in the bit array are 0
  184. func (bA *BitArray) IsEmpty() bool {
  185. if bA == nil {
  186. return true // should this be opposite?
  187. }
  188. bA.mtx.Lock()
  189. defer bA.mtx.Unlock()
  190. for _, e := range bA.Elems {
  191. if e > 0 {
  192. return false
  193. }
  194. }
  195. return true
  196. }
  197. // IsFull returns true iff all bits in the bit array are 1.
  198. func (bA *BitArray) IsFull() bool {
  199. if bA == nil {
  200. return true
  201. }
  202. bA.mtx.Lock()
  203. defer bA.mtx.Unlock()
  204. // Check all elements except the last
  205. for _, elem := range bA.Elems[:len(bA.Elems)-1] {
  206. if (^elem) != 0 {
  207. return false
  208. }
  209. }
  210. // Check that the last element has (lastElemBits) 1's
  211. lastElemBits := (bA.Bits+63)%64 + 1
  212. lastElem := bA.Elems[len(bA.Elems)-1]
  213. return (lastElem+1)&((uint64(1)<<uint(lastElemBits))-1) == 0
  214. }
  215. // PickRandom returns a random index for a set bit in the bit array.
  216. // If there is no such value, it returns 0, false.
  217. // It uses the global randomness in `random.go` to get this index.
  218. func (bA *BitArray) PickRandom() (int, bool) {
  219. if bA == nil {
  220. return 0, false
  221. }
  222. bA.mtx.Lock()
  223. trueIndices := bA.getTrueIndices()
  224. bA.mtx.Unlock()
  225. if len(trueIndices) == 0 { // no bits set to true
  226. return 0, false
  227. }
  228. return trueIndices[RandIntn(len(trueIndices))], true
  229. }
  230. func (bA *BitArray) getTrueIndices() []int {
  231. trueIndices := make([]int, 0, bA.Bits)
  232. curBit := 0
  233. numElems := len(bA.Elems)
  234. // set all true indices
  235. for i := 0; i < numElems-1; i++ {
  236. elem := bA.Elems[i]
  237. if elem == 0 {
  238. curBit += 64
  239. continue
  240. }
  241. for j := 0; j < 64; j++ {
  242. if (elem & (uint64(1) << uint64(j))) > 0 {
  243. trueIndices = append(trueIndices, curBit)
  244. }
  245. curBit++
  246. }
  247. }
  248. // handle last element
  249. lastElem := bA.Elems[numElems-1]
  250. numFinalBits := bA.Bits - curBit
  251. for i := 0; i < numFinalBits; i++ {
  252. if (lastElem & (uint64(1) << uint64(i))) > 0 {
  253. trueIndices = append(trueIndices, curBit)
  254. }
  255. curBit++
  256. }
  257. return trueIndices
  258. }
  259. // String returns a string representation of BitArray: BA{<bit-string>},
  260. // where <bit-string> is a sequence of 'x' (1) and '_' (0).
  261. // The <bit-string> includes spaces and newlines to help people.
  262. // For a simple sequence of 'x' and '_' characters with no spaces or newlines,
  263. // see the MarshalJSON() method.
  264. // Example: "BA{_x_}" or "nil-BitArray" for nil.
  265. func (bA *BitArray) String() string {
  266. return bA.StringIndented("")
  267. }
  268. // StringIndented returns the same thing as String(), but applies the indent
  269. // at every 10th bit, and twice at every 50th bit.
  270. func (bA *BitArray) StringIndented(indent string) string {
  271. if bA == nil {
  272. return "nil-BitArray"
  273. }
  274. bA.mtx.Lock()
  275. defer bA.mtx.Unlock()
  276. return bA.stringIndented(indent)
  277. }
  278. func (bA *BitArray) stringIndented(indent string) string {
  279. lines := []string{}
  280. bits := ""
  281. for i := 0; i < bA.Bits; i++ {
  282. if bA.getIndex(i) {
  283. bits += "x"
  284. } else {
  285. bits += "_"
  286. }
  287. if i%100 == 99 {
  288. lines = append(lines, bits)
  289. bits = ""
  290. }
  291. if i%10 == 9 {
  292. bits += indent
  293. }
  294. if i%50 == 49 {
  295. bits += indent
  296. }
  297. }
  298. if len(bits) > 0 {
  299. lines = append(lines, bits)
  300. }
  301. return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
  302. }
  303. // Bytes returns the byte representation of the bits within the bitarray.
  304. func (bA *BitArray) Bytes() []byte {
  305. bA.mtx.Lock()
  306. defer bA.mtx.Unlock()
  307. numBytes := (bA.Bits + 7) / 8
  308. bytes := make([]byte, numBytes)
  309. for i := 0; i < len(bA.Elems); i++ {
  310. elemBytes := [8]byte{}
  311. binary.LittleEndian.PutUint64(elemBytes[:], bA.Elems[i])
  312. copy(bytes[i*8:], elemBytes[:])
  313. }
  314. return bytes
  315. }
  316. // Update sets the bA's bits to be that of the other bit array.
  317. // The copying begins from the begin of both bit arrays.
  318. func (bA *BitArray) Update(o *BitArray) {
  319. if bA == nil || o == nil {
  320. return
  321. }
  322. bA.mtx.Lock()
  323. o.mtx.Lock()
  324. defer func() {
  325. bA.mtx.Unlock()
  326. o.mtx.Unlock()
  327. }()
  328. copy(bA.Elems, o.Elems)
  329. }
  330. // MarshalJSON implements json.Marshaler interface by marshaling bit array
  331. // using a custom format: a string of '-' or 'x' where 'x' denotes the 1 bit.
  332. func (bA *BitArray) MarshalJSON() ([]byte, error) {
  333. if bA == nil {
  334. return []byte("null"), nil
  335. }
  336. bA.mtx.Lock()
  337. defer bA.mtx.Unlock()
  338. bits := `"`
  339. for i := 0; i < bA.Bits; i++ {
  340. if bA.getIndex(i) {
  341. bits += `x`
  342. } else {
  343. bits += `_`
  344. }
  345. }
  346. bits += `"`
  347. return []byte(bits), nil
  348. }
  349. var bitArrayJSONRegexp = regexp.MustCompile(`\A"([_x]*)"\z`)
  350. // UnmarshalJSON implements json.Unmarshaler interface by unmarshaling a custom
  351. // JSON description.
  352. func (bA *BitArray) UnmarshalJSON(bz []byte) error {
  353. b := string(bz)
  354. if b == "null" {
  355. // This is required e.g. for encoding/json when decoding
  356. // into a pointer with pre-allocated BitArray.
  357. bA.Bits = 0
  358. bA.Elems = nil
  359. return nil
  360. }
  361. // Validate 'b'.
  362. match := bitArrayJSONRegexp.FindStringSubmatch(b)
  363. if match == nil {
  364. return fmt.Errorf("bitArray in JSON should be a string of format %q but got %s", bitArrayJSONRegexp.String(), b)
  365. }
  366. bits := match[1]
  367. // Construct new BitArray and copy over.
  368. numBits := len(bits)
  369. bA2 := NewBitArray(numBits)
  370. for i := 0; i < numBits; i++ {
  371. if bits[i] == 'x' {
  372. bA2.SetIndex(i, true)
  373. }
  374. }
  375. *bA = *bA2 //nolint:govet
  376. return nil
  377. }