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