1// Copyright 2015, Joe Tsai. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE.md file.
4
5// +build debug
6
7package prefix
8
9import (
10	"fmt"
11	"math"
12	"strings"
13)
14
15func max(a, b int) int {
16	if a > b {
17		return a
18	}
19	return b
20}
21
22func lenBase2(n uint) int {
23	return int(math.Ceil(math.Log2(float64(n + 1))))
24}
25func padBase2(v, n uint, m int) string {
26	s := fmt.Sprintf("%b", 1<<n|v)[1:]
27	if pad := m - len(s); pad > 0 {
28		return strings.Repeat(" ", pad) + s
29	}
30	return s
31}
32
33func lenBase10(n int) int {
34	return int(math.Ceil(math.Log10(float64(n + 1))))
35}
36func padBase10(n, m int) string {
37	s := fmt.Sprintf("%d", n)
38	if pad := m - len(s); pad > 0 {
39		return strings.Repeat(" ", pad) + s
40	}
41	return s
42}
43
44func (rc RangeCodes) String() string {
45	var maxLen, maxBase int
46	for _, c := range rc {
47		maxLen = max(maxLen, int(c.Len))
48		maxBase = max(maxBase, int(c.Base))
49	}
50
51	var ss []string
52	ss = append(ss, "{")
53	for i, c := range rc {
54		base := padBase10(int(c.Base), lenBase10(maxBase))
55		if c.Len > 0 {
56			base += fmt.Sprintf("-%d", c.End()-1)
57		}
58		ss = append(ss, fmt.Sprintf("\t%s:  {len: %s, range: %s},",
59			padBase10(int(i), lenBase10(len(rc)-1)),
60			padBase10(int(c.Len), lenBase10(maxLen)),
61			base,
62		))
63	}
64	ss = append(ss, "}")
65	return strings.Join(ss, "\n")
66}
67
68func (pc PrefixCodes) String() string {
69	var maxSym, maxLen, maxCnt int
70	for _, c := range pc {
71		maxSym = max(maxSym, int(c.Sym))
72		maxLen = max(maxLen, int(c.Len))
73		maxCnt = max(maxCnt, int(c.Cnt))
74	}
75
76	var ss []string
77	ss = append(ss, "{")
78	for _, c := range pc {
79		var cntStr string
80		if maxCnt > 0 {
81			cnt := int(32*float32(c.Cnt)/float32(maxCnt) + 0.5)
82			cntStr = fmt.Sprintf("%s |%s",
83				padBase10(int(c.Cnt), lenBase10(maxCnt)),
84				strings.Repeat("#", cnt),
85			)
86		}
87		ss = append(ss, fmt.Sprintf("\t%s:  %s,  %s",
88			padBase10(int(c.Sym), lenBase10(maxSym)),
89			padBase2(uint(c.Val), uint(c.Len), maxLen),
90			cntStr,
91		))
92	}
93	ss = append(ss, "}")
94	return strings.Join(ss, "\n")
95}
96
97func (pd Decoder) String() string {
98	var ss []string
99	ss = append(ss, "{")
100	if len(pd.chunks) > 0 {
101		ss = append(ss, "\tchunks: {")
102		for i, c := range pd.chunks {
103			label := "sym"
104			if uint(c&countMask) > uint(pd.chunkBits) {
105				label = "idx"
106			}
107			ss = append(ss, fmt.Sprintf("\t\t%s:  {%s: %s, len: %s}",
108				padBase2(uint(i), uint(pd.chunkBits), int(pd.chunkBits)),
109				label, padBase10(int(c>>countBits), 3),
110				padBase10(int(c&countMask), 2),
111			))
112		}
113		ss = append(ss, "\t},")
114
115		for j, links := range pd.links {
116			ss = append(ss, fmt.Sprintf("\tlinks[%d]: {", j))
117			linkBits := lenBase2(uint(pd.linkMask))
118			for i, c := range links {
119				ss = append(ss, fmt.Sprintf("\t\t%s:  {sym: %s, len: %s},",
120					padBase2(uint(i), uint(linkBits), int(linkBits)),
121					padBase10(int(c>>countBits), 3),
122					padBase10(int(c&countMask), 2),
123				))
124			}
125			ss = append(ss, "\t},")
126		}
127	}
128	ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pd.chunkMask))
129	ss = append(ss, fmt.Sprintf("\tlinkMask:  %b,", pd.linkMask))
130	ss = append(ss, fmt.Sprintf("\tchunkBits: %d,", pd.chunkBits))
131	ss = append(ss, fmt.Sprintf("\tMinBits:   %d,", pd.MinBits))
132	ss = append(ss, fmt.Sprintf("\tNumSyms:   %d,", pd.NumSyms))
133	ss = append(ss, "}")
134	return strings.Join(ss, "\n")
135}
136
137func (pe Encoder) String() string {
138	var maxLen int
139	for _, c := range pe.chunks {
140		maxLen = max(maxLen, int(c&countMask))
141	}
142
143	var ss []string
144	ss = append(ss, "{")
145	if len(pe.chunks) > 0 {
146		ss = append(ss, "\tchunks: {")
147		for i, c := range pe.chunks {
148			ss = append(ss, fmt.Sprintf("\t\t%s:  %s,",
149				padBase10(i, 3),
150				padBase2(uint(c>>countBits), uint(c&countMask), maxLen),
151			))
152		}
153		ss = append(ss, "\t},")
154	}
155	ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pe.chunkMask))
156	ss = append(ss, fmt.Sprintf("\tNumSyms:   %d,", pe.NumSyms))
157	ss = append(ss, "}")
158	return strings.Join(ss, "\n")
159}
160