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) }
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") }
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") }