/// <summary> /// Constructs a prime factorization of the integer provided. /// <example>For example, 60 = 2^2 * 3 * 5.</example> /// </summary> /// <param name="value">The integer for which a prime factorization will be constructed.</param> public static PrimeFactorization PrimeFactorization(this long value) { return(MathHelpers.PrimeFactorization(value)); }
public IEnumerable <BigInteger> PrimeFactorsByRationalSieve(BigInteger value, BigInteger bound) { if (IsPrimeByMillerRabin(value, 10)) { return new[] { value } } ; var primes = PrimesByAtkin(bound); var suitablePrimes = primes.Where(m => value % m == 0); if (suitablePrimes.Any()) { var product = suitablePrimes.Aggregate(BigInteger.One, (accumulator, current) => accumulator * current); return(suitablePrimes.Union(this.PrimeFactorsByRationalSieve(value / product, bound))); } var zValues = new Dictionary <BigInteger, List <List <int> > >(); for (int i = 1; i < value && zValues.Count < (primes.Count + 3); i++) { if (!IsBSmooth(i, bound) || !IsBSmooth(i + value, bound)) { continue; } var leftList = new List <int>(primes.Count); var rightList = new List <int>(primes.Count); foreach (var prime in primes) { var exponent = 1; while (i % BigInteger.Pow(prime, exponent) == 0) { exponent += 1; } leftList.Add(exponent - 1); exponent = 1; while ((i + value) % BigInteger.Pow(prime, exponent) == 0) { exponent += 1; } rightList.Add(exponent - 1); } zValues.Add(i, new List <List <int> > { leftList, rightList }); } if (zValues.Any() == false) { return(suitablePrimes); } var allEvens = zValues.Values.FirstOrDefault(m => m[0].All(n => n % 2 == 0) && m[1].All(n => n % 2 == 0)); if (allEvens == null) { for (int i = 0; i < zValues.Count && allEvens == null; i++) { for (int n = i + 1; n < zValues.Count && allEvens == null; n++) { var leftList = new List <int>(primes.Count); var rightList = new List <int>(primes.Count); for (int j = 0; j < primes.Count; j++) { var leftAddition = zValues.ElementAt(i).Value[0][j] + zValues.ElementAt(n).Value[0][j]; var rightAddition = zValues.ElementAt(i).Value[1][j] + zValues.ElementAt(n).Value[1][j]; if (leftAddition == rightAddition) { leftList.Add(0); rightList.Add(0); } else { leftList.Add(leftAddition); rightList.Add(rightAddition); } } if (leftList.All(m => m % 2 == 0) && rightList.All(m => m % 2 == 0)) { allEvens = new List <List <int> > { leftList, rightList } } ; } } } var leftProduct = BigInteger.One; var rightProduct = BigInteger.One; for (int i = 0; i < primes.Count; i++) { leftProduct *= BigInteger.Pow(primes.ElementAt(i), allEvens[0][i]); rightProduct *= BigInteger.Pow(primes.ElementAt(i), allEvens[1][i]); } var leftSquare = MathHelpers.Sqrt(leftProduct); var rightSquare = MathHelpers.Sqrt(rightProduct); return(suitablePrimes.Union(new[] { GreatestCommonFactor(Math.Abs((int)leftSquare - (int)rightSquare), value), GreatestCommonFactor((int)leftSquare + (int)rightSquare, value) })); }
/// <summary> /// Gets all of the prime numbers up to and including the limit using the sieve of Atkin(https://en.wikipedia.org/wiki/Sieve_of_atkin). /// </summary> /// <param name="limit">The limit.</param> public static ICollection <BigInteger> PrimesByAtkin(BigInteger limit) { var primes = new HashSet <BigInteger> { 2, 3, 5 }; if (limit <= 5) { return(primes.Where(m => m <= limit).ToArray()); } var cachedPrimes = MemoryCache.Default.Get("LargestAtkin"); if (cachedPrimes != null) { var castPrimes = (KeyValuePair <BigInteger, IOrderedEnumerable <BigInteger> >)cachedPrimes; if (limit == castPrimes.Key) { return(castPrimes.Value.ToArray()); } if (limit < castPrimes.Key) { return(castPrimes.Value.Where(m => m <= limit).ToArray()); } } /*var flip1 = new BigInteger[] { 1, 13, 17, 29, 37, 41, 49, 53 }; * var flip2 = new BigInteger[] { 7, 19, 31, 43 }; * var flip3 = new BigInteger[] { 11, 23, 47, 59 };*/ var flip1 = new BigInteger[] { 1, 5 }; var flip2 = new BigInteger[] { 7 }; var flip3 = new BigInteger[] { 11 }; // no built in sqrt, but MSDN offers this(http://msdn.microsoft.com/en-us/library/dd268263.aspx) var sqrt = new BigInteger(Math.Ceiling(MathHelpers.Sqrt(limit))); var numbers = new HashSet <BigInteger>(); Action <BigInteger> flipNumbers = (n) => { if (!numbers.Add(n)) { numbers.Remove(n); } }; for (BigInteger x = 1; x <= sqrt; x++) { for (BigInteger y = 1; y <= sqrt; y++) { BigInteger n = (4 * (x * x)) + (y * y); if (n <= limit && (flip1.Contains(n % 12))) { flipNumbers(n); } n = (3 * (x * x)) + (y * y); if (n <= limit && (flip2.Contains(n % 12))) { flipNumbers(n); } n = (3 * (x * x)) - (y * y); if (x > y && n <= limit && (flip3.Contains(n % 12))) { flipNumbers(n); } } } var sortedNumbers = numbers.OrderBy(m => m); foreach (var sieveNumber in sortedNumbers) { if (!numbers.Contains(sieveNumber)) { continue; } primes.Add(sieveNumber); var squareSieve = sieveNumber * sieveNumber; var multiplier = 1; while (multiplier * squareSieve <= limit) { numbers.Remove(multiplier * squareSieve); multiplier += 1; } } MemoryCache.Default["LargestAtkin"] = new KeyValuePair <BigInteger, IOrderedEnumerable <BigInteger> >(limit, primes.OrderBy(m => m)); return(primes); }
public IEnumerable <BigInteger> PrimeFactorsByRationalSieve(BigInteger value) { var bound = value < 10000 ? Math.Ceiling(MathHelpers.Sqrt(value)) : Math.Ceiling(Math.Pow(BigInteger.Log(value, 2), 3)); return(PrimeFactorsByRationalSieve(value, new BigInteger(bound))); }