github.com/tunabay/go-bitarray@v1.3.1/bitarray_shift.go (about) 1 // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved. 2 // Use of this source code is governed by the MIT license that can be found in 3 // the LICENSE file. 4 5 package bitarray 6 7 import ( 8 "math/bits" 9 ) 10 11 // Reverse returns the bit array with its bits in reversed order. 12 func (ba *BitArray) Reverse() *BitArray { 13 switch { 14 case ba.IsZero(): 15 return zeroBitArray 16 case ba.Len() == 1, ba.b == nil: 17 return ba 18 } 19 buf := make([]byte, len(ba.b)) 20 for i, o := range ba.b { 21 buf[len(ba.b)-1-i] = bits.Reverse8(o) 22 } 23 24 return NewFromBytes(buf, ba.NumPadding(), ba.nBits) 25 } 26 27 // ShiftLeft returns the bit array of shifted left by k bits. 28 // To shift to right, call ShiftLeft(-k). 29 func (ba *BitArray) ShiftLeft(k int) *BitArray { 30 switch { 31 case ba.IsZero(): 32 return zeroBitArray 33 case ba.b == nil: 34 return ba 35 case ba.nBits <= k, ba.nBits <= -k: 36 return &BitArray{nBits: ba.nBits} 37 case 0 < k: 38 return ba.shiftLeft(k) 39 case k < 0: 40 return ba.shiftRight(-k) 41 } 42 43 return ba 44 } 45 46 func (ba *BitArray) shiftLeft(k int) *BitArray { 47 if k&7 == 0 { 48 buf := allocByteSlice(len(ba.b)) 49 copy(buf, ba.b[k>>3:]) 50 return &BitArray{b: buf, nBits: ba.nBits} 51 } 52 53 return ba.Slice(k, ba.nBits).append1(&BitArray{nBits: k}) 54 } 55 56 func (ba *BitArray) shiftRight(k int) *BitArray { 57 if k&7 == 0 { 58 buf := allocByteSlice(len(ba.b)) 59 copy(buf[k>>3:], ba.b) 60 if npad := ba.NumPadding(); npad != 0 { 61 mask := byte(0xff) << npad 62 buf[len(buf)-1] &= mask 63 } 64 return &BitArray{b: buf, nBits: ba.nBits} 65 } 66 67 return (&BitArray{nBits: k}).append1(ba.Slice(0, ba.nBits-k)) 68 } 69 70 // RotateLeft returns the bit array of rotated left by k bits. 71 // To rotate to right, call RotateLeft(-k). 72 func (ba *BitArray) RotateLeft(k int) *BitArray { 73 switch { 74 case ba.IsZero(): 75 return zeroBitArray 76 case ba.b == nil: 77 return ba 78 case 0 < k: 79 return ba.rotateLeft(k) 80 case k < 0: 81 return ba.rotateRight(-k) 82 } 83 84 return ba 85 } 86 87 func (ba *BitArray) rotateLeft(k int) *BitArray { 88 k %= ba.nBits 89 switch { 90 case k == 0: 91 return ba 92 case k&7 == 0 && ba.nBits&7 == 0: 93 buf := allocByteSlice(len(ba.b)) 94 nbs := k >> 3 95 copy(buf, ba.b[nbs:]) 96 copy(buf[len(buf)-nbs:], ba.b) 97 return &BitArray{b: buf, nBits: ba.nBits} 98 } 99 100 return ba.Slice(k, ba.nBits).append1(ba.Slice(0, k)) 101 } 102 103 func (ba *BitArray) rotateRight(k int) *BitArray { 104 k %= ba.nBits 105 switch { 106 case k == 0: 107 return ba 108 case k&7 == 0 && ba.nBits&7 == 0: 109 buf := allocByteSlice(len(ba.b)) 110 nbs := k >> 3 111 copy(buf[nbs:], ba.b) 112 copy(buf, ba.b[len(ba.b)-nbs:]) 113 return &BitArray{b: buf, nBits: ba.nBits} 114 } 115 116 return ba.Slice(ba.nBits-k, ba.nBits).append1(ba.Slice(0, ba.nBits-k)) 117 }