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