93 lines
2.1 KiB
Go
93 lines
2.1 KiB
Go
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
|
|
}
|