...

Source file src/pkg/cmd/compile/internal/gc/mpint.go

     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	}
   305	

View as plain text