github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/float_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package grumpy 16 17 import ( 18 "math" 19 "math/big" 20 "testing" 21 ) 22 23 var ( 24 // bigLongNumber is a number that is too large to be converted to 25 // a float64. 26 bigLongNumber = new(big.Int).Exp(big.NewInt(10), big.NewInt(1000), nil) 27 // biggestFloat is the largest integer that can be converted to a 28 // Python long (in CPython) without overflow. 29 // Its value is 2**1024 - 2**(1024-54) - 1. 30 biggestFloat = func(z *big.Int) *big.Int { 31 z.SetBit(z, 1024, 1) 32 z.Sub(z, big.NewInt(1)) 33 z.SetBit(z, 1024-54, 0) 34 return z 35 }(new(big.Int)) 36 ) 37 38 func TestFloatArithmeticOps(t *testing.T) { 39 cases := []struct { 40 fun func(f *Frame, v, w *Object) (*Object, *BaseException) 41 v, w *Object 42 want *Object 43 wantExc *BaseException 44 }{ 45 {Add, NewFloat(1).ToObject(), NewFloat(1).ToObject(), NewFloat(2).ToObject(), nil}, 46 {Add, NewFloat(1.5).ToObject(), NewInt(1).ToObject(), NewFloat(2.5).ToObject(), nil}, 47 {Add, NewInt(1).ToObject(), NewFloat(1.5).ToObject(), NewFloat(2.5).ToObject(), nil}, 48 {Add, NewFloat(1.7976931348623157e+308).ToObject(), NewFloat(1.7976931348623157e+308).ToObject(), NewFloat(math.Inf(1)).ToObject(), nil}, 49 {Add, NewFloat(1.7976931348623157e+308).ToObject(), NewFloat(-1.7976931348623157e+308).ToObject(), NewFloat(0).ToObject(), nil}, 50 {Add, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), nil}, 51 {Add, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(-1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 52 {Add, newObject(ObjectType), NewFloat(-1).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'object' and 'float'")}, 53 {Div, NewFloat(12.5).ToObject(), NewFloat(4).ToObject(), NewFloat(3.125).ToObject(), nil}, 54 {Div, NewFloat(-12.5).ToObject(), NewInt(4).ToObject(), NewFloat(-3.125).ToObject(), nil}, 55 {Div, NewInt(25).ToObject(), NewFloat(5).ToObject(), NewFloat(5.0).ToObject(), nil}, 56 {Div, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 57 {Div, NewFloat(math.Inf(-1)).ToObject(), NewInt(-20).ToObject(), NewFloat(math.Inf(1)).ToObject(), nil}, 58 {Div, NewInt(1).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil}, 59 {Div, newObject(ObjectType), NewFloat(1.1).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for /: 'object' and 'float'")}, 60 {Div, True.ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 61 {Div, NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 62 {Div, NewFloat(1.0).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 63 {FloorDiv, NewFloat(12.5).ToObject(), NewFloat(4).ToObject(), NewFloat(3).ToObject(), nil}, 64 {FloorDiv, NewFloat(-12.5).ToObject(), NewInt(4).ToObject(), NewFloat(-4).ToObject(), nil}, 65 {FloorDiv, NewInt(25).ToObject(), NewFloat(5).ToObject(), NewFloat(5.0).ToObject(), nil}, 66 {FloorDiv, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 67 {FloorDiv, NewFloat(math.Inf(-1)).ToObject(), NewInt(-20).ToObject(), NewFloat(math.Inf(1)).ToObject(), nil}, 68 {FloorDiv, NewInt(1).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil}, 69 {FloorDiv, newObject(ObjectType), NewFloat(1.1).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'object' and 'float'")}, 70 {FloorDiv, NewFloat(1.0).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 71 {FloorDiv, True.ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 72 {FloorDiv, NewFloat(math.Inf(1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 73 {Mod, NewFloat(50.5).ToObject(), NewInt(10).ToObject(), NewFloat(0.5).ToObject(), nil}, 74 {Mod, NewFloat(50.5).ToObject(), NewFloat(-10).ToObject(), NewFloat(-9.5).ToObject(), nil}, 75 {Mod, NewFloat(-20.2).ToObject(), NewFloat(40).ToObject(), NewFloat(19.8).ToObject(), nil}, 76 {Mod, NewFloat(math.Inf(1)).ToObject(), NewInt(10).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 77 {Mod, NewInt(17).ToObject(), NewFloat(-4.25).ToObject(), NewFloat(0).ToObject(), nil}, 78 {Mod, NewInt(10).ToObject(), NewFloat(-8).ToObject(), NewFloat(-6).ToObject(), nil}, 79 {Mod, NewFloat(4.5).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(4.5).ToObject(), nil}, 80 {Mod, NewFloat(4.5).ToObject(), NewFloat(math.Inf(-1)).ToObject(), NewFloat(math.Inf(-1)).ToObject(), nil}, 81 {Mod, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(-1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 82 {Mod, None, NewFloat(42).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for %: 'NoneType' and 'float'")}, 83 {Mod, NewFloat(-32.25).ToObject(), NewInt(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 84 {Mod, NewFloat(math.Inf(-1)).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 85 {Mod, NewInt(2).ToObject(), NewFloat(0).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 86 {Mul, NewFloat(1.2).ToObject(), True.ToObject(), NewFloat(1.2).ToObject(), nil}, 87 {Mul, NewInt(-4).ToObject(), NewFloat(1.2).ToObject(), NewFloat(-4.8).ToObject(), nil}, 88 {Mul, NewFloat(math.Inf(1)).ToObject(), NewInt(-5).ToObject(), NewFloat(math.Inf(-1)).ToObject(), nil}, 89 {Mul, False.ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 90 {Mul, None, NewFloat(1.5).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'NoneType' and 'float'")}, 91 {Pow, NewFloat(2.0).ToObject(), NewInt(10).ToObject(), NewFloat(1024.0).ToObject(), nil}, 92 {Pow, NewFloat(2.0).ToObject(), NewFloat(-2.0).ToObject(), NewFloat(0.25).ToObject(), nil}, 93 {Pow, newObject(ObjectType), NewFloat(2.0).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'object' and 'float'")}, 94 {Pow, NewFloat(2.0).ToObject(), newObject(ObjectType), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'float' and 'object'")}, 95 {Sub, NewFloat(21.3).ToObject(), NewFloat(35.6).ToObject(), NewFloat(-14.3).ToObject(), nil}, 96 {Sub, True.ToObject(), NewFloat(1.5).ToObject(), NewFloat(-0.5).ToObject(), nil}, 97 {Sub, NewFloat(1.0).ToObject(), NewList().ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for -: 'float' and 'list'")}, 98 {Sub, NewFloat(math.Inf(1)).ToObject(), NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject(), nil}, 99 } 100 for _, cas := range cases { 101 switch got, result := checkInvokeResult(wrapFuncForTest(cas.fun), []*Object{cas.v, cas.w}, cas.want, cas.wantExc); result { 102 case checkInvokeResultExceptionMismatch: 103 t.Errorf("%s(%v, %v) raised %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.wantExc) 104 case checkInvokeResultReturnValueMismatch: 105 // Handle NaN specially, since NaN != NaN. 106 if got == nil || cas.want == nil || !got.isInstance(FloatType) || !cas.want.isInstance(FloatType) || 107 !math.IsNaN(toFloatUnsafe(got).Value()) || !math.IsNaN(toFloatUnsafe(cas.want).Value()) { 108 t.Errorf("%s(%v, %v) = %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.want) 109 } 110 } 111 } 112 } 113 114 func TestFloatDivMod(t *testing.T) { 115 cases := []invokeTestCase{ 116 {args: wrapArgs(12.5, 4.0), want: NewTuple2(NewFloat(3).ToObject(), NewFloat(0.5).ToObject()).ToObject()}, 117 {args: wrapArgs(-12.5, 4.0), want: NewTuple2(NewFloat(-4).ToObject(), NewFloat(3.5).ToObject()).ToObject()}, 118 {args: wrapArgs(25.0, 5.0), want: NewTuple2(NewFloat(5).ToObject(), NewFloat(0).ToObject()).ToObject()}, 119 {args: wrapArgs(-20.2, 40.0), want: NewTuple2(NewFloat(-1).ToObject(), NewFloat(19.8).ToObject()).ToObject()}, 120 {args: wrapArgs(math.Inf(1), math.Inf(1)), want: NewTuple2(NewFloat(math.NaN()).ToObject(), NewFloat(math.NaN()).ToObject()).ToObject()}, 121 {args: wrapArgs(math.Inf(1), math.Inf(-1)), want: NewTuple2(NewFloat(math.NaN()).ToObject(), NewFloat(math.NaN()).ToObject()).ToObject()}, 122 {args: wrapArgs(math.Inf(-1), -20.0), want: NewTuple2(NewFloat(math.Inf(1)).ToObject(), NewFloat(math.NaN()).ToObject()).ToObject()}, 123 {args: wrapArgs(1, math.Inf(1)), want: NewTuple2(NewFloat(0).ToObject(), NewFloat(1).ToObject()).ToObject()}, 124 {args: wrapArgs(newObject(ObjectType), 1.1), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'object' and 'float'")}, 125 {args: wrapArgs(True.ToObject(), 0.0), wantExc: mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 126 {args: wrapArgs(math.Inf(1), 0.0), wantExc: mustCreateException(ZeroDivisionErrorType, "float division or modulo by zero")}, 127 {args: wrapArgs(1.0, bigLongNumber), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 128 } 129 for _, cas := range cases { 130 switch got, result := checkInvokeResult(wrapFuncForTest(DivMod), cas.args, cas.want, cas.wantExc); result { 131 case checkInvokeResultExceptionMismatch: 132 t.Errorf("float.__divmod__%v raised %v, want %v", cas.args, got, cas.wantExc) 133 case checkInvokeResultReturnValueMismatch: 134 // Handle NaN specially, since NaN != NaN. 135 if got == nil || cas.want == nil || !got.isInstance(TupleType) || !cas.want.isInstance(TupleType) || 136 !isNaNTupleFloat(got, cas.want) { 137 t.Errorf("float.__divmod__%v = %v, want %v", cas.args, got, cas.want) 138 } 139 } 140 } 141 } 142 143 func isNaNTupleFloat(got, want *Object) bool { 144 if toTupleUnsafe(got).Len() != toTupleUnsafe(want).Len() { 145 return false 146 } 147 for i := 0; i < toTupleUnsafe(got).Len(); i++ { 148 if math.IsNaN(toFloatUnsafe(toTupleUnsafe(got).GetItem(i)).Value()) && 149 math.IsNaN(toFloatUnsafe(toTupleUnsafe(want).GetItem(i)).Value()) { 150 return true 151 } 152 } 153 return false 154 } 155 156 func TestFloatCompare(t *testing.T) { 157 cases := []invokeTestCase{ 158 {args: wrapArgs(1.0, 1.0), want: compareAllResultEq}, 159 {args: wrapArgs(30968.3958, 30968.3958), want: compareAllResultEq}, 160 {args: wrapArgs(-306.5, 101.0), want: compareAllResultLT}, 161 {args: wrapArgs(309683.958, 102.1), want: compareAllResultGT}, 162 {args: wrapArgs(0.9, 1), want: compareAllResultLT}, 163 {args: wrapArgs(0.0, 0), want: compareAllResultEq}, 164 {args: wrapArgs(1, 0.9), want: compareAllResultGT}, 165 {args: wrapArgs(0, 0.0), want: compareAllResultEq}, 166 {args: wrapArgs(0.0, None), want: compareAllResultGT}, 167 {args: wrapArgs(math.Inf(+1), bigLongNumber), want: compareAllResultGT}, 168 } 169 for _, cas := range cases { 170 if err := runInvokeTestCase(compareAll, &cas); err != "" { 171 t.Error(err) 172 } 173 } 174 } 175 176 func TestFloatInt(t *testing.T) { 177 cases := []invokeTestCase{ 178 {args: wrapArgs(IntType, -1209539058.2), want: NewInt(-1209539058).ToObject()}, 179 {args: wrapArgs(IntType, 2.994514758031654e+186), want: NewLong(func() *big.Int { i, _ := big.NewFloat(2.994514758031654e+186).Int(nil); return i }()).ToObject()}, 180 {args: wrapArgs(IntType, math.Inf(1)), wantExc: mustCreateException(OverflowErrorType, "cannot convert float infinity to integer")}, 181 {args: wrapArgs(IntType, math.Inf(-1)), wantExc: mustCreateException(OverflowErrorType, "cannot convert float infinity to integer")}, 182 {args: wrapArgs(IntType, math.NaN()), wantExc: mustCreateException(OverflowErrorType, "cannot convert float NaN to integer")}, 183 } 184 for _, cas := range cases { 185 if err := runInvokeMethodTestCase(IntType, "__new__", &cas); err != "" { 186 t.Error(err) 187 } 188 } 189 } 190 191 func TestFloatLong(t *testing.T) { 192 cases := []invokeTestCase{ 193 {args: wrapArgs(LongType, -3209539058.2), want: NewLong(big.NewInt(-3209539058)).ToObject()}, 194 {args: wrapArgs(LongType, 2.994514758031654e+186), want: NewLong(func() *big.Int { i, _ := big.NewFloat(2.994514758031654e+186).Int(nil); return i }()).ToObject()}, 195 {args: wrapArgs(LongType, math.Inf(1)), wantExc: mustCreateException(OverflowErrorType, "cannot convert float infinity to integer")}, 196 {args: wrapArgs(LongType, math.Inf(-1)), wantExc: mustCreateException(OverflowErrorType, "cannot convert float infinity to integer")}, 197 {args: wrapArgs(LongType, math.NaN()), wantExc: mustCreateException(OverflowErrorType, "cannot convert float NaN to integer")}, 198 } 199 for _, cas := range cases { 200 if err := runInvokeMethodTestCase(LongType, "__new__", &cas); err != "" { 201 t.Error(err) 202 } 203 } 204 } 205 206 func TestFloatHash(t *testing.T) { 207 cases := []invokeTestCase{ 208 {args: wrapArgs(NewFloat(0.0)), want: NewInt(0).ToObject()}, 209 {args: wrapArgs(NewFloat(3.14)), want: NewInt(3146129223).ToObject()}, 210 {args: wrapArgs(NewFloat(42.0)), want: NewInt(42).ToObject()}, 211 {args: wrapArgs(NewFloat(42.125)), want: NewInt(1413677056).ToObject()}, 212 {args: wrapArgs(NewFloat(math.Inf(1))), want: NewInt(314159).ToObject()}, 213 {args: wrapArgs(NewFloat(math.Inf(-1))), want: NewInt(-271828).ToObject()}, 214 {args: wrapArgs(NewFloat(math.NaN())), want: NewInt(0).ToObject()}, 215 } 216 for _, cas := range cases { 217 if err := runInvokeTestCase(wrapFuncForTest(floatHash), &cas); err != "" { 218 t.Error(err) 219 } 220 } 221 } 222 func TestFloatIsTrue(t *testing.T) { 223 cases := []invokeTestCase{ 224 {args: wrapArgs(0.0), want: False.ToObject()}, 225 {args: wrapArgs(0.0001), want: True.ToObject()}, 226 {args: wrapArgs(36983.91283), want: True.ToObject()}, 227 } 228 for _, cas := range cases { 229 if err := runInvokeTestCase(wrapFuncForTest(IsTrue), &cas); err != "" { 230 t.Error(err) 231 } 232 } 233 } 234 235 func TestFloatNew(t *testing.T) { 236 floatNew := mustNotRaise(GetAttr(NewRootFrame(), FloatType.ToObject(), NewStr("__new__"), nil)) 237 strictEqType := newTestClassStrictEq("StrictEq", FloatType) 238 newStrictEq := func(v float64) *Object { 239 f := Float{Object: Object{typ: strictEqType}, value: v} 240 return f.ToObject() 241 } 242 subType := newTestClass("SubType", []*Type{FloatType}, newStringDict(map[string]*Object{})) 243 subTypeObject := (&Float{Object: Object{typ: subType}, value: 3.14}).ToObject() 244 goodSlotType := newTestClass("GoodSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{ 245 "__float__": newBuiltinFunction("__float__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 246 return NewFloat(3.14).ToObject(), nil 247 }).ToObject(), 248 })) 249 badSlotType := newTestClass("BadSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{ 250 "__float__": newBuiltinFunction("__float__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 251 return newObject(ObjectType), nil 252 }).ToObject(), 253 })) 254 slotSubTypeType := newTestClass("SlotSubType", []*Type{ObjectType}, newStringDict(map[string]*Object{ 255 "__float__": newBuiltinFunction("__float__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) { 256 return subTypeObject, nil 257 }).ToObject(), 258 })) 259 260 cases := []invokeTestCase{ 261 {args: wrapArgs(FloatType), want: NewFloat(0).ToObject()}, 262 {args: wrapArgs(FloatType, 10.5), want: NewFloat(10.5).ToObject()}, 263 {args: wrapArgs(FloatType, -102.1), want: NewFloat(-102.1).ToObject()}, 264 {args: wrapArgs(FloatType, 42), want: NewFloat(42).ToObject()}, 265 {args: wrapArgs(FloatType, "1.024e3"), want: NewFloat(1024).ToObject()}, 266 {args: wrapArgs(FloatType, "-42"), want: NewFloat(-42).ToObject()}, 267 {args: wrapArgs(FloatType, math.Inf(1)), want: NewFloat(math.Inf(1)).ToObject()}, 268 {args: wrapArgs(FloatType, math.Inf(-1)), want: NewFloat(math.Inf(-1)).ToObject()}, 269 {args: wrapArgs(FloatType, math.NaN()), want: NewFloat(math.NaN()).ToObject()}, 270 {args: wrapArgs(FloatType, biggestFloat), want: NewFloat(math.MaxFloat64).ToObject()}, 271 {args: wrapArgs(FloatType, new(big.Int).Neg(biggestFloat)), want: NewFloat(-math.MaxFloat64).ToObject()}, 272 {args: wrapArgs(FloatType, new(big.Int).Sub(big.NewInt(-1), biggestFloat)), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 273 {args: wrapArgs(FloatType, new(big.Int).Add(biggestFloat, big.NewInt(1))), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 274 {args: wrapArgs(FloatType, bigLongNumber), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")}, 275 {args: wrapArgs(FloatType, newObject(goodSlotType)), want: NewFloat(3.14).ToObject()}, 276 {args: wrapArgs(FloatType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__float__ returned non-float (type object)")}, 277 {args: wrapArgs(FloatType, newObject(slotSubTypeType)), want: subTypeObject}, 278 {args: wrapArgs(strictEqType, 3.14), want: newStrictEq(3.14)}, 279 {args: wrapArgs(strictEqType, newObject(goodSlotType)), want: newStrictEq(3.14)}, 280 {args: wrapArgs(strictEqType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__float__ returned non-float (type object)")}, 281 {args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'__new__' requires 1 arguments")}, 282 {args: wrapArgs(IntType), wantExc: mustCreateException(TypeErrorType, "float.__new__(int): int is not a subtype of float")}, 283 {args: wrapArgs(FloatType, 123, None), wantExc: mustCreateException(TypeErrorType, "'__new__' of 'float' requires 0 or 1 arguments")}, 284 {args: wrapArgs(FloatType, "foo"), wantExc: mustCreateException(ValueErrorType, "could not convert string to float: foo")}, 285 {args: wrapArgs(FloatType, None), wantExc: mustCreateException(TypeErrorType, "float() argument must be a string or a number")}, 286 } 287 for _, cas := range cases { 288 switch got, match := checkInvokeResult(floatNew, cas.args, cas.want, cas.wantExc); match { 289 case checkInvokeResultExceptionMismatch: 290 t.Errorf("float.__new__%v raised %v, want %v", cas.args, got, cas.wantExc) 291 case checkInvokeResultReturnValueMismatch: 292 // Handle NaN specially, since NaN != NaN. 293 if got == nil || cas.want == nil || !got.isInstance(FloatType) || !cas.want.isInstance(FloatType) || 294 !math.IsNaN(toFloatUnsafe(got).Value()) || !math.IsNaN(toFloatUnsafe(cas.want).Value()) { 295 t.Errorf("float.__new__%v = %v, want %v", cas.args, got, cas.want) 296 } 297 } 298 } 299 } 300 301 func TestFloatRepr(t *testing.T) { 302 cases := []invokeTestCase{ 303 {args: wrapArgs(0.0), want: NewStr("0.0").ToObject()}, 304 {args: wrapArgs(0.1), want: NewStr("0.1").ToObject()}, 305 {args: wrapArgs(-303.5), want: NewStr("-303.5").ToObject()}, 306 {args: wrapArgs(231095835.0), want: NewStr("231095835.0").ToObject()}, 307 {args: wrapArgs(1e+6), want: NewStr("1000000.0").ToObject()}, 308 {args: wrapArgs(1e+15), want: NewStr("1000000000000000.0").ToObject()}, 309 {args: wrapArgs(1e+16), want: NewStr("1e+16").ToObject()}, 310 {args: wrapArgs(1e16), want: NewStr("1e+16").ToObject()}, 311 {args: wrapArgs(1e-6), want: NewStr("1e-06").ToObject()}, 312 {args: wrapArgs(math.Inf(1)), want: NewStr("inf").ToObject()}, 313 {args: wrapArgs(math.Inf(-1)), want: NewStr("-inf").ToObject()}, 314 {args: wrapArgs(math.NaN()), want: NewStr("nan").ToObject()}, 315 } 316 for _, cas := range cases { 317 if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" { 318 t.Error(err) 319 } 320 } 321 } 322 323 func TestFloatStr(t *testing.T) { 324 cases := []invokeTestCase{ 325 {args: wrapArgs(1.0), want: NewStr("1.0").ToObject()}, 326 {args: wrapArgs(-847.373), want: NewStr("-847.373").ToObject()}, 327 {args: wrapArgs(0.123456789123456789), want: NewStr("0.123456789123").ToObject()}, 328 {args: wrapArgs(1e+11), want: NewStr("100000000000.0").ToObject()}, 329 {args: wrapArgs(1e+12), want: NewStr("1e+12").ToObject()}, 330 {args: wrapArgs(1e-4), want: NewStr("0.0001").ToObject()}, 331 {args: wrapArgs(1e-5), want: NewStr("1e-05").ToObject()}, 332 {args: wrapArgs(math.Inf(1)), want: NewStr("inf").ToObject()}, 333 {args: wrapArgs(math.Inf(-1)), want: NewStr("-inf").ToObject()}, 334 {args: wrapArgs(math.NaN()), want: NewStr("nan").ToObject()}, 335 } 336 for _, cas := range cases { 337 if err := runInvokeTestCase(wrapFuncForTest(floatStr), &cas); err != "" { 338 t.Error(err) 339 } 340 } 341 }