github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/complex_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  	"errors"
    19  	"math"
    20  	"math/big"
    21  	"math/cmplx"
    22  	"testing"
    23  )
    24  
    25  func TestComplexAbs(t *testing.T) {
    26  	cases := []invokeTestCase{
    27  		{args: wrapArgs(complex(0, 0)), want: NewFloat(0).ToObject()},
    28  		{args: wrapArgs(complex(1, 1)), want: NewFloat(1.4142135623730951).ToObject()},
    29  		{args: wrapArgs(complex(1, 2)), want: NewFloat(2.23606797749979).ToObject()},
    30  		{args: wrapArgs(complex(3, 4)), want: NewFloat(5).ToObject()},
    31  		{args: wrapArgs(complex(-3, 4)), want: NewFloat(5).ToObject()},
    32  		{args: wrapArgs(complex(3, -4)), want: NewFloat(5).ToObject()},
    33  		{args: wrapArgs(-complex(3, 4)), want: NewFloat(5).ToObject()},
    34  		{args: wrapArgs(complex(0.123456e-3, 0)), want: NewFloat(0.000123456).ToObject()},
    35  		{args: wrapArgs(complex(0.123456e-3, 3.14151692e+7)), want: NewFloat(31415169.2).ToObject()},
    36  		{args: wrapArgs(complex(math.Inf(-1), 1.2)), want: NewFloat(math.Inf(1)).ToObject()},
    37  		{args: wrapArgs(complex(3.4, math.Inf(1))), want: NewFloat(math.Inf(1)).ToObject()},
    38  		{args: wrapArgs(complex(math.Inf(1), math.Inf(-1))), want: NewFloat(math.Inf(1)).ToObject()},
    39  		{args: wrapArgs(complex(math.Inf(1), math.NaN())), want: NewFloat(math.Inf(1)).ToObject()},
    40  		{args: wrapArgs(complex(math.NaN(), math.Inf(1))), want: NewFloat(math.Inf(1)).ToObject()},
    41  		{args: wrapArgs(complex(math.NaN(), 5.6)), want: NewFloat(math.NaN()).ToObject()},
    42  		{args: wrapArgs(complex(7.8, math.NaN())), want: NewFloat(math.NaN()).ToObject()},
    43  	}
    44  	for _, cas := range cases {
    45  		switch got, match := checkInvokeResult(wrapFuncForTest(complexAbs), cas.args, cas.want, cas.wantExc); match {
    46  		case checkInvokeResultReturnValueMismatch:
    47  			if got == nil || cas.want == nil || !got.isInstance(FloatType) || !cas.want.isInstance(FloatType) ||
    48  				!floatsAreSame(toFloatUnsafe(got).Value(), toFloatUnsafe(cas.want).Value()) {
    49  				t.Errorf("complex.__abs__%v = %v, want %v", cas.args, got, cas.want)
    50  			}
    51  		}
    52  	}
    53  }
    54  
    55  func TestComplexEq(t *testing.T) {
    56  	cases := []invokeTestCase{
    57  		{args: wrapArgs(complex(0, 0), 0), want: True.ToObject()},
    58  		{args: wrapArgs(complex(1, 0), 0), want: False.ToObject()},
    59  		{args: wrapArgs(complex(-12, 0), -12), want: True.ToObject()},
    60  		{args: wrapArgs(complex(-12, 0), 1), want: False.ToObject()},
    61  		{args: wrapArgs(complex(17.20, 0), 17.20), want: True.ToObject()},
    62  		{args: wrapArgs(complex(1.2, 0), 17.20), want: False.ToObject()},
    63  		{args: wrapArgs(complex(-4, 15), complex(-4, 15)), want: True.ToObject()},
    64  		{args: wrapArgs(complex(-4, 15), complex(1, 2)), want: False.ToObject()},
    65  		{args: wrapArgs(complex(math.Inf(1), 0), complex(math.Inf(1), 0)), want: True.ToObject()},
    66  		{args: wrapArgs(complex(math.Inf(1), 0), complex(0, math.Inf(1))), want: False.ToObject()},
    67  		{args: wrapArgs(complex(math.Inf(-1), 0), complex(math.Inf(-1), 0)), want: True.ToObject()},
    68  		{args: wrapArgs(complex(math.Inf(-1), 0), complex(0, math.Inf(-1))), want: False.ToObject()},
    69  		{args: wrapArgs(complex(math.Inf(1), math.Inf(1)), complex(math.Inf(1), math.Inf(1))), want: True.ToObject()},
    70  	}
    71  	for _, cas := range cases {
    72  		if err := runInvokeTestCase(wrapFuncForTest(complexEq), &cas); err != "" {
    73  			t.Error(err)
    74  		}
    75  	}
    76  }
    77  
    78  // FIXME(corona10): Since Go 1.9 moved to C99 float division and what CPython uses as well.
    79  // Some tests can be failed with version < Go 1.9. We need to detect Go version.
    80  // And changed expected values.
    81  
    82  func TestComplexBinaryOps(t *testing.T) {
    83  	cases := []struct {
    84  		fun     func(f *Frame, v, w *Object) (*Object, *BaseException)
    85  		v, w    *Object
    86  		want    *Object
    87  		wantExc *BaseException
    88  	}{
    89  		{Add, NewComplex(1 + 3i).ToObject(), NewInt(1).ToObject(), NewComplex(2 + 3i).ToObject(), nil},
    90  		{Add, NewComplex(1 + 3i).ToObject(), NewFloat(-1).ToObject(), NewComplex(3i).ToObject(), nil},
    91  		{Add, NewComplex(1 + 3i).ToObject(), NewInt(1).ToObject(), NewComplex(2 + 3i).ToObject(), nil},
    92  		{Add, NewComplex(1 + 3i).ToObject(), NewComplex(-1 - 3i).ToObject(), NewComplex(0i).ToObject(), nil},
    93  		{Add, NewFloat(math.Inf(1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.Inf(1), 3)).ToObject(), nil},
    94  		{Add, NewFloat(math.Inf(-1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.Inf(-1), 3)).ToObject(), nil},
    95  		{Add, NewFloat(math.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.NaN(), 3)).ToObject(), nil},
    96  		{Add, NewComplex(cmplx.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(cmplx.NaN()).ToObject(), nil},
    97  		{Add, NewFloat(math.Inf(-1)).ToObject(), NewComplex(complex(math.Inf(+1), 3)).ToObject(), NewComplex(complex(math.NaN(), 3)).ToObject(), nil},
    98  		{Add, NewComplex(1 + 3i).ToObject(), None, nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'complex' and 'NoneType'")},
    99  		{Add, None, NewComplex(1 + 3i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for +: 'NoneType' and 'complex'")},
   100  		{Add, NewInt(3).ToObject(), NewComplex(3i).ToObject(), NewComplex(3 + 3i).ToObject(), nil},
   101  		{Add, NewLong(big.NewInt(9999999)).ToObject(), NewComplex(3i).ToObject(), NewComplex(9999999 + 3i).ToObject(), nil},
   102  		{Add, NewFloat(3.5).ToObject(), NewComplex(3i).ToObject(), NewComplex(3.5 + 3i).ToObject(), nil},
   103  		{Div, NewComplex(1 + 2i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(1 + 0i).ToObject(), nil},
   104  		{Div, NewComplex(3 + 4i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(2.2 - 0.4i).ToObject(), nil},
   105  		{Div, NewComplex(3.14 - 0.618i).ToObject(), NewComplex(-0.123e-4 + 0.151692i).ToObject(), NewComplex(-4.075723201992163 - 20.69950866627519i).ToObject(), nil},
   106  		{Div, NewInt(3).ToObject(), NewComplex(3 - 4i).ToObject(), NewComplex(0.36 + 0.48i).ToObject(), nil},
   107  		{Div, NewComplex(3 + 4i).ToObject(), NewInt(-5).ToObject(), NewComplex(-0.6 - 0.8i).ToObject(), nil},
   108  		{Div, NewFloat(1.2).ToObject(), NewComplex(1 - 2i).ToObject(), NewComplex(0.24 + 0.48i).ToObject(), nil},
   109  		{Div, NewComplex(1 + 2i).ToObject(), NewFloat(-3.4).ToObject(), NewComplex(-0.29411764705882354 - 0.5882352941176471i).ToObject(), nil},
   110  		{Div, NewLong(big.NewInt(123)).ToObject(), NewComplex(3 + 4i).ToObject(), NewComplex(14.76 - 19.68i).ToObject(), nil},
   111  		{Div, NewComplex(3 - 4i).ToObject(), NewLong(big.NewInt(-34)).ToObject(), NewComplex(-0.08823529411764706 + 0.11764705882352941i).ToObject(), nil},
   112  		{Div, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject(), NewComplex(0i).ToObject(), nil},
   113  		{Div, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), 2)).ToObject(), NewComplex(0i).ToObject(), nil},
   114  		{Div, NewComplex(complex(math.Inf(1), math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), math.NaN())).ToObject(), nil},
   115  		{Div, NewComplex(complex(math.Inf(1), 4)).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject(), nil},
   116  		{Div, NewComplex(complex(3, math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(1))).ToObject(), nil},
   117  		{Div, NewComplex(complex(3, math.NaN())).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   118  		{Div, NewStr("foo").ToObject(), NewComplex(1 + 2i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for /: 'str' and 'complex'")},
   119  		{Div, NewComplex(3 + 4i).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   120  		{Div, NewComplex(complex(math.Inf(1), math.NaN())).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   121  		{Div, NewComplex(3 + 4i).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to complex")},
   122  		{FloorDiv, NewComplex(1 + 2i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(1 + 0i).ToObject(), nil},
   123  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(2 - 0i).ToObject(), nil},
   124  		{FloorDiv, NewComplex(3.14 - 0.618i).ToObject(), NewComplex(-0.123e-4 + 0.151692i).ToObject(), NewComplex(-5 - 0i).ToObject(), nil},
   125  		{FloorDiv, NewInt(3).ToObject(), NewComplex(3 - 4i).ToObject(), NewComplex(0i).ToObject(), nil},
   126  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewInt(-5).ToObject(), NewComplex(-1 + 0i).ToObject(), nil},
   127  		{FloorDiv, NewFloat(1.2).ToObject(), NewComplex(1 - 2i).ToObject(), NewComplex(0i).ToObject(), nil},
   128  		{FloorDiv, NewComplex(1 + 2i).ToObject(), NewFloat(-3.4).ToObject(), NewComplex(-1 + 0i).ToObject(), nil},
   129  		{FloorDiv, NewLong(big.NewInt(123)).ToObject(), NewComplex(3 + 4i).ToObject(), NewComplex(14 - 0i).ToObject(), nil},
   130  		{FloorDiv, NewComplex(3 - 4i).ToObject(), NewLong(big.NewInt(-34)).ToObject(), NewComplex(-1 + 0i).ToObject(), nil},
   131  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject(), NewComplex(0i).ToObject(), nil},
   132  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), 2)).ToObject(), NewComplex(0i).ToObject(), nil},
   133  		{FloorDiv, NewComplex(complex(math.Inf(1), math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), 0)).ToObject(), nil},
   134  		{FloorDiv, NewComplex(complex(math.Inf(1), 4)).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), 0)).ToObject(), nil},
   135  		{FloorDiv, NewComplex(complex(3, math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(1), 0)).ToObject(), nil},
   136  		{FloorDiv, NewComplex(complex(3, math.NaN())).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), 0)).ToObject(), nil},
   137  		{FloorDiv, NewStr("foo").ToObject(), NewComplex(1 + 2i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for //: 'str' and 'complex'")},
   138  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   139  		{FloorDiv, NewComplex(complex(math.Inf(1), math.NaN())).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   140  		{FloorDiv, NewComplex(3 + 4i).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to complex")},
   141  		{Mod, NewComplex(3 + 4i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(1 + 0i).ToObject(), nil},
   142  		{Mod, NewComplex(1 + 2i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(0i).ToObject(), nil},
   143  		{Mod, NewComplex(3.14 - 0.618i).ToObject(), NewComplex(-0.123e-4 + 0.151692i).ToObject(), NewComplex(3.1399385 + 0.14045999999999992i).ToObject(), nil},
   144  		{Mod, NewInt(3).ToObject(), NewComplex(3 - 4i).ToObject(), NewComplex(3 + 0i).ToObject(), nil},
   145  		{Mod, NewComplex(3 + 4i).ToObject(), NewInt(-5).ToObject(), NewComplex(-2 + 4i).ToObject(), nil},
   146  		{Mod, NewFloat(1.2).ToObject(), NewComplex(1 - 2i).ToObject(), NewComplex(1.2 + 0i).ToObject(), nil},
   147  		{Mod, NewComplex(1 + 2i).ToObject(), NewFloat(-3.4).ToObject(), NewComplex(-2.4 + 2i).ToObject(), nil},
   148  		{Mod, NewLong(big.NewInt(123)).ToObject(), NewComplex(3 + 4i).ToObject(), NewComplex(81 - 56i).ToObject(), nil},
   149  		{Mod, NewComplex(3 - 4i).ToObject(), NewLong(big.NewInt(-34)).ToObject(), NewComplex(-31 - 4i).ToObject(), nil},
   150  		{Mod, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   151  		{Mod, NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.Inf(1), 2)).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   152  		{Mod, NewComplex(complex(math.Inf(1), math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   153  		{Mod, NewComplex(complex(math.Inf(1), 4)).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), math.Inf(-1))).ToObject(), nil},
   154  		{Mod, NewComplex(complex(3, math.Inf(1))).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.Inf(-1), math.NaN())).ToObject(), nil},
   155  		{Mod, NewComplex(complex(3, math.NaN())).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   156  		{Mod, NewStr("foo").ToObject(), NewComplex(1 + 2i).ToObject(), nil, mustCreateException(TypeErrorType, "not all arguments converted during string formatting")},
   157  		{Mod, NewComplex(3 + 4i).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   158  		{Mod, NewComplex(complex(math.Inf(1), math.NaN())).ToObject(), NewComplex(0 + 0i).ToObject(), nil, mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   159  		{Mod, NewComplex(3 + 4i).ToObject(), NewLong(bigLongNumber).ToObject(), nil, mustCreateException(OverflowErrorType, "long int too large to convert to complex")},
   160  		{Sub, NewComplex(1 + 3i).ToObject(), NewComplex(1 + 3i).ToObject(), NewComplex(0i).ToObject(), nil},
   161  		{Sub, NewComplex(1 + 3i).ToObject(), NewComplex(3i).ToObject(), NewComplex(1).ToObject(), nil},
   162  		{Sub, NewComplex(1 + 3i).ToObject(), NewFloat(1).ToObject(), NewComplex(3i).ToObject(), nil},
   163  		{Sub, NewComplex(3i).ToObject(), NewFloat(1.2).ToObject(), NewComplex(-1.2 + 3i).ToObject(), nil},
   164  		{Sub, NewComplex(1 + 3i).ToObject(), NewComplex(1 + 3i).ToObject(), NewComplex(0i).ToObject(), nil},
   165  		{Sub, NewComplex(4 + 3i).ToObject(), NewInt(1).ToObject(), NewComplex(3 + 3i).ToObject(), nil},
   166  		{Sub, NewComplex(4 + 3i).ToObject(), NewLong(big.NewInt(99994)).ToObject(), NewComplex(-99990 + 3i).ToObject(), nil},
   167  		{Sub, NewFloat(math.Inf(1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.Inf(1), -3)).ToObject(), nil},
   168  		{Sub, NewFloat(math.Inf(-1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.Inf(-1), -3)).ToObject(), nil},
   169  		{Sub, NewComplex(1 + 3i).ToObject(), None, nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for -: 'complex' and 'NoneType'")},
   170  		{Sub, None, NewComplex(1 + 3i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for -: 'NoneType' and 'complex'")},
   171  		{Sub, NewFloat(math.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.NaN(), -3)).ToObject(), nil},
   172  		{Sub, NewComplex(cmplx.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(cmplx.NaN()).ToObject(), nil},
   173  		{Sub, NewFloat(math.Inf(-1)).ToObject(), NewComplex(complex(math.Inf(-1), 3)).ToObject(), NewComplex(complex(math.NaN(), -3)).ToObject(), nil},
   174  		{Mul, NewComplex(1 + 3i).ToObject(), NewComplex(1 + 3i).ToObject(), NewComplex(-8 + 6i).ToObject(), nil},
   175  		{Mul, NewComplex(1 + 3i).ToObject(), NewComplex(3i).ToObject(), NewComplex(-9 + 3i).ToObject(), nil},
   176  		{Mul, NewComplex(1 + 3i).ToObject(), NewFloat(1).ToObject(), NewComplex(1 + 3i).ToObject(), nil},
   177  		{Mul, NewComplex(3i).ToObject(), NewFloat(1.2).ToObject(), NewComplex(3.5999999999999996i).ToObject(), nil},
   178  		{Mul, NewComplex(1 + 3i).ToObject(), NewComplex(1 + 3i).ToObject(), NewComplex(-8 + 6i).ToObject(), nil},
   179  		{Mul, NewComplex(4 + 3i).ToObject(), NewInt(1).ToObject(), NewComplex(4 + 3i).ToObject(), nil},
   180  		{Mul, NewComplex(4 + 3i).ToObject(), NewLong(big.NewInt(99994)).ToObject(), NewComplex(399976 + 299982i).ToObject(), nil},
   181  		{Mul, NewFloat(math.Inf(1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.NaN(), math.Inf(1))).ToObject(), nil},
   182  		{Mul, NewFloat(math.Inf(-1)).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.NaN(), math.Inf(-1))).ToObject(), nil},
   183  		{Mul, NewComplex(1 + 3i).ToObject(), None, nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'complex' and 'NoneType'")},
   184  		{Mul, None, NewComplex(1 + 3i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for *: 'NoneType' and 'complex'")},
   185  		{Mul, NewFloat(math.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   186  		{Mul, NewComplex(cmplx.NaN()).ToObject(), NewComplex(3i).ToObject(), NewComplex(cmplx.NaN()).ToObject(), nil},
   187  		{Mul, NewFloat(math.Inf(-1)).ToObject(), NewComplex(complex(math.Inf(-1), 3)).ToObject(), NewComplex(complex(math.Inf(1), math.NaN())).ToObject(), nil},
   188  		{Pow, NewComplex(0i).ToObject(), NewComplex(0i).ToObject(), NewComplex(1 + 0i).ToObject(), nil},
   189  		{Pow, NewComplex(-1 + 0i).ToObject(), NewComplex(1i).ToObject(), NewComplex(0.04321391826377226 + 0i).ToObject(), nil},
   190  		{Pow, NewComplex(1 + 2i).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(-0.22251715680177264 + 0.10070913113607538i).ToObject(), nil},
   191  		{Pow, NewComplex(0i).ToObject(), NewComplex(-1 + 0i).ToObject(), NewComplex(complex(math.Inf(1), 0)).ToObject(), nil},
   192  		{Pow, NewComplex(0i).ToObject(), NewComplex(-1 + 1i).ToObject(), NewComplex(complex(math.Inf(1), math.Inf(1))).ToObject(), nil},
   193  		{Pow, NewComplex(complex(math.Inf(-1), 2)).ToObject(), NewComplex(1 + 2i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   194  		{Pow, NewComplex(1 + 2i).ToObject(), NewComplex(complex(1, math.Inf(1))).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   195  		{Pow, NewComplex(complex(math.NaN(), 1)).ToObject(), NewComplex(3 + 4i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject(), nil},
   196  		{Pow, NewComplex(3 + 4i).ToObject(), NewInt(3).ToObject(), NewComplex(-117 + 44.00000000000003i).ToObject(), nil},
   197  		{Pow, NewComplex(3 + 4i).ToObject(), NewFloat(3.1415).ToObject(), NewComplex(-152.8892667678244 + 35.555335130496516i).ToObject(), nil},
   198  		{Pow, NewComplex(3 + 4i).ToObject(), NewLong(big.NewInt(123)).ToObject(), NewComplex(5.393538720276193e+85 + 7.703512580443326e+85i).ToObject(), nil},
   199  		{Pow, NewComplex(1 + 2i).ToObject(), NewStr("foo").ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'complex' and 'str'")},
   200  		{Pow, NewStr("foo").ToObject(), NewComplex(1 + 2i).ToObject(), nil, mustCreateException(TypeErrorType, "unsupported operand type(s) for **: 'str' and 'complex'")},
   201  	}
   202  
   203  	for _, cas := range cases {
   204  		switch got, result := checkInvokeResult(wrapFuncForTest(cas.fun), []*Object{cas.v, cas.w}, cas.want, cas.wantExc); result {
   205  		case checkInvokeResultExceptionMismatch:
   206  			t.Errorf("%s(%v, %v) raised %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.wantExc)
   207  		case checkInvokeResultReturnValueMismatch:
   208  			if got == nil || cas.want == nil || !got.isInstance(ComplexType) || !cas.want.isInstance(ComplexType) ||
   209  				!complexesAreSame(toComplexUnsafe(got).Value(), toComplexUnsafe(cas.want).Value()) {
   210  				t.Errorf("%s(%v, %v) = %v, want %v", getFuncName(cas.fun), cas.v, cas.w, got, cas.want)
   211  			}
   212  		}
   213  	}
   214  }
   215  
   216  func TestComplexCompareNotSupported(t *testing.T) {
   217  	cases := []invokeTestCase{
   218  		{args: wrapArgs(complex(1, 2), 1), wantExc: mustCreateException(TypeErrorType, "no ordering relation is defined for complex numbers")},
   219  		{args: wrapArgs(complex(1, 2), 1.2), wantExc: mustCreateException(TypeErrorType, "no ordering relation is defined for complex numbers")},
   220  		{args: wrapArgs(complex(1, 2), math.NaN()), wantExc: mustCreateException(TypeErrorType, "no ordering relation is defined for complex numbers")},
   221  		{args: wrapArgs(complex(1, 2), math.Inf(-1)), wantExc: mustCreateException(TypeErrorType, "no ordering relation is defined for complex numbers")},
   222  		{args: wrapArgs(complex(1, 2), "abc"), want: NotImplemented},
   223  	}
   224  	for _, cas := range cases {
   225  		if err := runInvokeTestCase(wrapFuncForTest(complexCompareNotSupported), &cas); err != "" {
   226  			t.Error(err)
   227  		}
   228  	}
   229  }
   230  
   231  func TestComplexDivMod(t *testing.T) {
   232  	cases := []invokeTestCase{
   233  		{args: wrapArgs((1 + 2i), (1 + 2i)), want: NewTuple2(NewComplex(1+0i).ToObject(), NewComplex(0i).ToObject()).ToObject()},
   234  		{args: wrapArgs((3 + 4i), (1 + 2i)), want: NewTuple2(NewComplex(2-0i).ToObject(), NewComplex(1+0i).ToObject()).ToObject()},
   235  		{args: wrapArgs((3.14 - 0.618i), (-0.123e-4 + 0.151692i)), want: NewTuple2(NewComplex(-5-0i).ToObject(), NewComplex(3.1399385+0.14045999999999992i).ToObject()).ToObject()},
   236  		{args: wrapArgs(3, (3 - 4i)), want: NewTuple2(NewComplex(0i).ToObject(), NewComplex(3+0i).ToObject()).ToObject()},
   237  		{args: wrapArgs((3 + 4i), -5), want: NewTuple2(NewComplex(-1+0i).ToObject(), NewComplex(-2+4i).ToObject()).ToObject()},
   238  		{args: wrapArgs(1.2, (1 - 2i)), want: NewTuple2(NewComplex(0i).ToObject(), NewComplex(1.2+0i).ToObject()).ToObject()},
   239  		{args: wrapArgs((1 + 2i), -3.4), want: NewTuple2(NewComplex(-1+0i).ToObject(), NewComplex(-2.4+2i).ToObject()).ToObject()},
   240  		{args: wrapArgs(big.NewInt(123), (3 + 4i)), want: NewTuple2(NewComplex(14-0i).ToObject(), NewComplex(81-56i).ToObject()).ToObject()},
   241  		{args: wrapArgs((3 - 4i), big.NewInt(-34)), want: NewTuple2(NewComplex(-1+0i).ToObject(), NewComplex(-31-4i).ToObject()).ToObject()},
   242  		{args: wrapArgs((3 + 4i), complex(math.Inf(1), math.Inf(-1))), want: NewTuple2(NewComplex(0i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject()).ToObject()},
   243  		{args: wrapArgs((3 + 4i), complex(math.Inf(1), 2)), want: NewTuple2(NewComplex(0i).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject()).ToObject()},
   244  		{args: wrapArgs(complex(math.Inf(1), math.Inf(1)), (1 + 2i)), want: NewTuple2(NewComplex(complex(math.Inf(1), 0)).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject()).ToObject()},
   245  		{args: wrapArgs(complex(math.Inf(1), 4), (1 + 2i)), want: NewTuple2(NewComplex(complex(math.Inf(1), 0)).ToObject(), NewComplex(complex(math.NaN(), math.Inf(-1))).ToObject()).ToObject()},
   246  		{args: wrapArgs(complex(3, math.Inf(1)), (1 + 2i)), want: NewTuple2(NewComplex(complex(math.Inf(1), 0)).ToObject(), NewComplex(complex(math.Inf(-1), math.NaN())).ToObject()).ToObject()},
   247  		{args: wrapArgs(complex(3, math.NaN()), (1 + 2i)), want: NewTuple2(NewComplex(complex(math.NaN(), 0)).ToObject(), NewComplex(complex(math.NaN(), math.NaN())).ToObject()).ToObject()},
   248  		{args: wrapArgs("foo", (1 + 2i)), wantExc: mustCreateException(TypeErrorType, "unsupported operand type(s) for divmod(): 'str' and 'complex'")},
   249  		{args: wrapArgs((3 + 4i), (0 + 0i)), wantExc: mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   250  		{args: wrapArgs(complex(math.Inf(1), math.NaN()), (0 + 0i)), wantExc: mustCreateException(ZeroDivisionErrorType, "complex division or modulo by zero")},
   251  		{args: wrapArgs((3 + 4i), bigLongNumber), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to complex")},
   252  	}
   253  	for _, cas := range cases {
   254  		switch got, result := checkInvokeResult(wrapFuncForTest(DivMod), cas.args, cas.want, cas.wantExc); result {
   255  		case checkInvokeResultExceptionMismatch:
   256  			t.Errorf("complex.__divmod__%v raised %v, want %v", cas.args, got, cas.wantExc)
   257  		case checkInvokeResultReturnValueMismatch:
   258  			// Handle NaN specially, since NaN != NaN.
   259  			if got == nil || cas.want == nil || !got.isInstance(TupleType) || !cas.want.isInstance(TupleType) || !tupleComplexesAreSame(got, cas.want) {
   260  				t.Errorf("complex.__divmod__%v = %v, want %v", cas.args, got, cas.want)
   261  			}
   262  		}
   263  	}
   264  }
   265  
   266  func TestComplexNE(t *testing.T) {
   267  	cases := []invokeTestCase{
   268  		{args: wrapArgs(complex(0, 0), 0), want: False.ToObject()},
   269  		{args: wrapArgs(complex(1, 0), 0), want: True.ToObject()},
   270  		{args: wrapArgs(complex(-12, 0), -12), want: False.ToObject()},
   271  		{args: wrapArgs(complex(-12, 0), 1), want: True.ToObject()},
   272  		{args: wrapArgs(complex(17.20, 0), 17.20), want: False.ToObject()},
   273  		{args: wrapArgs(complex(1.2, 0), 17.20), want: True.ToObject()},
   274  		{args: wrapArgs(complex(-4, 15), complex(-4, 15)), want: False.ToObject()},
   275  		{args: wrapArgs(complex(-4, 15), complex(1, 2)), want: True.ToObject()},
   276  		{args: wrapArgs(complex(math.Inf(1), 0), complex(math.Inf(1), 0)), want: False.ToObject()},
   277  		{args: wrapArgs(complex(math.Inf(1), 0), complex(0, math.Inf(1))), want: True.ToObject()},
   278  		{args: wrapArgs(complex(math.Inf(-1), 0), complex(math.Inf(-1), 0)), want: False.ToObject()},
   279  		{args: wrapArgs(complex(math.Inf(-1), 0), complex(0, math.Inf(-1))), want: True.ToObject()},
   280  		{args: wrapArgs(complex(math.Inf(1), math.Inf(1)), complex(math.Inf(1), math.Inf(1))), want: False.ToObject()},
   281  	}
   282  	for _, cas := range cases {
   283  		if err := runInvokeTestCase(wrapFuncForTest(complexNE), &cas); err != "" {
   284  			t.Error(err)
   285  		}
   286  	}
   287  }
   288  
   289  func TestComplexNew(t *testing.T) {
   290  	complexNew := mustNotRaise(GetAttr(NewRootFrame(), ComplexType.ToObject(), NewStr("__new__"), nil))
   291  	goodSlotType := newTestClass("GoodSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{
   292  		"__complex__": newBuiltinFunction("__complex__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   293  			return NewComplex(complex(1, 2)).ToObject(), nil
   294  		}).ToObject(),
   295  	}))
   296  	badSlotType := newTestClass("BadSlot", []*Type{ObjectType}, newStringDict(map[string]*Object{
   297  		"__complex__": newBuiltinFunction("__complex__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   298  			return newObject(ObjectType), nil
   299  		}).ToObject(),
   300  	}))
   301  	strictEqType := newTestClassStrictEq("StrictEq", ComplexType)
   302  	newStrictEq := func(v complex128) *Object {
   303  		f := Complex{Object: Object{typ: strictEqType}, value: v}
   304  		return f.ToObject()
   305  	}
   306  	subType := newTestClass("SubType", []*Type{ComplexType}, newStringDict(map[string]*Object{}))
   307  	subTypeObject := (&Complex{Object: Object{typ: subType}, value: 3.14}).ToObject()
   308  	slotSubTypeType := newTestClass("SlotSubType", []*Type{ObjectType}, newStringDict(map[string]*Object{
   309  		"__complex__": newBuiltinFunction("__complex__", func(_ *Frame, _ Args, _ KWArgs) (*Object, *BaseException) {
   310  			return subTypeObject, nil
   311  		}).ToObject(),
   312  	}))
   313  	cases := []invokeTestCase{
   314  		{args: wrapArgs(ComplexType), want: NewComplex(0).ToObject()},
   315  		{args: wrapArgs(ComplexType, 56), want: NewComplex(complex(56, 0)).ToObject()},
   316  		{args: wrapArgs(ComplexType, -12), want: NewComplex(complex(-12, 0)).ToObject()},
   317  		{args: wrapArgs(ComplexType, 3.14), want: NewComplex(complex(3.14, 0)).ToObject()},
   318  		{args: wrapArgs(ComplexType, -703.4), want: NewComplex(complex(-703.4, 0)).ToObject()},
   319  		{args: wrapArgs(ComplexType, math.NaN()), want: NewComplex(complex(math.NaN(), 0)).ToObject()},
   320  		{args: wrapArgs(ComplexType, math.Inf(1)), want: NewComplex(complex(math.Inf(1), 0)).ToObject()},
   321  		{args: wrapArgs(ComplexType, math.Inf(-1)), want: NewComplex(complex(math.Inf(-1), 0)).ToObject()},
   322  		{args: wrapArgs(ComplexType, biggestFloat), want: NewComplex(complex(math.MaxFloat64, 0)).ToObject()},
   323  		{args: wrapArgs(ComplexType, new(big.Int).Neg(biggestFloat)), want: NewComplex(complex(-math.MaxFloat64, 0)).ToObject()},
   324  		{args: wrapArgs(ComplexType, new(big.Int).Sub(big.NewInt(-1), biggestFloat)), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")},
   325  		{args: wrapArgs(ComplexType, new(big.Int).Add(biggestFloat, big.NewInt(1))), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")},
   326  		{args: wrapArgs(ComplexType, bigLongNumber), wantExc: mustCreateException(OverflowErrorType, "long int too large to convert to float")},
   327  		{args: wrapArgs(ComplexType, complex(1, 2)), want: NewComplex(complex(1, 2)).ToObject()},
   328  		{args: wrapArgs(ComplexType, complex(-0.0001e-1, 3.14151692)), want: NewComplex(complex(-0.00001, 3.14151692)).ToObject()},
   329  		{args: wrapArgs(ComplexType, "23"), want: NewComplex(complex(23, 0)).ToObject()},
   330  		{args: wrapArgs(ComplexType, "-516"), want: NewComplex(complex(-516, 0)).ToObject()},
   331  		{args: wrapArgs(ComplexType, "1.003e4"), want: NewComplex(complex(10030, 0)).ToObject()},
   332  		{args: wrapArgs(ComplexType, "151.7"), want: NewComplex(complex(151.7, 0)).ToObject()},
   333  		{args: wrapArgs(ComplexType, "-74.02"), want: NewComplex(complex(-74.02, 0)).ToObject()},
   334  		{args: wrapArgs(ComplexType, "+38.29"), want: NewComplex(complex(38.29, 0)).ToObject()},
   335  		{args: wrapArgs(ComplexType, "8j"), want: NewComplex(complex(0, 8)).ToObject()},
   336  		{args: wrapArgs(ComplexType, "-17j"), want: NewComplex(complex(0, -17)).ToObject()},
   337  		{args: wrapArgs(ComplexType, "7.3j"), want: NewComplex(complex(0, 7.3)).ToObject()},
   338  		{args: wrapArgs(ComplexType, "-4.786j"), want: NewComplex(complex(0, -4.786)).ToObject()},
   339  		{args: wrapArgs(ComplexType, "+17.59123j"), want: NewComplex(complex(0, 17.59123)).ToObject()},
   340  		{args: wrapArgs(ComplexType, "-3.0007e3j"), want: NewComplex(complex(0, -3000.7)).ToObject()},
   341  		{args: wrapArgs(ComplexType, "1+2j"), want: NewComplex(complex(1, 2)).ToObject()},
   342  		{args: wrapArgs(ComplexType, "3.1415-23j"), want: NewComplex(complex(3.1415, -23)).ToObject()},
   343  		{args: wrapArgs(ComplexType, "-23+3.1415j"), want: NewComplex(complex(-23, 3.1415)).ToObject()},
   344  		{args: wrapArgs(ComplexType, "+451.2192+384.27j"), want: NewComplex(complex(451.2192, 384.27)).ToObject()},
   345  		{args: wrapArgs(ComplexType, "-38.378-283.28j"), want: NewComplex(complex(-38.378, -283.28)).ToObject()},
   346  		{args: wrapArgs(ComplexType, "1.76123e2+0.000007e6j"), want: NewComplex(complex(176.123, 7)).ToObject()},
   347  		{args: wrapArgs(ComplexType, "-nan+nanj"), want: NewComplex(complex(math.NaN(), math.NaN())).ToObject()},
   348  		{args: wrapArgs(ComplexType, "inf-infj"), want: NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject()},
   349  		{args: wrapArgs(ComplexType, 1, 2), want: NewComplex(complex(1, 2)).ToObject()},
   350  		{args: wrapArgs(ComplexType, 7, 23.45), want: NewComplex(complex(7, 23.45)).ToObject()},
   351  		{args: wrapArgs(ComplexType, 28.2537, -19), want: NewComplex(complex(28.2537, -19)).ToObject()},
   352  		{args: wrapArgs(ComplexType, -3.14, -0.685), want: NewComplex(complex(-3.14, -0.685)).ToObject()},
   353  		{args: wrapArgs(ComplexType, -47.234e+2, 2.374e+3), want: NewComplex(complex(-4723.4, 2374)).ToObject()},
   354  		{args: wrapArgs(ComplexType, -4.5, new(big.Int).Neg(biggestFloat)), want: NewComplex(complex(-4.5, -math.MaxFloat64)).ToObject()},
   355  		{args: wrapArgs(ComplexType, biggestFloat, biggestFloat), want: NewComplex(complex(math.MaxFloat64, math.MaxFloat64)).ToObject()},
   356  		{args: wrapArgs(ComplexType, 5, math.NaN()), want: NewComplex(complex(5, math.NaN())).ToObject()},
   357  		{args: wrapArgs(ComplexType, math.Inf(-1), -95), want: NewComplex(complex(math.Inf(-1), -95)).ToObject()},
   358  		{args: wrapArgs(ComplexType, math.NaN(), math.NaN()), want: NewComplex(complex(math.NaN(), math.NaN())).ToObject()},
   359  		{args: wrapArgs(ComplexType, math.Inf(1), math.Inf(-1)), want: NewComplex(complex(math.Inf(1), math.Inf(-1))).ToObject()},
   360  		{args: wrapArgs(ComplexType, complex(-48.8, 0.7395), 5.448), want: NewComplex(complex(-48.8, 6.1875)).ToObject()},
   361  		{args: wrapArgs(ComplexType, -3.14, complex(-4.5, -0.618)), want: NewComplex(complex(-2.5220000000000002, -4.5)).ToObject()},
   362  		{args: wrapArgs(ComplexType, complex(1, 2), complex(3, 4)), want: NewComplex(complex(-3, 5)).ToObject()},
   363  		{args: wrapArgs(ComplexType, complex(-2.47, 0.205e+2), complex(3.1, -0.4)), want: NewComplex(complex(-2.0700000000000003, 23.6)).ToObject()},
   364  		{args: wrapArgs(ComplexType, "bar", 1.2), wantExc: mustCreateException(TypeErrorType, "complex() can't take second arg if first is a string")},
   365  		{args: wrapArgs(ComplexType, "bar", None), wantExc: mustCreateException(TypeErrorType, "complex() can't take second arg if first is a string")},
   366  		{args: wrapArgs(ComplexType, 1.2, "baz"), wantExc: mustCreateException(TypeErrorType, "complex() second arg can't be a string")},
   367  		{args: wrapArgs(ComplexType, None, "baz"), wantExc: mustCreateException(TypeErrorType, "complex() second arg can't be a string")},
   368  		{args: wrapArgs(ComplexType, newObject(goodSlotType)), want: NewComplex(complex(1, 2)).ToObject()},
   369  		{args: wrapArgs(ComplexType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__complex__ returned non-complex (type object)")},
   370  		{args: wrapArgs(ComplexType, newObject(slotSubTypeType)), want: subTypeObject},
   371  		{args: wrapArgs(strictEqType, 3.14), want: newStrictEq(3.14)},
   372  		{args: wrapArgs(strictEqType, newObject(goodSlotType)), want: newStrictEq(complex(1, 2))},
   373  		{args: wrapArgs(strictEqType, newObject(badSlotType)), wantExc: mustCreateException(TypeErrorType, "__complex__ returned non-complex (type object)")},
   374  		{args: wrapArgs(), wantExc: mustCreateException(TypeErrorType, "'__new__' requires 1 arguments")},
   375  		{args: wrapArgs(FloatType), wantExc: mustCreateException(TypeErrorType, "complex.__new__(float): float is not a subtype of complex")},
   376  		{args: wrapArgs(ComplexType, None), wantExc: mustCreateException(TypeErrorType, "complex() argument must be a string or a number")},
   377  		{args: wrapArgs(ComplexType, "foo"), wantExc: mustCreateException(ValueErrorType, "complex() arg is a malformed string")},
   378  		{args: wrapArgs(ComplexType, 123, None, None), wantExc: mustCreateException(TypeErrorType, "'__new__' of 'complex' requires at most 2 arguments")},
   379  	}
   380  	for _, cas := range cases {
   381  		switch got, match := checkInvokeResult(complexNew, cas.args, cas.want, cas.wantExc); match {
   382  		case checkInvokeResultExceptionMismatch:
   383  			t.Errorf("complex.__new__%v raised %v, want %v", cas.args, got, cas.wantExc)
   384  		case checkInvokeResultReturnValueMismatch:
   385  			// Handle NaN specially, since NaN != NaN.
   386  			if got == nil || cas.want == nil || !got.isInstance(ComplexType) || !cas.want.isInstance(ComplexType) ||
   387  				!cmplx.IsNaN(toComplexUnsafe(got).Value()) || !cmplx.IsNaN(toComplexUnsafe(cas.want).Value()) {
   388  				t.Errorf("complex.__new__%v = %v, want %v", cas.args, got, cas.want)
   389  			}
   390  		}
   391  	}
   392  }
   393  
   394  func TestComplexNonZero(t *testing.T) {
   395  	cases := []invokeTestCase{
   396  		{args: wrapArgs(complex(0, 0)), want: False.ToObject()},
   397  		{args: wrapArgs(complex(.0, .0)), want: False.ToObject()},
   398  		{args: wrapArgs(complex(0.0, 0.1)), want: True.ToObject()},
   399  		{args: wrapArgs(complex(1, 0)), want: True.ToObject()},
   400  		{args: wrapArgs(complex(3.14, -0.001e+5)), want: True.ToObject()},
   401  		{args: wrapArgs(complex(math.NaN(), math.NaN())), want: True.ToObject()},
   402  		{args: wrapArgs(complex(math.Inf(-1), math.Inf(1))), want: True.ToObject()},
   403  	}
   404  	for _, cas := range cases {
   405  		if err := runInvokeTestCase(wrapFuncForTest(complexNonZero), &cas); err != "" {
   406  			t.Error(err)
   407  		}
   408  	}
   409  }
   410  
   411  func TestComplexPos(t *testing.T) {
   412  	cases := []invokeTestCase{
   413  		{args: wrapArgs(complex(0, 0)), want: NewComplex(complex(0, 0)).ToObject()},
   414  		{args: wrapArgs(complex(42, -0.1)), want: NewComplex(complex(42, -0.1)).ToObject()},
   415  		{args: wrapArgs(complex(-1.2, 375E+2)), want: NewComplex(complex(-1.2, 37500)).ToObject()},
   416  		{args: wrapArgs(complex(5, math.NaN())), want: NewComplex(complex(5, math.NaN())).ToObject()},
   417  		{args: wrapArgs(complex(math.Inf(1), 0.618)), want: NewComplex(complex(math.Inf(1), 0.618)).ToObject()},
   418  	}
   419  	for _, cas := range cases {
   420  		switch got, match := checkInvokeResult(wrapFuncForTest(complexPos), cas.args, cas.want, cas.wantExc); match {
   421  		case checkInvokeResultReturnValueMismatch:
   422  			if got == nil || cas.want == nil || !got.isInstance(ComplexType) || !cas.want.isInstance(ComplexType) ||
   423  				!complexesAreSame(toComplexUnsafe(got).Value(), toComplexUnsafe(cas.want).Value()) {
   424  				t.Errorf("complex.__pos__%v = %v, want %v", cas.args, got, cas.want)
   425  			}
   426  		}
   427  	}
   428  }
   429  
   430  func TestComplexRepr(t *testing.T) {
   431  	cases := []invokeTestCase{
   432  		{args: wrapArgs(complex(0.0, 0.0)), want: NewStr("0j").ToObject()},
   433  		{args: wrapArgs(complex(0.0, 1.0)), want: NewStr("1j").ToObject()},
   434  		{args: wrapArgs(complex(1.0, 2.0)), want: NewStr("(1+2j)").ToObject()},
   435  		{args: wrapArgs(complex(3.1, -4.2)), want: NewStr("(3.1-4.2j)").ToObject()},
   436  		{args: wrapArgs(complex(math.NaN(), math.NaN())), want: NewStr("(nan+nanj)").ToObject()},
   437  		{args: wrapArgs(complex(math.Inf(-1), math.Inf(1))), want: NewStr("(-inf+infj)").ToObject()},
   438  		{args: wrapArgs(complex(math.Inf(1), math.Inf(-1))), want: NewStr("(inf-infj)").ToObject()},
   439  	}
   440  	for _, cas := range cases {
   441  		if err := runInvokeTestCase(wrapFuncForTest(Repr), &cas); err != "" {
   442  			t.Error(err)
   443  		}
   444  	}
   445  }
   446  
   447  func TestParseComplex(t *testing.T) {
   448  	var ErrSyntax = errors.New("invalid syntax")
   449  	cases := []struct {
   450  		s    string
   451  		want complex128
   452  		err  error
   453  	}{
   454  		{"5", complex(5, 0), nil},
   455  		{"-3.14", complex(-3.14, 0), nil},
   456  		{"1.8456e3", complex(1845.6, 0), nil},
   457  		{"23j", complex(0, 23), nil},
   458  		{"7j", complex(0, 7), nil},
   459  		{"-365.12j", complex(0, -365.12), nil},
   460  		{"1+2j", complex(1, 2), nil},
   461  		{"-.3+.7j", complex(-0.3, 0.7), nil},
   462  		{"-1.3+2.7j", complex(-1.3, 2.7), nil},
   463  		{"48.39-20.3j", complex(48.39, -20.3), nil},
   464  		{"-1.23e2-30.303j", complex(-123, -30.303), nil},
   465  		{"-1.23e2-45.678e1j", complex(-123, -456.78), nil},
   466  		{"nan+nanj", complex(math.NaN(), math.NaN()), nil},
   467  		{"nan-nanj", complex(math.NaN(), math.NaN()), nil},
   468  		{"-nan-nanj", complex(math.NaN(), math.NaN()), nil},
   469  		{"inf+infj", complex(math.Inf(1), math.Inf(1)), nil},
   470  		{"inf-infj", complex(math.Inf(1), math.Inf(-1)), nil},
   471  		{"-inf-infj", complex(math.Inf(-1), math.Inf(-1)), nil},
   472  		{"infINIty+infinityj", complex(math.Inf(1), math.Inf(1)), nil},
   473  		{"3.4+j", complex(3.4, 1), nil},
   474  		{"21.98-j", complex(21.98, -1), nil},
   475  		{"+j", complex(0, 1), nil},
   476  		{"-j", complex(0, -1), nil},
   477  		{"j", complex(0, 1), nil},
   478  		{"(2.1-3.4j)", complex(2.1, -3.4), nil},
   479  		{"   (2.1-3.4j)    ", complex(2.1, -3.4), nil},
   480  		{"   (   2.1-3.4j    )     ", complex(2.1, -3.4), nil},
   481  		{" \t \n \r ( \t \n \r 2.1-3.4j \t \n \r ) \t \n \r ", complex(2.1, -3.4), nil},
   482  		{"     3.14-15.16j   ", complex(3.14, -15.16), nil},
   483  		{"(2.1-3.4j", complex(0, 0), ErrSyntax},
   484  		{"((2.1-3.4j))", complex(0, 0), ErrSyntax},
   485  		{"3.14 -15.16j", complex(0, 0), ErrSyntax},
   486  		{"3.14- 15.16j", complex(0, 0), ErrSyntax},
   487  		{"3.14-15.16 j", complex(0, 0), ErrSyntax},
   488  		{"3.14 - 15.16 j", complex(0, 0), ErrSyntax},
   489  		{"foo", complex(0, 0), ErrSyntax},
   490  		{"foo+bar", complex(0, 0), ErrSyntax},
   491  	}
   492  	for _, cas := range cases {
   493  		if got, _ := parseComplex(cas.s); !complexesAreSame(got, cas.want) {
   494  			t.Errorf("parseComplex(%q) = %g, want %g", cas.s, got, cas.want)
   495  		}
   496  	}
   497  }
   498  
   499  func TestComplexHash(t *testing.T) {
   500  	cases := []invokeTestCase{
   501  		{args: wrapArgs(complex(0.0, 0.0)), want: NewInt(0).ToObject()},
   502  		{args: wrapArgs(complex(0.0, 1.0)), want: NewInt(1000003).ToObject()},
   503  		{args: wrapArgs(complex(1.0, 0.0)), want: NewInt(1).ToObject()},
   504  		{args: wrapArgs(complex(3.1, -4.2)), want: NewInt(-1556830019620134).ToObject()},
   505  		{args: wrapArgs(complex(3.1, 4.2)), want: NewInt(1557030815934348).ToObject()},
   506  	}
   507  	for _, cas := range cases {
   508  		if err := runInvokeTestCase(wrapFuncForTest(complexHash), &cas); err != "" {
   509  			t.Error(err)
   510  		}
   511  	}
   512  }
   513  
   514  func floatsAreSame(a, b float64) bool {
   515  	return a == b || (math.IsNaN(a) && math.IsNaN(b))
   516  }
   517  
   518  func complexesAreSame(a, b complex128) bool {
   519  	return floatsAreSame(real(a), real(b)) && floatsAreSame(imag(a), imag(b))
   520  }
   521  
   522  func tupleComplexesAreSame(got, want *Object) bool {
   523  	if toTupleUnsafe(got).Len() != toTupleUnsafe(want).Len() {
   524  		return false
   525  	}
   526  	for i := 0; i < toTupleUnsafe(got).Len(); i++ {
   527  		if !complexesAreSame(toComplexUnsafe(toTupleUnsafe(got).GetItem(i)).Value(), toComplexUnsafe(toTupleUnsafe(want).GetItem(i)).Value()) {
   528  			return false
   529  		}
   530  	}
   531  	return true
   532  }