github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/go/exact/exact.go (about) 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. 4 5 // Package exact implements Values representing untyped 6 // Go constants and the corresponding operations. Values 7 // and operations have unlimited precision. 8 // 9 // A special Unknown value may be used when a value 10 // is unknown due to an error. Operations on unknown 11 // values produce unknown values unless specified 12 // otherwise. 13 // 14 package exact // import "go/exact" 15 16 import ( 17 "fmt" 18 "go/token" 19 "math/big" 20 "strconv" 21 ) 22 23 // Kind specifies the kind of value represented by a Value. 24 type Kind int 25 26 // Implementation note: Kinds must be enumerated in 27 // order of increasing "complexity" (used by match). 28 29 const ( 30 // unknown values 31 Unknown Kind = iota 32 33 // non-numeric values 34 Bool 35 String 36 37 // numeric values 38 Int 39 Float 40 Complex 41 ) 42 43 // A Value represents a mathematically exact value of a given Kind. 44 type Value interface { 45 // Kind returns the value kind; it is always the smallest 46 // kind in which the value can be represented exactly. 47 Kind() Kind 48 49 // String returns a human-readable form of the value. 50 String() string 51 52 // Prevent external implementations. 53 implementsValue() 54 } 55 56 // ---------------------------------------------------------------------------- 57 // Implementations 58 59 type ( 60 unknownVal struct{} 61 boolVal bool 62 stringVal string 63 int64Val int64 64 intVal struct{ val *big.Int } 65 floatVal struct{ val *big.Rat } 66 complexVal struct{ re, im *big.Rat } 67 ) 68 69 func (unknownVal) Kind() Kind { return Unknown } 70 func (boolVal) Kind() Kind { return Bool } 71 func (stringVal) Kind() Kind { return String } 72 func (int64Val) Kind() Kind { return Int } 73 func (intVal) Kind() Kind { return Int } 74 func (floatVal) Kind() Kind { return Float } 75 func (complexVal) Kind() Kind { return Complex } 76 77 func (unknownVal) String() string { return "unknown" } 78 func (x boolVal) String() string { return fmt.Sprintf("%v", bool(x)) } 79 func (x stringVal) String() string { return strconv.Quote(string(x)) } 80 func (x int64Val) String() string { return strconv.FormatInt(int64(x), 10) } 81 func (x intVal) String() string { return x.val.String() } 82 func (x floatVal) String() string { return x.val.String() } 83 func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) } 84 85 func (unknownVal) implementsValue() {} 86 func (boolVal) implementsValue() {} 87 func (stringVal) implementsValue() {} 88 func (int64Val) implementsValue() {} 89 func (intVal) implementsValue() {} 90 func (floatVal) implementsValue() {} 91 func (complexVal) implementsValue() {} 92 93 // int64 bounds 94 var ( 95 minInt64 = big.NewInt(-1 << 63) 96 maxInt64 = big.NewInt(1<<63 - 1) 97 ) 98 99 func normInt(x *big.Int) Value { 100 if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 { 101 return int64Val(x.Int64()) 102 } 103 return intVal{x} 104 } 105 106 func normFloat(x *big.Rat) Value { 107 if x.IsInt() { 108 return normInt(x.Num()) 109 } 110 return floatVal{x} 111 } 112 113 func normComplex(re, im *big.Rat) Value { 114 if im.Sign() == 0 { 115 return normFloat(re) 116 } 117 return complexVal{re, im} 118 } 119 120 // ---------------------------------------------------------------------------- 121 // Factories 122 123 // MakeUnknown returns the Unknown value. 124 func MakeUnknown() Value { return unknownVal{} } 125 126 // MakeBool returns the Bool value for x. 127 func MakeBool(b bool) Value { return boolVal(b) } 128 129 // MakeString returns the String value for x. 130 func MakeString(s string) Value { return stringVal(s) } 131 132 // MakeInt64 returns the Int value for x. 133 func MakeInt64(x int64) Value { return int64Val(x) } 134 135 // MakeUint64 returns the Int value for x. 136 func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) } 137 138 // MakeFloat64 returns the numeric value for x. 139 // If x is not finite, the result is unknown. 140 func MakeFloat64(x float64) Value { 141 if f := new(big.Rat).SetFloat64(x); f != nil { 142 return normFloat(f) 143 } 144 return unknownVal{} 145 } 146 147 // MakeFromLiteral returns the corresponding integer, floating-point, 148 // imaginary, character, or string value for a Go literal string. The 149 // result is nil if the literal string is invalid. 150 func MakeFromLiteral(lit string, tok token.Token) Value { 151 switch tok { 152 case token.INT: 153 if x, err := strconv.ParseInt(lit, 0, 64); err == nil { 154 return int64Val(x) 155 } 156 if x, ok := new(big.Int).SetString(lit, 0); ok { 157 return intVal{x} 158 } 159 160 case token.FLOAT: 161 if x, ok := new(big.Rat).SetString(lit); ok { 162 return normFloat(x) 163 } 164 165 case token.IMAG: 166 if n := len(lit); n > 0 && lit[n-1] == 'i' { 167 if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok { 168 return normComplex(big.NewRat(0, 1), im) 169 } 170 } 171 172 case token.CHAR: 173 if n := len(lit); n >= 2 { 174 if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil { 175 return int64Val(code) 176 } 177 } 178 179 case token.STRING: 180 if s, err := strconv.Unquote(lit); err == nil { 181 return stringVal(s) 182 } 183 } 184 185 return nil 186 } 187 188 // ---------------------------------------------------------------------------- 189 // Accessors 190 // 191 // For unknown arguments the result is the zero value for the respective 192 // accessor type, except for Sign, where the result is 1. 193 194 // BoolVal returns the Go boolean value of x, which must be a Bool or an Unknown. 195 // If x is Unknown, the result is false. 196 func BoolVal(x Value) bool { 197 switch x := x.(type) { 198 case boolVal: 199 return bool(x) 200 case unknownVal: 201 return false 202 } 203 panic(fmt.Sprintf("%v not a Bool", x)) 204 } 205 206 // StringVal returns the Go string value of x, which must be a String or an Unknown. 207 // If x is Unknown, the result is "". 208 func StringVal(x Value) string { 209 switch x := x.(type) { 210 case stringVal: 211 return string(x) 212 case unknownVal: 213 return "" 214 } 215 panic(fmt.Sprintf("%v not a String", x)) 216 } 217 218 // Int64Val returns the Go int64 value of x and whether the result is exact; 219 // x must be an Int or an Unknown. If the result is not exact, its value is undefined. 220 // If x is Unknown, the result is (0, false). 221 func Int64Val(x Value) (int64, bool) { 222 switch x := x.(type) { 223 case int64Val: 224 return int64(x), true 225 case intVal: 226 return x.val.Int64(), x.val.BitLen() <= 63 227 case unknownVal: 228 return 0, false 229 } 230 panic(fmt.Sprintf("%v not an Int", x)) 231 } 232 233 // Uint64Val returns the Go uint64 value of x and whether the result is exact; 234 // x must be an Int or an Unknown. If the result is not exact, its value is undefined. 235 // If x is Unknown, the result is (0, false). 236 func Uint64Val(x Value) (uint64, bool) { 237 switch x := x.(type) { 238 case int64Val: 239 return uint64(x), x >= 0 240 case intVal: 241 return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64 242 case unknownVal: 243 return 0, false 244 } 245 panic(fmt.Sprintf("%v not an Int", x)) 246 } 247 248 // Float32Val is like Float64Val but for float32 instead of float64. 249 func Float32Val(x Value) (float32, bool) { 250 switch x := x.(type) { 251 case int64Val: 252 f := float32(x) 253 return f, int64Val(f) == x 254 case intVal: 255 return ratToFloat32(new(big.Rat).SetFrac(x.val, int1)) 256 case floatVal: 257 return ratToFloat32(x.val) 258 case unknownVal: 259 return 0, false 260 } 261 panic(fmt.Sprintf("%v not a Float", x)) 262 } 263 264 // Float64Val returns the nearest Go float64 value of x and whether the result is exact; 265 // x must be numeric but not Complex, or Unknown. For values too small (too close to 0) 266 // to represent as float64, Float64Val silently underflows to 0. The result sign always 267 // matches the sign of x, even for 0. 268 // If x is Unknown, the result is (0, false). 269 func Float64Val(x Value) (float64, bool) { 270 switch x := x.(type) { 271 case int64Val: 272 f := float64(int64(x)) 273 return f, int64Val(f) == x 274 case intVal: 275 return new(big.Rat).SetFrac(x.val, int1).Float64() 276 case floatVal: 277 return x.val.Float64() 278 case unknownVal: 279 return 0, false 280 } 281 panic(fmt.Sprintf("%v not a Float", x)) 282 } 283 284 // BitLen returns the number of bits required to represent 285 // the absolute value x in binary representation; x must be an Int or an Unknown. 286 // If x is Unknown, the result is 0. 287 func BitLen(x Value) int { 288 switch x := x.(type) { 289 case int64Val: 290 return new(big.Int).SetInt64(int64(x)).BitLen() 291 case intVal: 292 return x.val.BitLen() 293 case unknownVal: 294 return 0 295 } 296 panic(fmt.Sprintf("%v not an Int", x)) 297 } 298 299 // Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0; 300 // x must be numeric or Unknown. For complex values x, the sign is 0 if x == 0, 301 // otherwise it is != 0. If x is Unknown, the result is 1. 302 func Sign(x Value) int { 303 switch x := x.(type) { 304 case int64Val: 305 switch { 306 case x < 0: 307 return -1 308 case x > 0: 309 return 1 310 } 311 return 0 312 case intVal: 313 return x.val.Sign() 314 case floatVal: 315 return x.val.Sign() 316 case complexVal: 317 return x.re.Sign() | x.im.Sign() 318 case unknownVal: 319 return 1 // avoid spurious division by zero errors 320 } 321 panic(fmt.Sprintf("%v not numeric", x)) 322 } 323 324 // ---------------------------------------------------------------------------- 325 // Support for serializing/deserializing integers 326 327 const ( 328 // Compute the size of a Word in bytes. 329 _m = ^big.Word(0) 330 _log = _m>>8&1 + _m>>16&1 + _m>>32&1 331 wordSize = 1 << _log 332 ) 333 334 // Bytes returns the bytes for the absolute value of x in little- 335 // endian binary representation; x must be an Int. 336 func Bytes(x Value) []byte { 337 var val *big.Int 338 switch x := x.(type) { 339 case int64Val: 340 val = new(big.Int).SetInt64(int64(x)) 341 case intVal: 342 val = x.val 343 default: 344 panic(fmt.Sprintf("%v not an Int", x)) 345 } 346 347 words := val.Bits() 348 bytes := make([]byte, len(words)*wordSize) 349 350 i := 0 351 for _, w := range words { 352 for j := 0; j < wordSize; j++ { 353 bytes[i] = byte(w) 354 w >>= 8 355 i++ 356 } 357 } 358 // remove leading 0's 359 for i > 0 && bytes[i-1] == 0 { 360 i-- 361 } 362 363 return bytes[:i] 364 } 365 366 // MakeFromBytes returns the Int value given the bytes of its little-endian 367 // binary representation. An empty byte slice argument represents 0. 368 func MakeFromBytes(bytes []byte) Value { 369 words := make([]big.Word, (len(bytes)+(wordSize-1))/wordSize) 370 371 i := 0 372 var w big.Word 373 var s uint 374 for _, b := range bytes { 375 w |= big.Word(b) << s 376 if s += 8; s == wordSize*8 { 377 words[i] = w 378 i++ 379 w = 0 380 s = 0 381 } 382 } 383 // store last word 384 if i < len(words) { 385 words[i] = w 386 i++ 387 } 388 // remove leading 0's 389 for i > 0 && words[i-1] == 0 { 390 i-- 391 } 392 393 return normInt(new(big.Int).SetBits(words[:i])) 394 } 395 396 // ---------------------------------------------------------------------------- 397 // Support for disassembling fractions 398 399 // Num returns the numerator of x; x must be Int, Float, or Unknown. 400 // If x is Unknown, the result is Unknown, otherwise it is an Int 401 // with the same sign as x. 402 func Num(x Value) Value { 403 switch x := x.(type) { 404 case unknownVal, int64Val, intVal: 405 return x 406 case floatVal: 407 return normInt(x.val.Num()) 408 } 409 panic(fmt.Sprintf("%v not Int or Float", x)) 410 } 411 412 // Denom returns the denominator of x; x must be Int, Float, or Unknown. 413 // If x is Unknown, the result is Unknown, otherwise it is an Int >= 1. 414 func Denom(x Value) Value { 415 switch x := x.(type) { 416 case unknownVal: 417 return x 418 case int64Val, intVal: 419 return int64Val(1) 420 case floatVal: 421 return normInt(x.val.Denom()) 422 } 423 panic(fmt.Sprintf("%v not Int or Float", x)) 424 } 425 426 // ---------------------------------------------------------------------------- 427 // Support for assembling/disassembling complex numbers 428 429 // MakeImag returns the numeric value x*i (possibly 0); 430 // x must be Int, Float, or Unknown. 431 // If x is Unknown, the result is Unknown. 432 func MakeImag(x Value) Value { 433 var im *big.Rat 434 switch x := x.(type) { 435 case unknownVal: 436 return x 437 case int64Val: 438 im = big.NewRat(int64(x), 1) 439 case intVal: 440 im = new(big.Rat).SetFrac(x.val, int1) 441 case floatVal: 442 im = x.val 443 default: 444 panic(fmt.Sprintf("%v not Int or Float", x)) 445 } 446 return normComplex(rat0, im) 447 } 448 449 // Real returns the real part of x, which must be a numeric or unknown value. 450 // If x is Unknown, the result is Unknown. 451 func Real(x Value) Value { 452 switch x := x.(type) { 453 case unknownVal, int64Val, intVal, floatVal: 454 return x 455 case complexVal: 456 return normFloat(x.re) 457 } 458 panic(fmt.Sprintf("%v not numeric", x)) 459 } 460 461 // Imag returns the imaginary part of x, which must be a numeric or unknown value. 462 // If x is Unknown, the result is Unknown. 463 func Imag(x Value) Value { 464 switch x := x.(type) { 465 case unknownVal: 466 return x 467 case int64Val, intVal, floatVal: 468 return int64Val(0) 469 case complexVal: 470 return normFloat(x.im) 471 } 472 panic(fmt.Sprintf("%v not numeric", x)) 473 } 474 475 // ---------------------------------------------------------------------------- 476 // Operations 477 478 // is32bit reports whether x can be represented using 32 bits. 479 func is32bit(x int64) bool { 480 const s = 32 481 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 482 } 483 484 // is63bit reports whether x can be represented using 63 bits. 485 func is63bit(x int64) bool { 486 const s = 63 487 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 488 } 489 490 // UnaryOp returns the result of the unary expression op y. 491 // The operation must be defined for the operand. 492 // If size >= 0 it specifies the ^ (xor) result size in bytes. 493 // If y is Unknown, the result is Unknown. 494 // 495 func UnaryOp(op token.Token, y Value, size int) Value { 496 switch op { 497 case token.ADD: 498 switch y.(type) { 499 case unknownVal, int64Val, intVal, floatVal, complexVal: 500 return y 501 } 502 503 case token.SUB: 504 switch y := y.(type) { 505 case unknownVal: 506 return y 507 case int64Val: 508 if z := -y; z != y { 509 return z // no overflow 510 } 511 return normInt(new(big.Int).Neg(big.NewInt(int64(y)))) 512 case intVal: 513 return normInt(new(big.Int).Neg(y.val)) 514 case floatVal: 515 return normFloat(new(big.Rat).Neg(y.val)) 516 case complexVal: 517 return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im)) 518 } 519 520 case token.XOR: 521 var z big.Int 522 switch y := y.(type) { 523 case unknownVal: 524 return y 525 case int64Val: 526 z.Not(big.NewInt(int64(y))) 527 case intVal: 528 z.Not(y.val) 529 default: 530 goto Error 531 } 532 // For unsigned types, the result will be negative and 533 // thus "too large": We must limit the result size to 534 // the type's size. 535 if size >= 0 { 536 s := uint(size) * 8 537 z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), s)) // z &^= (-1)<<s 538 } 539 return normInt(&z) 540 541 case token.NOT: 542 switch y := y.(type) { 543 case unknownVal: 544 return y 545 case boolVal: 546 return !y 547 } 548 } 549 550 Error: 551 panic(fmt.Sprintf("invalid unary operation %s%v", op, y)) 552 } 553 554 var ( 555 int1 = big.NewInt(1) 556 rat0 = big.NewRat(0, 1) 557 ) 558 559 func ord(x Value) int { 560 switch x.(type) { 561 default: 562 return 0 563 case boolVal, stringVal: 564 return 1 565 case int64Val: 566 return 2 567 case intVal: 568 return 3 569 case floatVal: 570 return 4 571 case complexVal: 572 return 5 573 } 574 } 575 576 // match returns the matching representation (same type) with the 577 // smallest complexity for two values x and y. If one of them is 578 // numeric, both of them must be numeric. If one of them is Unknown, 579 // both results are Unknown. 580 // 581 func match(x, y Value) (_, _ Value) { 582 if ord(x) > ord(y) { 583 y, x = match(y, x) 584 return x, y 585 } 586 // ord(x) <= ord(y) 587 588 switch x := x.(type) { 589 case unknownVal: 590 return x, x 591 592 case boolVal, stringVal, complexVal: 593 return x, y 594 595 case int64Val: 596 switch y := y.(type) { 597 case int64Val: 598 return x, y 599 case intVal: 600 return intVal{big.NewInt(int64(x))}, y 601 case floatVal: 602 return floatVal{big.NewRat(int64(x), 1)}, y 603 case complexVal: 604 return complexVal{big.NewRat(int64(x), 1), rat0}, y 605 } 606 607 case intVal: 608 switch y := y.(type) { 609 case intVal: 610 return x, y 611 case floatVal: 612 return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y 613 case complexVal: 614 return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y 615 } 616 617 case floatVal: 618 switch y := y.(type) { 619 case floatVal: 620 return x, y 621 case complexVal: 622 return complexVal{x.val, rat0}, y 623 } 624 } 625 626 panic("unreachable") 627 } 628 629 // BinaryOp returns the result of the binary expression x op y. 630 // The operation must be defined for the operands. If one of the 631 // operands is Unknown, the result is Unknown. 632 // To force integer division of Int operands, use op == token.QUO_ASSIGN 633 // instead of token.QUO; the result is guaranteed to be Int in this case. 634 // Division by zero leads to a run-time panic. 635 // 636 func BinaryOp(x Value, op token.Token, y Value) Value { 637 x, y = match(x, y) 638 639 switch x := x.(type) { 640 case unknownVal: 641 return x 642 643 case boolVal: 644 y := y.(boolVal) 645 switch op { 646 case token.LAND: 647 return x && y 648 case token.LOR: 649 return x || y 650 } 651 652 case int64Val: 653 a := int64(x) 654 b := int64(y.(int64Val)) 655 var c int64 656 switch op { 657 case token.ADD: 658 if !is63bit(a) || !is63bit(b) { 659 return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b))) 660 } 661 c = a + b 662 case token.SUB: 663 if !is63bit(a) || !is63bit(b) { 664 return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b))) 665 } 666 c = a - b 667 case token.MUL: 668 if !is32bit(a) || !is32bit(b) { 669 return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b))) 670 } 671 c = a * b 672 case token.QUO: 673 return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b))) 674 case token.QUO_ASSIGN: // force integer division 675 c = a / b 676 case token.REM: 677 c = a % b 678 case token.AND: 679 c = a & b 680 case token.OR: 681 c = a | b 682 case token.XOR: 683 c = a ^ b 684 case token.AND_NOT: 685 c = a &^ b 686 default: 687 goto Error 688 } 689 return int64Val(c) 690 691 case intVal: 692 a := x.val 693 b := y.(intVal).val 694 var c big.Int 695 switch op { 696 case token.ADD: 697 c.Add(a, b) 698 case token.SUB: 699 c.Sub(a, b) 700 case token.MUL: 701 c.Mul(a, b) 702 case token.QUO: 703 return normFloat(new(big.Rat).SetFrac(a, b)) 704 case token.QUO_ASSIGN: // force integer division 705 c.Quo(a, b) 706 case token.REM: 707 c.Rem(a, b) 708 case token.AND: 709 c.And(a, b) 710 case token.OR: 711 c.Or(a, b) 712 case token.XOR: 713 c.Xor(a, b) 714 case token.AND_NOT: 715 c.AndNot(a, b) 716 default: 717 goto Error 718 } 719 return normInt(&c) 720 721 case floatVal: 722 a := x.val 723 b := y.(floatVal).val 724 var c big.Rat 725 switch op { 726 case token.ADD: 727 c.Add(a, b) 728 case token.SUB: 729 c.Sub(a, b) 730 case token.MUL: 731 c.Mul(a, b) 732 case token.QUO: 733 c.Quo(a, b) 734 default: 735 goto Error 736 } 737 return normFloat(&c) 738 739 case complexVal: 740 y := y.(complexVal) 741 a, b := x.re, x.im 742 c, d := y.re, y.im 743 var re, im big.Rat 744 switch op { 745 case token.ADD: 746 // (a+c) + i(b+d) 747 re.Add(a, c) 748 im.Add(b, d) 749 case token.SUB: 750 // (a-c) + i(b-d) 751 re.Sub(a, c) 752 im.Sub(b, d) 753 case token.MUL: 754 // (ac-bd) + i(bc+ad) 755 var ac, bd, bc, ad big.Rat 756 ac.Mul(a, c) 757 bd.Mul(b, d) 758 bc.Mul(b, c) 759 ad.Mul(a, d) 760 re.Sub(&ac, &bd) 761 im.Add(&bc, &ad) 762 case token.QUO: 763 // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd 764 var ac, bd, bc, ad, s, cc, dd big.Rat 765 ac.Mul(a, c) 766 bd.Mul(b, d) 767 bc.Mul(b, c) 768 ad.Mul(a, d) 769 cc.Mul(c, c) 770 dd.Mul(d, d) 771 s.Add(&cc, &dd) 772 re.Add(&ac, &bd) 773 re.Quo(&re, &s) 774 im.Sub(&bc, &ad) 775 im.Quo(&im, &s) 776 default: 777 goto Error 778 } 779 return normComplex(&re, &im) 780 781 case stringVal: 782 if op == token.ADD { 783 return x + y.(stringVal) 784 } 785 } 786 787 Error: 788 panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y)) 789 } 790 791 // Shift returns the result of the shift expression x op s 792 // with op == token.SHL or token.SHR (<< or >>). x must be 793 // an Int or an Unknown. If x is Unknown, the result is x. 794 // 795 func Shift(x Value, op token.Token, s uint) Value { 796 switch x := x.(type) { 797 case unknownVal: 798 return x 799 800 case int64Val: 801 if s == 0 { 802 return x 803 } 804 switch op { 805 case token.SHL: 806 z := big.NewInt(int64(x)) 807 return normInt(z.Lsh(z, s)) 808 case token.SHR: 809 return x >> s 810 } 811 812 case intVal: 813 if s == 0 { 814 return x 815 } 816 var z big.Int 817 switch op { 818 case token.SHL: 819 return normInt(z.Lsh(x.val, s)) 820 case token.SHR: 821 return normInt(z.Rsh(x.val, s)) 822 } 823 } 824 825 panic(fmt.Sprintf("invalid shift %v %s %d", x, op, s)) 826 } 827 828 func cmpZero(x int, op token.Token) bool { 829 switch op { 830 case token.EQL: 831 return x == 0 832 case token.NEQ: 833 return x != 0 834 case token.LSS: 835 return x < 0 836 case token.LEQ: 837 return x <= 0 838 case token.GTR: 839 return x > 0 840 case token.GEQ: 841 return x >= 0 842 } 843 panic("unreachable") 844 } 845 846 // Compare returns the result of the comparison x op y. 847 // The comparison must be defined for the operands. 848 // If one of the operands is Unknown, the result is 849 // false. 850 // 851 func Compare(x Value, op token.Token, y Value) bool { 852 x, y = match(x, y) 853 854 switch x := x.(type) { 855 case unknownVal: 856 return false 857 858 case boolVal: 859 y := y.(boolVal) 860 switch op { 861 case token.EQL: 862 return x == y 863 case token.NEQ: 864 return x != y 865 } 866 867 case int64Val: 868 y := y.(int64Val) 869 switch op { 870 case token.EQL: 871 return x == y 872 case token.NEQ: 873 return x != y 874 case token.LSS: 875 return x < y 876 case token.LEQ: 877 return x <= y 878 case token.GTR: 879 return x > y 880 case token.GEQ: 881 return x >= y 882 } 883 884 case intVal: 885 return cmpZero(x.val.Cmp(y.(intVal).val), op) 886 887 case floatVal: 888 return cmpZero(x.val.Cmp(y.(floatVal).val), op) 889 890 case complexVal: 891 y := y.(complexVal) 892 re := x.re.Cmp(y.re) 893 im := x.im.Cmp(y.im) 894 switch op { 895 case token.EQL: 896 return re == 0 && im == 0 897 case token.NEQ: 898 return re != 0 || im != 0 899 } 900 901 case stringVal: 902 y := y.(stringVal) 903 switch op { 904 case token.EQL: 905 return x == y 906 case token.NEQ: 907 return x != y 908 case token.LSS: 909 return x < y 910 case token.LEQ: 911 return x <= y 912 case token.GTR: 913 return x > y 914 case token.GEQ: 915 return x >= y 916 } 917 } 918 919 panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y)) 920 }