-
Notifications
You must be signed in to change notification settings - Fork 6
/
waveletmatrix_builder.go
executable file
·113 lines (97 loc) · 2.43 KB
/
waveletmatrix_builder.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package waveletmatrix
import (
"errors"
"github.com/hideo55/go-sbvector"
)
type wmBuilderData struct {
wm *WMData
}
type wmBuilder interface {
Build(src []uint64) (WaveletMatrix, error)
}
var (
ErrorEmpty = errors.New("Argument is empty.")
)
func NewWM(src []uint64) (WaveletMatrix, error) {
builder := &wmBuilderData{}
builder.wm = &WMData{}
return builder.Build(src)
}
func (builder *wmBuilderData) Build(src []uint64) (WaveletMatrix, error) {
builder.wm = &WMData{}
wm := builder.wm
alphabetNum := getAlphabetNum(src)
wm.alphabetNum = alphabetNum
if alphabetNum == 0 {
return nil, ErrorEmpty
}
alphabetBitNum := log2(alphabetNum)
wm.alphabetBitNum = alphabetBitNum
wm.size = uint64(len(src))
wm.nodePos = make([][]uint64, alphabetBitNum)
bvBuilders := make([]sbvector.SuccinctBitVectorBuilder, alphabetBitNum)
for i := uint64(0); i < alphabetBitNum; i++ {
bvBuilders[i] = sbvector.NewVectorBuilder()
}
wm.bv = make([]*sbvector.BitVectorData, alphabetBitNum)
dummy := make([]uint64, 2)
dummy[0] = uint64(0)
dummy[1] = uint64(wm.size)
prev_begin_pos := &dummy
for i := uint64(0); i < alphabetBitNum; i++ {
wm.nodePos[i] = make([]uint64, (1 << (i + 1)))
for j := uint64(0); j < wm.size; j++ {
bit := (src[j] >> (alphabetBitNum - i - 1)) & 1
subscript := src[j] >> (alphabetBitNum - i)
bvElm := true
if bit == 0 {
bvElm = false
}
bvBuilders[i].Set((*prev_begin_pos)[subscript], bvElm)
(*prev_begin_pos)[subscript]++
wm.nodePos[i][(subscript<<1)|bit]++
}
cur_max := uint64(1) << i
rev := cur_max - uint64(1)
prev_rev := rev
for j := rev; j > 0; j-- {
rev ^= cur_max - (cur_max / 2 / (j & -j))
(*prev_begin_pos)[prev_rev] = (*prev_begin_pos)[rev]
prev_rev = rev
}
(*prev_begin_pos)[0] = 0
cur_max <<= 1
rev = uint64(0)
sum := uint64(0)
for j := uint64(0); j < cur_max; rev ^= cur_max - (cur_max / 2 / (j & -j)) {
t := wm.nodePos[i][rev]
wm.nodePos[i][rev] = sum
sum += t
j++
}
bv, _ := bvBuilders[i].Build(true, true)
wm.bv[i] = bv.(*sbvector.BitVectorData)
prev_begin_pos = &((*wm).nodePos[i])
}
return wm, nil
}
func getAlphabetNum(array []uint64) uint64 {
alphabetNum := uint64(0)
for i := 0; i < len(array); i++ {
if array[i] >= alphabetNum {
alphabetNum = array[i] + uint64(1)
}
}
return alphabetNum
}
func log2(x uint64) uint64 {
if x == 0 {
return 0
}
x--
bitNum := uint64(0)
for (x >> bitNum) != 0 {
bitNum++
}
return bitNum
}