func is32bit(x int64) bool {
	const s = 32
	return -1<<(s-1) <= x && x <= 1<<(s-1)-1
}
----------------------------------------------------------------------------
Operations
is32bit reports whether x can be represented using 32 bits.
package exact
import (
	"fmt"
	"go/token"
	"math/big"
	"strconv"
)
type Kind int
const (
	Unknown Kind = iota
	Bool
	String
	Int
	Float
	Complex
)
type Value interface {
	Kind() Kind
	String() string
	implementsValue()
}
type (
	unknownVal struct{}
	boolVal    bool
	stringVal  string
	int64Val   int64
	intVal     struct{ val *big.Int }
	floatVal   struct{ val *big.Rat }
	complexVal struct{ re, im *big.Rat }
)
func (unknownVal) Kind() Kind { return Unknown }
func (boolVal) Kind() Kind    { return Bool }
func (stringVal) Kind() Kind  { return String }
func (int64Val) Kind() Kind   { return Int }
func (intVal) Kind() Kind     { return Int }
func (floatVal) Kind() Kind   { return Float }
func (complexVal) Kind() Kind { return Complex }
func (unknownVal) String() string   { return "unknown" }
func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
func (x stringVal) String() string  { return strconv.Quote(string(x)) }
func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
func (x intVal) String() string     { return x.val.String() }
func (x floatVal) String() string   { return x.val.String() }
func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
func (unknownVal) implementsValue() {}
func (boolVal) implementsValue()    {}
func (stringVal) implementsValue()  {}
func (int64Val) implementsValue()   {}
func (intVal) implementsValue()     {}
func (floatVal) implementsValue()   {}
func (complexVal) implementsValue() {}
var (
	minInt64 = big.NewInt(-1 << 63)
	maxInt64 = big.NewInt(1<<63 - 1)
)
func normInt(x *big.Int) Value {
	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
		return int64Val(x.Int64())
	}
	return intVal{x}
}
func normFloat(x *big.Rat) Value {
	if x.IsInt() {
		return normInt(x.Num())
	}
	return floatVal{x}
}
func normComplex(re, im *big.Rat) Value {
	if im.Sign() == 0 {
		return normFloat(re)
	}
	return complexVal{re, im}
}
func MakeUnknown() Value { return unknownVal{} }
func MakeBool(b bool) Value { return boolVal(b) }
func MakeString(s string) Value { return stringVal(s) }
func MakeInt64(x int64) Value { return int64Val(x) }
func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
func MakeFloat64(x float64) Value {
	if f := new(big.Rat).SetFloat64(x); f != nil {
		return normFloat(f)
	}
	return unknownVal{}
}
func MakeFromLiteral(lit string, tok token.Token) Value {
	switch tok {
	case token.INT:
		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
			return int64Val(x)
		}
		if x, ok := new(big.Int).SetString(lit, 0); ok {
			return intVal{x}
		}
	case token.FLOAT:
		if x, ok := new(big.Rat).SetString(lit); ok {
			return normFloat(x)
		}
	case token.IMAG:
		if n := len(lit); n > 0 && lit[n-1] == 'i' {
			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
				return normComplex(big.NewRat(0, 1), im)
			}
		}
	case token.CHAR:
		if n := len(lit); n >= 2 {
			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
				return int64Val(code)
			}
		}
	case token.STRING:
		if s, err := strconv.Unquote(lit); err == nil {
			return stringVal(s)
		}
	}
	return nil
}
func BoolVal(x Value) bool {
	switch x := x.(type) {
	case boolVal:
		return bool(x)
	case unknownVal:
		return false
	}
	panic(fmt.Sprintf("%v not a Bool", x))
}
func StringVal(x Value) string {
	switch x := x.(type) {
	case stringVal:
		return string(x)
	case unknownVal:
		return ""
	}
	panic(fmt.Sprintf("%v not a String", x))
}
func Int64Val(x Value) (int64, bool) {
	switch x := x.(type) {
	case int64Val:
		return int64(x), true
	case intVal:
		return x.val.Int64(), x.val.BitLen() <= 63
	case unknownVal:
		return 0, false
	}
	panic(fmt.Sprintf("%v not an Int", x))
}
func Uint64Val(x Value) (uint64, bool) {
	switch x := x.(type) {
	case int64Val:
		return uint64(x), x >= 0
	case intVal:
		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
	case unknownVal:
		return 0, false
	}
	panic(fmt.Sprintf("%v not an Int", x))
}
func Float32Val(x Value) (float32, bool) {
	switch x := x.(type) {
	case int64Val:
		f := float32(x)
		return f, int64Val(f) == x
	case intVal:
		return ratToFloat32(new(big.Rat).SetFrac(x.val, int1))
	case floatVal:
		return ratToFloat32(x.val)
	case unknownVal:
		return 0, false
	}
	panic(fmt.Sprintf("%v not a Float", x))
}
func Float64Val(x Value) (float64, bool) {
	switch x := x.(type) {
	case int64Val:
		f := float64(int64(x))
		return f, int64Val(f) == x
	case intVal:
		return new(big.Rat).SetFrac(x.val, int1).Float64()
	case floatVal:
		return x.val.Float64()
	case unknownVal:
		return 0, false
	}
	panic(fmt.Sprintf("%v not a Float", x))
}
func BitLen(x Value) int {
	switch x := x.(type) {
	case int64Val:
		return new(big.Int).SetInt64(int64(x)).BitLen()
	case intVal:
		return x.val.BitLen()
	case unknownVal:
		return 0
	}
	panic(fmt.Sprintf("%v not an Int", x))
}
func Sign(x Value) int {
	switch x := x.(type) {
	case int64Val:
		switch {
		case x < 0:
			return -1
		case x > 0:
			return 1
		}
		return 0
	case intVal:
		return x.val.Sign()
	case floatVal:
		return x.val.Sign()
	case complexVal:
		return x.re.Sign() | x.im.Sign()
	case unknownVal:
		return 1  
	}
	panic(fmt.Sprintf("%v not numeric", x))
}
const (
	_m       = ^big.Word(0)
	_log     = _m>>8&1 + _m>>16&1 + _m>>32&1
	wordSize = 1 << _log
)
func Bytes(x Value) []byte {
	var val *big.Int
	switch x := x.(type) {
	case int64Val:
		val = new(big.Int).SetInt64(int64(x))
	case intVal:
		val = x.val
	default:
		panic(fmt.Sprintf("%v not an Int", x))
	}
	words := val.Bits()
	bytes := make([]byte, len(words)*wordSize)
	i := 0
	for _, w := range words {
		for j := 0; j < wordSize; j++ {
			bytes[i] = byte(w)
			w >>= 8
			i++
		}
	}
	for i > 0 && bytes[i-1] == 0 {
		i--
	}
	return bytes[:i]
}
func MakeFromBytes(bytes []byte) Value {
	words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
	i := 0
	var w big.Word
	var s uint
	for _, b := range bytes {
		w |= big.Word(b) << s
		if s += 8; s == wordSize*8 {
			words[i] = w
			i++
			w = 0
			s = 0
		}
	}
	if i < len(words) {
		words[i] = w
		i++
	}
	for i > 0 && words[i-1] == 0 {
		i--
	}
	return normInt(new(big.Int).SetBits(words[:i]))
}
func Num(x Value) Value {
	switch x := x.(type) {
	case unknownVal, int64Val, intVal:
		return x
	case floatVal:
		return normInt(x.val.Num())
	}
	panic(fmt.Sprintf("%v not Int or Float", x))
}
func Denom(x Value) Value {
	switch x := x.(type) {
	case unknownVal:
		return x
	case int64Val, intVal:
		return int64Val(1)
	case floatVal:
		return normInt(x.val.Denom())
	}
	panic(fmt.Sprintf("%v not Int or Float", x))
}
func MakeImag(x Value) Value {
	var im *big.Rat
	switch x := x.(type) {
	case unknownVal:
		return x
	case int64Val:
		im = big.NewRat(int64(x), 1)
	case intVal:
		im = new(big.Rat).SetFrac(x.val, int1)
	case floatVal:
		im = x.val
	default:
		panic(fmt.Sprintf("%v not Int or Float", x))
	}
	return normComplex(rat0, im)
}
func Real(x Value) Value {
	switch x := x.(type) {
	case unknownVal, int64Val, intVal, floatVal:
		return x
	case complexVal:
		return normFloat(x.re)
	}
	panic(fmt.Sprintf("%v not numeric", x))
}
func Imag(x Value) Value {
	switch x := x.(type) {
	case unknownVal:
		return x
	case int64Val, intVal, floatVal:
		return int64Val(0)
	case complexVal:
		return normFloat(x.im)
	}
	panic(fmt.Sprintf("%v not numeric", x))
}