github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/compile/internal/gc/mparith2.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  	"cmd/compile/internal/big"
     9  	"cmd/internal/obj"
    10  	"fmt"
    11  )
    12  
    13  /// implements fix arithmetic
    14  
    15  func mpsetovf(a *Mpint) {
    16  	a.Val.SetUint64(1) // avoid spurious div-zero errors
    17  	a.Ovf = true
    18  }
    19  
    20  func mptestovf(a *Mpint, extra int) bool {
    21  	// We don't need to be precise here, any reasonable upper limit would do.
    22  	// For now, use existing limit so we pass all the tests unchanged.
    23  	if a.Val.BitLen()+extra > Mpprec {
    24  		mpsetovf(a)
    25  	}
    26  	return a.Ovf
    27  }
    28  
    29  func mpmovefixfix(a, b *Mpint) {
    30  	a.Val.Set(&b.Val)
    31  }
    32  
    33  func mpmovefltfix(a *Mpint, b *Mpflt) int {
    34  	if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
    35  		return 0
    36  	}
    37  
    38  	const delta = 16 // a reasonably small number of bits > 0
    39  	var t big.Float
    40  	t.SetPrec(Mpprec - delta)
    41  
    42  	// try rounding down a little
    43  	t.SetMode(big.ToZero)
    44  	t.Set(&b.Val)
    45  	if _, acc := t.Int(&a.Val); acc == big.Exact {
    46  		return 0
    47  	}
    48  
    49  	// try rounding up a little
    50  	t.SetMode(big.AwayFromZero)
    51  	t.Set(&b.Val)
    52  	if _, acc := t.Int(&a.Val); acc == big.Exact {
    53  		return 0
    54  	}
    55  
    56  	return -1
    57  }
    58  
    59  func mpaddfixfix(a, b *Mpint, quiet int) {
    60  	if a.Ovf || b.Ovf {
    61  		if nsavederrors+nerrors == 0 {
    62  			Yyerror("ovf in mpaddfixfix")
    63  		}
    64  		mpsetovf(a)
    65  		return
    66  	}
    67  
    68  	a.Val.Add(&a.Val, &b.Val)
    69  
    70  	if mptestovf(a, 0) && quiet == 0 {
    71  		Yyerror("constant addition overflow")
    72  	}
    73  }
    74  
    75  func mpsubfixfix(a, b *Mpint) {
    76  	if a.Ovf || b.Ovf {
    77  		if nsavederrors+nerrors == 0 {
    78  			Yyerror("ovf in mpsubfixfix")
    79  		}
    80  		mpsetovf(a)
    81  		return
    82  	}
    83  
    84  	a.Val.Sub(&a.Val, &b.Val)
    85  
    86  	if mptestovf(a, 0) {
    87  		Yyerror("constant subtraction overflow")
    88  	}
    89  }
    90  
    91  func mpmulfixfix(a, b *Mpint) {
    92  	if a.Ovf || b.Ovf {
    93  		if nsavederrors+nerrors == 0 {
    94  			Yyerror("ovf in mpmulfixfix")
    95  		}
    96  		mpsetovf(a)
    97  		return
    98  	}
    99  
   100  	a.Val.Mul(&a.Val, &b.Val)
   101  
   102  	if mptestovf(a, 0) {
   103  		Yyerror("constant multiplication overflow")
   104  	}
   105  }
   106  
   107  func mpdivfixfix(a, b *Mpint) {
   108  	if a.Ovf || b.Ovf {
   109  		if nsavederrors+nerrors == 0 {
   110  			Yyerror("ovf in mpdivfixfix")
   111  		}
   112  		mpsetovf(a)
   113  		return
   114  	}
   115  
   116  	a.Val.Quo(&a.Val, &b.Val)
   117  
   118  	if mptestovf(a, 0) {
   119  		// can only happen for div-0 which should be checked elsewhere
   120  		Yyerror("constant division overflow")
   121  	}
   122  }
   123  
   124  func mpmodfixfix(a, b *Mpint) {
   125  	if a.Ovf || b.Ovf {
   126  		if nsavederrors+nerrors == 0 {
   127  			Yyerror("ovf in mpmodfixfix")
   128  		}
   129  		mpsetovf(a)
   130  		return
   131  	}
   132  
   133  	a.Val.Rem(&a.Val, &b.Val)
   134  
   135  	if mptestovf(a, 0) {
   136  		// should never happen
   137  		Yyerror("constant modulo overflow")
   138  	}
   139  }
   140  
   141  func mporfixfix(a, b *Mpint) {
   142  	if a.Ovf || b.Ovf {
   143  		if nsavederrors+nerrors == 0 {
   144  			Yyerror("ovf in mporfixfix")
   145  		}
   146  		mpsetovf(a)
   147  		return
   148  	}
   149  
   150  	a.Val.Or(&a.Val, &b.Val)
   151  }
   152  
   153  func mpandfixfix(a, b *Mpint) {
   154  	if a.Ovf || b.Ovf {
   155  		if nsavederrors+nerrors == 0 {
   156  			Yyerror("ovf in mpandfixfix")
   157  		}
   158  		mpsetovf(a)
   159  		return
   160  	}
   161  
   162  	a.Val.And(&a.Val, &b.Val)
   163  }
   164  
   165  func mpandnotfixfix(a, b *Mpint) {
   166  	if a.Ovf || b.Ovf {
   167  		if nsavederrors+nerrors == 0 {
   168  			Yyerror("ovf in mpandnotfixfix")
   169  		}
   170  		mpsetovf(a)
   171  		return
   172  	}
   173  
   174  	a.Val.AndNot(&a.Val, &b.Val)
   175  }
   176  
   177  func mpxorfixfix(a, b *Mpint) {
   178  	if a.Ovf || b.Ovf {
   179  		if nsavederrors+nerrors == 0 {
   180  			Yyerror("ovf in mpxorfixfix")
   181  		}
   182  		mpsetovf(a)
   183  		return
   184  	}
   185  
   186  	a.Val.Xor(&a.Val, &b.Val)
   187  }
   188  
   189  // shift left by s (or right by -s)
   190  func Mpshiftfix(a *Mpint, s int) {
   191  	switch {
   192  	case s > 0:
   193  		if mptestovf(a, s) {
   194  			Yyerror("constant shift overflow")
   195  			return
   196  		}
   197  		a.Val.Lsh(&a.Val, uint(s))
   198  	case s < 0:
   199  		a.Val.Rsh(&a.Val, uint(-s))
   200  	}
   201  }
   202  
   203  func mplshfixfix(a, b *Mpint) {
   204  	if a.Ovf || b.Ovf {
   205  		if nsavederrors+nerrors == 0 {
   206  			Yyerror("ovf in mplshfixfix")
   207  		}
   208  		mpsetovf(a)
   209  		return
   210  	}
   211  
   212  	s := Mpgetfix(b)
   213  	if s < 0 || s >= Mpprec {
   214  		Yyerror("stupid shift: %d", s)
   215  		Mpmovecfix(a, 0)
   216  		return
   217  	}
   218  
   219  	Mpshiftfix(a, int(s))
   220  }
   221  
   222  func mprshfixfix(a, b *Mpint) {
   223  	if a.Ovf || b.Ovf {
   224  		if nsavederrors+nerrors == 0 {
   225  			Yyerror("ovf in mprshfixfix")
   226  		}
   227  		mpsetovf(a)
   228  		return
   229  	}
   230  
   231  	s := Mpgetfix(b)
   232  	if s < 0 {
   233  		Yyerror("stupid shift: %d", s)
   234  		if a.Val.Sign() < 0 {
   235  			Mpmovecfix(a, -1)
   236  		} else {
   237  			Mpmovecfix(a, 0)
   238  		}
   239  		return
   240  	}
   241  
   242  	Mpshiftfix(a, int(-s))
   243  }
   244  
   245  func Mpcmpfixfix(a, b *Mpint) int {
   246  	return a.Val.Cmp(&b.Val)
   247  }
   248  
   249  func mpcmpfixc(b *Mpint, c int64) int {
   250  	return b.Val.Cmp(big.NewInt(c))
   251  }
   252  
   253  func mpnegfix(a *Mpint) {
   254  	a.Val.Neg(&a.Val)
   255  }
   256  
   257  func Mpgetfix(a *Mpint) int64 {
   258  	if a.Ovf {
   259  		if nsavederrors+nerrors == 0 {
   260  			Yyerror("constant overflow")
   261  		}
   262  		return 0
   263  	}
   264  
   265  	return a.Val.Int64()
   266  }
   267  
   268  func Mpmovecfix(a *Mpint, c int64) {
   269  	a.Val.SetInt64(c)
   270  }
   271  
   272  func mpatofix(a *Mpint, as string) {
   273  	_, ok := a.Val.SetString(as, 0)
   274  	if !ok {
   275  		// required syntax is [+-][0[x]]d*
   276  		// At the moment we lose precise error cause;
   277  		// the old code distinguished between:
   278  		// - malformed hex constant
   279  		// - malformed octal constant
   280  		// - malformed decimal constant
   281  		// TODO(gri) use different conversion function
   282  		Yyerror("malformed integer constant: %s", as)
   283  		a.Val.SetUint64(0)
   284  		return
   285  	}
   286  	if mptestovf(a, 0) {
   287  		Yyerror("constant too large: %s", as)
   288  	}
   289  }
   290  
   291  func (x *Mpint) String() string {
   292  	return Bconv(x, 0)
   293  }
   294  
   295  func Bconv(xval *Mpint, flag int) string {
   296  	if flag&obj.FmtSharp != 0 {
   297  		return fmt.Sprintf("%#x", &xval.Val)
   298  	}
   299  	return xval.Val.String()
   300  }