github.com/djordje200179/extendedlibrary/datastructures@v1.7.1-0.20240227175559-d09520a92dd4/cols/bitarray/array.go (about)

     1  package bitarray
     2  
     3  import (
     4  	"github.com/djordje200179/extendedlibrary/datastructures/cols"
     5  	"strings"
     6  )
     7  
     8  // Array is an optimized array of boolean values.
     9  // The zero value is ready to use. Do not copy a non-zero Array.
    10  type Array struct {
    11  	slice       []uint8
    12  	lastElemOff uint8
    13  }
    14  
    15  // New creates an empty Array.
    16  func New() *Array {
    17  	return &Array{
    18  		slice: make([]uint8, 0),
    19  	}
    20  }
    21  
    22  // NewWithSize creates an empty Array with the specified initial size.
    23  func NewWithSize(initialSize int) *Array {
    24  	arrSize := (initialSize + 7) / 8
    25  
    26  	return &Array{
    27  		slice:       make([]uint8, arrSize),
    28  		lastElemOff: uint8(initialSize % 8),
    29  	}
    30  }
    31  
    32  // NewWithCapacity creates an empty Array with the specified initial capacity.
    33  func NewWithCapacity(initialCapacity int) *Array {
    34  	arrCapacity := (initialCapacity + 7) / 8
    35  
    36  	return &Array{
    37  		slice:       make([]uint8, 0, arrCapacity),
    38  		lastElemOff: 0,
    39  	}
    40  }
    41  
    42  // NewFromSlice creates an Array from the specified slice.
    43  func NewFromSlice(slice []bool) *Array {
    44  	arr := NewWithSize(len(slice))
    45  
    46  	for i, val := range slice {
    47  		arr.Set(i, val)
    48  	}
    49  
    50  	return arr
    51  }
    52  
    53  // Size returns the number of bits in the Array.
    54  func (array *Array) Size() int {
    55  	if array.lastElemOff == 0 {
    56  		return len(array.slice) * 8
    57  	} else {
    58  		return (len(array.slice)-1)*8 + int(array.lastElemOff)
    59  	}
    60  }
    61  
    62  // Capacity returns the number of bits that the Array can hold without reallocating.
    63  func (array *Array) Capacity() int {
    64  	return cap(array.slice) * 8
    65  }
    66  
    67  func (array *Array) getRealIndex(index int) int {
    68  	size := array.Size()
    69  
    70  	if index >= size || index < -size {
    71  		panic(cols.IndexOutOfBoundsError{Index: index, Length: size})
    72  	}
    73  
    74  	if index < 0 {
    75  		index += size
    76  	}
    77  
    78  	return index
    79  }
    80  
    81  // Get returns the bit at the specified index.
    82  // Negative indices are interpreted as relative to the end of the Array.
    83  // Panics if the index is out of bounds.
    84  func (array *Array) Get(index int) bool {
    85  	index = array.getRealIndex(index)
    86  
    87  	elemIndex := index / 8
    88  	elemOff := index % 8
    89  	masked := array.slice[elemIndex] & (1 << elemOff)
    90  
    91  	return masked != 0
    92  }
    93  
    94  // Set sets the bit at the specified index to the specified value.
    95  // Negative indices are interpreted as relative to the end of the Array.
    96  // Panics if the index is out of bounds.
    97  func (array *Array) Set(index int, value bool) {
    98  	index = array.getRealIndex(index)
    99  
   100  	elemIndex := index / 8
   101  	elemOff := index % 8
   102  	elem := array.slice[elemIndex]
   103  
   104  	mask := uint8(1) << elemOff
   105  	if value {
   106  		elem |= mask
   107  	} else {
   108  		elem &= ^mask
   109  	}
   110  
   111  	array.slice[elemIndex] = elem
   112  }
   113  
   114  // SetAll sets all bits in the Array to the specified value.
   115  func (array *Array) SetAll(value bool) {
   116  	var elem uint8
   117  	if value {
   118  		elem = 0xFF
   119  	}
   120  
   121  	for i := range array.slice {
   122  		array.slice[i] = elem
   123  	}
   124  }
   125  
   126  // Flip flips the bit at the specified index.
   127  func (array *Array) Flip(index int) {
   128  	index = array.getRealIndex(index)
   129  
   130  	elemIndex := index / 8
   131  	elemOff := index % 8
   132  	elem := array.slice[elemIndex]
   133  
   134  	mask := uint8(1) << elemOff
   135  	elem ^= mask
   136  
   137  	array.slice[elemIndex] = elem
   138  }
   139  
   140  // FlipAll flips all bits in the Array.
   141  func (array *Array) FlipAll() {
   142  	for i, val := range array.slice {
   143  		array.slice[i] = ^val
   144  	}
   145  }
   146  
   147  // Append appends the specified bit value to the end of the Array.
   148  func (array *Array) Append(value bool) {
   149  	if array.lastElemOff == 0 {
   150  		array.slice = append(array.slice, 0)
   151  	}
   152  
   153  	array.lastElemOff = (array.lastElemOff + 1) % 8
   154  
   155  	array.Set(array.Size()-1, value)
   156  }
   157  
   158  // Insert inserts the specified bit value at the specified index.
   159  func (array *Array) Insert(index int, value bool) {
   160  	index = array.getRealIndex(index)
   161  
   162  	elemIndex := index / 8
   163  	elemOff := index % 8
   164  
   165  	if array.lastElemOff == 0 {
   166  		array.slice = append(array.slice, 0)
   167  	}
   168  	array.lastElemOff = (array.lastElemOff + 1) % 8
   169  
   170  	var lastBit bool
   171  	if elemOff != 0 {
   172  		elem := array.slice[elemIndex]
   173  
   174  		lastBit = elem&(1<<7) != 0
   175  		higherBits := elem >> elemOff << (elemOff + 1)
   176  		lowerBits := elem << (8 - elemOff) >> (8 - elemOff)
   177  
   178  		var shiftedValue uint8
   179  		if value {
   180  			shiftedValue = 1 << elemOff
   181  		}
   182  
   183  		newElem := higherBits | lowerBits | shiftedValue
   184  
   185  		array.slice[elemIndex] = newElem
   186  	}
   187  
   188  	for i := elemIndex + 1; i < len(array.slice); i++ {
   189  		elem := array.slice[i]
   190  
   191  		newLastBit := elem&(1<<7) != 0
   192  		elem = elem << 1
   193  
   194  		if lastBit {
   195  			elem |= 1
   196  		}
   197  
   198  		array.slice[i] = elem
   199  		lastBit = newLastBit
   200  	}
   201  }
   202  
   203  // Remove removes the bit at the specified index.
   204  func (array *Array) Remove(index int) {
   205  	index = array.getRealIndex(index)
   206  
   207  	elemIndex := index / 8
   208  	elemOff := index % 8
   209  
   210  	var firstBit bool
   211  	for i := len(array.slice) - 1; i > elemIndex; i-- {
   212  		elem := array.slice[i]
   213  
   214  		newFirstBit := elem&1 != 0
   215  		elem = elem >> 1
   216  
   217  		if firstBit {
   218  			elem |= 1 << 7
   219  		}
   220  
   221  		array.slice[i] = elem
   222  		firstBit = newFirstBit
   223  	}
   224  
   225  	if elemOff != 0 {
   226  		elem := array.slice[elemIndex]
   227  
   228  		higherBits := elem >> elemOff << elemOff
   229  		lowerBits := elem << (8 - elemOff) >> (8 - elemOff)
   230  
   231  		newElem := higherBits | lowerBits
   232  
   233  		array.slice[elemIndex] = newElem
   234  	}
   235  
   236  	array.lastElemOff = (array.lastElemOff - 1) % 8
   237  	if array.lastElemOff == 0 {
   238  		array.slice = array.slice[:len(array.slice)-1]
   239  	}
   240  }
   241  
   242  // Clear removes all bits from the Array.
   243  func (array *Array) Clear() {
   244  	array.slice = make([]uint8, 0)
   245  	array.lastElemOff = 0
   246  }
   247  
   248  // Reverse reverses the order of the bits in the Array.
   249  func (array *Array) Reverse() {
   250  	panic("not implemented")
   251  }
   252  
   253  // Join appends all bits from the specified Array to the end of the Array.
   254  func (array *Array) Join(other *Array) {
   255  	if array.lastElemOff == 0 {
   256  		array.slice = append(array.slice, other.slice...)
   257  		array.lastElemOff = other.lastElemOff
   258  	} else {
   259  		for i := range other.Size() {
   260  			array.Append(other.Get(i))
   261  		}
   262  	}
   263  
   264  	other.Clear()
   265  }
   266  
   267  // Clone returns a shallow copy of the Array.
   268  func (array *Array) Clone() *Array {
   269  	cloned := NewWithSize(array.Size())
   270  	cloned.lastElemOff = array.lastElemOff
   271  	copy(cloned.slice, array.slice)
   272  
   273  	return cloned
   274  }
   275  
   276  // String returns a string representation of the Array.
   277  func (array *Array) String() string {
   278  	var sb strings.Builder
   279  
   280  	for i := range array.Size() {
   281  		val := array.Get(i)
   282  
   283  		var char byte
   284  		if val {
   285  			char = '1'
   286  		} else {
   287  			char = '0'
   288  		}
   289  
   290  		sb.WriteByte(char)
   291  	}
   292  
   293  	return sb.String()
   294  }