-
Notifications
You must be signed in to change notification settings - Fork 0
/
lzma_len_coder.go
126 lines (113 loc) · 3.28 KB
/
lzma_len_coder.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
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (c) 2010, Andrei Vieru. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package lzma
type lenCoder struct {
choice []uint16
lowCoder []*rangeBitTreeCoder
midCoder []*rangeBitTreeCoder
highCoder *rangeBitTreeCoder
}
func newLenCoder(numPosStates /*1 << pb*/ uint32) *lenCoder {
lc := &lenCoder{
choice: initBitModels(2),
lowCoder: make([]*rangeBitTreeCoder, kNumPosStatesMax),
midCoder: make([]*rangeBitTreeCoder, kNumPosStatesMax),
highCoder: newRangeBitTreeCoder(kNumHighLenBits),
}
for i := uint32(0); i < numPosStates; i++ {
lc.lowCoder[i] = newRangeBitTreeCoder(kNumLowLenBits)
lc.midCoder[i] = newRangeBitTreeCoder(kNumMidLenBits)
}
return lc
}
func (lc *lenCoder) decode(rd *rangeDecoder, posState uint32) (res uint32) {
i := rd.decodeBit(lc.choice, 0)
if i == 0 {
res = lc.lowCoder[posState].decode(rd)
return
}
res = kNumLowLenSymbols
j := rd.decodeBit(lc.choice, 1)
if j == 0 {
k := lc.midCoder[posState].decode(rd)
res += k
return
} else {
l := lc.highCoder.decode(rd)
res = res + kNumMidLenSymbols + l
return
}
return
}
func (lc *lenCoder) encode(re *rangeEncoder, symbol, posState uint32) {
if symbol < kNumLowLenSymbols {
re.encode(lc.choice, 0, 0)
lc.lowCoder[posState].encode(re, symbol)
} else {
symbol -= kNumLowLenSymbols
re.encode(lc.choice, 0, 1)
if symbol < kNumMidLenSymbols {
re.encode(lc.choice, 1, 0)
lc.midCoder[posState].encode(re, symbol)
} else {
re.encode(lc.choice, 1, 1)
lc.highCoder.encode(re, symbol-kNumMidLenSymbols)
}
}
}
// write prices into prices []uint32
func (lc *lenCoder) setPrices(prices []uint32, posState, numSymbols, st uint32) {
a0 := getPrice0(lc.choice[0])
a1 := getPrice1(lc.choice[0])
b0 := a1 + getPrice0(lc.choice[1])
b1 := a1 + getPrice1(lc.choice[1])
var i uint32
for i = 0; i < kNumLowLenSymbols; i++ {
if i >= numSymbols {
return
}
prices[st+i] = a0 + lc.lowCoder[posState].getPrice(i)
}
for ; i < kNumLowLenSymbols+kNumMidLenSymbols; i++ {
if i >= numSymbols {
return
}
prices[st+i] = b0 + lc.midCoder[posState].getPrice(i-kNumLowLenSymbols)
}
for ; i < numSymbols; i++ {
prices[st+i] = b1 + lc.highCoder.getPrice(i-kNumLowLenSymbols-kNumMidLenSymbols)
}
}
type lenPriceTableCoder struct {
lc *lenCoder
prices []uint32
counters []uint32
tableSize uint32
}
func newLenPriceTableCoder(tableSize, numPosStates uint32) *lenPriceTableCoder {
pc := &lenPriceTableCoder{
lc: newLenCoder(numPosStates),
prices: make([]uint32, kNumLenSymbols<<kNumPosStatesBitsMax),
counters: make([]uint32, kNumPosStatesMax),
tableSize: tableSize,
}
for posState := uint32(0); posState < numPosStates; posState++ {
pc.updateTable(posState)
}
return pc
}
func (pc *lenPriceTableCoder) updateTable(posState uint32) {
pc.lc.setPrices(pc.prices, posState, pc.tableSize, posState*kNumLenSymbols)
pc.counters[posState] = pc.tableSize
}
func (pc *lenPriceTableCoder) getPrice(symbol, posState uint32) uint32 {
return pc.prices[posState*kNumLenSymbols+symbol]
}
func (pc *lenPriceTableCoder) encode(re *rangeEncoder, symbol, posState uint32) {
pc.lc.encode(re, symbol, posState)
pc.counters[posState]--
if pc.counters[posState] == 0 {
pc.updateTable(posState)
}
}