Source file src/pkg/math/big/rat.go
1
2
3
4
5
6
7 package big
8
9 import (
10 "encoding/binary"
11 "errors"
12 "fmt"
13 "math"
14 "strings"
15 )
16
17
18
19 type Rat struct {
20
21
22
23 a, b Int
24 }
25
26
27 func NewRat(a, b int64) *Rat {
28 return new(Rat).SetFrac64(a, b)
29 }
30
31
32
33 func (z *Rat) SetFloat64(f float64) *Rat {
34 const expMask = 1<<11 - 1
35 bits := math.Float64bits(f)
36 mantissa := bits & (1<<52 - 1)
37 exp := int((bits >> 52) & expMask)
38 switch exp {
39 case expMask:
40 return nil
41 case 0:
42 exp -= 1022
43 default:
44 mantissa |= 1 << 52
45 exp -= 1023
46 }
47
48 shift := 52 - exp
49
50
51 for mantissa&1 == 0 && shift > 0 {
52 mantissa >>= 1
53 shift--
54 }
55
56 z.a.SetUint64(mantissa)
57 z.a.neg = f < 0
58 z.b.Set(intOne)
59 if shift > 0 {
60 z.b.Lsh(&z.b, uint(shift))
61 } else {
62 z.a.Lsh(&z.a, uint(-shift))
63 }
64 return z.norm()
65 }
66
67
68
69 func isFinite(f float64) bool {
70 return math.Abs(f) <= math.MaxFloat64
71 }
72
73
74 func low64(z nat) uint64 {
75 if len(z) == 0 {
76 return 0
77 }
78 if _W == 32 && len(z) > 1 {
79 return uint64(z[1])<<32 | uint64(z[0])
80 }
81 return uint64(z[0])
82 }
83
84
85
86
87
88 func quotToFloat(a, b nat) (f float64, exact bool) {
89
90 alen := a.bitLen()
91 if alen == 0 {
92 return 0, true
93 }
94 blen := b.bitLen()
95 if blen == 0 {
96 panic("division by zero")
97 }
98
99
100
101
102
103
104
105 exp := alen - blen
106 var a2, b2 nat
107 a2 = a2.set(a)
108 b2 = b2.set(b)
109 if shift := 54 - exp; shift > 0 {
110 a2 = a2.shl(a2, uint(shift))
111 } else if shift < 0 {
112 b2 = b2.shl(b2, uint(-shift))
113 }
114
115
116
117
118 var q nat
119 q, r := q.div(a2, a2, b2)
120 mantissa := low64(q)
121 haveRem := len(r) > 0
122
123
124
125 if mantissa>>54 == 1 {
126 if mantissa&1 == 1 {
127 haveRem = true
128 }
129 mantissa >>= 1
130 exp++
131 }
132 if mantissa>>53 != 1 {
133 panic("expected exactly 54 bits of result")
134 }
135
136
137 if -1022-52 <= exp && exp <= -1022 {
138
139 shift := uint64(-1022 - (exp - 1))
140 lostbits := mantissa & (1<<shift - 1)
141 haveRem = haveRem || lostbits != 0
142 mantissa >>= shift
143 exp = -1023 + 2
144 }
145
146 exact = !haveRem
147 if mantissa&1 != 0 {
148 exact = false
149 if haveRem || mantissa&2 != 0 {
150 if mantissa++; mantissa >= 1<<54 {
151
152 mantissa >>= 1
153 exp++
154 }
155 }
156 }
157 mantissa >>= 1
158
159 f = math.Ldexp(float64(mantissa), exp-53)
160 if math.IsInf(f, 0) {
161 exact = false
162 }
163 return
164 }
165
166
167
168
169 func (x *Rat) Float64() (f float64, exact bool) {
170 b := x.b.abs
171 if len(b) == 0 {
172 b = b.set(natOne)
173 }
174 f, exact = quotToFloat(x.a.abs, b)
175 if x.a.neg {
176 f = -f
177 }
178 return
179 }
180
181
182 func (z *Rat) SetFrac(a, b *Int) *Rat {
183 z.a.neg = a.neg != b.neg
184 babs := b.abs
185 if len(babs) == 0 {
186 panic("division by zero")
187 }
188 if &z.a == b || alias(z.a.abs, babs) {
189 babs = nat(nil).set(babs)
190 }
191 z.a.abs = z.a.abs.set(a.abs)
192 z.b.abs = z.b.abs.set(babs)
193 return z.norm()
194 }
195
196
197 func (z *Rat) SetFrac64(a, b int64) *Rat {
198 z.a.SetInt64(a)
199 if b == 0 {
200 panic("division by zero")
201 }
202 if b < 0 {
203 b = -b
204 z.a.neg = !z.a.neg
205 }
206 z.b.abs = z.b.abs.setUint64(uint64(b))
207 return z.norm()
208 }
209
210
211 func (z *Rat) SetInt(x *Int) *Rat {
212 z.a.Set(x)
213 z.b.abs = z.b.abs.make(0)
214 return z
215 }
216
217
218 func (z *Rat) SetInt64(x int64) *Rat {
219 z.a.SetInt64(x)
220 z.b.abs = z.b.abs.make(0)
221 return z
222 }
223
224
225 func (z *Rat) Set(x *Rat) *Rat {
226 if z != x {
227 z.a.Set(&x.a)
228 z.b.Set(&x.b)
229 }
230 return z
231 }
232
233
234 func (z *Rat) Abs(x *Rat) *Rat {
235 z.Set(x)
236 z.a.neg = false
237 return z
238 }
239
240
241 func (z *Rat) Neg(x *Rat) *Rat {
242 z.Set(x)
243 z.a.neg = len(z.a.abs) > 0 && !z.a.neg
244 return z
245 }
246
247
248 func (z *Rat) Inv(x *Rat) *Rat {
249 if len(x.a.abs) == 0 {
250 panic("division by zero")
251 }
252 z.Set(x)
253 a := z.b.abs
254 if len(a) == 0 {
255 a = a.set(natOne)
256 }
257 b := z.a.abs
258 if b.cmp(natOne) == 0 {
259 b = b.make(0)
260 }
261 z.a.abs, z.b.abs = a, b
262 return z
263 }
264
265
266
267
268
269
270
271 func (x *Rat) Sign() int {
272 return x.a.Sign()
273 }
274
275
276 func (x *Rat) IsInt() bool {
277 return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
278 }
279
280
281
282
283
284 func (x *Rat) Num() *Int {
285 return &x.a
286 }
287
288
289
290
291 func (x *Rat) Denom() *Int {
292 x.b.neg = false
293 if len(x.b.abs) == 0 {
294 x.b.abs = x.b.abs.set(natOne)
295 }
296 return &x.b
297 }
298
299 func (z *Rat) norm() *Rat {
300 switch {
301 case len(z.a.abs) == 0:
302
303 z.a.neg = false
304 z.b.abs = z.b.abs.make(0)
305 case len(z.b.abs) == 0:
306
307 case z.b.abs.cmp(natOne) == 0:
308
309 z.b.abs = z.b.abs.make(0)
310 default:
311 neg := z.a.neg
312 z.a.neg = false
313 z.b.neg = false
314 if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
315 z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
316 z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
317 if z.b.abs.cmp(natOne) == 0 {
318
319 z.b.abs = z.b.abs.make(0)
320 }
321 }
322 z.a.neg = neg
323 }
324 return z
325 }
326
327
328
329
330 func mulDenom(z, x, y nat) nat {
331 switch {
332 case len(x) == 0:
333 return z.set(y)
334 case len(y) == 0:
335 return z.set(x)
336 }
337 return z.mul(x, y)
338 }
339
340
341
342 func scaleDenom(x *Int, f nat) *Int {
343 var z Int
344 if len(f) == 0 {
345 return z.Set(x)
346 }
347 z.abs = z.abs.mul(x.abs, f)
348 z.neg = x.neg
349 return &z
350 }
351
352
353
354
355
356
357
358 func (x *Rat) Cmp(y *Rat) int {
359 return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
360 }
361
362
363 func (z *Rat) Add(x, y *Rat) *Rat {
364 a1 := scaleDenom(&x.a, y.b.abs)
365 a2 := scaleDenom(&y.a, x.b.abs)
366 z.a.Add(a1, a2)
367 z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
368 return z.norm()
369 }
370
371
372 func (z *Rat) Sub(x, y *Rat) *Rat {
373 a1 := scaleDenom(&x.a, y.b.abs)
374 a2 := scaleDenom(&y.a, x.b.abs)
375 z.a.Sub(a1, a2)
376 z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
377 return z.norm()
378 }
379
380
381 func (z *Rat) Mul(x, y *Rat) *Rat {
382 z.a.Mul(&x.a, &y.a)
383 z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
384 return z.norm()
385 }
386
387
388
389 func (z *Rat) Quo(x, y *Rat) *Rat {
390 if len(y.a.abs) == 0 {
391 panic("division by zero")
392 }
393 a := scaleDenom(&x.a, y.b.abs)
394 b := scaleDenom(&y.a, x.b.abs)
395 z.a.abs = a.abs
396 z.b.abs = b.abs
397 z.a.neg = a.neg != b.neg
398 return z.norm()
399 }
400
401 func ratTok(ch rune) bool {
402 return strings.IndexRune("+-/0123456789.eE", ch) >= 0
403 }
404
405
406
407 func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
408 tok, err := s.Token(true, ratTok)
409 if err != nil {
410 return err
411 }
412 if strings.IndexRune("efgEFGv", ch) < 0 {
413 return errors.New("Rat.Scan: invalid verb")
414 }
415 if _, ok := z.SetString(string(tok)); !ok {
416 return errors.New("Rat.Scan: invalid syntax")
417 }
418 return nil
419 }
420
421
422
423
424
425 func (z *Rat) SetString(s string) (*Rat, bool) {
426 if len(s) == 0 {
427 return nil, false
428 }
429
430
431 sep := strings.Index(s, "/")
432 if sep >= 0 {
433 if _, ok := z.a.SetString(s[0:sep], 10); !ok {
434 return nil, false
435 }
436 s = s[sep+1:]
437 var err error
438 if z.b.abs, _, err = z.b.abs.scan(strings.NewReader(s), 10); err != nil {
439 return nil, false
440 }
441 return z.norm(), true
442 }
443
444
445 sep = strings.Index(s, ".")
446
447 e := strings.IndexAny(s, "eE")
448 var exp Int
449 if e >= 0 {
450 if e < sep {
451
452 return nil, false
453 }
454 if _, ok := exp.SetString(s[e+1:], 10); !ok {
455 return nil, false
456 }
457 s = s[0:e]
458 }
459 if sep >= 0 {
460 s = s[0:sep] + s[sep+1:]
461 exp.Sub(&exp, NewInt(int64(len(s)-sep)))
462 }
463
464 if _, ok := z.a.SetString(s, 10); !ok {
465 return nil, false
466 }
467 powTen := nat(nil).expNN(natTen, exp.abs, nil)
468 if exp.neg {
469 z.b.abs = powTen
470 z.norm()
471 } else {
472 z.a.abs = z.a.abs.mul(z.a.abs, powTen)
473 z.b.abs = z.b.abs.make(0)
474 }
475
476 return z, true
477 }
478
479
480 func (x *Rat) String() string {
481 s := "/1"
482 if len(x.b.abs) != 0 {
483 s = "/" + x.b.abs.decimalString()
484 }
485 return x.a.String() + s
486 }
487
488
489
490 func (x *Rat) RatString() string {
491 if x.IsInt() {
492 return x.a.String()
493 }
494 return x.String()
495 }
496
497
498
499 func (x *Rat) FloatString(prec int) string {
500 if x.IsInt() {
501 s := x.a.String()
502 if prec > 0 {
503 s += "." + strings.Repeat("0", prec)
504 }
505 return s
506 }
507
508
509 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
510
511 p := natOne
512 if prec > 0 {
513 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
514 }
515
516 r = r.mul(r, p)
517 r, r2 := r.div(nat(nil), r, x.b.abs)
518
519
520 r2 = r2.add(r2, r2)
521 if x.b.abs.cmp(r2) <= 0 {
522 r = r.add(r, natOne)
523 if r.cmp(p) >= 0 {
524 q = nat(nil).add(q, natOne)
525 r = nat(nil).sub(r, p)
526 }
527 }
528
529 s := q.decimalString()
530 if x.a.neg {
531 s = "-" + s
532 }
533
534 if prec > 0 {
535 rs := r.decimalString()
536 leadingZeros := prec - len(rs)
537 s += "." + strings.Repeat("0", leadingZeros) + rs
538 }
539
540 return s
541 }
542
543
544 const ratGobVersion byte = 1
545
546
547 func (x *Rat) GobEncode() ([]byte, error) {
548 buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S)
549 i := x.b.abs.bytes(buf)
550 j := x.a.abs.bytes(buf[0:i])
551 n := i - j
552 if int(uint32(n)) != n {
553
554 return nil, errors.New("Rat.GobEncode: numerator too large")
555 }
556 binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
557 j -= 1 + 4
558 b := ratGobVersion << 1
559 if x.a.neg {
560 b |= 1
561 }
562 buf[j] = b
563 return buf[j:], nil
564 }
565
566
567 func (z *Rat) GobDecode(buf []byte) error {
568 if len(buf) == 0 {
569 return errors.New("Rat.GobDecode: no data")
570 }
571 b := buf[0]
572 if b>>1 != ratGobVersion {
573 return errors.New(fmt.Sprintf("Rat.GobDecode: encoding version %d not supported", b>>1))
574 }
575 const j = 1 + 4
576 i := j + binary.BigEndian.Uint32(buf[j-4:j])
577 z.a.neg = b&1 != 0
578 z.a.abs = z.a.abs.setBytes(buf[j:i])
579 z.b.abs = z.b.abs.setBytes(buf[i:])
580 return nil
581 }
View as plain text