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.

209 lines
4.2 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
  1. package common
  2. import (
  3. "fmt"
  4. "io"
  5. "math/rand"
  6. "strings"
  7. . "github.com/tendermint/tendermint/binary"
  8. )
  9. // Not goroutine safe
  10. type BitArray struct {
  11. bits uint
  12. elems []uint64
  13. }
  14. func NewBitArray(bits uint) BitArray {
  15. return BitArray{bits, make([]uint64, (bits+63)/64)}
  16. }
  17. func ReadBitArray(r io.Reader, n *int64, err *error) BitArray {
  18. bits := ReadUVarInt(r, n, err)
  19. if bits == 0 {
  20. return BitArray{}
  21. }
  22. elemsWritten := ReadUVarInt(r, n, err)
  23. if *err != nil {
  24. return BitArray{}
  25. }
  26. bA := NewBitArray(bits)
  27. for i := uint(0); i < elemsWritten; i++ {
  28. bA.elems[i] = ReadUInt64(r, n, err)
  29. if *err != nil {
  30. return BitArray{}
  31. }
  32. }
  33. return bA
  34. }
  35. func (bA BitArray) WriteTo(w io.Writer) (n int64, err error) {
  36. WriteUVarInt(w, bA.bits, &n, &err)
  37. if bA.bits == 0 {
  38. return
  39. }
  40. // Count the last element > 0.
  41. elemsToWrite := 0
  42. for i, elem := range bA.elems {
  43. if elem > 0 {
  44. elemsToWrite = i + 1
  45. }
  46. }
  47. WriteUVarInt(w, uint(elemsToWrite), &n, &err)
  48. for i, elem := range bA.elems {
  49. if i >= elemsToWrite {
  50. break
  51. }
  52. WriteUInt64(w, elem, &n, &err)
  53. }
  54. return
  55. }
  56. func (bA BitArray) IsZero() bool {
  57. return bA.bits == 0
  58. }
  59. // NOTE: behavior is undefined if i >= bA.bits
  60. func (bA BitArray) GetIndex(i uint) bool {
  61. if i >= bA.bits {
  62. return false
  63. }
  64. return bA.elems[i/64]&uint64(1<<(i%64)) > 0
  65. }
  66. // NOTE: behavior is undefined if i >= bA.bits
  67. func (bA BitArray) SetIndex(i uint, v bool) bool {
  68. if i >= bA.bits {
  69. return false
  70. }
  71. if v {
  72. bA.elems[i/64] |= uint64(1 << (i % 64))
  73. } else {
  74. bA.elems[i/64] &= ^uint64(1 << (i % 64))
  75. }
  76. return true
  77. }
  78. func (bA BitArray) Copy() BitArray {
  79. c := make([]uint64, len(bA.elems))
  80. copy(c, bA.elems)
  81. return BitArray{bA.bits, c}
  82. }
  83. func (bA BitArray) copyBits(bits uint) BitArray {
  84. c := make([]uint64, (bits+63)/64)
  85. copy(c, bA.elems)
  86. return BitArray{bits, c}
  87. }
  88. // Returns a BitArray of larger bits size.
  89. func (bA BitArray) Or(o BitArray) BitArray {
  90. c := bA.copyBits(MaxUint(bA.bits, o.bits))
  91. for i := 0; i < len(c.elems); i++ {
  92. c.elems[i] |= o.elems[i]
  93. }
  94. return c
  95. }
  96. // Returns a BitArray of smaller bit size.
  97. func (bA BitArray) And(o BitArray) BitArray {
  98. c := bA.copyBits(MinUint(bA.bits, o.bits))
  99. for i := 0; i < len(c.elems); i++ {
  100. c.elems[i] &= o.elems[i]
  101. }
  102. return c
  103. }
  104. func (bA BitArray) Not() BitArray {
  105. c := bA.Copy()
  106. for i := 0; i < len(c.elems); i++ {
  107. c.elems[i] = ^c.elems[i]
  108. }
  109. return c
  110. }
  111. func (bA BitArray) Sub(o BitArray) BitArray {
  112. if bA.bits > o.bits {
  113. c := bA.Copy()
  114. for i := 0; i < len(o.elems)-1; i++ {
  115. c.elems[i] &= ^c.elems[i]
  116. }
  117. i := uint(len(o.elems) - 1)
  118. if i >= 0 {
  119. for idx := i * 64; idx < o.bits; idx++ {
  120. c.SetIndex(idx, c.GetIndex(idx) && !o.GetIndex(idx))
  121. }
  122. }
  123. return c
  124. } else {
  125. return bA.And(o.Not())
  126. }
  127. }
  128. func (bA BitArray) PickRandom() (uint, bool) {
  129. length := len(bA.elems)
  130. if length == 0 {
  131. return 0, false
  132. }
  133. randElemStart := rand.Intn(length)
  134. for i := 0; i < length; i++ {
  135. elemIdx := ((i + randElemStart) % length)
  136. if elemIdx < length-1 {
  137. if bA.elems[elemIdx] > 0 {
  138. randBitStart := rand.Intn(64)
  139. for j := 0; j < 64; j++ {
  140. bitIdx := ((j + randBitStart) % 64)
  141. if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
  142. return 64*uint(elemIdx) + uint(bitIdx), true
  143. }
  144. }
  145. panic("should not happen")
  146. }
  147. } else {
  148. // Special case for last elem, to ignore straggler bits
  149. elemBits := int(bA.bits) % 64
  150. if elemBits == 0 {
  151. elemBits = 64
  152. }
  153. randBitStart := rand.Intn(elemBits)
  154. for j := 0; j < elemBits; j++ {
  155. bitIdx := ((j + randBitStart) % elemBits)
  156. if (bA.elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
  157. return 64*uint(elemIdx) + uint(bitIdx), true
  158. }
  159. }
  160. }
  161. }
  162. return 0, false
  163. }
  164. func (bA BitArray) String() string {
  165. return bA.StringWithIndent("")
  166. }
  167. func (bA BitArray) StringWithIndent(indent string) string {
  168. lines := []string{}
  169. bits := ""
  170. for i := uint(0); i < bA.bits; i++ {
  171. if bA.GetIndex(i) {
  172. bits += "X"
  173. } else {
  174. bits += "_"
  175. }
  176. if i%100 == 99 {
  177. lines = append(lines, bits)
  178. bits = ""
  179. }
  180. if i%10 == 9 {
  181. bits += " "
  182. }
  183. if i%50 == 49 {
  184. bits += " "
  185. }
  186. }
  187. if len(bits) > 0 {
  188. lines = append(lines, bits)
  189. }
  190. return fmt.Sprintf("BA{%v:%v}", bA.bits, strings.Join(lines, indent))
  191. }