github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/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  }