github.com/bir3/gocompiler@v0.9.2202/extra/compress/zstd/fse_predefined.go (about)

     1  // Copyright 2019+ Klaus Post. All rights reserved.
     2  // License information can be found in the LICENSE file.
     3  // Based on work by Yann Collet, released under BSD License.
     4  
     5  package zstd
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"sync"
    11  )
    12  
    13  var (
    14  	// fsePredef are the predefined fse tables as defined here:
    15  	// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions
    16  	// These values are already transformed.
    17  	fsePredef [3]fseDecoder
    18  
    19  	// fsePredefEnc are the predefined encoder based on fse tables as defined here:
    20  	// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions
    21  	// These values are already transformed.
    22  	fsePredefEnc [3]fseEncoder
    23  
    24  	// symbolTableX contain the transformations needed for each type as defined in
    25  	// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#the-codes-for-literals-lengths-match-lengths-and-offsets
    26  	symbolTableX [3][]baseOffset
    27  
    28  	// maxTableSymbol is the biggest supported symbol for each table type
    29  	// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#the-codes-for-literals-lengths-match-lengths-and-offsets
    30  	maxTableSymbol = [3]uint8{tableLiteralLengths: maxLiteralLengthSymbol, tableOffsets: maxOffsetLengthSymbol, tableMatchLengths: maxMatchLengthSymbol}
    31  
    32  	// bitTables is the bits table for each table.
    33  	bitTables = [3][]byte{tableLiteralLengths: llBitsTable[:], tableOffsets: nil, tableMatchLengths: mlBitsTable[:]}
    34  )
    35  
    36  type tableIndex uint8
    37  
    38  const (
    39  	// indexes for fsePredef and symbolTableX
    40  	tableLiteralLengths tableIndex = 0
    41  	tableOffsets        tableIndex = 1
    42  	tableMatchLengths   tableIndex = 2
    43  
    44  	maxLiteralLengthSymbol = 35
    45  	maxOffsetLengthSymbol  = 30
    46  	maxMatchLengthSymbol   = 52
    47  )
    48  
    49  // baseOffset is used for calculating transformations.
    50  type baseOffset struct {
    51  	baseLine uint32
    52  	addBits  uint8
    53  }
    54  
    55  // fillBase will precalculate base offsets with the given bit distributions.
    56  func fillBase(dst []baseOffset, base uint32, bits ...uint8) {
    57  	if len(bits) != len(dst) {
    58  		panic(fmt.Sprintf("len(dst) (%d) != len(bits) (%d)", len(dst), len(bits)))
    59  	}
    60  	for i, bit := range bits {
    61  		if base > math.MaxInt32 {
    62  			panic("invalid decoding table, base overflows int32")
    63  		}
    64  
    65  		dst[i] = baseOffset{
    66  			baseLine: base,
    67  			addBits:  bit,
    68  		}
    69  		base += 1 << bit
    70  	}
    71  }
    72  
    73  var predef sync.Once
    74  
    75  func initPredefined() {
    76  	predef.Do(func() {
    77  		// Literals length codes
    78  		tmp := make([]baseOffset, 36)
    79  		for i := range tmp[:16] {
    80  			tmp[i] = baseOffset{
    81  				baseLine: uint32(i),
    82  				addBits:  0,
    83  			}
    84  		}
    85  		fillBase(tmp[16:], 16, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
    86  		symbolTableX[tableLiteralLengths] = tmp
    87  
    88  		// Match length codes
    89  		tmp = make([]baseOffset, 53)
    90  		for i := range tmp[:32] {
    91  			tmp[i] = baseOffset{
    92  				// The transformation adds the 3 length.
    93  				baseLine: uint32(i) + 3,
    94  				addBits:  0,
    95  			}
    96  		}
    97  		fillBase(tmp[32:], 35, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
    98  		symbolTableX[tableMatchLengths] = tmp
    99  
   100  		// Offset codes
   101  		tmp = make([]baseOffset, maxOffsetBits+1)
   102  		tmp[1] = baseOffset{
   103  			baseLine: 1,
   104  			addBits:  1,
   105  		}
   106  		fillBase(tmp[2:], 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)
   107  		symbolTableX[tableOffsets] = tmp
   108  
   109  		// Fill predefined tables and transform them.
   110  		// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions
   111  		for i := range fsePredef[:] {
   112  			f := &fsePredef[i]
   113  			switch tableIndex(i) {
   114  			case tableLiteralLengths:
   115  				// https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L243
   116  				f.actualTableLog = 6
   117  				copy(f.norm[:], []int16{4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
   118  					2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,
   119  					-1, -1, -1, -1})
   120  				f.symbolLen = 36
   121  			case tableOffsets:
   122  				// https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L281
   123  				f.actualTableLog = 5
   124  				copy(f.norm[:], []int16{
   125  					1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
   126  					1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1})
   127  				f.symbolLen = 29
   128  			case tableMatchLengths:
   129  				//https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L304
   130  				f.actualTableLog = 6
   131  				copy(f.norm[:], []int16{
   132  					1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
   133  					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
   134  					1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
   135  					-1, -1, -1, -1, -1})
   136  				f.symbolLen = 53
   137  			}
   138  			if err := f.buildDtable(); err != nil {
   139  				panic(fmt.Errorf("building table %v: %v", tableIndex(i), err))
   140  			}
   141  			if err := f.transform(symbolTableX[i]); err != nil {
   142  				panic(fmt.Errorf("building table %v: %v", tableIndex(i), err))
   143  			}
   144  			f.preDefined = true
   145  
   146  			// Create encoder as well
   147  			enc := &fsePredefEnc[i]
   148  			copy(enc.norm[:], f.norm[:])
   149  			enc.symbolLen = f.symbolLen
   150  			enc.actualTableLog = f.actualTableLog
   151  			if err := enc.buildCTable(); err != nil {
   152  				panic(fmt.Errorf("building encoding table %v: %v", tableIndex(i), err))
   153  			}
   154  			enc.setBits(bitTables[i])
   155  			enc.preDefined = true
   156  		}
   157  	})
   158  }