HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Fermat primality test

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fermattestprimality

Problem

Here is a simple working Java implementation of primality test for Fermat numbers. Is there something that I could change in code to achieve a better running time?

import java.math.BigInteger;

public class FPT 
{
    public static void main(String[] args)
    {
        double n;
        n = Double.parseDouble(args[0]);

        int e = (int)n;

        if (e > 1)
        {
            double m = Math.pow(2,n);
            int k = (int)m;
            BigInteger F;
            F = BigInteger.valueOf(2).pow(k).add(BigInteger.ONE);
            BigInteger s = new BigInteger ("8");
            double o = 1;
            double a = n - o ;
            double b = Math.pow(2,a) - o;
            int c = (int)b;

            for (int i = 1; i <= c; i ++)
            {
                 s=s.pow(4).subtract(BigInteger.valueOf(4).multiply(s.pow(2))).add(BigInteger.valueOf(2)).mod(F);
            }

            if (s.equals(BigInteger.ZERO))
            {
                System.out.println("prime");
            }
            else
            {
                System.out.println("composite");
            }
        }
        else
        {
            System.out.println("exponent must be greater than one");
        }
    }
}

Solution

I still can't quite figure out the way to this algorithm =/. But, from the Java point of view, you can gain 9-10% by changing your loop to:

for (int i = 1; i <= c; i ++) {
    BigInteger temp = s.pow(2);
    s = temp.pow(2).subtract(BigInteger.valueOf(4).multiply(temp)).add(BigInteger.valueOf(2)).mod(F);
}


...because the cached value can be used twice there.

Otherwise, the code is hard to read. It's not self explanatory nor commented and could be written in a better way - for a human to read, at least. But none of those changes would affect performance in any way.

EDIT: Additional 17% thanks to @Landei in comments.

for (int i = 1; i <= c; i ++) {
    BigInteger temp = s.modPow(BigInteger.valueOf(2), F);
    s = temp.pow(2).subtract(BigInteger.valueOf(4).multiply(temp)).add(BigInteger.valueOf(2));
}
s = s.mod(F);


That takes advantage of modPow() method which can do pow().mod() in one step without much additional overhead. Since the mod is not necessary to have every time, it is enough to do it in temp (that actually propagates twice into the resulting expression) and enjoy the substantial speedup. You need to add one proper mod after the loop is done, though.

Code Snippets

for (int i = 1; i <= c; i ++) {
    BigInteger temp = s.pow(2);
    s = temp.pow(2).subtract(BigInteger.valueOf(4).multiply(temp)).add(BigInteger.valueOf(2)).mod(F);
}
for (int i = 1; i <= c; i ++) {
    BigInteger temp = s.modPow(BigInteger.valueOf(2), F);
    s = temp.pow(2).subtract(BigInteger.valueOf(4).multiply(temp)).add(BigInteger.valueOf(2));
}
s = s.mod(F);

Context

StackExchange Code Review Q#10560, answer score: 4

Revisions (0)

No revisions yet.