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.

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