gitee.com/quant1x/engine@v1.8.4/labs/bitmap.go (about)

     1  package labs
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  const (
     9  	bitSize = 8
    10  )
    11  
    12  var bitmask = []byte{1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7}
    13  
    14  // Bitmap 首字母小写 只能调用 工厂函数 创建
    15  type Bitmap struct {
    16  	bits     []byte
    17  	bitCount uint64 // 已填入数字的数量
    18  	capacity uint64 // 容量
    19  }
    20  
    21  // NewBitmap 创建工厂函数
    22  func NewBitmap(maxnum uint64) *Bitmap {
    23  	return &Bitmap{bits: make([]byte, (maxnum+7)/bitSize), bitCount: 0, capacity: maxnum}
    24  }
    25  
    26  // Set 填入数字
    27  func (this *Bitmap) Set(num uint64) {
    28  	byteIndex, bitPos := this.offset(num)
    29  	// 1 左移 bitPos 位 进行 按位或 (置为 1)
    30  	this.bits[byteIndex] |= bitmask[bitPos]
    31  	this.bitCount++
    32  }
    33  
    34  // Reset 清除填入的数字
    35  func (this *Bitmap) Reset(num uint64) {
    36  	byteIndex, bitPos := this.offset(num)
    37  	// 重置为空位 (重置为 0)
    38  	this.bits[byteIndex] &= ^bitmask[bitPos]
    39  	this.bitCount--
    40  }
    41  
    42  // Test 数字是否在位图中
    43  func (this *Bitmap) Test(num uint64) bool {
    44  	byteIndex := num / bitSize
    45  	if byteIndex >= uint64(len(this.bits)) {
    46  		return false
    47  	}
    48  	bitPos := num % bitSize
    49  	// 右移 bitPos 位 和 1 进行 按位与
    50  	return !(this.bits[byteIndex]&bitmask[bitPos] == 0)
    51  }
    52  
    53  func (this *Bitmap) offset(num uint64) (byteIndex uint64, bitPos byte) {
    54  	byteIndex = num / bitSize // 字节索引
    55  	if byteIndex >= uint64(len(this.bits)) {
    56  		panic(fmt.Sprintf(" runtime error: index value %d out of range", byteIndex))
    57  		return
    58  	}
    59  	bitPos = byte(num % bitSize) // bit位置
    60  	return byteIndex, bitPos
    61  }
    62  
    63  // Size 位图的容量
    64  func (this *Bitmap) Size() uint64 {
    65  	return uint64(len(this.bits) * bitSize)
    66  }
    67  
    68  // IsEmpty 是否空位图
    69  func (this *Bitmap) IsEmpty() bool {
    70  	return this.bitCount == 0
    71  }
    72  
    73  // IsFully 是否已填满
    74  func (this *Bitmap) IsFully() bool {
    75  	return this.bitCount == this.capacity
    76  }
    77  
    78  // Count 已填入的数字个数
    79  func (this *Bitmap) Count() uint64 {
    80  	return this.bitCount
    81  }
    82  
    83  // GetData 获取填入的数字切片
    84  func (this *Bitmap) GetData() []uint64 {
    85  	var data []uint64
    86  	count := this.Size()
    87  	for index := uint64(0); index < count; index++ {
    88  		if this.Test(index) {
    89  			data = append(data, index)
    90  		}
    91  	}
    92  	return data
    93  }
    94  
    95  func (this *Bitmap) String() string {
    96  	var sb strings.Builder
    97  	for index := len(this.bits) - 1; index >= 0; index-- {
    98  		sb.WriteString(byteToBinaryString(this.bits[index]))
    99  		sb.WriteString(" ")
   100  	}
   101  	return sb.String()
   102  }
   103  
   104  func byteToBinaryString(data byte) string {
   105  	var sb strings.Builder
   106  	for index := 0; index < bitSize; index++ {
   107  		if (bitmask[7-index] & data) == 0 {
   108  			sb.WriteString("0")
   109  		} else {
   110  			sb.WriteString("1")
   111  		}
   112  	}
   113  	return sb.String()
   114  }