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 }