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