github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/mpint.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gc
     6  
     7  import (
     8  	"fmt"
     9  	"math/big"
    10  )
    11  
    12  // implements integer arithmetic
    13  
    14  // Mpint represents an integer constant.
    15  type Mpint struct {
    16  	Val  big.Int
    17  	Ovf  bool // set if Val overflowed compiler limit (sticky)
    18  	Rune bool // set if syntax indicates default type rune
    19  }
    20  
    21  func (a *Mpint) SetOverflow() {
    22  	a.Val.SetUint64(1) // avoid spurious div-zero errors
    23  	a.Ovf = true
    24  }
    25  
    26  func (a *Mpint) checkOverflow(extra int) bool {
    27  	// We don't need to be precise here, any reasonable upper limit would do.
    28  	// For now, use existing limit so we pass all the tests unchanged.
    29  	if a.Val.BitLen()+extra > Mpprec {
    30  		a.SetOverflow()
    31  	}
    32  	return a.Ovf
    33  }
    34  
    35  func (a *Mpint) Set(b *Mpint) {
    36  	a.Val.Set(&b.Val)
    37  }
    38  
    39  func (a *Mpint) SetFloat(b *Mpflt) bool {
    40  	// avoid converting huge floating-point numbers to integers
    41  	// (2*Mpprec is large enough to permit all tests to pass)
    42  	if b.Val.MantExp(nil) > 2*Mpprec {
    43  		a.SetOverflow()
    44  		return false
    45  	}
    46  
    47  	if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
    48  		return true
    49  	}
    50  
    51  	const delta = 16 // a reasonably small number of bits > 0
    52  	var t big.Float
    53  	t.SetPrec(Mpprec - delta)
    54  
    55  	// try rounding down a little
    56  	t.SetMode(big.ToZero)
    57  	t.Set(&b.Val)
    58  	if _, acc := t.Int(&a.Val); acc == big.Exact {
    59  		return true
    60  	}
    61  
    62  	// try rounding up a little
    63  	t.SetMode(big.AwayFromZero)
    64  	t.Set(&b.Val)
    65  	if _, acc := t.Int(&a.Val); acc == big.Exact {
    66  		return true
    67  	}
    68  
    69  	a.Ovf = false
    70  	return false
    71  }
    72  
    73  func (a *Mpint) Add(b *Mpint) {
    74  	if a.Ovf || b.Ovf {
    75  		if nsavederrors+nerrors == 0 {
    76  			Fatalf("ovf in Mpint Add")
    77  		}
    78  		a.SetOverflow()
    79  		return
    80  	}
    81  
    82  	a.Val.Add(&a.Val, &b.Val)
    83  
    84  	if a.checkOverflow(0) {
    85  		yyerror("constant addition overflow")
    86  	}
    87  }
    88  
    89  func (a *Mpint) Sub(b *Mpint) {
    90  	if a.Ovf || b.Ovf {
    91  		if nsavederrors+nerrors == 0 {
    92  			Fatalf("ovf in Mpint Sub")
    93  		}
    94  		a.SetOverflow()
    95  		return
    96  	}
    97  
    98  	a.Val.Sub(&a.Val, &b.Val)
    99  
   100  	if a.checkOverflow(0) {
   101  		yyerror("constant subtraction overflow")
   102  	}
   103  }
   104  
   105  func (a *Mpint) Mul(b *Mpint) {
   106  	if a.Ovf || b.Ovf {
   107  		if nsavederrors+nerrors == 0 {
   108  			Fatalf("ovf in Mpint Mul")
   109  		}
   110  		a.SetOverflow()
   111  		return
   112  	}
   113  
   114  	a.Val.Mul(&a.Val, &b.Val)
   115  
   116  	if a.checkOverflow(0) {
   117  		yyerror("constant multiplication overflow")
   118  	}
   119  }
   120  
   121  func (a *Mpint) Quo(b *Mpint) {
   122  	if a.Ovf || b.Ovf {
   123  		if nsavederrors+nerrors == 0 {
   124  			Fatalf("ovf in Mpint Quo")
   125  		}
   126  		a.SetOverflow()
   127  		return
   128  	}
   129  
   130  	a.Val.Quo(&a.Val, &b.Val)
   131  
   132  	if a.checkOverflow(0) {
   133  		// can only happen for div-0 which should be checked elsewhere
   134  		yyerror("constant division overflow")
   135  	}
   136  }
   137  
   138  func (a *Mpint) Rem(b *Mpint) {
   139  	if a.Ovf || b.Ovf {
   140  		if nsavederrors+nerrors == 0 {
   141  			Fatalf("ovf in Mpint Rem")
   142  		}
   143  		a.SetOverflow()
   144  		return
   145  	}
   146  
   147  	a.Val.Rem(&a.Val, &b.Val)
   148  
   149  	if a.checkOverflow(0) {
   150  		// should never happen
   151  		yyerror("constant modulo overflow")
   152  	}
   153  }
   154  
   155  func (a *Mpint) Or(b *Mpint) {
   156  	if a.Ovf || b.Ovf {
   157  		if nsavederrors+nerrors == 0 {
   158  			Fatalf("ovf in Mpint Or")
   159  		}
   160  		a.SetOverflow()
   161  		return
   162  	}
   163  
   164  	a.Val.Or(&a.Val, &b.Val)
   165  }
   166  
   167  func (a *Mpint) And(b *Mpint) {
   168  	if a.Ovf || b.Ovf {
   169  		if nsavederrors+nerrors == 0 {
   170  			Fatalf("ovf in Mpint And")
   171  		}
   172  		a.SetOverflow()
   173  		return
   174  	}
   175  
   176  	a.Val.And(&a.Val, &b.Val)
   177  }
   178  
   179  func (a *Mpint) AndNot(b *Mpint) {
   180  	if a.Ovf || b.Ovf {
   181  		if nsavederrors+nerrors == 0 {
   182  			Fatalf("ovf in Mpint AndNot")
   183  		}
   184  		a.SetOverflow()
   185  		return
   186  	}
   187  
   188  	a.Val.AndNot(&a.Val, &b.Val)
   189  }
   190  
   191  func (a *Mpint) Xor(b *Mpint) {
   192  	if a.Ovf || b.Ovf {
   193  		if nsavederrors+nerrors == 0 {
   194  			Fatalf("ovf in Mpint Xor")
   195  		}
   196  		a.SetOverflow()
   197  		return
   198  	}
   199  
   200  	a.Val.Xor(&a.Val, &b.Val)
   201  }
   202  
   203  func (a *Mpint) Lsh(b *Mpint) {
   204  	if a.Ovf || b.Ovf {
   205  		if nsavederrors+nerrors == 0 {
   206  			Fatalf("ovf in Mpint Lsh")
   207  		}
   208  		a.SetOverflow()
   209  		return
   210  	}
   211  
   212  	s := b.Int64()
   213  	if s < 0 || s >= Mpprec {
   214  		msg := "shift count too large"
   215  		if s < 0 {
   216  			msg = "invalid negative shift count"
   217  		}
   218  		yyerror("%s: %d", msg, s)
   219  		a.SetInt64(0)
   220  		return
   221  	}
   222  
   223  	if a.checkOverflow(int(s)) {
   224  		yyerror("constant shift overflow")
   225  		return
   226  	}
   227  	a.Val.Lsh(&a.Val, uint(s))
   228  }
   229  
   230  func (a *Mpint) Rsh(b *Mpint) {
   231  	if a.Ovf || b.Ovf {
   232  		if nsavederrors+nerrors == 0 {
   233  			Fatalf("ovf in Mpint Rsh")
   234  		}
   235  		a.SetOverflow()
   236  		return
   237  	}
   238  
   239  	s := b.Int64()
   240  	if s < 0 {
   241  		yyerror("invalid negative shift count: %d", s)
   242  		if a.Val.Sign() < 0 {
   243  			a.SetInt64(-1)
   244  		} else {
   245  			a.SetInt64(0)
   246  		}
   247  		return
   248  	}
   249  
   250  	a.Val.Rsh(&a.Val, uint(s))
   251  }
   252  
   253  func (a *Mpint) Cmp(b *Mpint) int {
   254  	return a.Val.Cmp(&b.Val)
   255  }
   256  
   257  func (a *Mpint) CmpInt64(c int64) int {
   258  	if c == 0 {
   259  		return a.Val.Sign() // common case shortcut
   260  	}
   261  	return a.Val.Cmp(big.NewInt(c))
   262  }
   263  
   264  func (a *Mpint) Neg() {
   265  	a.Val.Neg(&a.Val)
   266  }
   267  
   268  func (a *Mpint) Int64() int64 {
   269  	if a.Ovf {
   270  		if nsavederrors+nerrors == 0 {
   271  			Fatalf("constant overflow")
   272  		}
   273  		return 0
   274  	}
   275  
   276  	return a.Val.Int64()
   277  }
   278  
   279  func (a *Mpint) SetInt64(c int64) {
   280  	a.Val.SetInt64(c)
   281  }
   282  
   283  func (a *Mpint) SetString(as string) {
   284  	_, ok := a.Val.SetString(as, 0)
   285  	if !ok {
   286  		// The lexer checks for correct syntax of the literal
   287  		// and reports detailed errors. Thus SetString should
   288  		// never fail (in theory it might run out of memory,
   289  		// but that wouldn't be reported as an error here).
   290  		Fatalf("malformed integer constant: %s", as)
   291  		return
   292  	}
   293  	if a.checkOverflow(0) {
   294  		yyerror("constant too large: %s", as)
   295  	}
   296  }
   297  
   298  func (a *Mpint) GoString() string {
   299  	return a.Val.String()
   300  }
   301  
   302  func (a *Mpint) String() string {
   303  	return fmt.Sprintf("%#x", &a.Val)
   304  }