github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/big/rat.go (about)

     1  // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/big/rat.go
     2  
     3  // Copyright 2010 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // This file implements multi-precision rational numbers.
     8  
     9  package big
    10  
    11  import (
    12  	"encoding/binary"
    13  	"errors"
    14  	"fmt"
    15  	"math"
    16  )
    17  
    18  // A Rat represents a quotient a/b of arbitrary precision.
    19  // The zero value for a Rat represents the value 0.
    20  type Rat struct {
    21  	// To make zero values for Rat work w/o initialization,
    22  	// a zero value of b (len(b) == 0) acts like b == 1.
    23  	// a.neg determines the sign of the Rat, b.neg is ignored.
    24  	a, b Int
    25  }
    26  
    27  // NewRat creates a new Rat with numerator a and denominator b.
    28  func NewRat(a, b int64) *Rat {
    29  	return new(Rat).SetFrac64(a, b)
    30  }
    31  
    32  // SetFloat64 sets z to exactly f and returns z.
    33  // If f is not finite, SetFloat returns nil.
    34  func (z *Rat) SetFloat64(f float64) *Rat {
    35  	const expMask = 1<<11 - 1
    36  	bits := math.Float64bits(f)
    37  	mantissa := bits & (1<<52 - 1)
    38  	exp := int((bits >> 52) & expMask)
    39  	switch exp {
    40  	case expMask: // non-finite
    41  		return nil
    42  	case 0: // denormal
    43  		exp -= 1022
    44  	default: // normal
    45  		mantissa |= 1 << 52
    46  		exp -= 1023
    47  	}
    48  
    49  	shift := 52 - exp
    50  
    51  	// Optimization (?): partially pre-normalise.
    52  	for mantissa&1 == 0 && shift > 0 {
    53  		mantissa >>= 1
    54  		shift--
    55  	}
    56  
    57  	z.a.SetUint64(mantissa)
    58  	z.a.neg = f < 0
    59  	z.b.Set(intOne)
    60  	if shift > 0 {
    61  		z.b.Lsh(&z.b, uint(shift))
    62  	} else {
    63  		z.a.Lsh(&z.a, uint(-shift))
    64  	}
    65  	return z.norm()
    66  }
    67  
    68  // quotToFloat32 returns the non-negative float32 value
    69  // nearest to the quotient a/b, using round-to-even in
    70  // halfway cases.  It does not mutate its arguments.
    71  // Preconditions: b is non-zero; a and b have no common factors.
    72  func quotToFloat32(a, b nat) (f float32, exact bool) {
    73  	const (
    74  		// float size in bits
    75  		Fsize = 32
    76  
    77  		// mantissa
    78  		Msize  = 23
    79  		Msize1 = Msize + 1 // incl. implicit 1
    80  		Msize2 = Msize1 + 1
    81  
    82  		// exponent
    83  		Esize = Fsize - Msize1
    84  		Ebias = 1<<(Esize-1) - 1
    85  		Emin  = 1 - Ebias
    86  		Emax  = Ebias
    87  	)
    88  
    89  	// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
    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  	// 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
   100  	// (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
   101  	// This is 2 or 3 more than the float32 mantissa field width of Msize:
   102  	// - the optional extra bit is shifted away in step 3 below.
   103  	// - the high-order 1 is omitted in "normal" representation;
   104  	// - the low-order 1 will be used during rounding then discarded.
   105  	exp := alen - blen
   106  	var a2, b2 nat
   107  	a2 = a2.set(a)
   108  	b2 = b2.set(b)
   109  	if shift := Msize2 - 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  	// 2. Compute quotient and remainder (q, r).  NB: due to the
   116  	// extra shift, the low-order bit of q is logically the
   117  	// high-order bit of r.
   118  	var q nat
   119  	q, r := q.div(a2, a2, b2) // (recycle a2)
   120  	mantissa := low32(q)
   121  	haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
   122  
   123  	// 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
   124  	// (in effect---we accomplish this incrementally).
   125  	if mantissa>>Msize2 == 1 {
   126  		if mantissa&1 == 1 {
   127  			haveRem = true
   128  		}
   129  		mantissa >>= 1
   130  		exp++
   131  	}
   132  	if mantissa>>Msize1 != 1 {
   133  		panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
   134  	}
   135  
   136  	// 4. Rounding.
   137  	if Emin-Msize <= exp && exp <= Emin {
   138  		// Denormal case; lose 'shift' bits of precision.
   139  		shift := uint(Emin - (exp - 1)) // [1..Esize1)
   140  		lostbits := mantissa & (1<<shift - 1)
   141  		haveRem = haveRem || lostbits != 0
   142  		mantissa >>= shift
   143  		exp = 2 - Ebias // == exp + shift
   144  	}
   145  	// Round q using round-half-to-even.
   146  	exact = !haveRem
   147  	if mantissa&1 != 0 {
   148  		exact = false
   149  		if haveRem || mantissa&2 != 0 {
   150  			if mantissa++; mantissa >= 1<<Msize2 {
   151  				// Complete rollover 11...1 => 100...0, so shift is safe
   152  				mantissa >>= 1
   153  				exp++
   154  			}
   155  		}
   156  	}
   157  	mantissa >>= 1 // discard rounding bit.  Mantissa now scaled by 1<<Msize1.
   158  
   159  	f = float32(math.Ldexp(float64(mantissa), exp-Msize1))
   160  	if math.IsInf(float64(f), 0) {
   161  		exact = false
   162  	}
   163  	return
   164  }
   165  
   166  // quotToFloat64 returns the non-negative float64 value
   167  // nearest to the quotient a/b, using round-to-even in
   168  // halfway cases.  It does not mutate its arguments.
   169  // Preconditions: b is non-zero; a and b have no common factors.
   170  func quotToFloat64(a, b nat) (f float64, exact bool) {
   171  	const (
   172  		// float size in bits
   173  		Fsize = 64
   174  
   175  		// mantissa
   176  		Msize  = 52
   177  		Msize1 = Msize + 1 // incl. implicit 1
   178  		Msize2 = Msize1 + 1
   179  
   180  		// exponent
   181  		Esize = Fsize - Msize1
   182  		Ebias = 1<<(Esize-1) - 1
   183  		Emin  = 1 - Ebias
   184  		Emax  = Ebias
   185  	)
   186  
   187  	// TODO(adonovan): specialize common degenerate cases: 1.0, integers.
   188  	alen := a.bitLen()
   189  	if alen == 0 {
   190  		return 0, true
   191  	}
   192  	blen := b.bitLen()
   193  	if blen == 0 {
   194  		panic("division by zero")
   195  	}
   196  
   197  	// 1. Left-shift A or B such that quotient A/B is in [1<<Msize1, 1<<(Msize2+1)
   198  	// (Msize2 bits if A < B when they are left-aligned, Msize2+1 bits if A >= B).
   199  	// This is 2 or 3 more than the float64 mantissa field width of Msize:
   200  	// - the optional extra bit is shifted away in step 3 below.
   201  	// - the high-order 1 is omitted in "normal" representation;
   202  	// - the low-order 1 will be used during rounding then discarded.
   203  	exp := alen - blen
   204  	var a2, b2 nat
   205  	a2 = a2.set(a)
   206  	b2 = b2.set(b)
   207  	if shift := Msize2 - exp; shift > 0 {
   208  		a2 = a2.shl(a2, uint(shift))
   209  	} else if shift < 0 {
   210  		b2 = b2.shl(b2, uint(-shift))
   211  	}
   212  
   213  	// 2. Compute quotient and remainder (q, r).  NB: due to the
   214  	// extra shift, the low-order bit of q is logically the
   215  	// high-order bit of r.
   216  	var q nat
   217  	q, r := q.div(a2, a2, b2) // (recycle a2)
   218  	mantissa := low64(q)
   219  	haveRem := len(r) > 0 // mantissa&1 && !haveRem => remainder is exactly half
   220  
   221  	// 3. If quotient didn't fit in Msize2 bits, redo division by b2<<1
   222  	// (in effect---we accomplish this incrementally).
   223  	if mantissa>>Msize2 == 1 {
   224  		if mantissa&1 == 1 {
   225  			haveRem = true
   226  		}
   227  		mantissa >>= 1
   228  		exp++
   229  	}
   230  	if mantissa>>Msize1 != 1 {
   231  		panic(fmt.Sprintf("expected exactly %d bits of result", Msize2))
   232  	}
   233  
   234  	// 4. Rounding.
   235  	if Emin-Msize <= exp && exp <= Emin {
   236  		// Denormal case; lose 'shift' bits of precision.
   237  		shift := uint(Emin - (exp - 1)) // [1..Esize1)
   238  		lostbits := mantissa & (1<<shift - 1)
   239  		haveRem = haveRem || lostbits != 0
   240  		mantissa >>= shift
   241  		exp = 2 - Ebias // == exp + shift
   242  	}
   243  	// Round q using round-half-to-even.
   244  	exact = !haveRem
   245  	if mantissa&1 != 0 {
   246  		exact = false
   247  		if haveRem || mantissa&2 != 0 {
   248  			if mantissa++; mantissa >= 1<<Msize2 {
   249  				// Complete rollover 11...1 => 100...0, so shift is safe
   250  				mantissa >>= 1
   251  				exp++
   252  			}
   253  		}
   254  	}
   255  	mantissa >>= 1 // discard rounding bit.  Mantissa now scaled by 1<<Msize1.
   256  
   257  	f = math.Ldexp(float64(mantissa), exp-Msize1)
   258  	if math.IsInf(f, 0) {
   259  		exact = false
   260  	}
   261  	return
   262  }
   263  
   264  // Float32 returns the nearest float32 value for x and a bool indicating
   265  // whether f represents x exactly. If the magnitude of x is too large to
   266  // be represented by a float32, f is an infinity and exact is false.
   267  // The sign of f always matches the sign of x, even if f == 0.
   268  func (x *Rat) Float32() (f float32, exact bool) {
   269  	b := x.b.abs
   270  	if len(b) == 0 {
   271  		b = b.set(natOne) // materialize denominator
   272  	}
   273  	f, exact = quotToFloat32(x.a.abs, b)
   274  	if x.a.neg {
   275  		f = -f
   276  	}
   277  	return
   278  }
   279  
   280  // Float64 returns the nearest float64 value for x and a bool indicating
   281  // whether f represents x exactly. If the magnitude of x is too large to
   282  // be represented by a float64, f is an infinity and exact is false.
   283  // The sign of f always matches the sign of x, even if f == 0.
   284  func (x *Rat) Float64() (f float64, exact bool) {
   285  	b := x.b.abs
   286  	if len(b) == 0 {
   287  		b = b.set(natOne) // materialize denominator
   288  	}
   289  	f, exact = quotToFloat64(x.a.abs, b)
   290  	if x.a.neg {
   291  		f = -f
   292  	}
   293  	return
   294  }
   295  
   296  // SetFrac sets z to a/b and returns z.
   297  func (z *Rat) SetFrac(a, b *Int) *Rat {
   298  	z.a.neg = a.neg != b.neg
   299  	babs := b.abs
   300  	if len(babs) == 0 {
   301  		panic("division by zero")
   302  	}
   303  	if &z.a == b || alias(z.a.abs, babs) {
   304  		babs = nat(nil).set(babs) // make a copy
   305  	}
   306  	z.a.abs = z.a.abs.set(a.abs)
   307  	z.b.abs = z.b.abs.set(babs)
   308  	return z.norm()
   309  }
   310  
   311  // SetFrac64 sets z to a/b and returns z.
   312  func (z *Rat) SetFrac64(a, b int64) *Rat {
   313  	z.a.SetInt64(a)
   314  	if b == 0 {
   315  		panic("division by zero")
   316  	}
   317  	if b < 0 {
   318  		b = -b
   319  		z.a.neg = !z.a.neg
   320  	}
   321  	z.b.abs = z.b.abs.setUint64(uint64(b))
   322  	return z.norm()
   323  }
   324  
   325  // SetInt sets z to x (by making a copy of x) and returns z.
   326  func (z *Rat) SetInt(x *Int) *Rat {
   327  	z.a.Set(x)
   328  	z.b.abs = z.b.abs[:0]
   329  	return z
   330  }
   331  
   332  // SetInt64 sets z to x and returns z.
   333  func (z *Rat) SetInt64(x int64) *Rat {
   334  	z.a.SetInt64(x)
   335  	z.b.abs = z.b.abs[:0]
   336  	return z
   337  }
   338  
   339  // Set sets z to x (by making a copy of x) and returns z.
   340  func (z *Rat) Set(x *Rat) *Rat {
   341  	if z != x {
   342  		z.a.Set(&x.a)
   343  		z.b.Set(&x.b)
   344  	}
   345  	return z
   346  }
   347  
   348  // Abs sets z to |x| (the absolute value of x) and returns z.
   349  func (z *Rat) Abs(x *Rat) *Rat {
   350  	z.Set(x)
   351  	z.a.neg = false
   352  	return z
   353  }
   354  
   355  // Neg sets z to -x and returns z.
   356  func (z *Rat) Neg(x *Rat) *Rat {
   357  	z.Set(x)
   358  	z.a.neg = len(z.a.abs) > 0 && !z.a.neg // 0 has no sign
   359  	return z
   360  }
   361  
   362  // Inv sets z to 1/x and returns z.
   363  func (z *Rat) Inv(x *Rat) *Rat {
   364  	if len(x.a.abs) == 0 {
   365  		panic("division by zero")
   366  	}
   367  	z.Set(x)
   368  	a := z.b.abs
   369  	if len(a) == 0 {
   370  		a = a.set(natOne) // materialize numerator
   371  	}
   372  	b := z.a.abs
   373  	if b.cmp(natOne) == 0 {
   374  		b = b[:0] // normalize denominator
   375  	}
   376  	z.a.abs, z.b.abs = a, b // sign doesn't change
   377  	return z
   378  }
   379  
   380  // Sign returns:
   381  //
   382  //	-1 if x <  0
   383  //	 0 if x == 0
   384  //	+1 if x >  0
   385  //
   386  func (x *Rat) Sign() int {
   387  	return x.a.Sign()
   388  }
   389  
   390  // IsInt reports whether the denominator of x is 1.
   391  func (x *Rat) IsInt() bool {
   392  	return len(x.b.abs) == 0 || x.b.abs.cmp(natOne) == 0
   393  }
   394  
   395  // Num returns the numerator of x; it may be <= 0.
   396  // The result is a reference to x's numerator; it
   397  // may change if a new value is assigned to x, and vice versa.
   398  // The sign of the numerator corresponds to the sign of x.
   399  func (x *Rat) Num() *Int {
   400  	return &x.a
   401  }
   402  
   403  // Denom returns the denominator of x; it is always > 0.
   404  // The result is a reference to x's denominator; it
   405  // may change if a new value is assigned to x, and vice versa.
   406  func (x *Rat) Denom() *Int {
   407  	x.b.neg = false // the result is always >= 0
   408  	if len(x.b.abs) == 0 {
   409  		x.b.abs = x.b.abs.set(natOne) // materialize denominator
   410  	}
   411  	return &x.b
   412  }
   413  
   414  func (z *Rat) norm() *Rat {
   415  	switch {
   416  	case len(z.a.abs) == 0:
   417  		// z == 0 - normalize sign and denominator
   418  		z.a.neg = false
   419  		z.b.abs = z.b.abs[:0]
   420  	case len(z.b.abs) == 0:
   421  		// z is normalized int - nothing to do
   422  	case z.b.abs.cmp(natOne) == 0:
   423  		// z is int - normalize denominator
   424  		z.b.abs = z.b.abs[:0]
   425  	default:
   426  		neg := z.a.neg
   427  		z.a.neg = false
   428  		z.b.neg = false
   429  		if f := NewInt(0).binaryGCD(&z.a, &z.b); f.Cmp(intOne) != 0 {
   430  			z.a.abs, _ = z.a.abs.div(nil, z.a.abs, f.abs)
   431  			z.b.abs, _ = z.b.abs.div(nil, z.b.abs, f.abs)
   432  			if z.b.abs.cmp(natOne) == 0 {
   433  				// z is int - normalize denominator
   434  				z.b.abs = z.b.abs[:0]
   435  			}
   436  		}
   437  		z.a.neg = neg
   438  	}
   439  	return z
   440  }
   441  
   442  // mulDenom sets z to the denominator product x*y (by taking into
   443  // account that 0 values for x or y must be interpreted as 1) and
   444  // returns z.
   445  func mulDenom(z, x, y nat) nat {
   446  	switch {
   447  	case len(x) == 0:
   448  		return z.set(y)
   449  	case len(y) == 0:
   450  		return z.set(x)
   451  	}
   452  	return z.mul(x, y)
   453  }
   454  
   455  // scaleDenom computes x*f.
   456  // If f == 0 (zero value of denominator), the result is (a copy of) x.
   457  func scaleDenom(x *Int, f nat) *Int {
   458  	var z Int
   459  	if len(f) == 0 {
   460  		return z.Set(x)
   461  	}
   462  	z.abs = z.abs.mul(x.abs, f)
   463  	z.neg = x.neg
   464  	return &z
   465  }
   466  
   467  // Cmp compares x and y and returns:
   468  //
   469  //   -1 if x <  y
   470  //    0 if x == y
   471  //   +1 if x >  y
   472  //
   473  func (x *Rat) Cmp(y *Rat) int {
   474  	return scaleDenom(&x.a, y.b.abs).Cmp(scaleDenom(&y.a, x.b.abs))
   475  }
   476  
   477  // Add sets z to the sum x+y and returns z.
   478  func (z *Rat) Add(x, y *Rat) *Rat {
   479  	a1 := scaleDenom(&x.a, y.b.abs)
   480  	a2 := scaleDenom(&y.a, x.b.abs)
   481  	z.a.Add(a1, a2)
   482  	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
   483  	return z.norm()
   484  }
   485  
   486  // Sub sets z to the difference x-y and returns z.
   487  func (z *Rat) Sub(x, y *Rat) *Rat {
   488  	a1 := scaleDenom(&x.a, y.b.abs)
   489  	a2 := scaleDenom(&y.a, x.b.abs)
   490  	z.a.Sub(a1, a2)
   491  	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
   492  	return z.norm()
   493  }
   494  
   495  // Mul sets z to the product x*y and returns z.
   496  func (z *Rat) Mul(x, y *Rat) *Rat {
   497  	z.a.Mul(&x.a, &y.a)
   498  	z.b.abs = mulDenom(z.b.abs, x.b.abs, y.b.abs)
   499  	return z.norm()
   500  }
   501  
   502  // Quo sets z to the quotient x/y and returns z.
   503  // If y == 0, a division-by-zero run-time panic occurs.
   504  func (z *Rat) Quo(x, y *Rat) *Rat {
   505  	if len(y.a.abs) == 0 {
   506  		panic("division by zero")
   507  	}
   508  	a := scaleDenom(&x.a, y.b.abs)
   509  	b := scaleDenom(&y.a, x.b.abs)
   510  	z.a.abs = a.abs
   511  	z.b.abs = b.abs
   512  	z.a.neg = a.neg != b.neg
   513  	return z.norm()
   514  }
   515  
   516  // Gob codec version. Permits backward-compatible changes to the encoding.
   517  const ratGobVersion byte = 1
   518  
   519  // GobEncode implements the gob.GobEncoder interface.
   520  func (x *Rat) GobEncode() ([]byte, error) {
   521  	if x == nil {
   522  		return nil, nil
   523  	}
   524  	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
   525  	i := x.b.abs.bytes(buf)
   526  	j := x.a.abs.bytes(buf[:i])
   527  	n := i - j
   528  	if int(uint32(n)) != n {
   529  		// this should never happen
   530  		return nil, errors.New("Rat.GobEncode: numerator too large")
   531  	}
   532  	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
   533  	j -= 1 + 4
   534  	b := ratGobVersion << 1 // make space for sign bit
   535  	if x.a.neg {
   536  		b |= 1
   537  	}
   538  	buf[j] = b
   539  	return buf[j:], nil
   540  }
   541  
   542  // GobDecode implements the gob.GobDecoder interface.
   543  func (z *Rat) GobDecode(buf []byte) error {
   544  	if len(buf) == 0 {
   545  		// Other side sent a nil or default value.
   546  		*z = Rat{}
   547  		return nil
   548  	}
   549  	b := buf[0]
   550  	if b>>1 != ratGobVersion {
   551  		return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
   552  	}
   553  	const j = 1 + 4
   554  	i := j + binary.BigEndian.Uint32(buf[j-4:j])
   555  	z.a.neg = b&1 != 0
   556  	z.a.abs = z.a.abs.setBytes(buf[j:i])
   557  	z.b.abs = z.b.abs.setBytes(buf[i:])
   558  	return nil
   559  }
   560  
   561  // MarshalText implements the encoding.TextMarshaler interface.
   562  func (r *Rat) MarshalText() (text []byte, err error) {
   563  	return []byte(r.RatString()), nil
   564  }
   565  
   566  // UnmarshalText implements the encoding.TextUnmarshaler interface.
   567  func (r *Rat) UnmarshalText(text []byte) error {
   568  	if _, ok := r.SetString(string(text)); !ok {
   569  		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
   570  	}
   571  	return nil
   572  }