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.
160 lines
3.8 KiB
160 lines
3.8 KiB
5 years ago
|
// Copyright 2015, Joe Tsai. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE.md file.
|
||
|
|
||
|
// +build debug
|
||
|
|
||
|
package prefix
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
func max(a, b int) int {
|
||
|
if a > b {
|
||
|
return a
|
||
|
}
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
func lenBase2(n uint) int {
|
||
|
return int(math.Ceil(math.Log2(float64(n + 1))))
|
||
|
}
|
||
|
func padBase2(v, n uint, m int) string {
|
||
|
s := fmt.Sprintf("%b", 1<<n|v)[1:]
|
||
|
if pad := m - len(s); pad > 0 {
|
||
|
return strings.Repeat(" ", pad) + s
|
||
|
}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func lenBase10(n int) int {
|
||
|
return int(math.Ceil(math.Log10(float64(n + 1))))
|
||
|
}
|
||
|
func padBase10(n, m int) string {
|
||
|
s := fmt.Sprintf("%d", n)
|
||
|
if pad := m - len(s); pad > 0 {
|
||
|
return strings.Repeat(" ", pad) + s
|
||
|
}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func (rc RangeCodes) String() string {
|
||
|
var maxLen, maxBase int
|
||
|
for _, c := range rc {
|
||
|
maxLen = max(maxLen, int(c.Len))
|
||
|
maxBase = max(maxBase, int(c.Base))
|
||
|
}
|
||
|
|
||
|
var ss []string
|
||
|
ss = append(ss, "{")
|
||
|
for i, c := range rc {
|
||
|
base := padBase10(int(c.Base), lenBase10(maxBase))
|
||
|
if c.Len > 0 {
|
||
|
base += fmt.Sprintf("-%d", c.End()-1)
|
||
|
}
|
||
|
ss = append(ss, fmt.Sprintf("\t%s: {len: %s, range: %s},",
|
||
|
padBase10(int(i), lenBase10(len(rc)-1)),
|
||
|
padBase10(int(c.Len), lenBase10(maxLen)),
|
||
|
base,
|
||
|
))
|
||
|
}
|
||
|
ss = append(ss, "}")
|
||
|
return strings.Join(ss, "\n")
|
||
|
}
|
||
|
|
||
|
func (pc PrefixCodes) String() string {
|
||
|
var maxSym, maxLen, maxCnt int
|
||
|
for _, c := range pc {
|
||
|
maxSym = max(maxSym, int(c.Sym))
|
||
|
maxLen = max(maxLen, int(c.Len))
|
||
|
maxCnt = max(maxCnt, int(c.Cnt))
|
||
|
}
|
||
|
|
||
|
var ss []string
|
||
|
ss = append(ss, "{")
|
||
|
for _, c := range pc {
|
||
|
var cntStr string
|
||
|
if maxCnt > 0 {
|
||
|
cnt := int(32*float32(c.Cnt)/float32(maxCnt) + 0.5)
|
||
|
cntStr = fmt.Sprintf("%s |%s",
|
||
|
padBase10(int(c.Cnt), lenBase10(maxCnt)),
|
||
|
strings.Repeat("#", cnt),
|
||
|
)
|
||
|
}
|
||
|
ss = append(ss, fmt.Sprintf("\t%s: %s, %s",
|
||
|
padBase10(int(c.Sym), lenBase10(maxSym)),
|
||
|
padBase2(uint(c.Val), uint(c.Len), maxLen),
|
||
|
cntStr,
|
||
|
))
|
||
|
}
|
||
|
ss = append(ss, "}")
|
||
|
return strings.Join(ss, "\n")
|
||
|
}
|
||
|
|
||
|
func (pd Decoder) String() string {
|
||
|
var ss []string
|
||
|
ss = append(ss, "{")
|
||
|
if len(pd.chunks) > 0 {
|
||
|
ss = append(ss, "\tchunks: {")
|
||
|
for i, c := range pd.chunks {
|
||
|
label := "sym"
|
||
|
if uint(c&countMask) > uint(pd.chunkBits) {
|
||
|
label = "idx"
|
||
|
}
|
||
|
ss = append(ss, fmt.Sprintf("\t\t%s: {%s: %s, len: %s}",
|
||
|
padBase2(uint(i), uint(pd.chunkBits), int(pd.chunkBits)),
|
||
|
label, padBase10(int(c>>countBits), 3),
|
||
|
padBase10(int(c&countMask), 2),
|
||
|
))
|
||
|
}
|
||
|
ss = append(ss, "\t},")
|
||
|
|
||
|
for j, links := range pd.links {
|
||
|
ss = append(ss, fmt.Sprintf("\tlinks[%d]: {", j))
|
||
|
linkBits := lenBase2(uint(pd.linkMask))
|
||
|
for i, c := range links {
|
||
|
ss = append(ss, fmt.Sprintf("\t\t%s: {sym: %s, len: %s},",
|
||
|
padBase2(uint(i), uint(linkBits), int(linkBits)),
|
||
|
padBase10(int(c>>countBits), 3),
|
||
|
padBase10(int(c&countMask), 2),
|
||
|
))
|
||
|
}
|
||
|
ss = append(ss, "\t},")
|
||
|
}
|
||
|
}
|
||
|
ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pd.chunkMask))
|
||
|
ss = append(ss, fmt.Sprintf("\tlinkMask: %b,", pd.linkMask))
|
||
|
ss = append(ss, fmt.Sprintf("\tchunkBits: %d,", pd.chunkBits))
|
||
|
ss = append(ss, fmt.Sprintf("\tMinBits: %d,", pd.MinBits))
|
||
|
ss = append(ss, fmt.Sprintf("\tNumSyms: %d,", pd.NumSyms))
|
||
|
ss = append(ss, "}")
|
||
|
return strings.Join(ss, "\n")
|
||
|
}
|
||
|
|
||
|
func (pe Encoder) String() string {
|
||
|
var maxLen int
|
||
|
for _, c := range pe.chunks {
|
||
|
maxLen = max(maxLen, int(c&countMask))
|
||
|
}
|
||
|
|
||
|
var ss []string
|
||
|
ss = append(ss, "{")
|
||
|
if len(pe.chunks) > 0 {
|
||
|
ss = append(ss, "\tchunks: {")
|
||
|
for i, c := range pe.chunks {
|
||
|
ss = append(ss, fmt.Sprintf("\t\t%s: %s,",
|
||
|
padBase10(i, 3),
|
||
|
padBase2(uint(c>>countBits), uint(c&countMask), maxLen),
|
||
|
))
|
||
|
}
|
||
|
ss = append(ss, "\t},")
|
||
|
}
|
||
|
ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pe.chunkMask))
|
||
|
ss = append(ss, fmt.Sprintf("\tNumSyms: %d,", pe.NumSyms))
|
||
|
ss = append(ss, "}")
|
||
|
return strings.Join(ss, "\n")
|
||
|
}
|