github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/runtime/long.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  	"strings"
    23  	"sync"
    24  )
    25  
    26  // By convention in this file, we always use the variable
    27  // name "z" or "m" (in the case of DivMod) to refer to
    28  // a *big.Int that we intend to modify. For other big.Int
    29  // values, we use "x", "y" or other names. Variables z and m
    30  // must be allocated within the same function using a big.Int
    31  // constructor.
    32  // We must never modify the value field of a Long that has
    33  // already been made available to the rest of the program,
    34  // as this would violate the immutability of Python longs.
    35  
    36  // Long represents Python 'long' objects.
    37  type Long struct {
    38  	Object
    39  	value    big.Int
    40  	hashOnce sync.Once
    41  	hash     int
    42  }
    43  
    44  // NewLong returns a new Long holding the given value.
    45  func NewLong(x *big.Int) *Long {
    46  	result := Long{Object: Object{typ: LongType}}
    47  	result.value.Set(x)
    48  	return &result
    49  }
    50  
    51  // NewLongFromBytes returns a new Long holding the given bytes,
    52  // interpreted as a big endian unsigned integer.
    53  func NewLongFromBytes(b []byte) *Long {
    54  	result := Long{Object: Object{typ: LongType}}
    55  	result.value.SetBytes(b)
    56  	return &result
    57  }
    58  
    59  func toLongUnsafe(o *Object) *Long {
    60  	return (*Long)(o.toPointer())
    61  }
    62  
    63  // IntValue returns l's value as a plain int if it will not overflow.
    64  // Otherwise raises OverflowErrorType.
    65  func (l *Long) IntValue(f *Frame) (int, *BaseException) {
    66  	if !numInIntRange(&l.value) {
    67  		return 0, f.RaiseType(OverflowErrorType, "Python int too large to convert to a Go int")
    68  	}
    69  	return int(l.value.Int64()), nil
    70  }
    71  
    72  // ToObject upcasts l to an Object.
    73  func (l *Long) ToObject() *Object {
    74  	return &l.Object
    75  }
    76  
    77  // Value returns the underlying integer value held by l.
    78  func (l *Long) Value() *big.Int {
    79  	return new(big.Int).Set(&l.value)
    80  }
    81  
    82  // IsTrue returns false if l is zero, true otherwise.
    83  func (l *Long) IsTrue() bool {
    84  	return l.value.Sign() != 0
    85  }
    86  
    87  // Neg returns a new Long that is the negative of l.
    88  func (l *Long) Neg() *Long {
    89  	result := Long{Object: Object{typ: LongType}}
    90  	result.value.Set(&l.value)
    91  	result.value.Neg(&result.value)
    92  	return &result
    93  }
    94  
    95  // LongType is the object representing the Python 'long' type.
    96  var LongType = newBasisType("long", reflect.TypeOf(Long{}), toLongUnsafe, ObjectType)
    97  
    98  func longAbs(z, x *big.Int) {
    99  	z.Abs(x)
   100  }
   101  
   102  func longAdd(z, x, y *big.Int) {
   103  	z.Add(x, y)
   104  }
   105  
   106  func longAnd(z, x, y *big.Int) {
   107  	z.And(x, y)
   108  }
   109  
   110  func longDiv(z, x, y *big.Int) {
   111  	m := big.Int{}
   112  	longDivMod(x, y, z, &m)
   113  }
   114  
   115  func longDivAndMod(z, m, x, y *big.Int) {
   116  	longDivMod(x, y, z, m)
   117  }
   118  
   119  func longEq(x, y *big.Int) bool {
   120  	return x.Cmp(y) == 0
   121  }
   122  
   123  func longGE(x, y *big.Int) bool {
   124  	return x.Cmp(y) >= 0
   125  }
   126  
   127  func longGetNewArgs(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
   128  	if raised := checkMethodArgs(f, "__getnewargs__", args, LongType); raised != nil {
   129  		return nil, raised
   130  	}
   131  	return NewTuple1(args[0]).ToObject(), nil
   132  }
   133  
   134  func longGT(x, y *big.Int) bool {
   135  	return x.Cmp(y) > 0
   136  }
   137  
   138  func longFloat(f *Frame, o *Object) (*Object, *BaseException) {
   139  	flt, _ := new(big.Float).SetInt(&toLongUnsafe(o).value).Float64()
   140  	if math.IsInf(flt, 0) {
   141  		return nil, f.RaiseType(OverflowErrorType, "long int too large to convert to float")
   142  	}
   143  	return NewFloat(flt).ToObject(), nil
   144  }
   145  
   146  func hashBigInt(x *big.Int) int {
   147  	// TODO: Make this hash match that of cpython.
   148  	return hashString(x.Text(36))
   149  }
   150  
   151  func longHex(f *Frame, o *Object) (*Object, *BaseException) {
   152  	val := numberToBase("0x", 16, o) + "L"
   153  	return NewStr(val).ToObject(), nil
   154  }
   155  
   156  func longHash(f *Frame, o *Object) (*Object, *BaseException) {
   157  	l := toLongUnsafe(o)
   158  	l.hashOnce.Do(func() {
   159  		// Be compatible with int hashes.
   160  		if numInIntRange(&l.value) {
   161  			l.hash = int(l.value.Int64())
   162  		}
   163  		l.hash = hashBigInt(&l.value)
   164  	})
   165  	return NewInt(l.hash).ToObject(), nil
   166  }
   167  
   168  func longIndex(_ *Frame, o *Object) (*Object, *BaseException) {
   169  	return o, nil
   170  }
   171  
   172  func longInt(f *Frame, o *Object) (*Object, *BaseException) {
   173  	if l := &toLongUnsafe(o).value; numInIntRange(l) {
   174  		return NewInt(int(l.Int64())).ToObject(), nil
   175  	}
   176  	return o, nil
   177  }
   178  
   179  func longInvert(z, x *big.Int) {
   180  	z.Not(x)
   181  }
   182  
   183  func longLE(x, y *big.Int) bool {
   184  	return x.Cmp(y) <= 0
   185  }
   186  
   187  func longLShift(z, x *big.Int, n uint) {
   188  	z.Lsh(x, n)
   189  }
   190  
   191  func longLong(f *Frame, o *Object) (*Object, *BaseException) {
   192  	if o.typ == LongType {
   193  		return o, nil
   194  	}
   195  	l := Long{Object: Object{typ: LongType}}
   196  	l.value.Set(&toLongUnsafe(o).value)
   197  	return l.ToObject(), nil
   198  }
   199  
   200  func longLT(x, y *big.Int) bool {
   201  	return x.Cmp(y) < 0
   202  }
   203  
   204  func longMul(z, x, y *big.Int) {
   205  	z.Mul(x, y)
   206  }
   207  
   208  func longMod(m, x, y *big.Int) {
   209  	z := &big.Int{}
   210  	longDivMod(x, y, z, m)
   211  }
   212  
   213  func longNative(f *Frame, o *Object) (reflect.Value, *BaseException) {
   214  	return reflect.ValueOf(toLongUnsafe(o).Value()), nil
   215  }
   216  
   217  func longNE(x, y *big.Int) bool {
   218  	return x.Cmp(y) != 0
   219  }
   220  
   221  func longNeg(z, x *big.Int) {
   222  	z.Neg(x)
   223  }
   224  
   225  func longNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) {
   226  	if t != LongType {
   227  		// Allocate a plain long and then copy its value into an
   228  		// object of the long subtype.
   229  		i, raised := longNew(f, LongType, args, nil)
   230  		if raised != nil {
   231  			return nil, raised
   232  		}
   233  		result := toLongUnsafe(newObject(t))
   234  		result.value = toLongUnsafe(i).value
   235  		return result.ToObject(), nil
   236  	}
   237  	argc := len(args)
   238  	if argc == 0 {
   239  		return NewLong(big.NewInt(0)).ToObject(), nil
   240  	}
   241  	o := args[0]
   242  	baseArg := 10
   243  	if argc == 1 {
   244  		if slot := o.typ.slots.Long; slot != nil {
   245  			result, raised := slot.Fn(f, o)
   246  			if raised != nil {
   247  				return nil, raised
   248  			}
   249  			if !result.isInstance(LongType) {
   250  				format := "__long__ returned non-long (type %s)"
   251  				return nil, f.RaiseType(TypeErrorType, fmt.Sprintf(format, result.typ.Name()))
   252  			}
   253  			return result, nil
   254  		}
   255  		if raised := checkMethodArgs(f, "__new__", args, StrType); raised != nil {
   256  			return nil, raised
   257  		}
   258  	} else {
   259  		if raised := checkMethodArgs(f, "__new__", args, StrType, IntType); raised != nil {
   260  			return nil, raised
   261  		}
   262  		baseArg = toIntUnsafe(args[1]).Value()
   263  		if baseArg != 0 && (baseArg < 2 || baseArg > 36) {
   264  			return nil, f.RaiseType(ValueErrorType, "long() base must be >= 2 and <= 36")
   265  		}
   266  	}
   267  	s := strings.TrimSpace(toStrUnsafe(o).Value())
   268  	if len(s) > 0 && (s[len(s)-1] == 'L' || s[len(s)-1] == 'l') {
   269  		s = s[:len(s)-1]
   270  	}
   271  	base := baseArg
   272  	if len(s) > 2 {
   273  		detectedBase := 0
   274  		switch s[:2] {
   275  		case "0b", "0B":
   276  			detectedBase = 2
   277  		case "0o", "0O":
   278  			detectedBase = 8
   279  		case "0x", "0X":
   280  			detectedBase = 16
   281  		}
   282  		if detectedBase != 0 && (baseArg == 0 || baseArg == detectedBase) {
   283  			s = s[2:]
   284  			base = detectedBase
   285  		}
   286  	}
   287  	if base == 0 {
   288  		base = 10
   289  	}
   290  	i := big.Int{}
   291  	if _, ok := i.SetString(s, base); !ok {
   292  		format := "invalid literal for long() with base %d: %s"
   293  		return nil, f.RaiseType(ValueErrorType, fmt.Sprintf(format, baseArg, toStrUnsafe(o).Value()))
   294  	}
   295  	return NewLong(&i).ToObject(), nil
   296  }
   297  
   298  func longNonZero(x *big.Int) bool {
   299  	return x.Sign() != 0
   300  }
   301  
   302  func longOct(f *Frame, o *Object) (*Object, *BaseException) {
   303  	val := numberToBase("0", 8, o) + "L"
   304  	if val == "00L" {
   305  		val = "0L"
   306  	}
   307  	return NewStr(val).ToObject(), nil
   308  }
   309  
   310  func longOr(z, x, y *big.Int) {
   311  	z.Or(x, y)
   312  }
   313  
   314  func longPos(z, x *big.Int) {
   315  	z.Set(x)
   316  }
   317  
   318  func longRepr(f *Frame, o *Object) (*Object, *BaseException) {
   319  	return NewStr(toLongUnsafe(o).value.Text(10) + "L").ToObject(), nil
   320  }
   321  
   322  func longRShift(z, x *big.Int, n uint) {
   323  	z.Rsh(x, n)
   324  }
   325  
   326  func longStr(f *Frame, o *Object) (*Object, *BaseException) {
   327  	return NewStr(toLongUnsafe(o).value.Text(10)).ToObject(), nil
   328  }
   329  
   330  func longSub(z, x, y *big.Int) {
   331  	z.Sub(x, y)
   332  }
   333  
   334  func longXor(z, x, y *big.Int) {
   335  	z.Xor(x, y)
   336  }
   337  
   338  func initLongType(dict map[string]*Object) {
   339  	dict["__getnewargs__"] = newBuiltinFunction("__getnewargs__", longGetNewArgs).ToObject()
   340  	LongType.slots.Abs = longUnaryOpSlot(longAbs)
   341  	LongType.slots.Add = longBinaryOpSlot(longAdd)
   342  	LongType.slots.And = longBinaryOpSlot(longAnd)
   343  	LongType.slots.Div = longDivModOpSlot(longDiv)
   344  	LongType.slots.DivMod = longDivAndModOpSlot(longDivAndMod)
   345  	LongType.slots.Eq = longBinaryBoolOpSlot(longEq)
   346  	LongType.slots.Float = &unaryOpSlot{longFloat}
   347  	LongType.slots.FloorDiv = longDivModOpSlot(longDiv)
   348  	LongType.slots.GE = longBinaryBoolOpSlot(longGE)
   349  	LongType.slots.GT = longBinaryBoolOpSlot(longGT)
   350  	LongType.slots.Hash = &unaryOpSlot{longHash}
   351  	LongType.slots.Hex = &unaryOpSlot{longHex}
   352  	LongType.slots.Index = &unaryOpSlot{longIndex}
   353  	LongType.slots.Int = &unaryOpSlot{longInt}
   354  	LongType.slots.Invert = longUnaryOpSlot(longInvert)
   355  	LongType.slots.LE = longBinaryBoolOpSlot(longLE)
   356  	LongType.slots.LShift = longShiftOpSlot(longLShift)
   357  	LongType.slots.LT = longBinaryBoolOpSlot(longLT)
   358  	LongType.slots.Long = &unaryOpSlot{longLong}
   359  	LongType.slots.Mod = longDivModOpSlot(longMod)
   360  	LongType.slots.Mul = longBinaryOpSlot(longMul)
   361  	LongType.slots.Native = &nativeSlot{longNative}
   362  	LongType.slots.NE = longBinaryBoolOpSlot(longNE)
   363  	LongType.slots.Neg = longUnaryOpSlot(longNeg)
   364  	LongType.slots.New = &newSlot{longNew}
   365  	LongType.slots.NonZero = longUnaryBoolOpSlot(longNonZero)
   366  	LongType.slots.Oct = &unaryOpSlot{longOct}
   367  	LongType.slots.Or = longBinaryOpSlot(longOr)
   368  	LongType.slots.Pos = longUnaryOpSlot(longPos)
   369  	// This operation can return a float, it must use binaryOpSlot directly.
   370  	LongType.slots.Pow = &binaryOpSlot{longPow}
   371  	LongType.slots.RAdd = longRBinaryOpSlot(longAdd)
   372  	LongType.slots.RAnd = longRBinaryOpSlot(longAnd)
   373  	LongType.slots.RDiv = longRDivModOpSlot(longDiv)
   374  	LongType.slots.RDivMod = longRDivAndModOpSlot(longDivAndMod)
   375  	LongType.slots.Repr = &unaryOpSlot{longRepr}
   376  	LongType.slots.RFloorDiv = longRDivModOpSlot(longDiv)
   377  	LongType.slots.RMod = longRDivModOpSlot(longMod)
   378  	LongType.slots.RMul = longRBinaryOpSlot(longMul)
   379  	LongType.slots.ROr = longRBinaryOpSlot(longOr)
   380  	LongType.slots.RLShift = longRShiftOpSlot(longLShift)
   381  	// This operation can return a float, it must use binaryOpSlot directly.
   382  	LongType.slots.RPow = &binaryOpSlot{longRPow}
   383  	LongType.slots.RRShift = longRShiftOpSlot(longRShift)
   384  	LongType.slots.RShift = longShiftOpSlot(longRShift)
   385  	LongType.slots.RSub = longRBinaryOpSlot(longSub)
   386  	LongType.slots.RXor = longRBinaryOpSlot(longXor)
   387  	LongType.slots.Str = &unaryOpSlot{longStr}
   388  	LongType.slots.Sub = longBinaryOpSlot(longSub)
   389  	LongType.slots.Xor = longBinaryOpSlot(longXor)
   390  }
   391  
   392  func longCallUnary(fun func(z, x *big.Int), v *Long) *Object {
   393  	l := Long{Object: Object{typ: LongType}}
   394  	fun(&l.value, &v.value)
   395  	return l.ToObject()
   396  }
   397  
   398  func longCallUnaryBool(fun func(x *big.Int) bool, v *Long) *Object {
   399  	return GetBool(fun(&v.value)).ToObject()
   400  }
   401  
   402  func longCallBinary(fun func(z, x, y *big.Int), v, w *Long) *Object {
   403  	l := Long{Object: Object{typ: LongType}}
   404  	fun(&l.value, &v.value, &w.value)
   405  	return l.ToObject()
   406  }
   407  
   408  func longCallBinaryTuple(fun func(z, m, x, y *big.Int), v, w *Long) *Object {
   409  	l := Long{Object: Object{typ: LongType}}
   410  	ll := Long{Object: Object{typ: LongType}}
   411  	fun(&l.value, &ll.value, &v.value, &w.value)
   412  	return NewTuple2(l.ToObject(), ll.ToObject()).ToObject()
   413  }
   414  
   415  func longCallBinaryBool(fun func(x, y *big.Int) bool, v, w *Long) *Object {
   416  	return GetBool(fun(&v.value, &w.value)).ToObject()
   417  }
   418  
   419  func longCallShift(fun func(z, x *big.Int, n uint), f *Frame, v, w *Long) (*Object, *BaseException) {
   420  	if !numInIntRange(&w.value) {
   421  		return nil, f.RaiseType(OverflowErrorType, "long int too large to convert to int")
   422  	}
   423  	if w.value.Sign() < 0 {
   424  		return nil, f.RaiseType(ValueErrorType, "negative shift count")
   425  	}
   426  	l := Long{Object: Object{typ: LongType}}
   427  	fun(&l.value, &v.value, uint(w.value.Int64()))
   428  	return l.ToObject(), nil
   429  }
   430  
   431  func longCallDivMod(fun func(z, x, y *big.Int), f *Frame, v, w *Long) (*Object, *BaseException) {
   432  	if w.value.Sign() == 0 {
   433  		return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero")
   434  	}
   435  	return longCallBinary(fun, v, w), nil
   436  }
   437  
   438  func longCallDivAndMod(fun func(z, m, x, y *big.Int), f *Frame, v, w *Long) (*Object, *BaseException) {
   439  	if w.value.Sign() == 0 {
   440  		return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero")
   441  	}
   442  	return longCallBinaryTuple(fun, v, w), nil
   443  }
   444  
   445  func longUnaryOpSlot(fun func(z, x *big.Int)) *unaryOpSlot {
   446  	f := func(_ *Frame, v *Object) (*Object, *BaseException) {
   447  		return longCallUnary(fun, toLongUnsafe(v)), nil
   448  	}
   449  	return &unaryOpSlot{f}
   450  }
   451  
   452  func longUnaryBoolOpSlot(fun func(x *big.Int) bool) *unaryOpSlot {
   453  	f := func(_ *Frame, v *Object) (*Object, *BaseException) {
   454  		return longCallUnaryBool(fun, toLongUnsafe(v)), nil
   455  	}
   456  	return &unaryOpSlot{f}
   457  }
   458  
   459  func longBinaryOpSlot(fun func(z, x, y *big.Int)) *binaryOpSlot {
   460  	f := func(_ *Frame, v, w *Object) (*Object, *BaseException) {
   461  		if w.isInstance(IntType) {
   462  			w = intToLong(toIntUnsafe(w)).ToObject()
   463  		} else if !w.isInstance(LongType) {
   464  			return NotImplemented, nil
   465  		}
   466  		return longCallBinary(fun, toLongUnsafe(v), toLongUnsafe(w)), nil
   467  	}
   468  	return &binaryOpSlot{f}
   469  }
   470  
   471  func longRBinaryOpSlot(fun func(z, x, y *big.Int)) *binaryOpSlot {
   472  	f := func(_ *Frame, v, w *Object) (*Object, *BaseException) {
   473  		if w.isInstance(IntType) {
   474  			w = intToLong(toIntUnsafe(w)).ToObject()
   475  		} else if !w.isInstance(LongType) {
   476  			return NotImplemented, nil
   477  		}
   478  		return longCallBinary(fun, toLongUnsafe(w), toLongUnsafe(v)), nil
   479  	}
   480  	return &binaryOpSlot{f}
   481  }
   482  
   483  func longDivModOpSlot(fun func(z, x, y *big.Int)) *binaryOpSlot {
   484  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   485  		if w.isInstance(IntType) {
   486  			w = intToLong(toIntUnsafe(w)).ToObject()
   487  		} else if !w.isInstance(LongType) {
   488  			return NotImplemented, nil
   489  		}
   490  		return longCallDivMod(fun, f, toLongUnsafe(v), toLongUnsafe(w))
   491  	}
   492  	return &binaryOpSlot{f}
   493  }
   494  
   495  func longRDivModOpSlot(fun func(z, x, y *big.Int)) *binaryOpSlot {
   496  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   497  		if w.isInstance(IntType) {
   498  			w = intToLong(toIntUnsafe(w)).ToObject()
   499  		} else if !w.isInstance(LongType) {
   500  			return NotImplemented, nil
   501  		}
   502  		return longCallDivMod(fun, f, toLongUnsafe(w), toLongUnsafe(v))
   503  	}
   504  	return &binaryOpSlot{f}
   505  }
   506  
   507  func longDivAndModOpSlot(fun func(z, m, x, y *big.Int)) *binaryOpSlot {
   508  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   509  		if w.isInstance(IntType) {
   510  			w = intToLong(toIntUnsafe(w)).ToObject()
   511  		} else if !w.isInstance(LongType) {
   512  			return NotImplemented, nil
   513  		}
   514  		return longCallDivAndMod(fun, f, toLongUnsafe(v), toLongUnsafe(w))
   515  	}
   516  	return &binaryOpSlot{f}
   517  }
   518  
   519  func longRDivAndModOpSlot(fun func(z, m, x, y *big.Int)) *binaryOpSlot {
   520  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   521  		if w.isInstance(IntType) {
   522  			w = intToLong(toIntUnsafe(w)).ToObject()
   523  		} else if !w.isInstance(LongType) {
   524  			return NotImplemented, nil
   525  		}
   526  		return longCallDivAndMod(fun, f, toLongUnsafe(w), toLongUnsafe(v))
   527  	}
   528  	return &binaryOpSlot{f}
   529  }
   530  
   531  func longShiftOpSlot(fun func(z, x *big.Int, n uint)) *binaryOpSlot {
   532  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   533  		if w.isInstance(IntType) {
   534  			w = intToLong(toIntUnsafe(w)).ToObject()
   535  		} else if !w.isInstance(LongType) {
   536  			return NotImplemented, nil
   537  		}
   538  		return longCallShift(fun, f, toLongUnsafe(v), toLongUnsafe(w))
   539  	}
   540  	return &binaryOpSlot{f}
   541  }
   542  
   543  func longRShiftOpSlot(fun func(z, x *big.Int, n uint)) *binaryOpSlot {
   544  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   545  		if w.isInstance(IntType) {
   546  			w = intToLong(toIntUnsafe(w)).ToObject()
   547  		} else if !w.isInstance(LongType) {
   548  			return NotImplemented, nil
   549  		}
   550  		return longCallShift(fun, f, toLongUnsafe(w), toLongUnsafe(v))
   551  	}
   552  	return &binaryOpSlot{f}
   553  }
   554  
   555  func longBinaryBoolOpSlot(fun func(x, y *big.Int) bool) *binaryOpSlot {
   556  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   557  		if w.isInstance(IntType) {
   558  			w = intToLong(toIntUnsafe(w)).ToObject()
   559  		} else if !w.isInstance(LongType) {
   560  			return NotImplemented, nil
   561  		}
   562  		return longCallBinaryBool(fun, toLongUnsafe(v), toLongUnsafe(w)), nil
   563  	}
   564  	return &binaryOpSlot{f}
   565  }
   566  
   567  func longRBinaryBoolOpSlot(fun func(x, y *big.Int) bool) *binaryOpSlot {
   568  	f := func(f *Frame, v, w *Object) (*Object, *BaseException) {
   569  		if w.isInstance(IntType) {
   570  			w = intToLong(toIntUnsafe(w)).ToObject()
   571  		} else if !w.isInstance(LongType) {
   572  			return NotImplemented, nil
   573  		}
   574  		return longCallBinaryBool(fun, toLongUnsafe(w), toLongUnsafe(v)), nil
   575  	}
   576  	return &binaryOpSlot{f}
   577  }
   578  
   579  func longPow(f *Frame, v, w *Object) (*Object, *BaseException) {
   580  	var wLong *big.Int
   581  
   582  	vLong := toLongUnsafe(v).Value()
   583  	if w.isInstance(LongType) {
   584  		wLong = toLongUnsafe(w).Value()
   585  	} else if w.isInstance(IntType) {
   586  		wLong = big.NewInt(int64(toIntUnsafe(w).Value()))
   587  	} else {
   588  		return NotImplemented, nil
   589  	}
   590  
   591  	if wLong.Sign() < 0 {
   592  		// The result will be a float, so we call the floating point function.
   593  		var vFloat, wFloat *Object
   594  		var raised *BaseException
   595  
   596  		vFloat, raised = longFloat(f, v)
   597  		if raised != nil {
   598  			return nil, raised
   599  		}
   600  		// w might be an int or a long
   601  		if w.isInstance(LongType) {
   602  			wFloat, raised = longFloat(f, w)
   603  			if raised != nil {
   604  				return nil, raised
   605  			}
   606  		} else if w.isInstance(IntType) {
   607  			wFloat = NewFloat(float64(toIntUnsafe(w).Value())).ToObject()
   608  		} else {
   609  			// This point should not be reachable
   610  			return nil, f.RaiseType(SystemErrorType, "internal error in longPow")
   611  		}
   612  		return floatPow(f, vFloat, wFloat)
   613  	}
   614  
   615  	return NewLong(big.NewInt(0).Exp(vLong, wLong, nil)).ToObject(), nil
   616  }
   617  
   618  func longRPow(f *Frame, v, w *Object) (*Object, *BaseException) {
   619  	if w.isInstance(LongType) {
   620  		return longPow(f, w, v)
   621  	}
   622  	if w.isInstance(IntType) {
   623  		wLong := NewLong(big.NewInt(int64(toIntUnsafe(w).Value()))).ToObject()
   624  		return longPow(f, wLong, v)
   625  	}
   626  	return NotImplemented, nil
   627  }
   628  
   629  func longDivMod(x, y, z, m *big.Int) {
   630  	z.QuoRem(x, y, m)
   631  	if m.Sign() == -y.Sign() {
   632  		// In Python the result of the modulo operator is always the
   633  		// same sign as the divisor, whereas in Go, the result is
   634  		// always the same sign as the dividend. Therefore we need to
   635  		// do an adjustment when the sign of the modulo result differs
   636  		// from that of the divisor.
   637  		m.Add(m, y)
   638  		// Relatedly, in Python the result of division truncates toward
   639  		// negative infinity whereas it truncates toward zero in Go.
   640  		// The fact that the signs of the divisor and the modulo result
   641  		// differ implies that the quotient is also negative so we also
   642  		// adjust the quotient here.
   643  		z.Sub(z, big.NewInt(1))
   644  	}
   645  }