func info(a *big.Int, n uint) {
	dtrunc := int64(float64(a.BitLen())*.30103) - 10
	var first, rest big.Int
	rest.Exp(first.SetInt64(10), rest.SetInt64(dtrunc), nil)
	first.Quo(a, &rest)
	fstr := first.String()
	fmt.Printf("%d! begins %s... and has %d digits.\n",
		n, fstr, int64(len(fstr))+dtrunc)
}
func Factorial(n uint64) (r *big.Int) {
	var oddFactNDiv2, oddFactNDiv4 big.Int

	// closes on oddFactNDiv2, oddFactNDiv4
	oddSwing := func(n uint64) (r *big.Int) {

		if n < uint64(len(smallOddSwing)) {
			return big.NewInt(smallOddSwing[n])
		}

		length := (n - 1) / 4
		if n%4 != 2 {
			length++
		}
		high := n - (n+1)&1
		ndiv4 := n / 4

		var oddFact big.Int
		if ndiv4 < uint64(len(smallOddFactorial)) {
			oddFact.SetInt64(smallOddFactorial[ndiv4])
			r = &oddFact
		} else {
			r = &oddFactNDiv4
		}

		return oddFact.Quo(oddProduct(high, length), r)
	}

	// closes on oddFactNDiv2, oddFactNDiv4, oddSwing, and itself
	var oddFactorial func(uint64) *big.Int
	oddFactorial = func(n uint64) (oddFact *big.Int) {
		if n < uint64(len(smallOddFactorial)) {
			oddFact = big.NewInt(smallOddFactorial[n])
		} else {
			oddFact = oddFactorial(n / 2)
			oddFact.Mul(oddFact.Mul(oddFact, oddFact), oddSwing(n))
		}

		oddFactNDiv4.Set(&oddFactNDiv2)
		oddFactNDiv2.Set(oddFact)
		return oddFact
	}

	oddFactNDiv2.SetInt64(1)
	oddFactNDiv4.SetInt64(1)
	r = oddFactorial(n)
	exp := uint(n - uint64(xmath.BitCount64(n)))
	return r.Lsh(r, exp)
}
Esempio n. 3
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:
		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")
}
Esempio n. 4
0
func number_divide(x, y Obj) Obj {
	xfx := (uintptr(unsafe.Pointer(x)) & fixnum_mask) == fixnum_tag
	yfx := (uintptr(unsafe.Pointer(y)) & fixnum_mask) == fixnum_tag
	if xfx && yfx {
		i1 := int(uintptr(unsafe.Pointer(x))) >> fixnum_shift
		i2 := int(uintptr(unsafe.Pointer(y))) >> fixnum_shift
		// A good optimizer will combine the div and mod into
		// one instruction.
		r, m := i1/i2, i1%i2
		if m == 0 && r > fixnum_min && r < fixnum_max {
			return Make_fixnum(r)
		} else {
			return wrap(big.NewRat(int64(i1), int64(i2)))
		}
	}

	if (!xfx && (uintptr(unsafe.Pointer(x))&heap_mask) != heap_tag) ||
		(!yfx && (uintptr(unsafe.Pointer(y))&heap_mask) != heap_tag) {
		panic("bad type")
	}

	if xfx {
		x = wrap(big.NewInt(int64(fixnum_to_int(x))))
	}
	if yfx {
		y = wrap(big.NewInt(int64(fixnum_to_int(y))))
		//return wrap(z.Div(vx,vy))
	}

	switch vx := (*x).(type) {
	case *big.Int:
		var z *big.Int = big.NewInt(0)
		switch vy := (*y).(type) {
		case *big.Int:
			return simpBig(z.Div(vx, vy))
		case *big.Rat:
			z := big.NewRat(1, 1)
			z.SetInt(vx)
			return simpRat(z.Quo(z, vy))
		default:
			panic("bad type")
		}
	case *big.Rat:
		z := big.NewRat(1, 1)
		switch vy := (*y).(type) {
		case *big.Int:
			z.SetInt(vy)
			return simpRat(z.Quo(vx, z))
		case *big.Rat:
			return simpRat(z.Quo(vx, vy))
		}
	}
	panic("bad type")
}