func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} { var z big.Int switch op { case token.ADD: return z.Add(x, y) case token.SUB: return z.Sub(x, y) case token.MUL: return z.Mul(x, y) case token.QUO: return z.Quo(x, y) case token.REM: return z.Rem(x, y) case token.AND: return z.And(x, y) case token.OR: return z.Or(x, y) case token.XOR: return z.Xor(x, y) case token.AND_NOT: return z.AndNot(x, y) case token.SHL: // The shift length must be uint, or untyped int and // convertible to uint. // TODO 32/64bit if y.BitLen() > 32 { panic("Excessive shift length") } return z.Lsh(x, uint(y.Int64())) case token.SHR: if y.BitLen() > 32 { panic("Excessive shift length") } return z.Rsh(x, uint(y.Int64())) case token.EQL: return x.Cmp(y) == 0 case token.NEQ: return x.Cmp(y) != 0 case token.LSS: return x.Cmp(y) < 0 case token.LEQ: return x.Cmp(y) <= 0 case token.GTR: return x.Cmp(y) > 0 case token.GEQ: return x.Cmp(y) >= 0 } panic("unreachable") }
func bigIntRem(oldValues [][]byte, newValues [][]byte, w float64) (result [][]byte) { var sum *big.Int if oldValues != nil { sum = new(big.Int).SetBytes(oldValues[0]) for _, b := range newValues { sum.Rem(sum, new(big.Int).Mul(common.DecodeBigInt(b), big.NewInt(int64(w)))) } } else { sum = new(big.Int).Mul(new(big.Int).SetBytes(newValues[0]), big.NewInt(int64(w))) for _, b := range newValues[1:] { sum.Rem(sum, new(big.Int).Mul(common.DecodeBigInt(b), big.NewInt(int64(w)))) } } return [][]byte{sum.Bytes()} }
// Bign produces a uniformly distributed random number in the range [0, max). // It panics if max <= 0. func (r RNG) Bign(max *big.Int) *big.Int { if max.Sign() <= 0 { panic("maximum zero or below") } nbits := max.BitLen() + 1 m := new(big.Int) m.Sub(m.SetBit(m, nbits, 1), big.NewInt(1)) k := new(big.Int) k.Rem(m, max) k.Sub(m, k) x := r.Big(nbits) for x.Cmp(k) > 0 { x = r.Big(nbits) } return x.Rem(x, max) }
func powm(base, exp, modulus *big.Int) *big.Int { exp2 := big.NewInt(0).SetBytes(exp.Bytes()) base2 := big.NewInt(0).SetBytes(base.Bytes()) modulus2 := big.NewInt(0).SetBytes(modulus.Bytes()) zero := big.NewInt(0) result := big.NewInt(1) temp := new(big.Int) for zero.Cmp(exp2) != 0 { if temp.Rem(exp2, big.NewInt(2)).Cmp(zero) != 0 { result = result.Mul(result, base2) result = result.Rem(result, modulus2) } exp2 = exp2.Rsh(exp2, 1) base2 = base2.Mul(base2, base2) base2 = base2.Rem(base2, modulus2) } return result }
func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} { var z big.Int switch op { case token.ADD: return z.Add(x, y) case token.SUB: return z.Sub(x, y) case token.MUL: return z.Mul(x, y) case token.QUO: return z.Quo(x, y) case token.REM: return z.Rem(x, y) case token.AND: return z.And(x, y) case token.OR: return z.Or(x, y) case token.XOR: return z.Xor(x, y) case token.AND_NOT: return z.AndNot(x, y) case token.SHL: panic("unimplemented") case token.SHR: panic("unimplemented") case token.EQL: return x.Cmp(y) == 0 case token.NEQ: return x.Cmp(y) != 0 case token.LSS: return x.Cmp(y) < 0 case token.LEQ: return x.Cmp(y) <= 0 case token.GTR: return x.Cmp(y) > 0 case token.GEQ: return x.Cmp(y) >= 0 } panic("unreachable") }
// binaryOpConst returns the result of the constant evaluation x op y; // both operands must be of the same "kind" (boolean, numeric, or string). // If intDiv is true, division (op == token.QUO) is using integer division // (and the result is guaranteed to be integer) rather than floating-point // division. Division by zero leads to a run-time panic. // func binaryOpConst(x, y interface{}, op token.Token, intDiv bool) interface{} { x, y = matchConst(x, y) switch x := x.(type) { case bool: y := y.(bool) switch op { case token.LAND: return x && y case token.LOR: return x || y default: unreachable() } case int64: y := y.(int64) switch op { case token.ADD: // TODO(gri) can do better than this if is63bit(x) && is63bit(y) { return x + y } return normalizeIntConst(new(big.Int).Add(big.NewInt(x), big.NewInt(y))) case token.SUB: // TODO(gri) can do better than this if is63bit(x) && is63bit(y) { return x - y } return normalizeIntConst(new(big.Int).Sub(big.NewInt(x), big.NewInt(y))) case token.MUL: // TODO(gri) can do better than this if is32bit(x) && is32bit(y) { return x * y } return normalizeIntConst(new(big.Int).Mul(big.NewInt(x), big.NewInt(y))) case token.REM: return x % y case token.QUO: if intDiv { return x / y } return normalizeRatConst(new(big.Rat).SetFrac(big.NewInt(x), big.NewInt(y))) case token.AND: return x & y case token.OR: return x | y case token.XOR: return x ^ y case token.AND_NOT: return x &^ y default: unreachable() } case *big.Int: y := y.(*big.Int) var z big.Int switch op { case token.ADD: z.Add(x, y) case token.SUB: z.Sub(x, y) case token.MUL: z.Mul(x, y) case token.REM: z.Rem(x, y) case token.QUO: if intDiv { z.Quo(x, y) } else { return normalizeRatConst(new(big.Rat).SetFrac(x, y)) } case token.AND: z.And(x, y) case token.OR: z.Or(x, y) case token.XOR: z.Xor(x, y) case token.AND_NOT: z.AndNot(x, y) default: unreachable() } return normalizeIntConst(&z) case *big.Rat: y := y.(*big.Rat) var z big.Rat switch op { case token.ADD: z.Add(x, y) case token.SUB: z.Sub(x, y) case token.MUL: z.Mul(x, y) case token.QUO: z.Quo(x, y) default: unreachable() } return normalizeRatConst(&z) case complex: y := y.(complex) a, b := x.re, x.im c, d := y.re, y.im var re, im big.Rat switch op { case token.ADD: // (a+c) + i(b+d) re.Add(a, c) im.Add(b, d) case token.SUB: // (a-c) + i(b-d) re.Sub(a, c) im.Sub(b, d) case token.MUL: // (ac-bd) + i(bc+ad) var ac, bd, bc, ad big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) re.Sub(&ac, &bd) im.Add(&bc, &ad) case token.QUO: // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd var ac, bd, bc, ad, s big.Rat ac.Mul(a, c) bd.Mul(b, d) bc.Mul(b, c) ad.Mul(a, d) s.Add(c.Mul(c, c), d.Mul(d, d)) re.Add(&ac, &bd) re.Quo(&re, &s) im.Sub(&bc, &ad) im.Quo(&im, &s) default: unreachable() } return normalizeComplexConst(complex{&re, &im}) case string: if op == token.ADD { return x + y.(string) } } unreachable() return nil }
// Post-order traversal, equivalent to postfix notation. func Eval(node interface{}) (*big.Int, error) { switch nn := node.(type) { case *ast.BinaryExpr: z := new(big.Int) x, xerr := Eval(nn.X) if xerr != nil { return nil, xerr } y, yerr := Eval(nn.Y) if yerr != nil { return nil, yerr } switch nn.Op { case token.ADD: return z.Add(x, y), nil case token.SUB: return z.Sub(x, y), nil case token.MUL: return z.Mul(x, y), nil case token.QUO: if y.Sign() == 0 { // 0 denominator return nil, DivideByZero } return z.Quo(x, y), nil case token.REM: if y.Sign() == 0 { return nil, DivideByZero } return z.Rem(x, y), nil case token.AND: return z.And(x, y), nil case token.OR: return z.Or(x, y), nil case token.XOR: return z.Xor(x, y), nil case token.SHL: if y.Sign() < 0 { // negative shift return nil, NegativeShift } return z.Lsh(x, uint(y.Int64())), nil case token.SHR: if y.Sign() < 0 { return nil, NegativeShift } return z.Rsh(x, uint(y.Int64())), nil case token.AND_NOT: return z.AndNot(x, y), nil default: return nil, UnknownOpErr } case *ast.UnaryExpr: var z *big.Int var err error if z, err = Eval(nn.X); err != nil { return nil, err } switch nn.Op { case token.SUB: // -x return z.Neg(z), nil case token.XOR: // ^x return z.Not(z), nil case token.ADD: // +x (useless) return z, nil } case *ast.BasicLit: z := new(big.Int) switch nn.Kind { case token.INT: z.SetString(nn.Value, 0) return z, nil default: return nil, UnknownLitErr } case *ast.ParenExpr: z, err := Eval(nn.X) if err != nil { return nil, err } return z, nil case *ast.CallExpr: ident, ok := nn.Fun.(*ast.Ident) if !ok { return nil, UnknownTokenErr // quarter to four am; dunno correct error } var f Func f, ok = FuncMap[ident.Name] if !ok { return nil, UnknownFuncErr } var aerr error args := make([]*big.Int, len(nn.Args)) for i, a := range nn.Args { if args[i], aerr = Eval(a); aerr != nil { return nil, aerr } } x, xerr := f(args...) if xerr != nil { return nil, xerr } return x, nil } return nil, UnknownTokenErr }