src.elv.sh@v0.21.0-dev.0.20240515223629-06979efb9a2a/pkg/eval/vals/num_test.go (about) 1 package vals 2 3 import ( 4 "math" 5 "math/big" 6 "testing" 7 8 "src.elv.sh/pkg/testutil" 9 "src.elv.sh/pkg/tt" 10 ) 11 12 // Test utilities. 13 14 const ( 15 zeros = "0000000000000000000" 16 // Values that exceed the range of int64, used for testing BigInt. 17 z = "1" + zeros + "0" 18 z1 = "1" + zeros + "1" // z+1 19 z2 = "1" + zeros + "2" // z+2 20 z3 = "1" + zeros + "3" // z+3 21 zz = "2" + zeros + "0" // 2z 22 zz1 = "2" + zeros + "1" // 2z+1 23 zz2 = "2" + zeros + "2" // 2z+2 24 zz3 = "2" + zeros + "3" // 2z+3 25 ) 26 27 func TestParseNum(t *testing.T) { 28 tt.Test(t, ParseNum, 29 Args("1").Rets(1), 30 31 Args(z).Rets(bigInt(z)), 32 33 Args("1/2").Rets(big.NewRat(1, 2)), 34 Args("2/1").Rets(2), 35 Args(z+"/1").Rets(bigInt(z)), 36 37 Args("1.0").Rets(1.0), 38 Args("1e-5").Rets(1e-5), 39 40 Args("x").Rets(nil), 41 Args("x/y").Rets(nil), 42 ) 43 } 44 45 func TestUnifyNums(t *testing.T) { 46 tt.Test(t, UnifyNums, 47 Args([]Num{1, 2, 3, 4}, Int). 48 Rets([]int{1, 2, 3, 4}), 49 50 Args([]Num{1, 2, 3, bigInt(z)}, Int). 51 Rets([]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), bigInt(z)}), 52 53 Args([]Num{1, 2, 3, big.NewRat(1, 2)}, Int). 54 Rets([]*big.Rat{ 55 big.NewRat(1, 1), big.NewRat(2, 1), 56 big.NewRat(3, 1), big.NewRat(1, 2)}), 57 Args([]Num{1, 2, bigInt(z), big.NewRat(1, 2)}, Int). 58 Rets([]*big.Rat{ 59 big.NewRat(1, 1), big.NewRat(2, 1), bigRat(z), big.NewRat(1, 2)}), 60 61 Args([]Num{1, 2, 3, 4.0}, Int). 62 Rets([]float64{1, 2, 3, 4}), 63 Args([]Num{1, 2, big.NewRat(1, 2), 4.0}, Int). 64 Rets([]float64{1, 2, 0.5, 4}), 65 Args([]Num{1, 2, big.NewInt(3), 4.0}, Int). 66 Rets([]float64{1, 2, 3, 4}), 67 Args([]Num{1, 2, bigInt(z), 4.0}, Int). 68 Rets([]float64{1, 2, math.Inf(1), 4}), 69 70 Args([]Num{1, 2, 3, 4}, BigInt). 71 Rets([]*big.Int{ 72 big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4)}), 73 ) 74 } 75 76 func TestUnifyNums2(t *testing.T) { 77 tt.Test(t, UnifyNums2, 78 Args(1, 2, Int).Rets(1, 2), 79 Args(1, bigInt(z), Int).Rets(big.NewInt(1), bigInt(z)), 80 Args(1, big.NewRat(1, 2), Int).Rets(big.NewRat(1, 1), big.NewRat(1, 2)), 81 Args(1, 2.0, Int).Rets(1.0, 2.0), 82 Args(1, 2, BigInt).Rets(big.NewInt(1), big.NewInt(2)), 83 ) 84 } 85 86 func TestInvalidNumType(t *testing.T) { 87 tt.Test(t, testutil.Recover, 88 Args(func() { UnifyNums([]Num{int32(0)}, 0) }).Rets("invalid num type int32"), 89 Args(func() { PromoteToBigInt(int32(0)) }).Rets("invalid num type int32"), 90 Args(func() { PromoteToBigRat(int32(0)) }).Rets("invalid num type int32"), 91 Args(func() { ConvertToFloat64(int32(0)) }).Rets("invalid num type int32"), 92 ) 93 } 94 95 func TestInt64ToNum(t *testing.T) { 96 n := Int64ToNum(1) 97 if _, isInt := n.(int); !isInt { 98 t.Errorf("got %T, want int", n) 99 } 100 101 if math.MaxInt != math.MaxInt64 { 102 n = Int64ToNum(math.MaxInt64) 103 if _, isBigInt := n.(*big.Int); !isBigInt { 104 t.Errorf("got %T, want *big.Int", n) 105 } 106 } 107 } 108 109 func TestUint64ToNum(t *testing.T) { 110 n := Uint64ToNum(1) 111 if _, isInt := n.(int); !isInt { 112 t.Errorf("got %T, want int", n) 113 } 114 115 n = Uint64ToNum(math.MaxUint64) 116 if _, isBigInt := n.(*big.Int); !isBigInt { 117 t.Errorf("got %T, want *big.Int", n) 118 } 119 } 120 121 func bigInt(s string) *big.Int { 122 z, ok := new(big.Int).SetString(s, 0) 123 if !ok { 124 panic("cannot parse as big int: " + s) 125 } 126 return z 127 } 128 129 func bigRat(s string) *big.Rat { 130 z, ok := new(big.Rat).SetString(s) 131 if !ok { 132 panic("cannot parse as big rat: " + s) 133 } 134 return z 135 }