/// <summary> /// Metoda faktoryzacji na czynniki pierwsze z wykorzystaniem algorytmu Rho Pollarda /// dziala dla liczb 32bit /// /// https://www.cs.colorado.edu/~srirams/courses/csci2824-spr14/pollardsRho.html /// http://www.geeksforgeeks.org/pollards-rho-algorithm-prime-factorization/ /// https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm /// https://pl.wikipedia.org/wiki/Algorytm_faktoryzacji_rho_Pollarda /// /// opierajac sie na pierwszym znalezionym dzielniku dziala ok 2,5x szybciej niz w przypadku listy z ograniczona iloscia iteracji (1200ms do 3000ms) /// </summary> /// <param name="n"></param> /// <returns>zwraca słownik w postaci (czynnik, ilość)</returns> public Dictionary <long, long> PollardRhoPrimeFactors(long n) { PrimeNumbersCheck pcheck = new PrimeNumbersCheck(); Dictionary <long, long> primeFactors = new Dictionary <long, long>(); if (pcheck.IsPrimeMRTest(n)) { return(primeFactors); } //okreslenie poteg 2 if (GetPrimeFactorPowerAndUpdateList(n, 2, out n, primeFactors, pcheck)) { return(primeFactors); } Random gen = new Random(); List <long> toCheck = new List <long>() { n }; long nv = n; while (nv > 1) { long v = nv; if (toCheck.Count > 0) { v = toCheck[0]; toCheck.RemoveAt(0); } //long c = gen.Next(2, (int)v); //long startx = gen.Next(1, (int)v); long c = RandomLong(2, v, gen); long startx = RandomLong(1, v, gen); //List<long> factors = GetPollardRhoFactorsList(v, startx, c); List <long> factors = GetPollardRhoSingleFactor(v, startx, c); //singlefactor ok 2,5x szybciej niz z lista i ograniczeniem petli foreach (long factor in factors) { if (pcheck.IsPrimeMRTest(factor)) { if (!primeFactors.ContainsKey(factor)) { if (GetPrimeFactorPowerAndUpdateList(nv, factor, out nv, primeFactors, pcheck)) { break; } } } else { if (!toCheck.Contains(factor)) { toCheck.Add(factor); } long d = n / factor; if (!toCheck.Contains(d)) { toCheck.Add(d); } } } } return(primeFactors); }
/// <summary> /// Liczy ilosc potege podzielnika, aktualizuje liczbe. /// Jezeli ostatnim podzielnikiem jest liczba pierwsza to zwraca true, w przeciwnym wypadku false. /// </summary> /// <param name="n"></param> /// <param name="factor"></param> /// <param name="newn"></param> /// <param name="primeFactors"></param> /// <param name="pcheck"></param> /// <returns></returns> private bool GetPrimeFactorPowerAndUpdateList(long n, long factor, out long newn, Dictionary <long, long> primeFactors, PrimeNumbersCheck pcheck) { long cnt = GetFactorPower(n, factor, out newn); if (cnt > 0) { primeFactors[factor] = cnt; //ostatni dzielnik jest liczba pierwsza if (pcheck.IsPrimeMRTest(newn)) { primeFactors[newn] = 1; newn = 1; return(true); } } return(false); }