Source file src/pkg/math/big/ftoa.go
1
2
3
4
5
6
7
8
9 package big
10
11 import (
12 "bytes"
13 "fmt"
14 "strconv"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 func (x *Float) Text(format byte, prec int) string {
48 cap := 10
49 if prec > 0 {
50 cap += prec
51 }
52 return string(x.Append(make([]byte, 0, cap), format, prec))
53 }
54
55
56
57 func (x *Float) String() string {
58 return x.Text('g', 10)
59 }
60
61
62
63 func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
64
65 if x.neg {
66 buf = append(buf, '-')
67 }
68
69
70 if x.form == inf {
71 if !x.neg {
72 buf = append(buf, '+')
73 }
74 return append(buf, "Inf"...)
75 }
76
77
78 switch fmt {
79 case 'b':
80 return x.fmtB(buf)
81 case 'p':
82 return x.fmtP(buf)
83 case 'x':
84 return x.fmtX(buf, prec)
85 }
86
87
88
89
90
91
92
93 var d decimal
94 if x.form == finite {
95
96 d.init(x.mant, int(x.exp)-x.mant.bitLen())
97 }
98
99
100 shortest := false
101 if prec < 0 {
102 shortest = true
103 roundShortest(&d, x)
104
105 switch fmt {
106 case 'e', 'E':
107 prec = len(d.mant) - 1
108 case 'f':
109 prec = max(len(d.mant)-d.exp, 0)
110 case 'g', 'G':
111 prec = len(d.mant)
112 }
113 } else {
114
115 switch fmt {
116 case 'e', 'E':
117
118 d.round(1 + prec)
119 case 'f':
120
121 d.round(d.exp + prec)
122 case 'g', 'G':
123 if prec == 0 {
124 prec = 1
125 }
126 d.round(prec)
127 }
128 }
129
130
131 switch fmt {
132 case 'e', 'E':
133 return fmtE(buf, fmt, prec, d)
134 case 'f':
135 return fmtF(buf, prec, d)
136 case 'g', 'G':
137
138 eprec := prec
139 if eprec > len(d.mant) && len(d.mant) >= d.exp {
140 eprec = len(d.mant)
141 }
142
143
144
145
146 if shortest {
147 eprec = 6
148 }
149 exp := d.exp - 1
150 if exp < -4 || exp >= eprec {
151 if prec > len(d.mant) {
152 prec = len(d.mant)
153 }
154 return fmtE(buf, fmt+'e'-'g', prec-1, d)
155 }
156 if prec > d.exp {
157 prec = len(d.mant)
158 }
159 return fmtF(buf, max(prec-d.exp, 0), d)
160 }
161
162
163 if x.neg {
164 buf = buf[:len(buf)-1]
165 }
166 return append(buf, '%', fmt)
167 }
168
169 func roundShortest(d *decimal, x *Float) {
170
171 if len(d.mant) == 0 {
172 return
173 }
174
175
176
177
178
179
180
181
182
183
184
185
186 mant := nat(nil).set(x.mant)
187 exp := int(x.exp) - mant.bitLen()
188 s := mant.bitLen() - int(x.prec+1)
189 switch {
190 case s < 0:
191 mant = mant.shl(mant, uint(-s))
192 case s > 0:
193 mant = mant.shr(mant, uint(+s))
194 }
195 exp += s
196
197
198
199 var lower decimal
200 var tmp nat
201 lower.init(tmp.sub(mant, natOne), exp)
202
203
204 var upper decimal
205 upper.init(tmp.add(mant, natOne), exp)
206
207
208
209
210 inclusive := mant[0]&2 == 0
211
212
213
214 for i, m := range d.mant {
215 l := lower.at(i)
216 u := upper.at(i)
217
218
219
220
221 okdown := l != m || inclusive && i+1 == len(lower.mant)
222
223
224
225 okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
226
227
228
229 switch {
230 case okdown && okup:
231 d.round(i + 1)
232 return
233 case okdown:
234 d.roundDown(i + 1)
235 return
236 case okup:
237 d.roundUp(i + 1)
238 return
239 }
240 }
241 }
242
243
244 func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
245
246 ch := byte('0')
247 if len(d.mant) > 0 {
248 ch = d.mant[0]
249 }
250 buf = append(buf, ch)
251
252
253 if prec > 0 {
254 buf = append(buf, '.')
255 i := 1
256 m := min(len(d.mant), prec+1)
257 if i < m {
258 buf = append(buf, d.mant[i:m]...)
259 i = m
260 }
261 for ; i <= prec; i++ {
262 buf = append(buf, '0')
263 }
264 }
265
266
267 buf = append(buf, fmt)
268 var exp int64
269 if len(d.mant) > 0 {
270 exp = int64(d.exp) - 1
271 }
272 if exp < 0 {
273 ch = '-'
274 exp = -exp
275 } else {
276 ch = '+'
277 }
278 buf = append(buf, ch)
279
280
281 if exp < 10 {
282 buf = append(buf, '0')
283 }
284 return strconv.AppendInt(buf, exp, 10)
285 }
286
287
288 func fmtF(buf []byte, prec int, d decimal) []byte {
289
290 if d.exp > 0 {
291 m := min(len(d.mant), d.exp)
292 buf = append(buf, d.mant[:m]...)
293 for ; m < d.exp; m++ {
294 buf = append(buf, '0')
295 }
296 } else {
297 buf = append(buf, '0')
298 }
299
300
301 if prec > 0 {
302 buf = append(buf, '.')
303 for i := 0; i < prec; i++ {
304 buf = append(buf, d.at(d.exp+i))
305 }
306 }
307
308 return buf
309 }
310
311
312
313
314
315
316
317
318 func (x *Float) fmtB(buf []byte) []byte {
319 if x.form == zero {
320 return append(buf, '0')
321 }
322
323 if debugFloat && x.form != finite {
324 panic("non-finite float")
325 }
326
327
328
329 m := x.mant
330 switch w := uint32(len(x.mant)) * _W; {
331 case w < x.prec:
332 m = nat(nil).shl(m, uint(x.prec-w))
333 case w > x.prec:
334 m = nat(nil).shr(m, uint(w-x.prec))
335 }
336
337 buf = append(buf, m.utoa(10)...)
338 buf = append(buf, 'p')
339 e := int64(x.exp) - int64(x.prec)
340 if e >= 0 {
341 buf = append(buf, '+')
342 }
343 return strconv.AppendInt(buf, e, 10)
344 }
345
346
347
348
349
350
351
352 func (x *Float) fmtX(buf []byte, prec int) []byte {
353 if x.form == zero {
354 buf = append(buf, "0x0"...)
355 if prec > 0 {
356 buf = append(buf, '.')
357 for i := 0; i < prec; i++ {
358 buf = append(buf, '0')
359 }
360 }
361 buf = append(buf, "p+00"...)
362 return buf
363 }
364
365 if debugFloat && x.form != finite {
366 panic("non-finite float")
367 }
368
369
370 var n uint
371 if prec < 0 {
372 n = 1 + (x.MinPrec()-1+3)/4*4
373 } else {
374 n = 1 + 4*uint(prec)
375 }
376
377 x = new(Float).SetPrec(n).SetMode(x.mode).Set(x)
378
379
380 m := x.mant
381 switch w := uint(len(x.mant)) * _W; {
382 case w < n:
383 m = nat(nil).shl(m, n-w)
384 case w > n:
385 m = nat(nil).shr(m, w-n)
386 }
387 exp := x.exp - 1
388
389 hm := m.utoa(16)
390 if debugFloat && hm[0] != '1' {
391 panic("incorrect mantissa: " + string(hm))
392 }
393 buf = append(buf, "0x1"...)
394 if len(hm) > 1 {
395 buf = append(buf, '.')
396 buf = append(buf, hm[1:]...)
397 }
398
399 buf = append(buf, 'p')
400 exp64 := int64(exp)
401 if exp64 >= 0 {
402 buf = append(buf, '+')
403 } else {
404 exp64 = -exp64
405 buf = append(buf, '-')
406 }
407
408 if exp64 < 10 {
409 buf = append(buf, '0')
410 }
411 return strconv.AppendInt(buf, exp64, 10)
412 }
413
414
415
416
417
418
419
420 func (x *Float) fmtP(buf []byte) []byte {
421 if x.form == zero {
422 return append(buf, '0')
423 }
424
425 if debugFloat && x.form != finite {
426 panic("non-finite float")
427 }
428
429
430
431
432 m := x.mant
433 i := 0
434 for i < len(m) && m[i] == 0 {
435 i++
436 }
437 m = m[i:]
438
439 buf = append(buf, "0x."...)
440 buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
441 buf = append(buf, 'p')
442 if x.exp >= 0 {
443 buf = append(buf, '+')
444 }
445 return strconv.AppendInt(buf, int64(x.exp), 10)
446 }
447
448 func min(x, y int) int {
449 if x < y {
450 return x
451 }
452 return y
453 }
454
455 var _ fmt.Formatter = &floatZero
456
457
458
459
460
461
462
463
464
465
466 func (x *Float) Format(s fmt.State, format rune) {
467 prec, hasPrec := s.Precision()
468 if !hasPrec {
469 prec = 6
470 }
471
472 switch format {
473 case 'e', 'E', 'f', 'b', 'p', 'x':
474
475 case 'F':
476
477 format = 'f'
478 case 'v':
479
480 format = 'g'
481 fallthrough
482 case 'g', 'G':
483 if !hasPrec {
484 prec = -1
485 }
486 default:
487 fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
488 return
489 }
490 var buf []byte
491 buf = x.Append(buf, byte(format), prec)
492 if len(buf) == 0 {
493 buf = []byte("?")
494 }
495
496
497 var sign string
498 switch {
499 case buf[0] == '-':
500 sign = "-"
501 buf = buf[1:]
502 case buf[0] == '+':
503
504 sign = "+"
505 if s.Flag(' ') {
506 sign = " "
507 }
508 buf = buf[1:]
509 case s.Flag('+'):
510 sign = "+"
511 case s.Flag(' '):
512 sign = " "
513 }
514
515 var padding int
516 if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
517 padding = width - len(sign) - len(buf)
518 }
519
520 switch {
521 case s.Flag('0') && !x.IsInf():
522
523 writeMultiple(s, sign, 1)
524 writeMultiple(s, "0", padding)
525 s.Write(buf)
526 case s.Flag('-'):
527
528 writeMultiple(s, sign, 1)
529 s.Write(buf)
530 writeMultiple(s, " ", padding)
531 default:
532
533 writeMultiple(s, " ", padding)
534 writeMultiple(s, sign, 1)
535 s.Write(buf)
536 }
537 }
538
View as plain text