1
// Copyright 2013 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.
5
// Package exact implements mathematically exact values
6
// and operations for untyped Go constant values.
8
// A special Unknown value may be used when a constant
9
// value is unknown due to an error; operations on unknown
10
// values produce unknown values.
21
// Kind specifies the kind of value represented by a Value.
24
// Implementation note: Kinds must be enumerated in
25
// order of increasing "complexity" (used by match).
41
// A Value represents a mathematically precise value of a given Kind.
42
type Value interface {
43
// Kind returns the value kind; it is always the smallest
44
// kind in which the value can be represented exactly.
47
// String returns a human-readable form of the value.
50
// Prevent external implementations.
54
// ----------------------------------------------------------------------------
62
intVal struct{ val *big.Int }
63
floatVal struct{ val *big.Rat }
64
complexVal struct{ re, im *big.Rat }
67
func (unknownVal) Kind() Kind { return Unknown }
68
func (boolVal) Kind() Kind { return Bool }
69
func (stringVal) Kind() Kind { return String }
70
func (int64Val) Kind() Kind { return Int }
71
func (intVal) Kind() Kind { return Int }
72
func (floatVal) Kind() Kind { return Float }
73
func (complexVal) Kind() Kind { return Complex }
75
func (unknownVal) String() string { return "unknown" }
76
func (x boolVal) String() string { return fmt.Sprintf("%v", bool(x)) }
77
func (x stringVal) String() string { return strconv.Quote(string(x)) }
78
func (x int64Val) String() string { return strconv.FormatInt(int64(x), 10) }
79
func (x intVal) String() string { return x.val.String() }
80
func (x floatVal) String() string { return x.val.String() }
81
func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
83
func (unknownVal) implementsValue() {}
84
func (boolVal) implementsValue() {}
85
func (stringVal) implementsValue() {}
86
func (int64Val) implementsValue() {}
87
func (intVal) implementsValue() {}
88
func (floatVal) implementsValue() {}
89
func (complexVal) implementsValue() {}
93
minInt64 = big.NewInt(-1 << 63)
94
maxInt64 = big.NewInt(1<<63 - 1)
97
func normInt(x *big.Int) Value {
98
if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
99
return int64Val(x.Int64())
104
func normFloat(x *big.Rat) Value {
106
return normInt(x.Num())
111
func normComplex(re, im *big.Rat) Value {
115
return complexVal{re, im}
118
// ----------------------------------------------------------------------------
121
// MakeUnknown returns the Unknown value.
122
func MakeUnknown() Value { return unknownVal{} }
124
// MakeBool returns the Bool value for x.
125
func MakeBool(b bool) Value { return boolVal(b) }
127
// MakeString returns the String value for x.
128
func MakeString(s string) Value { return stringVal(s) }
130
// MakeInt64 returns the Int value for x.
131
func MakeInt64(x int64) Value { return int64Val(x) }
133
// MakeUint64 returns the Int value for x.
134
func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
136
// MakeFloat64 returns the numeric value for x.
137
// If x is not finite, the result is unknown.
138
func MakeFloat64(x float64) Value {
139
if f := new(big.Rat).SetFloat64(x); f != nil {
145
// MakeFromLiteral returns the corresponding integer, floating-point,
146
// imaginary, character, or string value for a Go literal string. The
147
// result is nil if the literal string is invalid.
148
func MakeFromLiteral(lit string, tok token.Token) Value {
151
if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
154
if x, ok := new(big.Int).SetString(lit, 0); ok {
159
if x, ok := new(big.Rat).SetString(lit); ok {
164
if n := len(lit); n > 0 && lit[n-1] == 'i' {
165
if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
166
return normComplex(big.NewRat(0, 1), im)
171
if n := len(lit); n >= 2 {
172
if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
173
return int64Val(code)
178
if s, err := strconv.Unquote(lit); err == nil {
186
// ----------------------------------------------------------------------------
189
// For unknown arguments the result is the zero value for the respective
190
// accessor type, except for Sign, where the result is 1.
192
// BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown.
193
// If x is Unknown, the result is false.
194
func BoolVal(x Value) bool {
195
switch x := x.(type) {
201
panic(fmt.Sprintf("%v not a Bool", x))
204
// StringVal returns the Go string value of x, which must be a String or an Unknown.
205
// If x is Unknown, the result is "".
206
func StringVal(x Value) string {
207
switch x := x.(type) {
213
panic(fmt.Sprintf("%v not a String", x))
216
// Int64Val returns the Go int64 value of x and whether the result is exact;
217
// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
218
// If x is Unknown, the result is (0, false).
219
func Int64Val(x Value) (int64, bool) {
220
switch x := x.(type) {
222
return int64(x), true
224
return x.val.Int64(), x.val.BitLen() <= 63
228
panic(fmt.Sprintf("%v not an Int", x))
231
// Uint64Val returns the Go uint64 value of x and whether the result is exact;
232
// x must be an Int or an Unknown. If the result is not exact, its value is undefined.
233
// If x is Unknown, the result is (0, false).
234
func Uint64Val(x Value) (uint64, bool) {
235
switch x := x.(type) {
237
return uint64(x), x >= 0
239
return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
243
panic(fmt.Sprintf("%v not an Int", x))
246
// Float64Val returns the nearest Go float64 value of x and whether the result is exact;
247
// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
248
// to represent as float64, Float64Val silently underflows to 0. The result sign always
249
// matches the sign of x, even for 0.
250
// If x is Unknown, the result is (0, false).
251
func Float64Val(x Value) (float64, bool) {
252
switch x := x.(type) {
254
f := float64(int64(x))
255
return f, int64Val(f) == x
257
return new(big.Rat).SetFrac(x.val, int1).Float64()
259
return x.val.Float64()
263
panic(fmt.Sprintf("%v not a Float", x))
266
// BitLen returns the number of bits required to represent
267
// the absolute value x in binary representation; x must be an Int or an Unknown.
268
// If x is Unknown, the result is 0.
269
func BitLen(x Value) int {
270
switch x := x.(type) {
272
return new(big.Int).SetInt64(int64(x)).BitLen()
274
return x.val.BitLen()
278
panic(fmt.Sprintf("%v not an Int", x))
281
// Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
282
// x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0,
283
// otherwise it is != 0. If x is Unknown, the result is 1.
284
func Sign(x Value) int {
285
switch x := x.(type) {
299
return x.re.Sign() | x.im.Sign()
301
return 1 // avoid spurious division by zero errors
303
panic(fmt.Sprintf("%v not numeric", x))
306
// ----------------------------------------------------------------------------
307
// Support for serializing/deserializing integers
310
// Compute the size of a Word in bytes.
312
_log = _m>>8&1 + _m>>16&1 + _m>>32&1
316
// Bytes returns the bytes for the absolute value of x in little-
317
// endian binary representation; x must be an Int.
318
func Bytes(x Value) []byte {
320
switch x := x.(type) {
322
val = new(big.Int).SetInt64(int64(x))
326
panic(fmt.Sprintf("%v not an Int", x))
330
bytes := make([]byte, len(words)*wordSize)
333
for _, w := range words {
334
for j := 0; j < wordSize; j++ {
340
// remove leading 0's
341
for i > 0 && bytes[i-1] == 0 {
348
// MakeFromBytes returns the Int value given the bytes of its little-endian
349
// binary representation. An empty byte slice argument represents 0.
350
func MakeFromBytes(bytes []byte) Value {
351
words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize)
356
for _, b := range bytes {
357
w |= big.Word(b) << s
358
if s += 8; s == wordSize*8 {
370
// remove leading 0's
371
for i > 0 && words[i-1] == 0 {
375
return normInt(new(big.Int).SetBits(words[:i]))
378
// ----------------------------------------------------------------------------
379
// Support for disassembling fractions
381
// Num returns the numerator of x; x must be Int, Float, or Unknown.
382
// If x is Unknown, the result is Unknown, otherwise it is an Int.
383
func Num(x Value) Value {
384
switch x := x.(type) {
385
case unknownVal, int64Val, intVal:
388
return normInt(x.val.Num())
390
panic(fmt.Sprintf("%v not Int or Float", x))
393
// Denom returns the denominator of x; x must be Int, Float, or Unknown.
394
// If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
395
func Denom(x Value) Value {
396
switch x := x.(type) {
399
case int64Val, intVal:
402
return normInt(x.val.Denom())
404
panic(fmt.Sprintf("%v not Int or Float", x))
407
// ----------------------------------------------------------------------------
408
// Support for assembling/disassembling complex numbers
410
// MakeImag returns the numeric value x*i (possibly 0);
411
// x must be Int, Float, or Unknown.
412
// If x is Unknown, the result is Unknown.
413
func MakeImag(x Value) Value {
415
switch x := x.(type) {
419
im = big.NewRat(int64(x), 1)
421
im = new(big.Rat).SetFrac(x.val, int1)
425
panic(fmt.Sprintf("%v not Int or Float", x))
427
return normComplex(rat0, im)
430
// Real returns the real part of x, which must be a numeric or unknown value.
431
// If x is Unknown, the result is Unknown.
432
func Real(x Value) Value {
433
switch x := x.(type) {
434
case unknownVal, int64Val, intVal, floatVal:
437
return normFloat(x.re)
439
panic(fmt.Sprintf("%v not numeric", x))
442
// Imag returns the imaginary part of x, which must be a numeric or unknown value.
443
// If x is Unknown, the result is Unknown.
444
func Imag(x Value) Value {
445
switch x := x.(type) {
448
case int64Val, intVal, floatVal:
451
return normFloat(x.im)
453
panic(fmt.Sprintf("%v not numeric", x))
456
// ----------------------------------------------------------------------------
459
// is32bit reports whether x can be represented using 32 bits.
460
func is32bit(x int64) bool {
462
return -1<<(s-1) <= x && x <= 1<<(s-1)-1
465
// is63bit reports whether x can be represented using 63 bits.
466
func is63bit(x int64) bool {
468
return -1<<(s-1) <= x && x <= 1<<(s-1)-1
471
// UnaryOp returns the result of the unary expression op y.
472
// The operation must be defined for the operand.
473
// If size >= 0 it specifies the ^ (xor) result size in bytes.
474
// If y is Unknown, the result is Unknown.
476
func UnaryOp(op token.Token, y Value, size int) Value {
480
case unknownVal, int64Val, intVal, floatVal, complexVal:
485
switch y := y.(type) {
490
return z // no overflow
492
return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
494
return normInt(new(big.Int).Neg(y.val))
496
return normFloat(new(big.Rat).Neg(y.val))
498
return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
503
switch y := y.(type) {
507
z.Not(big.NewInt(int64(y)))
513
// For unsigned types, the result will be negative and
514
// thus "too large": We must limit the result size to
518
z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s
523
switch y := y.(type) {
532
panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
537
rat0 = big.NewRat(0, 1)
540
func ord(x Value) int {
555
// match returns the matching representation (same type) with the
556
// smallest complexity for two values x and y. If one of them is
557
// numeric, both of them must be numeric. If one of them is Unknown,
558
// both results are Unknown.
560
func match(x, y Value) (_, _ Value) {
567
switch x := x.(type) {
571
case boolVal, stringVal, complexVal:
575
switch y := y.(type) {
579
return intVal{big.NewInt(int64(x))}, y
581
return floatVal{big.NewRat(int64(x), 1)}, y
583
return complexVal{big.NewRat(int64(x), 1), rat0}, y
587
switch y := y.(type) {
591
return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
593
return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
597
switch y := y.(type) {
601
return complexVal{x.val, rat0}, y
608
// BinaryOp returns the result of the binary expression x op y.
609
// The operation must be defined for the operands. If one of the
610
// operands is Unknown, the result is Unknown.
611
// To force integer division of Int operands, use op == token.QUO_ASSIGN
612
// instead of token.QUO; the result is guaranteed to be Int in this case.
613
// Division by zero leads to a run-time panic.
615
func BinaryOp(x Value, op token.Token, y Value) Value {
618
switch x := x.(type) {
633
b := int64(y.(int64Val))
637
if !is63bit(a) || !is63bit(b) {
638
return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
642
if !is63bit(a) || !is63bit(b) {
643
return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
647
if !is32bit(a) || !is32bit(b) {
648
return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
652
return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
653
case token.QUO_ASSIGN: // force integer division
682
return normFloat(new(big.Rat).SetFrac(a, b))
683
case token.QUO_ASSIGN: // force integer division
702
b := y.(floatVal).val
733
// (ac-bd) + i(bc+ad)
734
var ac, bd, bc, ad big.Rat
742
// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
743
var ac, bd, bc, ad, s, cc, dd big.Rat
758
return normComplex(&re, &im)
762
return x + y.(stringVal)
767
panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
770
// Shift returns the result of the shift expression x op s
771
// with op == token.SHL or token.SHR (<< or >>). x must be
772
// an Int or an Unknown. If x is Unknown, the result is x.
774
func Shift(x Value, op token.Token, s uint) Value {
775
switch x := x.(type) {
785
z := big.NewInt(int64(x))
786
return normInt(z.Lsh(z, s))
798
return normInt(z.Lsh(x.val, s))
800
return normInt(z.Rsh(x.val, s))
804
panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s))
807
func cmpZero(x int, op token.Token) bool {
825
// Compare returns the result of the comparison x op y.
826
// The comparison must be defined for the operands.
827
// If one of the operands is Unknown, the result is
830
func Compare(x Value, op token.Token, y Value) bool {
833
switch x := x.(type) {
864
return cmpZero(x.val.Cmp(y.(intVal).val), op)
867
return cmpZero(x.val.Cmp(y.(floatVal).val), op)
875
return re == 0 && im == 0
877
return re != 0 || im != 0
898
panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))