Task: Fermat numbers


C++: #include <iostream>
#include <vector>
#include <boost/integer/common_factor.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/miller_rabin.hpp>

typedef boost::multiprecision::cpp_int integer;

integer fermat(unsigned int n) {
    unsigned int p = 1;
    for (unsigned int i = 0; i < n; ++i)
        p *= 2;
    return 1 + pow(integer(2), p);
}

inline void g(integer& x, const integer& n) {
    x *= x;
    x += 1;
    x %= n;
}

integer pollard_rho(const integer& n) {
    integer x = 2, y = 2, d = 1, z = 1;
    int count = 0;
    for (;;) {
        g(x, n);
        g(y, n);
        g(y, n);
        d = abs(x - y);
        z = (z * d) % n;
        ++count;
        if (count == 100) {
            d = gcd(z, n);
            if (d != 1)
                break;
            z = 1;
            count = 0;
        }
    }
    if (d == n)
        return 0;
    return d;
}

std::vector<integer> get_prime_factors(integer n) {
    std::vector<integer> factors;
    for (;;) {
        if (miller_rabin_test(n, 25)) {
            factors.push_back(n);
            break;
        }
        integer f = pollard_rho(n);
        if (f == 0) {
            factors.push_back(n);
            break;
        }
        factors.push_back(f);
        n /= f;
    }
    return factors;
}

void print_vector(const std::vector<integer>& factors) {
    if (factors.empty())
        return;
    auto i = factors.begin();
    std::cout << *i++;
    for (; i != factors.end(); ++i)
        std::cout << ", " << *i;
    std::cout << '\n';
}

int main() {
    std::cout << "First 10 Fermat numbers:\n";
    for (unsigned int i = 0; i < 10; ++i)
        std::cout << "F(" << i << ") = " << fermat(i) << '\n';
    std::cout << "\nPrime factors:\n";
    for (unsigned int i = 0; i < 9; ++i) {
        std::cout << "F(" << i << "): ";
        print_vector(get_prime_factors(fermat(i)));
    }
    return 0;
}




Java: import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class FermatNumbers {

    public static void main(String[] args) {
        System.out.println("First 10 Fermat numbers:");
        for ( int i = 0 ; i < 10 ; i++ ) {
            System.out.printf("F[%d] = %s\n", i, fermat(i));
        }
        System.out.printf("%nFirst 12 Fermat numbers factored:%n");
        for ( int i = 0 ; i < 13 ; i++ ) {
            System.out.printf("F[%d] = %s\n", i, getString(getFactors(i, fermat(i))));
        }
    }
    
    private static String getString(List<BigInteger> factors) {
        if ( factors.size() == 1 ) {
            return factors.get(0) + " (PRIME)";
        }
        return factors.stream().map(v -> v.toString()).map(v -> v.startsWith("-") ? "(C" + v.replace("-", "") + ")" : v).collect(Collectors.joining(" * "));
    }

    private static Map<Integer, String> COMPOSITE = new HashMap<>();
    static {
        COMPOSITE.put(9, "5529");
        COMPOSITE.put(10, "6078");
        COMPOSITE.put(11, "1037");
        COMPOSITE.put(12, "5488");
        COMPOSITE.put(13, "2884");
    }

    private static List<BigInteger> getFactors(int fermatIndex, BigInteger n) {
        List<BigInteger> factors = new ArrayList<>();
        BigInteger factor = BigInteger.ONE;
        while ( true ) {
            if ( n.isProbablePrime(100) ) {
                factors.add(n);
                break;
            }
            else {
                if ( COMPOSITE.containsKey(fermatIndex) ) {
                    String stop = COMPOSITE.get(fermatIndex);
                    if ( n.toString().startsWith(stop) ) {
                        factors.add(new BigInteger("-" + n.toString().length()));
                        break;
                    }
                }
                factor = pollardRhoFast(n);
                if ( factor.compareTo(BigInteger.ZERO) == 0 ) {
                    factors.add(n);
                    break;
                }
                else {
                    factors.add(factor);
                    n = n.divide(factor);
                }
            }
        }
        return factors;
    }
    
    private static final BigInteger TWO = BigInteger.valueOf(2);
    
    private static BigInteger fermat(int n) {
        return TWO.pow((int)Math.pow(2, n)).add(BigInteger.ONE);
    }
        
    
    @SuppressWarnings("unused")
    private static BigInteger pollardRho(BigInteger n) {
        BigInteger x = BigInteger.valueOf(2);
        BigInteger y = BigInteger.valueOf(2);
        BigInteger d = BigInteger.ONE;
        while ( d.compareTo(BigInteger.ONE) == 0 ) {
            x = pollardRhoG(x, n);
            y = pollardRhoG(pollardRhoG(y, n), n);
            d = x.subtract(y).abs().gcd(n);
        }
        if ( d.compareTo(n) == 0 ) {
            return BigInteger.ZERO;
        }
        return d;
    }
    
    
    
    
    
    
    private static BigInteger pollardRhoFast(BigInteger n) {
        long start = System.currentTimeMillis();
        BigInteger x = BigInteger.valueOf(2);
        BigInteger y = BigInteger.valueOf(2);
        BigInteger d = BigInteger.ONE;
        int count = 0;
        BigInteger z = BigInteger.ONE;
        while ( true ) {
            x = pollardRhoG(x, n);
            y = pollardRhoG(pollardRhoG(y, n), n);
            d = x.subtract(y).abs();
            z = z.multiply(d).mod(n);
            count++;
            if ( count == 100 ) {
                d = z.gcd(n);
                if ( d.compareTo(BigInteger.ONE) != 0 ) {
                    break;
                }
                z = BigInteger.ONE;
                count = 0;
            }
        }
        long end = System.currentTimeMillis();
        System.out.printf("    Pollard rho try factor %s elapsed time = %d ms (factor = %s).%n", n, (end-start), d);
        if ( d.compareTo(n) == 0 ) {
            return BigInteger.ZERO;
        }
        return d;
    }

    private static BigInteger pollardRhoG(BigInteger x, BigInteger n) {
        return x.multiply(x).add(BigInteger.ONE).mod(n);
    }

}