github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/compress/bzip2/move_to_front.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bzip2 6 7 // moveToFrontDecoder implements a move-to-front list. Such a list is an 8 // efficient way to transform a string with repeating elements into one with 9 // many small valued numbers, which is suitable for entropy encoding. It works 10 // by starting with an initial list of symbols and references symbols by their 11 // index into that list. When a symbol is referenced, it's moved to the front 12 // of the list. Thus, a repeated symbol ends up being encoded with many zeros, 13 // as the symbol will be at the front of the list after the first access. 14 type moveToFrontDecoder struct { 15 // Rather than actually keep the list in memory, the symbols are stored 16 // as a circular, double linked list with the symbol indexed by head 17 // at the front of the list. 18 symbols []byte 19 next []uint8 20 prev []uint8 21 head uint8 22 } 23 24 // newMTFDecoder creates a move-to-front decoder with an explicit initial list 25 // of symbols. 26 func newMTFDecoder(symbols []byte) *moveToFrontDecoder { 27 if len(symbols) > 256 { 28 panic("too many symbols") 29 } 30 31 m := &moveToFrontDecoder{ 32 symbols: symbols, 33 next: make([]uint8, len(symbols)), 34 prev: make([]uint8, len(symbols)), 35 } 36 37 m.threadLinkedList() 38 return m 39 } 40 41 // newMTFDecoderWithRange creates a move-to-front decoder with an initial 42 // symbol list of 0...n-1. 43 func newMTFDecoderWithRange(n int) *moveToFrontDecoder { 44 if n > 256 { 45 panic("newMTFDecoderWithRange: cannot have > 256 symbols") 46 } 47 48 m := &moveToFrontDecoder{ 49 symbols: make([]uint8, n), 50 next: make([]uint8, n), 51 prev: make([]uint8, n), 52 } 53 54 for i := 0; i < n; i++ { 55 m.symbols[i] = byte(i) 56 } 57 58 m.threadLinkedList() 59 return m 60 } 61 62 // threadLinkedList creates the initial linked-list pointers. 63 func (m *moveToFrontDecoder) threadLinkedList() { 64 if len(m.symbols) == 0 { 65 return 66 } 67 68 m.prev[0] = uint8(len(m.symbols) - 1) 69 70 for i := 0; i < len(m.symbols)-1; i++ { 71 m.next[i] = uint8(i + 1) 72 m.prev[i+1] = uint8(i) 73 } 74 75 m.next[len(m.symbols)-1] = 0 76 } 77 78 func (m *moveToFrontDecoder) Decode(n int) (b byte) { 79 // Most of the time, n will be zero so it's worth dealing with this 80 // simple case. 81 if n == 0 { 82 return m.symbols[m.head] 83 } 84 85 i := m.head 86 for j := 0; j < n; j++ { 87 i = m.next[i] 88 } 89 b = m.symbols[i] 90 91 m.next[m.prev[i]] = m.next[i] 92 m.prev[m.next[i]] = m.prev[i] 93 m.next[i] = m.head 94 m.prev[i] = m.prev[m.head] 95 m.next[m.prev[m.head]] = i 96 m.prev[m.head] = i 97 m.head = i 98 99 return 100 } 101 102 // First returns the symbol at the front of the list. 103 func (m *moveToFrontDecoder) First() byte { 104 return m.symbols[m.head] 105 }