-
Notifications
You must be signed in to change notification settings - Fork 0
/
shiftvertical.go
84 lines (70 loc) · 2.24 KB
/
shiftvertical.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package bits
import (
"math"
)
// ShiftDown takes a matrix of bytes and shifts a column of bits down
// by 'count'. Bits pushed off the bottom are rotated back around to
// the top. Each slice in the matrix is expected to be the same length.
func ShiftDown(matrix [][]byte, index float64, count float64) [][]byte {
yCursor := len(matrix) - int(count)
return shiftVertical(matrix, index, count, yCursor)
}
// ShiftUp takes a matrix of bytes and shifts a column of bits up
// by 'count'. Bits pushed off the top are rotated back around to
// the bottom. Each slice in the matrix is expected to be the same length.
func ShiftUp(matrix [][]byte, index float64, count float64) [][]byte {
yCursor := int(count)
return shiftVertical(matrix, index, count, yCursor)
}
func shiftVertical(matrix [][]byte, index float64, count float64, yCursor int) [][]byte {
validateVerticalShift(matrix, index, count)
xByte, mask := getMaskForByteArrayIndex(index)
froms := copyColumnBytes(matrix, yCursor, xByte)
copyIntoMatrix(froms, matrix, xByte, mask)
return matrix
}
func validateVerticalShift(matrix [][]byte, index float64, count float64) {
if int(count) >= len(matrix) {
panic("Must shift by a number less than the bits in the array")
}
if !matrixIsLongEnough(matrix, index) {
panic("Each slice in the matrix must be as long as the index")
}
if count <= 0 {
panic("Must shift by a number greater than 0")
}
}
func matrixIsLongEnough(matrix [][]byte, index float64) bool {
for i := 0; i < len(matrix); i++ {
if len(matrix[i]) < (int(index)/8 + 1) {
return false
}
}
return true
}
func getMaskForByteArrayIndex(index float64) (xByte int, mask byte) {
div := index / 8.0
xByte = int(math.Trunc(div))
offset := math.Remainder(index, 8)
if offset < 0 {
offset += 8
}
mask = NewSimpleCopyPasteMask(uint8(offset))
return
}
func copyColumnBytes(matrix [][]byte, rowStart, xIndex int) []byte {
froms := make([]byte, len(matrix))
for i := 0; i < len(matrix); i++ {
froms[i] = matrix[rowStart][xIndex]
rowStart++
if rowStart >= len(matrix) {
rowStart = 0
}
}
return froms
}
func copyIntoMatrix(from []byte, into [][]byte, xIndex int, mask byte) {
for i := 0; i < len(into); i++ {
into[i][xIndex] = CopyPaste(from[i], into[i][xIndex], mask)
}
}