Beispiel #1
0
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")
}
Beispiel #2
0
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()}
}
Beispiel #3
0
// 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)
}
Beispiel #4
0
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")
}
Beispiel #6
0
// 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
}
Beispiel #7
0
// 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
}