1
2
3
4
5
6
7 package apd
8
9 import (
10 "fmt"
11 "strconv"
12 )
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 func (d *Decimal) Text(format byte) string {
29 var buf [16]byte
30 return string(d.Append(buf[:0], format))
31 }
32
33
34
35 func (d *Decimal) String() string {
36 return d.Text('G')
37 }
38
39
40
41 const lowestZeroNegativeCoefficientCockroach = -2000
42
43
44
45 func (d *Decimal) Append(buf []byte, fmtString byte) []byte {
46
47 if d.Negative {
48 buf = append(buf, '-')
49 }
50
51 switch d.Form {
52 case Finite:
53
54 case NaN:
55 return append(buf, "NaN"...)
56 case NaNSignaling:
57 return append(buf, "sNaN"...)
58 case Infinite:
59 return append(buf, "Infinity"...)
60 default:
61 return append(buf, "unknown"...)
62 }
63
64 var scratch [16]byte
65 digits := d.Coeff.Append(scratch[:0], 10)
66 switch fmtString {
67 case 'e', 'E':
68 return fmtE(buf, fmtString, d, digits)
69 case 'f':
70 return fmtF(buf, d, digits)
71 case 'g', 'G':
72 digitLen := len(digits)
73
74
75
76
77
78
79
80
81
82
83 if d.Coeff.BitLen() == 0 && d.Exponent >= lowestZeroNegativeCoefficientCockroach && d.Exponent < 0 {
84 digitLen += int(-d.Exponent)
85 }
86
87 const adjExponentLimit = -6
88 adj := int(d.Exponent) + (digitLen - 1)
89 if d.Exponent <= 0 && adj >= adjExponentLimit {
90 return fmtF(buf, d, digits)
91 }
92
93
94
95 return fmtE(buf, fmtString+'e'-'g', d, digits)
96 }
97
98 if d.Negative {
99 buf = buf[:len(buf)-1]
100 }
101 return append(buf, '%', fmtString)
102 }
103
104
105 func fmtE(buf []byte, fmt byte, d *Decimal, digits []byte) []byte {
106 adj := int64(d.Exponent) + int64(len(digits)) - 1
107 buf = append(buf, digits[0])
108 if len(digits) > 1 {
109 buf = append(buf, '.')
110 buf = append(buf, digits[1:]...)
111 }
112 buf = append(buf, fmt)
113 var ch byte
114 if adj < 0 {
115 ch = '-'
116 adj = -adj
117 } else {
118 ch = '+'
119 }
120 buf = append(buf, ch)
121 return strconv.AppendInt(buf, adj, 10)
122 }
123
124
125 func fmtF(buf []byte, d *Decimal, digits []byte) []byte {
126 if d.Exponent < 0 {
127 if left := -int(d.Exponent) - len(digits); left >= 0 {
128 buf = append(buf, "0."...)
129 for i := 0; i < left; i++ {
130 buf = append(buf, '0')
131 }
132 buf = append(buf, digits...)
133 } else if left < 0 {
134 offset := -left
135 buf = append(buf, digits[:offset]...)
136 buf = append(buf, '.')
137 buf = append(buf, digits[offset:]...)
138 }
139 } else if d.Exponent >= 0 {
140 buf = append(buf, digits...)
141 for i := int32(0); i < d.Exponent; i++ {
142 buf = append(buf, '0')
143 }
144 }
145 return buf
146 }
147
148 var _ fmt.Formatter = decimalZero
149
150
151
152
153
154
155
156 func (d *Decimal) Format(s fmt.State, format rune) {
157 switch format {
158 case 'e', 'E', 'f', 'g', 'G':
159
160 case 'F':
161
162 format = 'f'
163 case 'v', 's':
164
165 format = 'G'
166 default:
167 fmt.Fprintf(s, "%%!%c(*apd.Decimal=%s)", format, d.String())
168 return
169 }
170 var buf []byte
171 buf = d.Append(buf, byte(format))
172 if len(buf) == 0 {
173 buf = []byte("?")
174 }
175
176
177 var sign string
178 switch {
179 case buf[0] == '-':
180 sign = "-"
181 buf = buf[1:]
182 case buf[0] == '+':
183
184 sign = "+"
185 if s.Flag(' ') {
186 sign = " "
187 }
188 buf = buf[1:]
189 case s.Flag('+'):
190 sign = "+"
191 case s.Flag(' '):
192 sign = " "
193 }
194
195 var padding int
196 if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
197 padding = width - len(sign) - len(buf)
198 }
199
200 switch {
201 case s.Flag('0') && d.Form == Finite:
202
203 writeMultiple(s, sign, 1)
204 writeMultiple(s, "0", padding)
205 s.Write(buf)
206 case s.Flag('-'):
207
208 writeMultiple(s, sign, 1)
209 s.Write(buf)
210 writeMultiple(s, " ", padding)
211 default:
212
213 writeMultiple(s, " ", padding)
214 writeMultiple(s, sign, 1)
215 s.Write(buf)
216 }
217 }
218
219
220 func writeMultiple(s fmt.State, text string, count int) {
221 if len(text) > 0 {
222 b := []byte(text)
223 for ; count > 0; count-- {
224 s.Write(b)
225 }
226 }
227 }
228
View as plain text