github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/mods/math/math_test.go (about) 1 package math 2 3 import ( 4 "math" 5 "math/big" 6 "strconv" 7 "testing" 8 9 "src.elv.sh/pkg/eval" 10 "src.elv.sh/pkg/eval/errs" 11 . "src.elv.sh/pkg/eval/evaltest" 12 ) 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 ) 21 22 var minIntString = strconv.Itoa(minInt) 23 24 func TestMath(t *testing.T) { 25 setup := func(ev *eval.Evaler) { 26 ev.AddGlobal(eval.NsBuilder{}.AddNs("math", Ns).Ns()) 27 } 28 TestWithSetup(t, setup, 29 That("math:abs 2").Puts(2), 30 That("math:abs -2").Puts(2), 31 That("math:abs "+minIntString).Puts(bigInt(minIntString[1:])), 32 That("math:abs "+z).Puts(bigInt(z)), 33 That("math:abs -"+z).Puts(bigInt(z)), 34 That("math:abs -1/2").Puts(big.NewRat(1, 2)), 35 That("math:abs 1/2").Puts(big.NewRat(1, 2)), 36 That("math:abs 2.1").Puts(2.1), 37 That("math:abs -2.1").Puts(2.1), 38 39 That("math:is-inf 1.3").Puts(false), 40 That("math:is-inf &sign=0 inf").Puts(true), 41 That("math:is-inf &sign=1 inf").Puts(true), 42 That("math:is-inf &sign=-1 -inf").Puts(true), 43 That("math:is-inf &sign=1 -inf").Puts(false), 44 That("math:is-inf -inf").Puts(true), 45 That("math:is-inf nan").Puts(false), 46 That("math:is-inf 1").Puts(false), 47 That("math:is-inf "+z).Puts(false), 48 That("math:is-inf 1/2").Puts(false), 49 50 That("math:is-nan 1.3").Puts(false), 51 That("math:is-nan inf").Puts(false), 52 That("math:is-nan nan").Puts(true), 53 That("math:is-nan 1").Puts(false), 54 That("math:is-nan "+z).Puts(false), 55 That("math:is-nan 1/2").Puts(false), 56 57 That("math:max").Throws( 58 errs.ArityMismatch{What: "arguments here", ValidLow: 1, ValidHigh: -1, Actual: 0}, 59 "math:max"), 60 That("math:max 42").Puts(42), 61 That("math:max -3 3 10 -4").Puts(10), 62 That("math:max 2 10 "+z).Puts(bigInt(z)), 63 That("math:max "+z1+" "+z2+" "+z).Puts(bigInt(z2)), 64 That("math:max 1/2 1/3 2/3").Puts(big.NewRat(2, 3)), 65 That("math:max 1.0 2.0").Puts(2.0), 66 That("math:max 3 NaN 5").Puts(math.NaN()), 67 68 That("math:min").Throws( 69 errs.ArityMismatch{What: "arguments here", ValidLow: 1, ValidHigh: -1, Actual: 0}, 70 "math:min"), 71 That("math:min 42").Puts(42), 72 That("math:min -3 3 10 -4").Puts(-4), 73 That("math:min 2 10 "+z).Puts(2), 74 That("math:min "+z1+" "+z2+" "+z).Puts(bigInt(z)), 75 That("math:min 1/2 1/3 2/3").Puts(big.NewRat(1, 3)), 76 That("math:min 1.0 2.0").Puts(1.0), 77 That("math:min 3 NaN 5").Puts(math.NaN()), 78 79 // Tests below this line are tests against simple bindings for Go's math package. 80 81 That("put $math:pi").Puts(math.Pi), 82 That("put $math:e").Puts(math.E), 83 84 That("math:ceil 2.1").Puts(3.0), 85 That("math:ceil -2.1").Puts(-2.0), 86 87 That("math:floor 2.1").Puts(2.0), 88 That("math:floor -2.1").Puts(-3.0), 89 90 That("math:round 2.1").Puts(2.0), 91 That("math:round -2.1").Puts(-2.0), 92 That("math:round 2.5").Puts(3.0), 93 That("math:round -2.5").Puts(-3.0), 94 That("math:round (float64 Inf)").Puts(math.Inf(1)), 95 That("math:round (float64 NaN)").Puts(math.NaN()), 96 97 That("math:round-to-even 2.1").Puts(2.0), 98 That("math:round-to-even -2.1").Puts(-2.0), 99 That("math:round-to-even 2.5").Puts(2.0), 100 That("math:round-to-even -2.5").Puts(-2.0), 101 That("math:round-to-even (float64 Inf)").Puts(math.Inf(1)), 102 That("math:round-to-even (float64 NaN)").Puts(math.NaN()), 103 104 That("math:trunc 2.1").Puts(2.0), 105 That("math:trunc -2.1").Puts(-2.0), 106 That("math:trunc 2.5").Puts(2.0), 107 That("math:trunc -2.5").Puts(-2.0), 108 That("math:trunc (float64 Inf)").Puts(math.Inf(1)), 109 That("math:trunc (float64 NaN)").Puts(math.NaN()), 110 111 That("math:log $math:e").Puts(1.0), 112 That("math:log 1").Puts(0.0), 113 That("math:log 0").Puts(math.Inf(-1)), 114 That("math:log -1").Puts(math.NaN()), 115 116 That("math:log10 10.0").Puts(1.0), 117 That("math:log10 100.0").Puts(2.0), 118 That("math:log10 1").Puts(0.0), 119 That("math:log10 0").Puts(math.Inf(-1)), 120 That("math:log10 -1").Puts(math.NaN()), 121 122 That("math:log2 8").Puts(3.0), 123 That("math:log2 1024.0").Puts(10.0), 124 That("math:log2 1").Puts(0.0), 125 That("math:log2 0").Puts(math.Inf(-1)), 126 That("math:log2 -1").Puts(math.NaN()), 127 128 That("math:cos 0").Puts(1.0), 129 That("math:cos 1").Puts(math.Cos(1.0)), 130 That("math:cos $math:pi").Puts(-1.0), 131 132 That("math:cosh 0").Puts(1.0), 133 That("math:cosh inf").Puts(math.Inf(1)), 134 That("math:cosh nan").Puts(math.NaN()), 135 136 That("math:sin 0").Puts(0.0), 137 That("math:sin 1").Puts(math.Sin(1.0)), 138 That("math:sin $math:pi").Puts(math.Sin(math.Pi)), 139 140 That("math:sinh 0").Puts(0.0), 141 That("math:sinh inf").Puts(math.Inf(1)), 142 That("math:sinh nan").Puts(math.NaN()), 143 144 That("math:tan 0").Puts(0.0), 145 That("math:tan 1").Puts(math.Tan(1.0)), 146 That("math:tan $math:pi").Puts(math.Tan(math.Pi)), 147 148 That("math:tanh 0").Puts(0.0), 149 That("math:tanh inf").Puts(1.0), 150 That("math:tanh nan").Puts(math.NaN()), 151 152 // This block of tests isn't strictly speaking necessary. But it helps 153 // ensure that we're not just confirming Go statements such as 154 // math.Tan(math.Pi) == math.Tan(math.Pi) 155 // are true. The ops that should return a zero value do not actually 156 // do so. Which illustrates why an approximate match is needed. 157 That("math:cos 1").Puts(Approximately{F: 0.5403023058681397174}), 158 That("math:sin 1").Puts(Approximately{F: 0.8414709848078965066}), 159 That("math:sin $math:pi").Puts(Approximately{F: 0.0}), 160 That("math:tan 1").Puts(Approximately{F: 1.5574077246549023}), 161 That("math:tan $math:pi").Puts(Approximately{F: 0.0}), 162 163 That("math:sqrt 0").Puts(0.0), 164 That("math:sqrt 4").Puts(2.0), 165 That("math:sqrt -4").Puts(math.NaN()), 166 167 // Test the inverse trigonometric block of functions. 168 That("math:acos 0").Puts(math.Acos(0)), 169 That("math:acos 1").Puts(math.Acos(1)), 170 That("math:acos 1.00001").Puts(math.NaN()), 171 172 That("math:asin 0").Puts(math.Asin(0)), 173 That("math:asin 1").Puts(math.Asin(1)), 174 That("math:asin 1.00001").Puts(math.NaN()), 175 176 That("math:atan 0").Puts(math.Atan(0)), 177 That("math:atan 1").Puts(math.Atan(1)), 178 That("math:atan inf").Puts(math.Pi/2), 179 180 // Test the inverse hyperbolic trigonometric block of functions. 181 That("math:acosh 0").Puts(math.Acosh(0)), 182 That("math:acosh 1").Puts(math.Acosh(1)), 183 That("math:acosh nan").Puts(math.NaN()), 184 185 That("math:asinh 0").Puts(math.Asinh(0)), 186 That("math:asinh 1").Puts(math.Asinh(1)), 187 That("math:asinh inf").Puts(math.Inf(1)), 188 189 That("math:atanh 0").Puts(math.Atanh(0)), 190 That("math:atanh 1").Puts(math.Inf(1)), 191 192 That("math:pow nan 2").Puts(math.NaN()), 193 That("math:pow inf 2").Puts(math.Inf(1)), 194 That("math:pow 1 3").Puts(1.0), 195 That("math:pow 2 3").Puts(8.0), 196 That("math:pow -2 2").Puts(4.0), 197 198 That("math:pow10 0").Puts(1.0), 199 That("math:pow10 3").Puts(1000.0), 200 That("math:pow10 -3").Puts(0.001), 201 ) 202 } 203 204 func bigInt(s string) *big.Int { 205 z, ok := new(big.Int).SetString(s, 0) 206 if !ok { 207 panic("cannot parse as big int: " + s) 208 } 209 return z 210 }