Ai
3 Star 0 Fork 0

mirrors_go-python/gpython

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
bigint.go 13.81 KB
一键复制 编辑 原始数据 按行查看 历史
Nick Craig-Wood 提交于 2015-06-29 03:15 +08:00 . py: fix GoInt and GoInt64 for BigInts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
// BigInt objects
package py
import (
"fmt"
"math"
"math/big"
)
type BigInt big.Int
var BigIntType = NewType("bigint", "Holds large integers")
// Type of this BigInt object
func (o *BigInt) Type() *Type {
return BigIntType
}
func (a *BigInt) M__str__() (Object, error) {
return String(fmt.Sprintf("%d", (*big.Int)(a))), nil
}
func (a *BigInt) M__repr__() (Object, error) {
return a.M__str__()
}
// Some common BigInts
var (
bigInt0 = (*BigInt)(big.NewInt(0))
bigInt1 = (*BigInt)(big.NewInt(1))
bigInt10 = (*BigInt)(big.NewInt(10))
bigIntMin = (*BigInt)(big.NewInt(IntMin))
bigIntMax = (*BigInt)(big.NewInt(IntMax))
)
// Errors
var (
overflowError = ExceptionNewf(OverflowError, "Python int too large to convert to int64")
overflowErrorGo = ExceptionNewf(OverflowError, "Python int too large to convert to a go int")
overflowErrorFloat = ExceptionNewf(OverflowError, "long int too large to convert to float")
expectingBigInt = ExceptionNewf(TypeError, "a big int is required")
)
// Checks that obj is exactly a BigInt and returns an error if not
func BigIntCheckExact(obj Object) (*BigInt, error) {
bigInt, ok := obj.(*BigInt)
if !ok {
return nil, expectingBigInt
}
return bigInt, nil
}
// Checks that obj is exactly a bigInd and returns an error if not
func BigIntCheck(obj Object) (*BigInt, error) {
// FIXME should be checking subclasses
return BigIntCheckExact(obj)
}
// Arithmetic
// Convert an Object to an BigInt
//
// Retrurns ok as to whether the conversion worked or not
func convertToBigInt(other Object) (*BigInt, bool) {
switch b := other.(type) {
case Int:
return (*BigInt)(big.NewInt(int64(b))), true
case *BigInt:
return b, true
case Bool:
if b {
return bigInt1, true
} else {
return bigInt0, true
}
}
return nil, false
}
// Truncates to Int
//
// If it is outside the range of an Int it will return an error
func (x *BigInt) Int() (Int, error) {
if (*big.Int)(x).Cmp((*big.Int)(bigIntMax)) <= 0 && (*big.Int)(x).Cmp((*big.Int)(bigIntMin)) >= 0 {
return Int((*big.Int)(x).Int64()), nil
}
return 0, overflowError
}
// MaybeInt truncates to Int if it can, otherwise returns the original BigInt
func (x *BigInt) MaybeInt() Object {
i, err := x.Int()
if err != nil {
return x
}
return i
}
// Truncates to go int
//
// If it is outside the range of an go int it will return an error
func (x *BigInt) GoInt() (int, error) {
z, err := x.Int()
if err != nil {
return 0, err
}
return z.GoInt()
}
// Truncates to go int64
//
// If it is outside the range of an go int64 it will return an error
func (x *BigInt) GoInt64() (int64, error) {
z, err := x.Int()
if err != nil {
return 0, err
}
return int64(z), nil
}
// Frexp produces frac and exp such that a ~= frac × 2**exp
func (a *BigInt) Frexp() (frac float64, exp int) {
aBig := (*big.Int)(a)
bits := aBig.BitLen()
exp = bits - 63
t := new(big.Int).Set(aBig)
switch {
case exp > 0:
t.Rsh(t, uint(exp))
case exp < 0:
t.Lsh(t, uint(-exp))
}
// t should now have 63 bits of the integer in and will fit in
// an int64
return float64(t.Int64()), exp
}
// Truncates to Float
//
// If it is outside the range of an Float it will return an error
func (a *BigInt) Float() (Float, error) {
frac, exp := a.Frexp()
// FIXME this is a bit approximate but errs on the low side so
// we won't ever produce +Infs
if exp > float64MaxExponent-63 {
return 0, overflowErrorFloat
}
return Float(math.Ldexp(frac, exp)), nil
}
func (a *BigInt) M__neg__() (Object, error) {
return (*BigInt)(new(big.Int).Neg((*big.Int)(a))), nil
}
func (a *BigInt) M__pos__() (Object, error) {
return a, nil
}
func (a *BigInt) M__abs__() (Object, error) {
if (*big.Int)(a).Sign() >= 0 {
return a, nil
}
return (*BigInt)(new(big.Int).Abs((*big.Int)(a))), nil
}
func (a *BigInt) M__invert__() (Object, error) {
return (*BigInt)(new(big.Int).Not((*big.Int)(a))), nil
}
func (a *BigInt) M__add__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Add((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__radd__(other Object) (Object, error) {
return a.M__add__(other)
}
func (a *BigInt) M__iadd__(other Object) (Object, error) {
return a.M__add__(other)
}
func (a *BigInt) M__sub__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Sub((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rsub__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Sub((*big.Int)(b), (*big.Int)(a))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__isub__(other Object) (Object, error) {
return a.M__sub__(other)
}
func (a *BigInt) M__mul__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Mul((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rmul__(other Object) (Object, error) {
return a.M__mul__(other)
}
func (a *BigInt) M__imul__(other Object) (Object, error) {
return a.M__mul__(other)
}
func (a *BigInt) M__truediv__(other Object) (Object, error) {
b, err := MakeFloat(other)
if err != nil {
return nil, err
}
fa, err := a.Float()
if err != nil {
return nil, err
}
fb := b.(Float)
if fb == 0 {
return nil, divisionByZero
}
return Float(fa / fb), nil
}
func (a *BigInt) M__rtruediv__(other Object) (Object, error) {
b, err := MakeFloat(other)
if err != nil {
return nil, err
}
fa, err := a.Float()
if err != nil {
return nil, err
}
fb := b.(Float)
if fa == 0 {
return nil, divisionByZero
}
return Float(fb / fa), nil
}
func (a *BigInt) M__itruediv__(other Object) (Object, error) {
return a.M__truediv__(other)
}
func (a *BigInt) M__floordiv__(other Object) (Object, error) {
result, _, err := a.M__divmod__(other)
return result, err
}
func (a *BigInt) M__rfloordiv__(other Object) (Object, error) {
result, _, err := a.M__rdivmod__(other)
return result, err
}
func (a *BigInt) M__ifloordiv__(other Object) (Object, error) {
result, _, err := a.M__divmod__(other)
return result, err
}
func (a *BigInt) M__mod__(other Object) (Object, error) {
_, result, err := a.M__divmod__(other)
return result, err
}
func (a *BigInt) M__rmod__(other Object) (Object, error) {
_, result, err := a.M__rdivmod__(other)
return result, err
}
func (a *BigInt) M__imod__(other Object) (Object, error) {
_, result, err := a.M__divmod__(other)
return result, err
}
func (a *BigInt) divMod(b *BigInt) (Object, Object, error) {
if (*big.Int)(b).Sign() == 0 {
return nil, nil, divisionByZero
}
r := new(big.Int)
q := new(big.Int)
q.QuoRem((*big.Int)(a), (*big.Int)(b), r)
// Implement floor division
negativeResult := (*big.Int)(a).Sign() < 0
if (*big.Int)(b).Sign() < 0 {
negativeResult = !negativeResult
}
if negativeResult && r.Sign() != 0 {
q.Sub(q, (*big.Int)(bigInt1))
r.Add(r, (*big.Int)(b))
}
return (*BigInt)(q).MaybeInt(), (*BigInt)(r).MaybeInt(), nil
}
func (a *BigInt) M__divmod__(other Object) (Object, Object, error) {
if b, ok := convertToBigInt(other); ok {
return a.divMod(b)
}
return NotImplemented, NotImplemented, nil
}
func (a *BigInt) M__rdivmod__(other Object) (Object, Object, error) {
if b, ok := convertToBigInt(other); ok {
return b.divMod(a)
}
return NotImplemented, NotImplemented, nil
}
// Raise to the power a**b or if m != nil, a**b mod m
func (a *BigInt) pow(b, m *BigInt) (Object, error) {
// -ve power => make float
if (*big.Int)(b).Sign() < 0 {
if m != nil {
return nil, ExceptionNewf(TypeError, "pow() 2nd argument cannot be negative when 3rd argument specified")
}
fa, err := a.Float()
if err != nil {
return nil, err
}
fb, err := b.Float()
if err != nil {
return nil, err
}
return fa.M__pow__(fb, None)
}
return (*BigInt)(new(big.Int).Exp((*big.Int)(a), (*big.Int)(b), (*big.Int)(m))).MaybeInt(), nil
}
func (a *BigInt) M__pow__(other, modulus Object) (Object, error) {
var m *BigInt
if modulus != None {
var ok bool
if m, ok = convertToBigInt(modulus); !ok {
return NotImplemented, nil
}
}
if b, ok := convertToBigInt(other); ok {
return a.pow(b, m)
}
return NotImplemented, nil
}
func (a *BigInt) M__rpow__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return b.pow(a, nil)
}
return NotImplemented, nil
}
func (a *BigInt) M__ipow__(other, modulus Object) (Object, error) {
return a.M__pow__(other, modulus)
}
func (a *BigInt) M__lshift__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
bb, err := b.GoInt()
if err != nil {
return nil, err
}
if bb < 0 {
return nil, negativeShiftCount
}
return (*BigInt)(new(big.Int).Lsh((*big.Int)(a), uint(bb))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rlshift__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
aa, err := a.GoInt()
if err != nil {
return nil, err
}
if aa < 0 {
return nil, negativeShiftCount
}
return (*BigInt)(new(big.Int).Lsh((*big.Int)(b), uint(aa))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__ilshift__(other Object) (Object, error) {
return a.M__lshift__(other)
}
func (a *BigInt) M__rshift__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
bb, err := b.GoInt()
if err != nil {
return nil, err
}
if bb < 0 {
return nil, negativeShiftCount
}
return (*BigInt)(new(big.Int).Rsh((*big.Int)(a), uint(bb))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rrshift__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
aa, err := a.GoInt()
if err != nil {
return nil, err
}
if aa < 0 {
return nil, negativeShiftCount
}
return (*BigInt)(new(big.Int).Rsh((*big.Int)(b), uint(aa))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__irshift__(other Object) (Object, error) {
return a.M__rshift__(other)
}
func (a *BigInt) M__and__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).And((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rand__(other Object) (Object, error) {
return a.M__and__(other)
}
func (a *BigInt) M__iand__(other Object) (Object, error) {
return a.M__and__(other)
}
func (a *BigInt) M__xor__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Xor((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__rxor__(other Object) (Object, error) {
return a.M__xor__(other)
}
func (a *BigInt) M__ixor__(other Object) (Object, error) {
return a.M__xor__(other)
}
func (a *BigInt) M__or__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return (*BigInt)(new(big.Int).Or((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__ror__(other Object) (Object, error) {
return a.M__or__(other)
}
func (a *BigInt) M__ior__(other Object) (Object, error) {
return a.M__or__(other)
}
func (a *BigInt) M__bool__() (Object, error) {
return NewBool((*big.Int)(a).Sign() != 0), nil
}
func (a *BigInt) M__index__() (Int, error) {
return a.Int()
}
func (a *BigInt) M__int__() (Object, error) {
return a, nil
}
func (a *BigInt) M__float__() (Object, error) {
return a.Float()
}
func (a *BigInt) M__complex__() (Object, error) {
// FIXME this is broken
if r, ok := convertToComplex(a); ok {
return r, nil
}
return cantConvert(a, "complex")
}
func (a *BigInt) M__round__(digits Object) (Object, error) {
if b, ok := convertToBigInt(digits); ok {
if (*big.Int)(b).Sign() >= 0 {
return a, nil
}
negative := false
r := new(big.Int).Set((*big.Int)(a))
if r.Sign() < 0 {
r.Neg(r)
negative = true
}
negB := new(big.Int).Neg((*big.Int)(b))
scale := new(big.Int).Exp((*big.Int)(bigInt10), negB, nil)
digits := new(big.Int).Mod(r, scale)
r.Sub(r, digits)
// Round
digits.Lsh(digits, 1)
if digits.Cmp(scale) >= 0 {
r.Add(r, scale)
}
if negative {
r.Neg(r)
}
return (*BigInt)(r), nil
}
return cantConvert(digits, "int")
}
// Rich comparison
func (a *BigInt) M__lt__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) < 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__le__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) <= 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__eq__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) == 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__ne__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) != 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__gt__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) > 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__ge__(other Object) (Object, error) {
if b, ok := convertToBigInt(other); ok {
return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) >= 0), nil
}
return NotImplemented, nil
}
func (a *BigInt) M__ceil__() (Object, error) {
return a, nil
}
func (a *BigInt) M__floor__() (Object, error) {
return a, nil
}
func (a *BigInt) M__trunc__() (Object, error) {
return a, nil
}
// Check interface is satisfied
var _ Object = (*BigInt)(nil)
var _ floatArithmetic = (*BigInt)(nil)
var _ booleanArithmetic = (*BigInt)(nil)
var _ conversionBetweenTypes = (*BigInt)(nil)
var _ I__bool__ = (*BigInt)(nil)
var _ I__index__ = (*BigInt)(nil)
var _ richComparison = (*BigInt)(nil)
var _ IGoInt = (*BigInt)(nil)
var _ IGoInt64 = (*BigInt)(nil)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors_go-python/gpython.git
git@gitee.com:mirrors_go-python/gpython.git
mirrors_go-python
gpython
gpython
v0.0.1

搜索帮助