github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/numeric.go (about) 1 package grumpy 2 3 import ( 4 "math/big" 5 "strings" 6 ) 7 8 const ( 9 // Here we calculate the number of bits in a uint and use that to 10 // create a typeless constant _maxuint which is the largest value that 11 // can be held by a uint. We then use that to create the constants 12 // MaxInt and MinInt below. 13 // Because these constants are typeless, they can be used wherever 14 // a numeric value is needed, without a conversion like int64(). 15 // A typeless number remains untyped when shifted, even if the shift 16 // count is typed. 17 // Start with the two's complement of 0 as a uint which is 0xffff...ff. 18 // This is the number we are after, but it currently has a type (uint). 19 // Dividing it by 0xff gives us 0x0101...01 for the length of a uint. 20 // Taking that mod 15 is effectively counting the ones - one for each 21 // byte in a uint, so we have either 4 or 8. 22 // We multiply by 8 and shift, and now we have 2^32 or 2^64 as a 23 // typeless constant number. 24 // We subtract 1 from that to get maxuint. 25 _maxuint = 1<<(^uint(0)/0xff%15*8) - 1 26 27 // MaxInt is the largest (most positive) number that can be stored as an int. 28 MaxInt = _maxuint >> 1 29 // MinInt is the smallest (most negative) number that can be stored as an int. 30 // The absolute value of MinInt is Maxint+1, thus it can be tricky to deal with. 31 MinInt = -(_maxuint + 1) >> 1 32 ) 33 34 var ( 35 maxIntBig = big.NewInt(MaxInt) 36 minIntBig = big.NewInt(MinInt) 37 ) 38 39 func numParseInteger(z *big.Int, s string, base int) (*big.Int, bool) { 40 s = strings.TrimSpace(s) 41 if len(s) > 2 && s[0] == '0' { 42 switch s[1] { 43 case 'b', 'B': 44 if base == 0 || base == 2 { 45 base = 2 46 s = s[2:] 47 } 48 case 'o', 'O': 49 if base == 0 || base == 8 { 50 base = 8 51 s = s[2:] 52 } 53 case 'x', 'X': 54 if base == 0 || base == 16 { 55 base = 16 56 s = s[2:] 57 } 58 default: 59 base = 8 60 } 61 } 62 if base == 0 { 63 base = 10 64 } 65 return z.SetString(s, base) 66 } 67 68 func numInIntRange(i *big.Int) bool { 69 return i.Cmp(minIntBig) >= 0 && i.Cmp(maxIntBig) <= 0 70 }