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