Source file src/pkg/math/big/ratconv.go
1
2
3
4
5
6
7 package big
8
9 import (
10 "errors"
11 "fmt"
12 "io"
13 "strconv"
14 "strings"
15 )
16
17 func ratTok(ch rune) bool {
18 return strings.ContainsRune("+-/0123456789.eE", ch)
19 }
20
21 var ratZero Rat
22 var _ fmt.Scanner = &ratZero
23
24
25
26 func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
27 tok, err := s.Token(true, ratTok)
28 if err != nil {
29 return err
30 }
31 if !strings.ContainsRune("efgEFGv", ch) {
32 return errors.New("Rat.Scan: invalid verb")
33 }
34 if _, ok := z.SetString(string(tok)); !ok {
35 return errors.New("Rat.Scan: invalid syntax")
36 }
37 return nil
38 }
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 func (z *Rat) SetString(s string) (*Rat, bool) {
58 if len(s) == 0 {
59 return nil, false
60 }
61
62
63
64 if sep := strings.Index(s, "/"); sep >= 0 {
65 if _, ok := z.a.SetString(s[:sep], 0); !ok {
66 return nil, false
67 }
68 r := strings.NewReader(s[sep+1:])
69 var err error
70 if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
71 return nil, false
72 }
73
74 if _, err = r.ReadByte(); err != io.EOF {
75 return nil, false
76 }
77 if len(z.b.abs) == 0 {
78 return nil, false
79 }
80 return z.norm(), true
81 }
82
83
84 r := strings.NewReader(s)
85
86
87 neg, err := scanSign(r)
88 if err != nil {
89 return nil, false
90 }
91
92
93 var base int
94 var fcount int
95 z.a.abs, base, fcount, err = z.a.abs.scan(r, 0, true)
96 if err != nil {
97 return nil, false
98 }
99
100
101 var exp int64
102 var ebase int
103 exp, ebase, err = scanExponent(r, true, true)
104 if err != nil {
105 return nil, false
106 }
107
108
109 if _, err = r.ReadByte(); err != io.EOF {
110 return nil, false
111 }
112
113
114 if len(z.a.abs) == 0 {
115 return z, true
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 var exp2, exp5 int64
132 if fcount < 0 {
133
134
135
136 d := int64(fcount)
137 switch base {
138 case 10:
139 exp5 = d
140 fallthrough
141 case 2:
142 exp2 = d
143 case 8:
144 exp2 = d * 3
145 case 16:
146 exp2 = d * 4
147 default:
148 panic("unexpected mantissa base")
149 }
150
151 }
152
153
154 switch ebase {
155 case 10:
156 exp5 += exp
157 fallthrough
158 case 2:
159 exp2 += exp
160 default:
161 panic("unexpected exponent base")
162 }
163
164
165
166
167 if exp5 != 0 {
168 n := exp5
169 if n < 0 {
170 n = -n
171 }
172 pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil)
173 if exp5 > 0 {
174 z.a.abs = z.a.abs.mul(z.a.abs, pow5)
175 z.b.abs = z.b.abs.setWord(1)
176 } else {
177 z.b.abs = pow5
178 }
179 } else {
180 z.b.abs = z.b.abs.setWord(1)
181 }
182
183
184 if exp2 > 0 {
185 if int64(uint(exp2)) != exp2 {
186 panic("exponent too large")
187 }
188 z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
189 } else if exp2 < 0 {
190 if int64(uint(-exp2)) != -exp2 {
191 panic("exponent too large")
192 }
193 z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
194 }
195
196 z.a.neg = neg && len(z.a.abs) > 0
197
198 return z.norm(), true
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, err error) {
218
219 ch, err := r.ReadByte()
220 if err != nil {
221 if err == io.EOF {
222 err = nil
223 }
224 return 0, 10, err
225 }
226
227
228 switch ch {
229 case 'e', 'E':
230 base = 10
231 case 'p', 'P':
232 if base2ok {
233 base = 2
234 break
235 }
236 fallthrough
237 default:
238 r.UnreadByte()
239 return 0, 10, nil
240 }
241
242
243 var digits []byte
244 ch, err = r.ReadByte()
245 if err == nil && (ch == '+' || ch == '-') {
246 if ch == '-' {
247 digits = append(digits, '-')
248 }
249 ch, err = r.ReadByte()
250 }
251
252
253
254
255 prev := '.'
256 invalSep := false
257
258
259 hasDigits := false
260 for err == nil {
261 if '0' <= ch && ch <= '9' {
262 digits = append(digits, ch)
263 prev = '0'
264 hasDigits = true
265 } else if ch == '_' && sepOk {
266 if prev != '0' {
267 invalSep = true
268 }
269 prev = '_'
270 } else {
271 r.UnreadByte()
272 break
273 }
274 ch, err = r.ReadByte()
275 }
276
277 if err == io.EOF {
278 err = nil
279 }
280 if err == nil && !hasDigits {
281 err = errNoDigits
282 }
283 if err == nil {
284 exp, err = strconv.ParseInt(string(digits), 10, 64)
285 }
286
287 if err == nil && (invalSep || prev == '_') {
288 err = errInvalSep
289 }
290
291 return
292 }
293
294
295 func (x *Rat) String() string {
296 return string(x.marshal())
297 }
298
299
300 func (x *Rat) marshal() []byte {
301 var buf []byte
302 buf = x.a.Append(buf, 10)
303 buf = append(buf, '/')
304 if len(x.b.abs) != 0 {
305 buf = x.b.Append(buf, 10)
306 } else {
307 buf = append(buf, '1')
308 }
309 return buf
310 }
311
312
313
314 func (x *Rat) RatString() string {
315 if x.IsInt() {
316 return x.a.String()
317 }
318 return x.String()
319 }
320
321
322
323
324 func (x *Rat) FloatString(prec int) string {
325 var buf []byte
326
327 if x.IsInt() {
328 buf = x.a.Append(buf, 10)
329 if prec > 0 {
330 buf = append(buf, '.')
331 for i := prec; i > 0; i-- {
332 buf = append(buf, '0')
333 }
334 }
335 return string(buf)
336 }
337
338
339 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
340
341 p := natOne
342 if prec > 0 {
343 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
344 }
345
346 r = r.mul(r, p)
347 r, r2 := r.div(nat(nil), r, x.b.abs)
348
349
350 r2 = r2.add(r2, r2)
351 if x.b.abs.cmp(r2) <= 0 {
352 r = r.add(r, natOne)
353 if r.cmp(p) >= 0 {
354 q = nat(nil).add(q, natOne)
355 r = nat(nil).sub(r, p)
356 }
357 }
358
359 if x.a.neg {
360 buf = append(buf, '-')
361 }
362 buf = append(buf, q.utoa(10)...)
363
364 if prec > 0 {
365 buf = append(buf, '.')
366 rs := r.utoa(10)
367 for i := prec - len(rs); i > 0; i-- {
368 buf = append(buf, '0')
369 }
370 buf = append(buf, rs...)
371 }
372
373 return string(buf)
374 }
375
View as plain text