-2

I’ve seen this question already being asked on Stack but I couldn’t find any concrete answer or at least the answer I understand. So here is my question:

How could I parallelize the factorization of a big number?

I’ve seen answers like this: “ … He just needs to spawn a new thread for each factor found, then have some sort of synchronized object to collect all the factors”

But I don’t quite understand how this could be done. Could someone please explain it using an example?

JohnD
  • 19
  • 5
  • 1
    If you mean computing different portions using threads, chances are that will probably show things down unless you have a huge number to factor since setting up threads and managing synchronization increases overhead. And if you do have a huge number you may want to search for factorization algorithms which do more than just check for division by existing primes. – WJS Mar 09 '22 at 22:05
  • Yes, I tried searching online but couldn’t find anything. Could you please be more specific, have you heard of some specific algorithm? – JohnD Mar 10 '22 at 08:58
  • This should keep you busy for a while. [Integer Factorization](https://en.wikipedia.org/wiki/Integer_factorization) – WJS Mar 10 '22 at 17:40

1 Answers1

0

If you have a list of primes. You can do it like this (for real large numbers it can take a while). Use a map to hold a frequency count of prime factors and the number of times they occur.

  • continue dividing target by current prime until it doesn't divide
  • then use BigInteger to check the value to see if it is a prime (this greatly speeds up the process if the remaining value is huge and a prime).
  • continue until all factors have been found or you run out of primes.
long candidate = 498977279919318060L;

Map<Long, Integer> factors = new TreeMap<>();
for (long p : primes) {
    while (candidate % p == 0) {
        factors.compute(p, (k,v) -> v == null ? 1 : v+1);
        candidate/=p;
    }
    if (BigInteger.valueOf(candidate).isProbablePrime(99)) {
        factors.put(candidate,1);
        candidate = 1;
        break;
    }
}
if (candidate != 1) {
    System.out.println("factorization incomplete - stopped at " + candidate);
}

factors.entrySet().forEach(System.out::println);

prints

2=2
3=5
5=1
7=1
19=3
29=1
73=2
101=1
137=1

You can verify the result by first, raising each factor to its frequency and then computing the product of those results using reduce.

long val = factors.entrySet().stream()
        .mapToLong(e -> (long) Math
                .pow(e.getKey().doubleValue(), e.getValue()))
        .reduce(1L, (a, b) -> a * b);

System.out.println(val);

prints

498977279919318060
WJS
  • 36,363
  • 4
  • 24
  • 39
  • Thank you so much for this amazing answer! However, I need to find a way to parallelize the factorization. I do have a list of primes up to the number I need to factorize and I should use it. In the lectures, we were introduced to trial division and we should somehow make it work in parallel. I just can’t see how this could be done as each step is dependent upon the result of the previous one. – JohnD Mar 10 '22 at 21:16
  • You need to provide more information. I have no idea how you were told to do this in parallel or what that means exactly (other than using threads). – WJS Mar 10 '22 at 21:36
  • Ok. I'll try to explain. I was given the sequential version of sieve of Eratosthenes that produce an array of primes up to number N. I then need to factorize 100 numbers less that N*N where N is 2mil, 20mil,...2bil using this array and I must parallelize each factorization. Sequential algorithm we were shown uses this approach: https://www.geeksforgeeks.org/java-program-for-efficiently-print-all-prime-factors-of-a-given-number/ and We should somehow adapt it to run in parallel and achieve speedups >1 contra sequential factorization. – JohnD Mar 11 '22 at 12:23
  • Check out https://stackoverflow.com/questions/59074797/parallelizing-sieve-of-eratosthenes-in-java. And search the web. There are articles on this. – WJS Mar 11 '22 at 13:35