[ 
https://issues.apache.org/jira/browse/MATH-841?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13428849#comment-13428849
 ] 

Sebastien Riou commented on MATH-841:
-------------------------------------

Here it is:
public static int gcd(final int p, final int q) {
        int a = p;
        int b = q;
        if ((a == 0) || (b == 0)) {
            if ((a == Integer.MIN_VALUE) || (b == Integer.MIN_VALUE)){
                throw new 
MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS,p, q);
            }
            return FastMath.abs(a+b);
        }
        long al=a;
        long bl=b;
        boolean useLong=false;
        if(a<0){
            if(Integer.MIN_VALUE==a) useLong=true;
            else a=-a;
            al=-al;
        }
        if(b<0){
            if(Integer.MIN_VALUE==b) useLong=true;
            else b=-b;
            bl=-bl;
        }
        if(useLong){
            if(al==bl) throw new 
MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS,p, q);
            long blbu=bl;
            bl=al;
            al=blbu % al;
            if(0L==al){
                if(bl>Integer.MAX_VALUE) throw new 
MathArithmeticException(LocalizedFormats.GCD_OVERFLOW_32_BITS,p, q);
                return (int)bl;
            }
            blbu=bl;
            //now al and bl can fit in int, so we use the int agorithm for 
speed matters
            b=(int)al;
            a=(int)(blbu % al);
        }
        return gcdEuclideIterative(a,b); 
    }
    //direct translation of the gcd definition into an iterative form
    //rule 1: gcd(a,0)=a
    //rule 2: gcd(a,b)=gcd(b,a mod b)
    static int gcdEuclideIterative(int x,int y){
        assert(x>=0);
        assert(y>=0);
        while(0!=x && 0!=y){
            int xbu=x;
            x=y;//gcd(a,b)=gcd(b,a mod b)
            y=xbu%y;
        }
        return x+y;//gcd(a,0)=a
    }

                
> gcd speed up
> ------------
>
>                 Key: MATH-841
>                 URL: https://issues.apache.org/jira/browse/MATH-841
>             Project: Commons Math
>          Issue Type: Improvement
>    Affects Versions: 3.0
>         Environment: ubuntu 32bits/intel-i5/java6
>            Reporter: Sebastien Riou
>            Priority: Trivial
>              Labels: patch, performance
>             Fix For: 3.1
>
>         Attachments: patchGcdInt.txt
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> The gcd(int,int) method of ArithmeticUtils seems 2 times slower than the 
> naive approach using modulo operator. The following test code runs in 11s 
> with current version and in 6s with the patch.
> public void testApache(){
>         Random rng=new Random(0);
>         long checksum=0;
>         long start=System.nanoTime();
>         checksum+=gcd(0,Integer.MAX_VALUE);
>         checksum+=gcd(Integer.MAX_VALUE,0);
>         checksum+=gcd(Integer.MAX_VALUE,rng.nextInt());
>         for(int i=0;i<10000;i++) 
> checksum+=gcd(rng.nextInt(),Integer.MAX_VALUE);
>         checksum+=gcd(Integer.MAX_VALUE,Integer.MAX_VALUE);
>         checksum+=gcd(Integer.MIN_VALUE,1<<30);
>         checksum+=gcd(1<<30,1<<30);
>         checksum+=gcd(3 * (1<<20),9 * (1<<15));
>         for(int i=0;i<30000000;i++) 
> checksum+=gcd(rng.nextInt(),rng.nextInt());
>         long end=System.nanoTime();
>         long tns=end-start;
>         long tms=(tns+500000)/1000000;
>         long ts=(tms+500)/1000;
>         System.out.println("exec time="+ts+"s, ("+tms+"ms), 
> checksum="+checksum);
>         assertEquals(9023314441L,checksum);
>     }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to