package primes import "math/big" // Factor represents a factor with a base (Prime) and an exponent (Exponent) type Factor struct { Prime int64 Exponent int } // Factorize calculates the factors of n and returns it as a slice of Factor's (uses a default cache). func Factorize(n int64) []Factor { return FactorizeCache(primes, n) } // FactorizeCache calculates the factors of n and returns it as a slice of Factor's and specifies the cache to use. func FactorizeCache(c Cache, n int64) []Factor { if 1 > n { return []Factor{} } var factors []Factor it := NewIteratorFromCache(c) for it.Next() { p := it.Get() var exp int for n%p == 0 { n /= p exp++ } if 0 < exp { factors = append(factors, Factor{p, exp}) } if n < p*p { break } } if 1 < n { factors = append(factors, Factor{n, 1}) } else if 1 == n && 0 == len(factors) { return []Factor{{1, 1}} } return factors } // MustBigIntToInt64 returns the int64 representation of the big int n. If n is too large the method panics. func MustBigIntToInt64(n *big.Int) int64 { if !n.IsInt64() { panic("n can't be represented as a int64") } return n.Int64() } // FactorizeBigInt calculates the factors of n and returns it as a slice of Factor's. If the base of a factor is larger than can be represented as a int64 the method will panic. func FactorizeBigInt(n *big.Int) []Factor { n = big.NewInt(0).Set(n) var one = big.NewInt(1) if one.Cmp(n) > 0 { return []Factor{} } var zero = big.NewInt(0) var divModZero = func(p *big.Int) bool { var quo, rem = big.NewInt(0), big.NewInt(0) quo.QuoRem(n, p, rem) if rem.Cmp(zero) == 0 { n = quo return true } return false } var factors []Factor it := NewIterator() for it.Next() { var p = big.NewInt(it.Get()) var exp int for divModZero(p) { exp++ } if 0 < exp { factors = append(factors, Factor{it.Get(), exp}) } p.Mul(p, p) if n.Cmp(p) < 0 { break } } if one.Cmp(n) < 0 { factors = append(factors, Factor{MustBigIntToInt64(n), 1}) } else if one.Cmp(n) == 0 && 0 == len(factors) { return []Factor{{1, 1}} } return factors }