github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/runtime/int.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  	"fmt"
    19  	"math"
    20  	"math/big"
    21  	"reflect"
    22  	"strconv"
    23  )
    24  
    25  const (
    26  	internedIntMin = -2
    27  	internedIntMax = 300
    28  )
    29  
    30  var (
    31  	internedInts = makeInternedInts()
    32  )
    33  
    34  // Int represents Python 'int' objects.
    35  type Int struct {
    36  	Object
    37  	value int
    38  }
    39  
    40  // NewInt returns a new Int holding the given integer value.
    41  func NewInt(value int) *Int {
    42  	if value >= internedIntMin && value <= internedIntMax {
    43  		return &internedInts[value-internedIntMin]
    44  	}
    45  	return &Int{Object{typ: IntType}, value}
    46  }
    47  
    48  func toIntUnsafe(o *Object) *Int {
    49  	return (*Int)(o.toPointer())
    50  }
    51  
    52  // ToObject upcasts i to an Object.
    53  func (i *Int) ToObject() *Object {
    54  	return &i.Object
    55  }
    56  
    57  // Value returns the underlying integer value held by i.
    58  func (i *Int) Value() int {
    59  	return i.value
    60  }
    61  
    62  // IsTrue returns false if i is zero, true otherwise.
    63  func (i *Int) IsTrue() bool {
    64  	return i.Value() != 0
    65  }
    66  
    67  // IntType is the object representing the Python 'int' type.
    68  var IntType = newBasisType("int", reflect.TypeOf(Int{}), toIntUnsafe, ObjectType)
    69  
    70  func intAbs(f *Frame, o *Object) (*Object, *BaseException) {
    71  	z := toIntUnsafe(o)
    72  	if z.Value() > 0 {
    73  		return z.ToObject(), nil
    74  	}
    75  	return intNeg(f, o)
    76  }
    77  
    78  func intAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
    79  	return intAddMulOp(f, "__add__", v, w, intCheckedAdd, longAdd)
    80  }
    81  
    82  func intAnd(f *Frame, v, w *Object) (*Object, *BaseException) {
    83  	if !w.isInstance(IntType) {
    84  		return NotImplemented, nil
    85  	}
    86  	return NewInt(toIntUnsafe(v).Value() & toIntUnsafe(w).Value()).ToObject(), nil
    87  }
    88  
    89  func intDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
    90  	return intDivModOp(f, "__div__", v, w, intCheckedDiv, longDiv)
    91  }
    92  
    93  func intDivMod(f *Frame, v, w *Object) (*Object, *BaseException) {
    94  	return intDivAndModOp(f, "__divmod__", v, w, intCheckedDivMod, longDivAndMod)
    95  }
    96  
    97  func intEq(f *Frame, v, w *Object) (*Object, *BaseException) {
    98  	return intCompare(compareOpEq, toIntUnsafe(v), w), nil
    99  }
   100  
   101  func intGE(f *Frame, v, w *Object) (*Object, *BaseException) {
   102  	return intCompare(compareOpGE, toIntUnsafe(v), w), nil
   103  }
   104  
   105  func intGetNewArgs(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   106  	if raised := checkMethodArgs(f, "__getnewargs__", args, IntType); raised != nil {
   107  		return nil, raised
   108  	}
   109  	return NewTuple1(args[0]).ToObject(), nil
   110  }
   111  
   112  func intGT(f *Frame, v, w *Object) (*Object, *BaseException) {
   113  	return intCompare(compareOpGT, toIntUnsafe(v), w), nil
   114  }
   115  
   116  func intFloat(f *Frame, o *Object) (*Object, *BaseException) {
   117  	i := toIntUnsafe(o).Value()
   118  	return NewFloat(float64(i)).ToObject(), nil
   119  }
   120  
   121  func intHash(f *Frame, o *Object) (*Object, *BaseException) {
   122  	return o, nil
   123  }
   124  
   125  func intHex(f *Frame, o *Object) (*Object, *BaseException) {
   126  	val := numberToBase("0x", 16, o)
   127  	return NewStr(val).ToObject(), nil
   128  }
   129  
   130  func intIndex(f *Frame, o *Object) (*Object, *BaseException) {
   131  	return o, nil
   132  }
   133  
   134  func intInt(f *Frame, o *Object) (*Object, *BaseException) {
   135  	if o.typ == IntType {
   136  		return o, nil
   137  	}
   138  	return NewInt(toIntUnsafe(o).Value()).ToObject(), nil
   139  }
   140  
   141  func intInvert(f *Frame, o *Object) (*Object, *BaseException) {
   142  	return NewInt(^toIntUnsafe(o).Value()).ToObject(), nil
   143  }
   144  
   145  func intLE(f *Frame, v, w *Object) (*Object, *BaseException) {
   146  	return intCompare(compareOpLE, toIntUnsafe(v), w), nil
   147  }
   148  
   149  func intLong(f *Frame, o *Object) (*Object, *BaseException) {
   150  	return NewLong(big.NewInt(int64(toIntUnsafe(o).Value()))).ToObject(), nil
   151  }
   152  
   153  func intLShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   154  	return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return v, w, false })
   155  }
   156  
   157  func intLT(f *Frame, v, w *Object) (*Object, *BaseException) {
   158  	return intCompare(compareOpLT, toIntUnsafe(v), w), nil
   159  }
   160  
   161  func intMod(f *Frame, v, w *Object) (*Object, *BaseException) {
   162  	return intDivModOp(f, "__mod__", v, w, intCheckedMod, longMod)
   163  }
   164  
   165  func intMul(f *Frame, v, w *Object) (*Object, *BaseException) {
   166  	return intAddMulOp(f, "__mul__", v, w, intCheckedMul, longMul)
   167  }
   168  
   169  func intNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
   170  	return reflect.ValueOf(toIntUnsafe(o).Value()), nil
   171  }
   172  
   173  func intNE(f *Frame, v, w *Object) (*Object, *BaseException) {
   174  	return intCompare(compareOpNE, toIntUnsafe(v), w), nil
   175  }
   176  
   177  func intNeg(f *Frame, o *Object) (*Object, *BaseException) {
   178  	z := toIntUnsafe(o)
   179  	if z.Value() == MinInt {
   180  		nz := big.NewInt(int64(z.Value()))
   181  		return NewLong(nz.Neg(nz)).ToObject(), nil
   182  	}
   183  	return NewInt(-z.Value()).ToObject(), nil
   184  }
   185  
   186  func intNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
   187  	if len(args) == 0 {
   188  		return newObject(t), nil
   189  	}
   190  	o := args[0]
   191  	if len(args) == 1 && o.typ.slots.Int != nil {
   192  		i, raised := ToInt(f, o)
   193  		if raised != nil {
   194  			return nil, raised
   195  		}
   196  		if t == IntType {
   197  			return i, nil
   198  		}
   199  		n := 0
   200  		if i.isInstance(LongType) {
   201  			n, raised = toLongUnsafe(i).IntValue(f)
   202  			if raised != nil {
   203  				return nil, raised
   204  			}
   205  		} else {
   206  			n = toIntUnsafe(i).Value()
   207  		}
   208  		ret := newObject(t)
   209  		toIntUnsafe(ret).value = n
   210  		return ret, nil
   211  	}
   212  	if len(args) > 2 {
   213  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("int() takes at most 2 arguments (%d given)", len(args)))
   214  	}
   215  	if !o.isInstance(StrType) {
   216  		if len(args) == 2 {
   217  			return nil, f.RaiseType(TypeErrorType, "int() can't convert non-string with explicit base")
   218  		}
   219  		return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("int() argument must be a string or a number, not '%s'", o.typ.Name()))
   220  	}
   221  	s := toStrUnsafe(o).Value()
   222  	base := 10
   223  	if len(args) == 2 {
   224  		var raised *BaseException
   225  		base, raised = ToIntValue(f, args[1])
   226  		if raised != nil {
   227  			return nil, raised
   228  		}
   229  		if base < 0 || base == 1 || base > 36 {
   230  			return nil, f.RaiseType(ValueErrorType, "int() base must be >= 2 and <= 36")
   231  		}
   232  	}
   233  	i, ok := numParseInteger(new(big.Int), s, base)
   234  	if !ok {
   235  		format := "invalid literal for int() with base %d: %s"
   236  		return nil, f.RaiseType(ValueErrorType, fmt.Sprintf(format, base, s))
   237  	}
   238  	if !numInIntRange(i) {
   239  		if t == IntType {
   240  			return NewLong(i).ToObject(), nil
   241  		}
   242  		return nil, f.RaiseType(OverflowErrorType, "Python int too large to convert to a Go int")
   243  	}
   244  	if t != IntType {
   245  		o := newObject(t)
   246  		toIntUnsafe(o).value = int(i.Int64())
   247  		return o, nil
   248  	}
   249  	return NewInt(int(i.Int64())).ToObject(), nil
   250  }
   251  
   252  func intNonZero(f *Frame, o *Object) (*Object, *BaseException) {
   253  	return GetBool(toIntUnsafe(o).Value() != 0).ToObject(), nil
   254  }
   255  
   256  func intOct(f *Frame, o *Object) (*Object, *BaseException) {
   257  	val := numberToBase("0", 8, o)
   258  	if val == "00" {
   259  		val = "0"
   260  	}
   261  	return NewStr(val).ToObject(), nil
   262  }
   263  
   264  func intOr(f *Frame, v, w *Object) (*Object, *BaseException) {
   265  	if !w.isInstance(IntType) {
   266  		return NotImplemented, nil
   267  	}
   268  	return NewInt(toIntUnsafe(v).Value() | toIntUnsafe(w).Value()).ToObject(), nil
   269  }
   270  
   271  func intPos(f *Frame, o *Object) (*Object, *BaseException) {
   272  	return o, nil
   273  }
   274  
   275  func intPow(f *Frame, v, w *Object) (*Object, *BaseException) {
   276  	if w.isInstance(IntType) {
   277  		// First try to use the faster floating point arithmetic
   278  		// on the CPU, then falls back to slower methods.
   279  		// IEEE float64 has 52bit of precision, so the result should be
   280  		// less than MaxInt32 to be representable as an exact integer.
   281  		// This assumes that int is at least 32bit.
   282  		vInt := toIntUnsafe(v).Value()
   283  		wInt := toIntUnsafe(w).Value()
   284  		if 0 < vInt && vInt <= math.MaxInt32 && 0 < wInt && wInt <= math.MaxInt32 {
   285  			res := math.Pow(float64(vInt), float64(wInt))
   286  			// Can the result be interpreted as an int?
   287  			if !math.IsNaN(res) && !math.IsInf(res, 0) && res <= math.MaxInt32 {
   288  				return NewInt(int(res)).ToObject(), nil
   289  			}
   290  		}
   291  		// Special cases.
   292  		if vInt == 0 {
   293  			if wInt < 0 {
   294  				return nil, f.RaiseType(ZeroDivisionErrorType, "0.0 cannot be raised to a negative power")
   295  			}
   296  			if wInt == 0 {
   297  				return NewInt(1).ToObject(), nil
   298  			}
   299  			return NewInt(0).ToObject(), nil
   300  		}
   301  		// If w < 0, the result must be a floating point number.
   302  		// We convert both arguments to float and continue.
   303  		if wInt < 0 {
   304  			return floatPow(f, NewFloat(float64(vInt)).ToObject(), NewFloat(float64(wInt)).ToObject())
   305  		}
   306  		// Else we convert to Long and continue there.
   307  		return longPow(f, NewLong(big.NewInt(int64(vInt))).ToObject(), NewLong(big.NewInt(int64(wInt))).ToObject())
   308  	}
   309  	return NotImplemented, nil
   310  }
   311  
   312  func intRAdd(f *Frame, v, w *Object) (*Object, *BaseException) {
   313  	return intAddMulOp(f, "__radd__", v, w, intCheckedAdd, longAdd)
   314  }
   315  
   316  func intRDiv(f *Frame, v, w *Object) (*Object, *BaseException) {
   317  	return intDivModOp(f, "__rdiv__", v, w, func(v, w int) (int, divModResult) {
   318  		return intCheckedDiv(w, v)
   319  	}, func(z, x, y *big.Int) {
   320  		longDiv(z, y, x)
   321  	})
   322  }
   323  
   324  func intRDivMod(f *Frame, v, w *Object) (*Object, *BaseException) {
   325  	return intDivAndModOp(f, "__rdivmod__", v, w, func(v, w int) (int, int, divModResult) {
   326  		return intCheckedDivMod(w, v)
   327  	}, func(z, m, x, y *big.Int) {
   328  		longDivAndMod(z, m, y, x)
   329  	})
   330  }
   331  
   332  func intRepr(f *Frame, o *Object) (*Object, *BaseException) {
   333  	return NewStr(strconv.FormatInt(int64(toIntUnsafe(o).Value()), 10)).ToObject(), nil
   334  }
   335  
   336  func intRMod(f *Frame, v, w *Object) (*Object, *BaseException) {
   337  	return intDivModOp(f, "__rmod__", v, w, func(v, w int) (int, divModResult) {
   338  		return intCheckedMod(w, v)
   339  	}, func(z, x, y *big.Int) {
   340  		longMod(z, y, x)
   341  	})
   342  }
   343  
   344  func intRMul(f *Frame, v, w *Object) (*Object, *BaseException) {
   345  	return intAddMulOp(f, "__rmul__", v, w, intCheckedMul, longMul)
   346  }
   347  
   348  func intRLShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   349  	return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return w, v, false })
   350  }
   351  
   352  func intRRShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   353  	return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return w, v, true })
   354  }
   355  
   356  func intRShift(f *Frame, v, w *Object) (*Object, *BaseException) {
   357  	return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return v, w, true })
   358  }
   359  
   360  func intRSub(f *Frame, v, w *Object) (*Object, *BaseException) {
   361  	return intAddMulOp(f, "__rsub__", v, w, func(v, w int) (int, bool) {
   362  		return intCheckedSub(w, v)
   363  	}, func(z, x, y *big.Int) {
   364  		longSub(z, y, x)
   365  	})
   366  }
   367  
   368  func intSub(f *Frame, v, w *Object) (*Object, *BaseException) {
   369  	return intAddMulOp(f, "__sub__", v, w, intCheckedSub, longSub)
   370  }
   371  
   372  func intXor(f *Frame, v, w *Object) (*Object, *BaseException) {
   373  	if !w.isInstance(IntType) {
   374  		return NotImplemented, nil
   375  	}
   376  	return NewInt(toIntUnsafe(v).Value() ^ toIntUnsafe(w).Value()).ToObject(), nil
   377  }
   378  
   379  func initIntType(dict map[string]*Object) {
   380  	dict["__getnewargs__"] = newBuiltinFunction("__getnewargs__", intGetNewArgs).ToObject()
   381  	IntType.slots.Abs = &unaryOpSlot{intAbs}
   382  	IntType.slots.Add = &binaryOpSlot{intAdd}
   383  	IntType.slots.And = &binaryOpSlot{intAnd}
   384  	IntType.slots.Div = &binaryOpSlot{intDiv}
   385  	IntType.slots.DivMod = &binaryOpSlot{intDivMod}
   386  	IntType.slots.Eq = &binaryOpSlot{intEq}
   387  	IntType.slots.FloorDiv = &binaryOpSlot{intDiv}
   388  	IntType.slots.GE = &binaryOpSlot{intGE}
   389  	IntType.slots.GT = &binaryOpSlot{intGT}
   390  	IntType.slots.Float = &unaryOpSlot{intFloat}
   391  	IntType.slots.Hash = &unaryOpSlot{intHash}
   392  	IntType.slots.Hex = &unaryOpSlot{intHex}
   393  	IntType.slots.Index = &unaryOpSlot{intIndex}
   394  	IntType.slots.Int = &unaryOpSlot{intInt}
   395  	IntType.slots.Invert = &unaryOpSlot{intInvert}
   396  	IntType.slots.LE = &binaryOpSlot{intLE}
   397  	IntType.slots.LShift = &binaryOpSlot{intLShift}
   398  	IntType.slots.LT = &binaryOpSlot{intLT}
   399  	IntType.slots.Long = &unaryOpSlot{intLong}
   400  	IntType.slots.Mod = &binaryOpSlot{intMod}
   401  	IntType.slots.Mul = &binaryOpSlot{intMul}
   402  	IntType.slots.Native = &nativeSlot{intNative}
   403  	IntType.slots.NE = &binaryOpSlot{intNE}
   404  	IntType.slots.Neg = &unaryOpSlot{intNeg}
   405  	IntType.slots.New = &newSlot{intNew}
   406  	IntType.slots.NonZero = &unaryOpSlot{intNonZero}
   407  	IntType.slots.Oct = &unaryOpSlot{intOct}
   408  	IntType.slots.Or = &binaryOpSlot{intOr}
   409  	IntType.slots.Pos = &unaryOpSlot{intPos}
   410  	IntType.slots.Pow = &binaryOpSlot{intPow}
   411  	IntType.slots.RAdd = &binaryOpSlot{intRAdd}
   412  	IntType.slots.RAnd = &binaryOpSlot{intAnd}
   413  	IntType.slots.RDiv = &binaryOpSlot{intRDiv}
   414  	IntType.slots.RDivMod = &binaryOpSlot{intRDivMod}
   415  	IntType.slots.Repr = &unaryOpSlot{intRepr}
   416  	IntType.slots.RFloorDiv = &binaryOpSlot{intRDiv}
   417  	IntType.slots.RMod = &binaryOpSlot{intRMod}
   418  	IntType.slots.RMul = &binaryOpSlot{intRMul}
   419  	IntType.slots.ROr = &binaryOpSlot{intOr}
   420  	IntType.slots.RLShift = &binaryOpSlot{intRLShift}
   421  	IntType.slots.RRShift = &binaryOpSlot{intRRShift}
   422  	IntType.slots.RShift = &binaryOpSlot{intRShift}
   423  	IntType.slots.RSub = &binaryOpSlot{intRSub}
   424  	IntType.slots.RXor = &binaryOpSlot{intXor}
   425  	IntType.slots.Sub = &binaryOpSlot{intSub}
   426  	IntType.slots.Xor = &binaryOpSlot{intXor}
   427  }
   428  
   429  type divModResult int
   430  
   431  const (
   432  	divModOK           divModResult = iota
   433  	divModOverflow                  = iota
   434  	divModZeroDivision              = iota
   435  )
   436  
   437  func intCompare(op compareOp, v *Int, w *Object) *Object {
   438  	if !w.isInstance(IntType) {
   439  		return NotImplemented
   440  	}
   441  	lhs, rhs := v.Value(), toIntUnsafe(w).Value()
   442  	result := false
   443  	switch op {
   444  	case compareOpLT:
   445  		result = lhs < rhs
   446  	case compareOpLE:
   447  		result = lhs <= rhs
   448  	case compareOpEq:
   449  		result = lhs == rhs
   450  	case compareOpNE:
   451  		result = lhs != rhs
   452  	case compareOpGE:
   453  		result = lhs >= rhs
   454  	case compareOpGT:
   455  		result = lhs > rhs
   456  	}
   457  	return GetBool(result).ToObject()
   458  }
   459  
   460  func intAddMulOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, bool), bigFun func(z, x, y *big.Int)) (*Object, *BaseException) {
   461  	if !w.isInstance(IntType) {
   462  		return NotImplemented, nil
   463  	}
   464  	r, ok := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value())
   465  	if !ok {
   466  		return longCallBinary(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil
   467  	}
   468  	return NewInt(r).ToObject(), nil
   469  }
   470  
   471  func intCheckedDiv(v, w int) (int, divModResult) {
   472  	q, _, r := intCheckedDivMod(v, w)
   473  	return q, r
   474  }
   475  
   476  func intCheckedDivMod(v, w int) (int, int, divModResult) {
   477  	if w == 0 {
   478  		return 0, 0, divModZeroDivision
   479  	}
   480  	if v == MinInt && w == -1 {
   481  		return 0, 0, divModOverflow
   482  	}
   483  	q := v / w
   484  	m := v % w
   485  	if m != 0 && (w^m) < 0 {
   486  		// In Python the result of the modulo operator is always the
   487  		// same sign as the divisor, whereas in Go, the result is
   488  		// always the same sign as the dividend. Therefore we need to
   489  		// do an adjustment when the sign of the modulo result differs
   490  		// from that of the divisor.
   491  		m += w
   492  		// Relatedly, in Python the result of division truncates toward
   493  		// negative infinity whereas it truncates toward zero in Go.
   494  		// The fact that the signs of the divisor and the modulo result
   495  		// differ implies that the quotient is also negative so we also
   496  		// adjust the quotient here.
   497  		q--
   498  	}
   499  	return q, m, divModOK
   500  }
   501  
   502  func intCheckedAdd(v, w int) (int, bool) {
   503  	if (v > 0 && w > MaxInt-v) || (v < 0 && w < MinInt-v) {
   504  		return 0, false
   505  	}
   506  	return v + w, true
   507  }
   508  
   509  func intCheckedMod(v, w int) (int, divModResult) {
   510  	_, m, r := intCheckedDivMod(v, w)
   511  	return m, r
   512  }
   513  
   514  func intCheckedMul(v, w int) (int, bool) {
   515  	if v == 0 || w == 0 || v == 1 || w == 1 {
   516  		return v * w, true
   517  	}
   518  	// Since MinInt can only be multiplied by zero and one safely and we've
   519  	// already handled that case above, we know this multiplication will
   520  	// overflow. Unfortunately the division check below will fail to catch
   521  	// this by coincidence: MinInt * -1 overflows to MinInt, causing the
   522  	// expression x/w to overflow, coincidentally producing MinInt which
   523  	// makes it seem as though the multiplication was correct.
   524  	if v == MinInt || w == MinInt {
   525  		return 0, false
   526  	}
   527  	x := v * w
   528  	if x/w != v {
   529  		return 0, false
   530  	}
   531  	return x, true
   532  }
   533  
   534  func intCheckedSub(v, w int) (int, bool) {
   535  	if (w > 0 && v < MinInt+w) || (w < 0 && v > MaxInt+w) {
   536  		return 0, false
   537  	}
   538  	return v - w, true
   539  }
   540  
   541  func intDivModOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, divModResult), bigFun func(z, x, y *big.Int)) (*Object, *BaseException) {
   542  	if !w.isInstance(IntType) {
   543  		return NotImplemented, nil
   544  	}
   545  	x, r := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value())
   546  	switch r {
   547  	case divModOverflow:
   548  		return longCallBinary(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil
   549  	case divModZeroDivision:
   550  		return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero")
   551  	}
   552  	return NewInt(x).ToObject(), nil
   553  }
   554  
   555  func intDivAndModOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, int, divModResult), bigFun func(z, m, x, y *big.Int)) (*Object, *BaseException) {
   556  	if !w.isInstance(IntType) {
   557  		return NotImplemented, nil
   558  	}
   559  	q, m, r := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value())
   560  	switch r {
   561  	case divModOverflow:
   562  		return longCallBinaryTuple(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil
   563  	case divModZeroDivision:
   564  		return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero")
   565  	}
   566  	return NewTuple2(NewInt(q).ToObject(), NewInt(m).ToObject()).ToObject(), nil
   567  }
   568  
   569  func intShiftOp(f *Frame, v, w *Object, fun func(int, int) (int, int, bool)) (*Object, *BaseException) {
   570  	if !w.isInstance(IntType) {
   571  		return NotImplemented, nil
   572  	}
   573  	lhs, rhs, rshift := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value())
   574  	if rhs < 0 {
   575  		return nil, f.RaiseType(ValueErrorType, "negative shift count")
   576  	}
   577  	var result int
   578  	n := uint(rhs)
   579  	if rshift {
   580  		result = lhs >> n
   581  	} else {
   582  		result = lhs << n
   583  		if result>>n != lhs {
   584  			return NewLong(new(big.Int).Lsh(big.NewInt(int64(lhs)), n)).ToObject(), nil
   585  		}
   586  	}
   587  	return NewInt(result).ToObject(), nil
   588  }
   589  
   590  func intToLong(o *Int) *Long {
   591  	return NewLong(big.NewInt(int64(o.Value())))
   592  }
   593  
   594  func makeInternedInts() [internedIntMax - internedIntMin + 1]Int {
   595  	var ints [internedIntMax - internedIntMin + 1]Int
   596  	for i := internedIntMin; i <= internedIntMax; i++ {
   597  		ints[i-internedIntMin] = Int{Object{typ: IntType}, i}
   598  	}
   599  	return ints
   600  }