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