src/pkg/compress/bzip2/move_to_front.go - The Go Programming Language

Golang

Source file src/pkg/compress/bzip2/move_to_front.go

     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	}