|  | // Copyright 2011 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package bzip2 | 
|  |  | 
|  | // moveToFrontDecoder implements a move-to-front list. Such a list is an | 
|  | // efficient way to transform a string with repeating elements into one with | 
|  | // many small valued numbers, which is suitable for entropy encoding. It works | 
|  | // by starting with an initial list of symbols and references symbols by their | 
|  | // index into that list. When a symbol is referenced, it's moved to the front | 
|  | // of the list. Thus, a repeated symbol ends up being encoded with many zeros, | 
|  | // as the symbol will be at the front of the list after the first access. | 
|  | type moveToFrontDecoder []byte | 
|  |  | 
|  | // newMTFDecoder creates a move-to-front decoder with an explicit initial list | 
|  | // of symbols. | 
|  | func newMTFDecoder(symbols []byte) moveToFrontDecoder { | 
|  | if len(symbols) > 256 { | 
|  | panic("too many symbols") | 
|  | } | 
|  | return moveToFrontDecoder(symbols) | 
|  | } | 
|  |  | 
|  | // newMTFDecoderWithRange creates a move-to-front decoder with an initial | 
|  | // symbol list of 0...n-1. | 
|  | func newMTFDecoderWithRange(n int) moveToFrontDecoder { | 
|  | if n > 256 { | 
|  | panic("newMTFDecoderWithRange: cannot have > 256 symbols") | 
|  | } | 
|  |  | 
|  | m := make([]byte, n) | 
|  | for i := 0; i < n; i++ { | 
|  | m[i] = byte(i) | 
|  | } | 
|  | return moveToFrontDecoder(m) | 
|  | } | 
|  |  | 
|  | func (m moveToFrontDecoder) Decode(n int) (b byte) { | 
|  | // Implement move-to-front with a simple copy. This approach | 
|  | // beats more sophisticated approaches in benchmarking, probably | 
|  | // because it has high locality of reference inside of a | 
|  | // single cache line (most move-to-front operations have n < 64). | 
|  | b = m[n] | 
|  | copy(m[1:], m[:n]) | 
|  | m[0] = b | 
|  | return | 
|  | } | 
|  |  | 
|  | // First returns the symbol at the front of the list. | 
|  | func (m moveToFrontDecoder) First() byte { | 
|  | return m[0] | 
|  | } |