Skip to content

Commit 2bad1f2

Browse files
committed
Densify BinaryVector
1 parent a78442d commit 2bad1f2

14 files changed

+174
-134
lines changed

binary_matrix.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,11 @@ func genericColumns(M BinaryMatrix) []BinaryVector {
149149
// xxx test
150150
func genericColumnVector(M BinaryMatrix, index int) BinaryVector {
151151
rows := M.NumRows()
152-
vector := make([]uint8, rows)
152+
vector := NewBinaryVector(rows)
153153
for i := 0; i < rows; i++ {
154-
vector[i] = M.Get(i,index)
154+
if M.Get(i, index) != 0 {
155+
vector.Set(i, 1)
156+
}
155157
}
156158
return vector
157159
}
@@ -424,7 +426,7 @@ func genericRandomize(M BinaryMatrix) {
424426
for i := 0; i < rows; i++ {
425427
vector := randomBitVector(cols)
426428
for j := 0; j < cols; j++ {
427-
M.Set(i, j, vector[j])
429+
M.Set(i, j, vector.Get(j))
428430
}
429431
}
430432
}
@@ -439,7 +441,7 @@ func genericRandomizeWithDensity(M BinaryMatrix, density float64) {
439441
vector := randomBitVector(cols)
440442
for j := 0; j < cols; j++ {
441443
if rand.Float64() < density {
442-
M.Set(i, j, vector[j])
444+
M.Set(i, j, vector.Get(j))
443445
}
444446
}
445447
}
@@ -496,9 +498,11 @@ func genericGetRows(M BinaryMatrix) []BinaryVector {
496498
// xxx test
497499
func genericRowVector(M BinaryMatrix, index int) BinaryVector {
498500
cols := M.NumColumns()
499-
vector := make([]uint8, cols)
501+
vector := NewBinaryVector(cols)
500502
for j := 0; j < cols; j++ {
501-
vector[j] = M.Get(index, j)
503+
if M.Get(index, j) != 0 {
504+
vector.Set(j, 1)
505+
}
502506
}
503507
return vector
504508
}
@@ -574,13 +578,15 @@ func genericSetFromString(M BinaryMatrix, s string) {
574578
func genericSetFromRowVectors(M BinaryMatrix, rowData []BinaryVector) {
575579
rows := M.NumRows()
576580
cols := M.NumColumns()
577-
if (len(rowData) != rows) || (len(rowData[0]) != cols) {
581+
if (len(rowData) != rows) || (rowData[0].Length() != cols) {
578582
panic(fmt.Sprintf("matrix shape not compatible: (%dx%d) != (%dx%d)",
579-
rows, cols, len(rowData), len(rowData[0])))
583+
rows, cols, len(rowData), rowData[0].Length()))
580584
}
581585
for i := 0; i < rows; i++ {
582586
for j := 0; j < cols; j++ {
583-
M.Set(i, j, rowData[i][j])
587+
if rowData[i].Get(j) != 0 {
588+
M.Set(i, j, 1)
589+
}
584590
}
585591
}
586592
}

binary_matrix_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ func TestBinaryMatrix_ColumnVector(t *testing.T) {
461461
{1, 1, 0, 1},
462462
}),
463463
column: 2,
464-
want: BinaryVector{1, 1, 0},
464+
want: NewBinaryVectorFromInts([]uint8{1, 1, 0}),
465465
},
466466
}
467467
for _, tt := range tests {
@@ -490,10 +490,10 @@ func TestBinaryMatrix_Columns(t *testing.T) {
490490
{1, 1, 0, 1},
491491
}),
492492
want: []BinaryVector{
493-
{1, 0, 1},
494-
{0, 1, 1},
495-
{1, 1, 0},
496-
{0, 0, 1},
493+
NewBinaryVectorFromInts([]uint8{1, 0, 1}),
494+
NewBinaryVectorFromInts([]uint8{0, 1, 1}),
495+
NewBinaryVectorFromInts([]uint8{1, 1, 0}),
496+
NewBinaryVectorFromInts([]uint8{0, 0, 1}),
497497
},
498498
},
499499
}

binary_vector.go

Lines changed: 98 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,122 +2,153 @@ package golsv
22

33
import (
44
"bytes"
5+
"crypto/rand"
56
"fmt"
6-
"math/rand"
7+
mathrand "math/rand"
8+
"github.com/lukechampine/fastxor"
79
)
810

9-
// xxx densify?
10-
type BinaryVector []uint8
11+
type BinaryVector struct {
12+
length int
13+
data []byte
14+
}
1115

1216
func NewBinaryVector(n int) BinaryVector {
13-
return make([]uint8, n)
17+
return BinaryVector{
18+
n,
19+
make([]byte, words(n)),
20+
}
21+
}
22+
23+
func words(n int) int {
24+
return (n + 7) / 8
1425
}
1526

1627
func NewBinaryVectorFromInts(ints []uint8) BinaryVector {
17-
cols := len(ints)
18-
V := NewBinaryVector(cols)
19-
for j := 0; j < cols; j++ {
20-
V[j] = ints[j]
28+
rows := len(ints)
29+
v := NewBinaryVector(rows)
30+
for i, b := range ints {
31+
if b != 0 {
32+
v.Set(i, 1)
33+
}
34+
}
35+
return v
36+
}
37+
38+
func NewBinaryVectorFromString(s string) BinaryVector {
39+
v := NewBinaryVector(len(s))
40+
for i, c := range s {
41+
if c == '1' {
42+
v.Set(i, 1)
43+
}
2144
}
22-
return V
45+
return v
2346
}
2447

2548
func ZeroVector(n int) BinaryVector {
26-
return make([]uint8, n)
49+
return NewBinaryVector(n)
2750
}
2851

2952
// xxx test
30-
func (V BinaryVector) Add(U BinaryVector) BinaryVector {
31-
W := NewBinaryVector(len(V))
32-
for i := 0; i < len(V); i++ {
33-
W[i] = V[i] ^ U[i]
34-
}
35-
return W
53+
func (v BinaryVector) Add(u BinaryVector) BinaryVector {
54+
w := NewBinaryVector(v.Length())
55+
fastxor.Bytes(w.data, v.data, u.data)
56+
return w
3657
}
3758

3859
// xxx test
39-
func (V BinaryVector) Equal(U BinaryVector) bool {
40-
if len(V) != len(U) {
41-
return false
42-
}
43-
for i := 0; i < len(V); i++ {
44-
if V[i] != U[i] {
45-
return false
46-
}
47-
}
48-
return true
60+
func (v BinaryVector) AddInPlace(u BinaryVector) {
61+
fastxor.Bytes(v.data, v.data, u.data)
62+
}
63+
64+
// xxx test
65+
func (v BinaryVector) Equal(u BinaryVector) bool {
66+
return v.length == u.length && bytes.Equal(v.data, u.data)
67+
}
68+
69+
// xxx test
70+
func (v BinaryVector) Get(i int) uint8 {
71+
return (v.data[i/8] >> uint(i%8)) & 1
4972
}
5073

5174
// xxx experimental
52-
func (V BinaryVector) IntegerDotProduct(U BinaryVector) int {
75+
func (v BinaryVector) IntegerDotProduct(u BinaryVector) int {
5376
d := 0
54-
for i := 0; i < len(V); i++ {
55-
d += int(V[i]) * int(U[i])
77+
for i := 0; i < v.Length(); i++ {
78+
d += int(v.Get(i)) * int(u.Get(i))
5679
}
5780
return d
5881
}
5982

6083
// xxx test
61-
func (V BinaryVector) Length() int {
62-
return len(V)
84+
func (v BinaryVector) Length() int {
85+
return v.length
6386
}
6487

65-
// xxx rename to DenseBinaryMatrix
66-
func (V BinaryVector) Matrix() *DenseBinaryMatrix {
67-
rows := len(V)
68-
M := NewDenseBinaryMatrix(rows, 1)
69-
for i := 0; i < rows; i++ {
70-
M.Set(i, 0, V[i])
71-
}
88+
// xxx rename to DenseBinaryMatrix?
89+
func (v BinaryVector) Matrix() *DenseBinaryMatrix {
90+
M := NewDenseBinaryMatrix(v.Length(), 1)
91+
copy(M.Data, v.data)
7292
return M
7393
}
7494

75-
func (V BinaryVector) IsZero() bool {
76-
for _, elem := range V {
77-
if elem != 0 {
95+
func (v BinaryVector) IsZero() bool {
96+
for _, d := range v.data {
97+
if d != 0 {
7898
return false
7999
}
80100
}
81101
return true
82102
}
83103

84-
func (V BinaryVector) Project(n int, predicate func (i int) bool) BinaryVector {
85-
pV := NewBinaryVector(n)
104+
func (v BinaryVector) Project(n int, predicate func (i int) bool) BinaryVector {
105+
pv := NewBinaryVector(n)
86106
j := 0
87-
for i, b := range V {
107+
for i := 0; i < v.Length(); i++ {
88108
if predicate(i) {
89-
pV[j] = b
109+
pv.Set(j, v.Get(i))
90110
j++
91111
}
92112
}
93-
return pV
113+
return pv
94114
}
95115

96116
// xxx test
97-
func (V BinaryVector) RandomizeWithWeight(weight int) {
98-
n := len(V)
117+
func (v BinaryVector) RandomizeWithWeight(weight int) {
118+
n := v.Length()
99119
for i := 0; i < n; i++ {
100-
V[i] = 0
120+
v.Set(i, 0)
101121
}
102122
for i := 0; i < weight; i++ {
103-
V[rand.Intn(n)] = 1
123+
v.Set(mathrand.Intn(n), 1)
104124
}
105125
}
106126

107127
// xxx test
108-
func (V BinaryVector) SparseBinaryMatrix() *Sparse {
109-
rows := len(V)
128+
func (v BinaryVector) Set(i int, b uint8) {
129+
if b == 0 {
130+
v.data[i/8] &= ^(1 << uint(i%8))
131+
} else {
132+
v.data[i/8] |= 1 << uint(i%8)
133+
}
134+
}
135+
136+
// xxx test
137+
func (v BinaryVector) SparseBinaryMatrix() *Sparse {
138+
rows := v.Length()
110139
M := NewSparseBinaryMatrix(rows, 1)
111140
for i := 0; i < rows; i++ {
112-
M.Set(i, 0, V[i])
141+
if v.Get(i) == 1 {
142+
M.Set(i, 0, 1)
143+
}
113144
}
114145
return M
115146
}
116147

117-
func (V BinaryVector) String() string {
148+
func (v BinaryVector) String() string {
118149
var buf bytes.Buffer
119-
for _, b := range V {
120-
if b == 0 {
150+
for i := 0; i < v.Length(); i++ {
151+
if v.Get(i) == 0 {
121152
buf.WriteString("0")
122153
} else {
123154
buf.WriteString("1")
@@ -126,12 +157,12 @@ func (V BinaryVector) String() string {
126157
return buf.String()
127158
}
128159

129-
func (V BinaryVector) SupportString() string {
160+
func (v BinaryVector) SupportString() string {
130161
var buf bytes.Buffer
131162
first := true
132163
buf.WriteString("[+")
133-
for i, b := range V {
134-
if b == 1 {
164+
for i := 0; i < v.Length(); i++ {
165+
if v.Get(i) == 1 {
135166
if !first {
136167
buf.WriteString(",")
137168
}
@@ -143,22 +174,23 @@ func (V BinaryVector) SupportString() string {
143174
return buf.String()
144175
}
145176

146-
func (V BinaryVector) Weight() int {
177+
func (v BinaryVector) Weight() int {
147178
weight := 0
148-
for _, b := range V {
149-
if b == 1 {
179+
for i := 0; i < v.Length(); i++ {
180+
if v.Get(i) == 1 {
150181
weight++
151182
}
152183
}
153184
return weight
154185
}
155186

156187
func randomBitVector(length int) BinaryVector {
157-
vector := make([]uint8, length)
158-
for i := 0; i < length; i++ {
159-
vector[i] = uint8(rand.Intn(2))
188+
v := NewBinaryVector(length)
189+
_, err := rand.Read(v.data)
190+
if err != nil {
191+
panic(err)
160192
}
161-
return vector
193+
return v
162194
}
163195

164196
// xxx move to BinaryVector

0 commit comments

Comments
 (0)