Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1096 lines
22 KiB
1096 lines
22 KiB
package rardecode |
|
|
|
import ( |
|
"errors" |
|
"io" |
|
) |
|
|
|
const ( |
|
rangeBottom = 1 << 15 |
|
rangeTop = 1 << 24 |
|
|
|
maxFreq = 124 |
|
|
|
intBits = 7 |
|
periodBits = 7 |
|
binScale = 1 << (intBits + periodBits) |
|
|
|
n0 = 1 |
|
n1 = 4 |
|
n2 = 4 |
|
n3 = 4 |
|
n4 = (128 + 3 - 1*n1 - 2*n2 - 3*n3) / 4 |
|
nIndexes = n0 + n1 + n2 + n3 + n4 |
|
|
|
// memory is allocated in units. A unit contains unitSize number of bytes. |
|
// A unit can store one context or two states. |
|
unitSize = 12 |
|
|
|
maxUint16 = 1<<16 - 1 |
|
freeMark = -1 |
|
) |
|
|
|
var ( |
|
errCorruptPPM = errors.New("rardecode: corrupt ppm data") |
|
|
|
expEscape = []byte{25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2} |
|
initBinEsc = []uint16{0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051} |
|
|
|
ns2Index [256]byte |
|
ns2BSIndex [256]byte |
|
|
|
// units2Index maps the number of units in a block to a freelist index |
|
units2Index [128 + 1]byte |
|
// index2Units maps a freelist index to the size of the block in units |
|
index2Units [nIndexes]int32 |
|
) |
|
|
|
func init() { |
|
ns2BSIndex[0] = 2 * 0 |
|
ns2BSIndex[1] = 2 * 1 |
|
for i := 2; i < 11; i++ { |
|
ns2BSIndex[i] = 2 * 2 |
|
} |
|
for i := 11; i < 256; i++ { |
|
ns2BSIndex[i] = 2 * 3 |
|
} |
|
|
|
var j, n byte |
|
for i := range ns2Index { |
|
ns2Index[i] = n |
|
if j <= 3 { |
|
n++ |
|
j = n |
|
} else { |
|
j-- |
|
} |
|
} |
|
|
|
var ii byte |
|
var iu, units int32 |
|
for i, n := range []int{n0, n1, n2, n3, n4} { |
|
for j := 0; j < n; j++ { |
|
units += int32(i) |
|
index2Units[ii] = units |
|
for iu <= units { |
|
units2Index[iu] = ii |
|
iu++ |
|
} |
|
ii++ |
|
} |
|
} |
|
} |
|
|
|
type rangeCoder struct { |
|
br io.ByteReader |
|
code uint32 |
|
low uint32 |
|
rnge uint32 |
|
} |
|
|
|
func (r *rangeCoder) init(br io.ByteReader) error { |
|
r.br = br |
|
r.low = 0 |
|
r.rnge = ^uint32(0) |
|
for i := 0; i < 4; i++ { |
|
c, err := r.br.ReadByte() |
|
if err != nil { |
|
return err |
|
} |
|
r.code = r.code<<8 | uint32(c) |
|
} |
|
return nil |
|
} |
|
|
|
func (r *rangeCoder) currentCount(scale uint32) uint32 { |
|
r.rnge /= scale |
|
return (r.code - r.low) / r.rnge |
|
} |
|
|
|
func (r *rangeCoder) normalize() error { |
|
for { |
|
if r.low^(r.low+r.rnge) >= rangeTop { |
|
if r.rnge >= rangeBottom { |
|
return nil |
|
} |
|
r.rnge = -r.low & (rangeBottom - 1) |
|
} |
|
c, err := r.br.ReadByte() |
|
if err != nil { |
|
return err |
|
} |
|
r.code = r.code<<8 | uint32(c) |
|
r.rnge <<= 8 |
|
r.low <<= 8 |
|
} |
|
} |
|
|
|
func (r *rangeCoder) decode(lowCount, highCount uint32) error { |
|
r.low += r.rnge * lowCount |
|
r.rnge *= highCount - lowCount |
|
|
|
return r.normalize() |
|
} |
|
|
|
type see2Context struct { |
|
summ uint16 |
|
shift byte |
|
count byte |
|
} |
|
|
|
func newSee2Context(i uint16) see2Context { |
|
return see2Context{i << (periodBits - 4), (periodBits - 4), 4} |
|
} |
|
|
|
func (s *see2Context) mean() uint32 { |
|
if s == nil { |
|
return 1 |
|
} |
|
n := s.summ >> s.shift |
|
if n == 0 { |
|
return 1 |
|
} |
|
s.summ -= n |
|
return uint32(n) |
|
} |
|
|
|
func (s *see2Context) update() { |
|
if s == nil || s.shift >= periodBits { |
|
return |
|
} |
|
s.count-- |
|
if s.count == 0 { |
|
s.summ += s.summ |
|
s.count = 3 << s.shift |
|
s.shift++ |
|
} |
|
} |
|
|
|
type state struct { |
|
sym byte |
|
freq byte |
|
|
|
// succ can point to a context or byte in memory. |
|
// A context pointer is a positive integer. It is an index into the states |
|
// array that points to the first of two states which the context is |
|
// marshalled into. |
|
// A byte pointer is a negative integer. The magnitude represents the position |
|
// in bytes from the bottom of the memory. As memory is modelled as an array of |
|
// states, this is used to calculate which state, and where in the state the |
|
// byte is stored. |
|
// A zero value represents a nil pointer. |
|
succ int32 |
|
} |
|
|
|
// uint16 return a uint16 stored in the sym and freq fields of a state |
|
func (s state) uint16() uint16 { return uint16(s.sym) | uint16(s.freq)<<8 } |
|
|
|
// setUint16 stores a uint16 in the sym and freq fields of a state |
|
func (s *state) setUint16(n uint16) { s.sym = byte(n); s.freq = byte(n >> 8) } |
|
|
|
// A context is marshalled into a slice of two states. |
|
// The first state contains the number of states, and the suffix pointer. |
|
// If there is only one state, the second state contains that state. |
|
// If there is more than one state, the second state contains the summFreq |
|
// and the index to the slice of states. |
|
type context struct { |
|
i int32 // index into the states array for context |
|
s []state // slice of two states representing context |
|
a *subAllocator |
|
} |
|
|
|
// succPtr returns a pointer value for the context to be stored in a state.succ |
|
func (c *context) succPtr() int32 { return c.i } |
|
|
|
func (c *context) numStates() int { return int(c.s[0].uint16()) } |
|
|
|
func (c *context) setNumStates(n int) { c.s[0].setUint16(uint16(n)) } |
|
|
|
func (c *context) statesIndex() int32 { return c.s[1].succ } |
|
|
|
func (c *context) setStatesIndex(n int32) { c.s[1].succ = n } |
|
|
|
func (c *context) suffix() *context { return c.a.succContext(c.s[0].succ) } |
|
|
|
func (c *context) setSuffix(sc *context) { c.s[0].succ = sc.i } |
|
|
|
func (c *context) summFreq() uint16 { return c.s[1].uint16() } |
|
|
|
func (c *context) setSummFreq(f uint16) { c.s[1].setUint16(f) } |
|
|
|
func (c *context) notEq(ctx *context) bool { return c.i != ctx.i } |
|
|
|
func (c *context) states() []state { |
|
if ns := int32(c.s[0].uint16()); ns != 1 { |
|
i := c.s[1].succ |
|
return c.a.states[i : i+ns] |
|
} |
|
return c.s[1:] |
|
} |
|
|
|
// shrinkStates shrinks the state list down to size states |
|
func (c *context) shrinkStates(states []state, size int) []state { |
|
i1 := units2Index[(len(states)+1)>>1] |
|
i2 := units2Index[(size+1)>>1] |
|
|
|
if size == 1 { |
|
// store state in context, and free states block |
|
n := c.statesIndex() |
|
c.s[1] = states[0] |
|
states = c.s[1:] |
|
c.a.addFreeBlock(n, i1) |
|
} else if i1 != i2 { |
|
if n := c.a.removeFreeBlock(i2); n > 0 { |
|
// allocate new block and copy |
|
copy(c.a.states[n:], states[:size]) |
|
states = c.a.states[n:] |
|
// free old block |
|
c.a.addFreeBlock(c.statesIndex(), i1) |
|
c.setStatesIndex(n) |
|
} else { |
|
// split current block, and free units not needed |
|
n = c.statesIndex() + index2Units[i2]<<1 |
|
u := index2Units[i1] - index2Units[i2] |
|
c.a.freeUnits(n, u) |
|
} |
|
} |
|
c.setNumStates(size) |
|
return states[:size] |
|
} |
|
|
|
// expandStates expands the states list by one |
|
func (c *context) expandStates() []state { |
|
states := c.states() |
|
ns := len(states) |
|
if ns == 1 { |
|
s := states[0] |
|
n := c.a.allocUnits(1) |
|
if n == 0 { |
|
return nil |
|
} |
|
c.setStatesIndex(n) |
|
states = c.a.states[n:] |
|
states[0] = s |
|
} else if ns&0x1 == 0 { |
|
u := ns >> 1 |
|
i1 := units2Index[u] |
|
i2 := units2Index[u+1] |
|
if i1 != i2 { |
|
n := c.a.allocUnits(i2) |
|
if n == 0 { |
|
return nil |
|
} |
|
copy(c.a.states[n:], states) |
|
c.a.addFreeBlock(c.statesIndex(), i1) |
|
c.setStatesIndex(n) |
|
states = c.a.states[n:] |
|
} |
|
} |
|
c.setNumStates(ns + 1) |
|
return states[:ns+1] |
|
} |
|
|
|
type subAllocator struct { |
|
// memory for allocation is split into two heaps |
|
|
|
heap1MaxBytes int32 // maximum bytes available in heap1 |
|
heap1Lo int32 // heap1 bottom in number of bytes |
|
heap1Hi int32 // heap1 top in number of bytes |
|
heap2Lo int32 // heap2 bottom index in states |
|
heap2Hi int32 // heap2 top index in states |
|
glueCount int |
|
|
|
// Each freeList entry contains an index into states for the beginning |
|
// of a free block. The first state in that block may contain an index |
|
// to another free block and so on. The size of the free block in units |
|
// (2 states) for that freeList index can be determined from the |
|
// index2Units array. |
|
freeList [nIndexes]int32 |
|
|
|
// Instead of bytes, memory is represented by a slice of states. |
|
// context's are marshalled to and from a pair of states. |
|
// multiple bytes are stored in a state. |
|
states []state |
|
} |
|
|
|
func (a *subAllocator) init(maxMB int) { |
|
bytes := int32(maxMB) << 20 |
|
heap2Units := bytes / 8 / unitSize * 7 |
|
a.heap1MaxBytes = bytes - heap2Units*unitSize |
|
// Add one for the case when bytes are not a multiple of unitSize |
|
heap1Units := a.heap1MaxBytes/unitSize + 1 |
|
// Calculate total size in state's. Add 1 unit so we can reserve the first unit. |
|
// This will allow us to use the zero index as a nil pointer. |
|
n := int(1+heap1Units+heap2Units) * 2 |
|
if cap(a.states) > n { |
|
a.states = a.states[:n] |
|
} else { |
|
a.states = make([]state, n) |
|
} |
|
} |
|
|
|
func (a *subAllocator) restart() { |
|
// Pad heap1 start by 1 unit and enough bytes so that there is no |
|
// gap between heap1 end and heap2 start. |
|
a.heap1Lo = unitSize + (unitSize - a.heap1MaxBytes%unitSize) |
|
a.heap1Hi = unitSize + (a.heap1MaxBytes/unitSize+1)*unitSize |
|
a.heap2Lo = a.heap1Hi / unitSize * 2 |
|
a.heap2Hi = int32(len(a.states)) |
|
a.glueCount = 0 |
|
for i := range a.freeList { |
|
a.freeList[i] = 0 |
|
} |
|
for i := range a.states { |
|
a.states[i] = state{} |
|
} |
|
} |
|
|
|
// pushByte puts a byte on the heap and returns a state.succ index that |
|
// can be used to retrieve it. |
|
func (a *subAllocator) pushByte(c byte) int32 { |
|
si := a.heap1Lo / 6 // state index |
|
oi := a.heap1Lo % 6 // byte position in state |
|
switch oi { |
|
case 0: |
|
a.states[si].sym = c |
|
case 1: |
|
a.states[si].freq = c |
|
default: |
|
n := (uint(oi) - 2) * 8 |
|
mask := ^(uint32(0xFF) << n) |
|
succ := uint32(a.states[si].succ) & mask |
|
succ |= uint32(c) << n |
|
a.states[si].succ = int32(succ) |
|
} |
|
a.heap1Lo++ |
|
if a.heap1Lo >= a.heap1Hi { |
|
return 0 |
|
} |
|
return -a.heap1Lo |
|
} |
|
|
|
// popByte reverses the previous pushByte |
|
func (a *subAllocator) popByte() { a.heap1Lo-- } |
|
|
|
// succByte returns a byte from the heap given a state.succ index |
|
func (a *subAllocator) succByte(i int32) byte { |
|
i = -i |
|
si := i / 6 |
|
oi := i % 6 |
|
switch oi { |
|
case 0: |
|
return a.states[si].sym |
|
case 1: |
|
return a.states[si].freq |
|
default: |
|
n := (uint(oi) - 2) * 8 |
|
succ := uint32(a.states[si].succ) >> n |
|
return byte(succ & 0xff) |
|
} |
|
} |
|
|
|
// succContext returns a context given a state.succ index |
|
func (a *subAllocator) succContext(i int32) *context { |
|
if i <= 0 { |
|
return nil |
|
} |
|
return &context{i: i, s: a.states[i : i+2 : i+2], a: a} |
|
} |
|
|
|
// succIsNil returns whether a state.succ points to nothing |
|
func (a *subAllocator) succIsNil(i int32) bool { return i == 0 } |
|
|
|
// nextByteAddr takes a state.succ value representing a pointer |
|
// to a byte, and returns the next bytes address |
|
func (a *subAllocator) nextByteAddr(n int32) int32 { return n - 1 } |
|
|
|
func (a *subAllocator) removeFreeBlock(i byte) int32 { |
|
n := a.freeList[i] |
|
if n != 0 { |
|
a.freeList[i] = a.states[n].succ |
|
a.states[n] = state{} |
|
} |
|
return n |
|
} |
|
|
|
func (a *subAllocator) addFreeBlock(n int32, i byte) { |
|
a.states[n].succ = a.freeList[i] |
|
a.freeList[i] = n |
|
} |
|
|
|
func (a *subAllocator) freeUnits(n, u int32) { |
|
i := units2Index[u] |
|
if u != index2Units[i] { |
|
i-- |
|
a.addFreeBlock(n, i) |
|
u -= index2Units[i] |
|
n += index2Units[i] << 1 |
|
i = units2Index[u] |
|
} |
|
a.addFreeBlock(n, i) |
|
} |
|
|
|
func (a *subAllocator) glueFreeBlocks() { |
|
var freeIndex int32 |
|
|
|
for i, n := range a.freeList { |
|
s := state{succ: freeMark} |
|
s.setUint16(uint16(index2Units[i])) |
|
for n != 0 { |
|
states := a.states[n:] |
|
states[1].succ = freeIndex |
|
freeIndex = n |
|
n = states[0].succ |
|
states[0] = s |
|
} |
|
a.freeList[i] = 0 |
|
} |
|
|
|
for i := freeIndex; i != 0; i = a.states[i+1].succ { |
|
if a.states[i].succ != freeMark { |
|
continue |
|
} |
|
u := int32(a.states[i].uint16()) |
|
states := a.states[i+u<<1:] |
|
for len(states) > 0 && states[0].succ == freeMark { |
|
u += int32(states[0].uint16()) |
|
if u > maxUint16 { |
|
break |
|
} |
|
states[0].succ = 0 |
|
a.states[i].setUint16(uint16(u)) |
|
states = a.states[i+u<<1:] |
|
} |
|
} |
|
|
|
for n := freeIndex; n != 0; n = a.states[n+1].succ { |
|
if a.states[n].succ != freeMark { |
|
continue |
|
} |
|
a.states[n].succ = 0 |
|
u := int32(a.states[n].uint16()) |
|
m := n |
|
for u > 128 { |
|
a.addFreeBlock(m, nIndexes-1) |
|
u -= 128 |
|
m += 256 |
|
} |
|
a.freeUnits(m, u) |
|
} |
|
} |
|
|
|
func (a *subAllocator) allocUnitsRare(index byte) int32 { |
|
if a.glueCount == 0 { |
|
a.glueCount = 255 |
|
a.glueFreeBlocks() |
|
if n := a.removeFreeBlock(index); n > 0 { |
|
return n |
|
} |
|
} |
|
// try to find a larger free block and split it |
|
for i := index + 1; i < nIndexes; i++ { |
|
if n := a.removeFreeBlock(i); n > 0 { |
|
u := index2Units[i] - index2Units[index] |
|
a.freeUnits(n+index2Units[index]<<1, u) |
|
return n |
|
} |
|
} |
|
a.glueCount-- |
|
|
|
// try to allocate units from the top of heap1 |
|
n := a.heap1Hi - index2Units[index]*unitSize |
|
if n > a.heap1Lo { |
|
a.heap1Hi = n |
|
return a.heap1Hi / unitSize * 2 |
|
} |
|
return 0 |
|
} |
|
|
|
func (a *subAllocator) allocUnits(i byte) int32 { |
|
// try to allocate a free block |
|
if n := a.removeFreeBlock(i); n > 0 { |
|
return n |
|
} |
|
// try to allocate from the bottom of heap2 |
|
n := index2Units[i] << 1 |
|
if a.heap2Lo+n <= a.heap2Hi { |
|
lo := a.heap2Lo |
|
a.heap2Lo += n |
|
return lo |
|
} |
|
return a.allocUnitsRare(i) |
|
} |
|
|
|
func (a *subAllocator) newContext(s state, suffix *context) *context { |
|
var n int32 |
|
if a.heap2Lo < a.heap2Hi { |
|
// allocate from top of heap2 |
|
a.heap2Hi -= 2 |
|
n = a.heap2Hi |
|
} else if n = a.removeFreeBlock(1); n == 0 { |
|
if n = a.allocUnitsRare(1); n == 0 { |
|
return nil |
|
} |
|
} |
|
c := &context{i: n, s: a.states[n : n+2 : n+2], a: a} |
|
c.s[0] = state{} |
|
c.setNumStates(1) |
|
c.s[1] = s |
|
if suffix != nil { |
|
c.setSuffix(suffix) |
|
} |
|
return c |
|
} |
|
|
|
func (a *subAllocator) newContextSize(ns int) *context { |
|
c := a.newContext(state{}, nil) |
|
c.setNumStates(ns) |
|
i := units2Index[(ns+1)>>1] |
|
n := a.allocUnits(i) |
|
c.setStatesIndex(n) |
|
return c |
|
} |
|
|
|
type model struct { |
|
maxOrder int |
|
orderFall int |
|
initRL int |
|
runLength int |
|
prevSuccess byte |
|
escCount byte |
|
prevSym byte |
|
initEsc byte |
|
minC *context |
|
maxC *context |
|
rc rangeCoder |
|
a subAllocator |
|
charMask [256]byte |
|
binSumm [128][64]uint16 |
|
see2Cont [25][16]see2Context |
|
} |
|
|
|
func (m *model) restart() { |
|
for i := range m.charMask { |
|
m.charMask[i] = 0 |
|
} |
|
m.escCount = 1 |
|
|
|
if m.maxOrder < 12 { |
|
m.initRL = -m.maxOrder - 1 |
|
} else { |
|
m.initRL = -12 - 1 |
|
} |
|
m.orderFall = m.maxOrder |
|
m.runLength = m.initRL |
|
m.prevSuccess = 0 |
|
|
|
m.a.restart() |
|
|
|
c := m.a.newContextSize(256) |
|
c.setSummFreq(257) |
|
states := c.states() |
|
for i := range states { |
|
states[i] = state{sym: byte(i), freq: 1} |
|
} |
|
m.minC = c |
|
m.maxC = c |
|
m.prevSym = 0 |
|
|
|
for i := range m.binSumm { |
|
for j, esc := range initBinEsc { |
|
n := binScale - esc/(uint16(i)+2) |
|
for k := j; k < len(m.binSumm[i]); k += len(initBinEsc) { |
|
m.binSumm[i][k] = n |
|
} |
|
} |
|
} |
|
|
|
for i := range m.see2Cont { |
|
see := newSee2Context(5*uint16(i) + 10) |
|
for j := range m.see2Cont[i] { |
|
m.see2Cont[i][j] = see |
|
} |
|
} |
|
} |
|
|
|
func (m *model) init(br io.ByteReader, reset bool, maxOrder, maxMB int) error { |
|
err := m.rc.init(br) |
|
if err != nil { |
|
return err |
|
} |
|
if !reset { |
|
if m.minC == nil { |
|
return errCorruptPPM |
|
} |
|
return nil |
|
} |
|
|
|
m.a.init(maxMB) |
|
|
|
if maxOrder == 1 { |
|
return errCorruptPPM |
|
} |
|
m.maxOrder = maxOrder |
|
m.restart() |
|
return nil |
|
} |
|
|
|
func (m *model) rescale(s *state) *state { |
|
if s.freq <= maxFreq { |
|
return s |
|
} |
|
c := m.minC |
|
|
|
var summFreq uint16 |
|
|
|
s.freq += 4 |
|
states := c.states() |
|
escFreq := c.summFreq() + 4 |
|
|
|
for i := range states { |
|
f := states[i].freq |
|
escFreq -= uint16(f) |
|
if m.orderFall != 0 { |
|
f++ |
|
} |
|
f >>= 1 |
|
summFreq += uint16(f) |
|
states[i].freq = f |
|
|
|
if i == 0 || f <= states[i-1].freq { |
|
continue |
|
} |
|
j := i - 1 |
|
for j > 0 && f > states[j-1].freq { |
|
j-- |
|
} |
|
t := states[i] |
|
copy(states[j+1:i+1], states[j:i]) |
|
states[j] = t |
|
} |
|
|
|
i := len(states) - 1 |
|
for states[i].freq == 0 { |
|
i-- |
|
escFreq++ |
|
} |
|
if i != len(states)-1 { |
|
states = c.shrinkStates(states, i+1) |
|
} |
|
s = &states[0] |
|
if i == 0 { |
|
for { |
|
s.freq -= s.freq >> 1 |
|
escFreq >>= 1 |
|
if escFreq <= 1 { |
|
return s |
|
} |
|
} |
|
} |
|
summFreq += escFreq - (escFreq >> 1) |
|
c.setSummFreq(summFreq) |
|
return s |
|
} |
|
|
|
func (m *model) decodeBinSymbol() (*state, error) { |
|
c := m.minC |
|
s := &c.states()[0] |
|
|
|
ns := c.suffix().numStates() |
|
i := m.prevSuccess + ns2BSIndex[ns-1] + byte(m.runLength>>26)&0x20 |
|
if m.prevSym >= 64 { |
|
i += 8 |
|
} |
|
if s.sym >= 64 { |
|
i += 2 * 8 |
|
} |
|
bs := &m.binSumm[s.freq-1][i] |
|
mean := (*bs + 1<<(periodBits-2)) >> periodBits |
|
|
|
if m.rc.currentCount(binScale) < uint32(*bs) { |
|
err := m.rc.decode(0, uint32(*bs)) |
|
if s.freq < 128 { |
|
s.freq++ |
|
} |
|
*bs += 1<<intBits - mean |
|
m.prevSuccess = 1 |
|
m.runLength++ |
|
return s, err |
|
} |
|
err := m.rc.decode(uint32(*bs), binScale) |
|
*bs -= mean |
|
m.initEsc = expEscape[*bs>>10] |
|
m.charMask[s.sym] = m.escCount |
|
m.prevSuccess = 0 |
|
return nil, err |
|
} |
|
|
|
func (m *model) decodeSymbol1() (*state, error) { |
|
c := m.minC |
|
states := c.states() |
|
scale := uint32(c.summFreq()) |
|
// protect against divide by zero |
|
// TODO: look at why this happens, may be problem elsewhere |
|
if scale == 0 { |
|
return nil, errCorruptPPM |
|
} |
|
count := m.rc.currentCount(scale) |
|
m.prevSuccess = 0 |
|
|
|
var n uint32 |
|
for i := range states { |
|
s := &states[i] |
|
n += uint32(s.freq) |
|
if n <= count { |
|
continue |
|
} |
|
err := m.rc.decode(n-uint32(s.freq), n) |
|
s.freq += 4 |
|
c.setSummFreq(uint16(scale + 4)) |
|
if i == 0 { |
|
if 2*n > scale { |
|
m.prevSuccess = 1 |
|
m.runLength++ |
|
} |
|
} else { |
|
if s.freq <= states[i-1].freq { |
|
return s, err |
|
} |
|
states[i-1], states[i] = states[i], states[i-1] |
|
s = &states[i-1] |
|
} |
|
return m.rescale(s), err |
|
} |
|
|
|
for _, s := range states { |
|
m.charMask[s.sym] = m.escCount |
|
} |
|
return nil, m.rc.decode(n, scale) |
|
} |
|
|
|
func (m *model) makeEscFreq(c *context, numMasked int) *see2Context { |
|
ns := c.numStates() |
|
if ns == 256 { |
|
return nil |
|
} |
|
diff := ns - numMasked |
|
|
|
var i int |
|
if m.prevSym >= 64 { |
|
i = 8 |
|
} |
|
if diff < c.suffix().numStates()-ns { |
|
i++ |
|
} |
|
if int(c.summFreq()) < 11*ns { |
|
i += 2 |
|
} |
|
if numMasked > diff { |
|
i += 4 |
|
} |
|
return &m.see2Cont[ns2Index[diff-1]][i] |
|
} |
|
|
|
func (m *model) decodeSymbol2(numMasked int) (*state, error) { |
|
c := m.minC |
|
|
|
see := m.makeEscFreq(c, numMasked) |
|
scale := see.mean() |
|
|
|
var i int |
|
var hi uint32 |
|
states := c.states() |
|
sl := make([]*state, len(states)-numMasked) |
|
for j := range sl { |
|
for m.charMask[states[i].sym] == m.escCount { |
|
i++ |
|
} |
|
hi += uint32(states[i].freq) |
|
sl[j] = &states[i] |
|
i++ |
|
} |
|
|
|
scale += hi |
|
count := m.rc.currentCount(scale) |
|
|
|
if count >= scale { |
|
return nil, errCorruptPPM |
|
} |
|
if count >= hi { |
|
err := m.rc.decode(hi, scale) |
|
if see != nil { |
|
see.summ += uint16(scale) |
|
} |
|
for _, s := range sl { |
|
m.charMask[s.sym] = m.escCount |
|
} |
|
return nil, err |
|
} |
|
|
|
hi = uint32(sl[0].freq) |
|
for hi <= count { |
|
sl = sl[1:] |
|
hi += uint32(sl[0].freq) |
|
} |
|
s := sl[0] |
|
|
|
err := m.rc.decode(hi-uint32(s.freq), hi) |
|
|
|
see.update() |
|
|
|
m.escCount++ |
|
m.runLength = m.initRL |
|
|
|
s.freq += 4 |
|
c.setSummFreq(c.summFreq() + 4) |
|
return m.rescale(s), err |
|
} |
|
|
|
func (c *context) findState(sym byte) *state { |
|
var i int |
|
states := c.states() |
|
for i = range states { |
|
if states[i].sym == sym { |
|
break |
|
} |
|
} |
|
return &states[i] |
|
} |
|
|
|
func (m *model) createSuccessors(s, ss *state) *context { |
|
var sl []*state |
|
|
|
if m.orderFall != 0 { |
|
sl = append(sl, s) |
|
} |
|
|
|
c := m.minC |
|
for suff := c.suffix(); suff != nil; suff = c.suffix() { |
|
c = suff |
|
|
|
if ss == nil { |
|
ss = c.findState(s.sym) |
|
} |
|
if ss.succ != s.succ { |
|
c = m.a.succContext(ss.succ) |
|
break |
|
} |
|
sl = append(sl, ss) |
|
ss = nil |
|
} |
|
|
|
if len(sl) == 0 { |
|
return c |
|
} |
|
|
|
var up state |
|
up.sym = m.a.succByte(s.succ) |
|
up.succ = m.a.nextByteAddr(s.succ) |
|
|
|
states := c.states() |
|
if len(states) > 1 { |
|
s = c.findState(up.sym) |
|
|
|
cf := uint16(s.freq) - 1 |
|
s0 := c.summFreq() - uint16(len(states)) - cf |
|
|
|
if 2*cf <= s0 { |
|
if 5*cf > s0 { |
|
up.freq = 2 |
|
} else { |
|
up.freq = 1 |
|
} |
|
} else { |
|
up.freq = byte(1 + (2*cf+3*s0-1)/(2*s0)) |
|
} |
|
} else { |
|
up.freq = states[0].freq |
|
} |
|
|
|
for i := len(sl) - 1; i >= 0; i-- { |
|
c = m.a.newContext(up, c) |
|
if c == nil { |
|
return nil |
|
} |
|
sl[i].succ = c.succPtr() |
|
} |
|
return c |
|
} |
|
|
|
func (m *model) update(s *state) { |
|
if m.orderFall == 0 { |
|
if c := m.a.succContext(s.succ); c != nil { |
|
m.minC = c |
|
m.maxC = c |
|
return |
|
} |
|
} |
|
|
|
if m.escCount == 0 { |
|
m.escCount = 1 |
|
for i := range m.charMask { |
|
m.charMask[i] = 0 |
|
} |
|
} |
|
|
|
var ss *state // matching minC.suffix state |
|
|
|
if s.freq < maxFreq/4 && m.minC.suffix() != nil { |
|
c := m.minC.suffix() |
|
states := c.states() |
|
|
|
var i int |
|
if len(states) > 1 { |
|
for states[i].sym != s.sym { |
|
i++ |
|
} |
|
if i > 0 && states[i].freq >= states[i-1].freq { |
|
states[i-1], states[i] = states[i], states[i-1] |
|
i-- |
|
} |
|
if states[i].freq < maxFreq-9 { |
|
states[i].freq += 2 |
|
c.setSummFreq(c.summFreq() + 2) |
|
} |
|
} else if states[0].freq < 32 { |
|
states[0].freq++ |
|
} |
|
ss = &states[i] // save later for createSuccessors |
|
} |
|
|
|
if m.orderFall == 0 { |
|
c := m.createSuccessors(s, ss) |
|
if c == nil { |
|
m.restart() |
|
} else { |
|
m.minC = c |
|
m.maxC = c |
|
s.succ = c.succPtr() |
|
} |
|
return |
|
} |
|
|
|
succ := m.a.pushByte(s.sym) |
|
if m.a.succIsNil(succ) { |
|
m.restart() |
|
return |
|
} |
|
|
|
var minC *context |
|
if m.a.succIsNil(s.succ) { |
|
s.succ = succ |
|
minC = m.minC |
|
} else { |
|
minC = m.a.succContext(s.succ) |
|
if minC == nil { |
|
minC = m.createSuccessors(s, ss) |
|
if minC == nil { |
|
m.restart() |
|
return |
|
} |
|
} |
|
m.orderFall-- |
|
if m.orderFall == 0 { |
|
succ = minC.succPtr() |
|
if m.maxC.notEq(m.minC) { |
|
m.a.popByte() |
|
} |
|
} |
|
} |
|
|
|
n := m.minC.numStates() |
|
s0 := int(m.minC.summFreq()) - n - int(s.freq-1) |
|
for c := m.maxC; c.notEq(m.minC); c = c.suffix() { |
|
var summFreq uint16 |
|
|
|
states := c.expandStates() |
|
if states == nil { |
|
m.restart() |
|
return |
|
} |
|
if ns := len(states) - 1; ns != 1 { |
|
summFreq = c.summFreq() |
|
if 4*ns <= n && int(summFreq) <= 8*ns { |
|
summFreq += 2 |
|
} |
|
if 2*ns < n { |
|
summFreq++ |
|
} |
|
} else { |
|
p := &states[0] |
|
if p.freq < maxFreq/4-1 { |
|
p.freq += p.freq |
|
} else { |
|
p.freq = maxFreq - 4 |
|
} |
|
summFreq = uint16(p.freq) + uint16(m.initEsc) |
|
if n > 3 { |
|
summFreq++ |
|
} |
|
} |
|
|
|
cf := 2 * int(s.freq) * int(summFreq+6) |
|
sf := s0 + int(summFreq) |
|
var freq byte |
|
if cf >= 6*sf { |
|
switch { |
|
case cf >= 15*sf: |
|
freq = 7 |
|
case cf >= 12*sf: |
|
freq = 6 |
|
case cf >= 9*sf: |
|
freq = 5 |
|
default: |
|
freq = 4 |
|
} |
|
summFreq += uint16(freq) |
|
} else { |
|
switch { |
|
case cf >= 4*sf: |
|
freq = 3 |
|
case cf > sf: |
|
freq = 2 |
|
default: |
|
freq = 1 |
|
} |
|
summFreq += 3 |
|
} |
|
states[len(states)-1] = state{sym: s.sym, freq: freq, succ: succ} |
|
c.setSummFreq(summFreq) |
|
} |
|
m.minC = minC |
|
m.maxC = minC |
|
} |
|
|
|
func (m *model) ReadByte() (byte, error) { |
|
if m.minC == nil { |
|
return 0, errCorruptPPM |
|
} |
|
var s *state |
|
var err error |
|
if m.minC.numStates() == 1 { |
|
s, err = m.decodeBinSymbol() |
|
} else { |
|
s, err = m.decodeSymbol1() |
|
} |
|
for s == nil && err == nil { |
|
n := m.minC.numStates() |
|
for m.minC.numStates() == n { |
|
m.orderFall++ |
|
m.minC = m.minC.suffix() |
|
if m.minC == nil { |
|
return 0, errCorruptPPM |
|
} |
|
} |
|
s, err = m.decodeSymbol2(n) |
|
} |
|
if err != nil { |
|
return 0, err |
|
} |
|
|
|
// save sym so it doesn't get overwritten by a possible restart() |
|
sym := s.sym |
|
m.update(s) |
|
m.prevSym = sym |
|
return sym, nil |
|
}
|
|
|