Factor a large number efficiently with gmp

前端 未结 4 1465
忘了有多久
忘了有多久 2020-12-17 02:06

I need to get all the prime factors of large numbers that can easily get to 1k bits. The numbers are practically random so it shouldn\'t be hard. How do I do it efficiently?

4条回答
  •  庸人自扰
    2020-12-17 03:09

    You could use Pollard p-1 factorization algorithm if the number you want to factor has small prime factors. It has factored out a 30 digit prime factor of the number 2 ^ 740 + 1. ECM is a similar but sub-exponetial algorithm but implementation is more difficult. The amount of time the algorithm is based on what the bound b is set as. It will factor any number which has a factor p where p - 1 is b-smooth.

    //Pollard p - 1 factorization algorithm
    
    void factor(mpz_t g, mpz_t n, long b)
    {
        //sieve for primes
        std::vector r;
    
        for(int i = 0; i < b; i++)
            r.push_back(true);
    
    
        for(int i = 2; i < ceil(sqrt(b - 1)); i++)
            if(r.at(i) == true)
                for(int j = i * i; j < b; j += i)
                    r.at(j) = false;
    
        std::vector p;
        std::vector a;
        for(int i = 2; i < b; i++)
            if(r[i] == true)
            {
                p.push_back(i);//Append the prime on to the vector
                int temp = floor(log(b) / log(i)); //temp = logb(i)
    
                // put primes in to sieve
                // a = the maximum power for p ^ a < bound b
                if(temp == 0)
                    a.push_back(1);
                else
                    a.push_back(temp);                
            }
    
        int m = p.size();//m = number of primes under bound b
    
        mpz_t c;// c is the number Which will be exponated
        mpz_init(c);
        long two = 2;
        mpz_set_ui(c, two);// set c to 2
    
        int z = 0;
        long x = 2;
    
        // loop c until a factor is found
        for(;;)
        {
        mpz_set_si( c, x);
    
        //powering ladder
        for(long i = 0; i < m; i++)
            for(long j = 0; j < a[i]; j++)
                mpz_powm_ui(c , c, (p[i]), n);
    
        //check if a factor has been found;
        mpz_sub_ui(c ,c,1);
        mpz_gcd(g ,c, n);
        mpz_add_ui(c , c, 1);
    
        //if g is a factor return else increment c
        if((mpz_cmp_si(g,1)) > 0 && (mpz_cmp(g,n)) < 0)
            return;
        else if (x > b)
            break;
        else
            x++;
        }
    
    }
    
    
    int main()
    {
        mpz_t x;
        mpz_t g;
    
        //intialize g and x
        mpz_init(g);
        mpz_init_set_str(x,"167698757698757868925234234253423534235342655234234235342353423546435347",10);
    
        //p-1 will factor x as long as it has a factor p where p - 1 is b-smooth(has all prime factors less than bound b)
        factor(g , x, 1000);
    
        //output the factor, it will output 1 if algorithm fails
        mpz_out_str(NULL, 10, g);
    
        return 0;
    }
    

    Outputs - 7465647 Execution time - 0.003 seconds

    Another Factoring algorithm created by J.Pollard was Pollards Rho algorithm which is not that quick but requires very little space. Their are also ways to parrelize it. Its complexity is O(n^1/4)

    //Pollard rho factoring algorithm
    void rho(mpz_t g, mpz_t n)
    {
        mpz_t x;
        mpz_t y;
        mpz_init_set_ui(x ,2);
        mpz_init_set_ui(y ,2);//initialize x and y as 2
        mpz_set_ui(g , 1);
        mpz_t temp;
        mpz_init(temp);
    
        if(mpz_probab_prime_p(n,25) != 0)
            return;//test if n is prime with miller rabin test
    
        int count;
        int t1 = 0;
        int t2 = 1;
        int nextTerm = t1 + t2;
        while(mpz_cmp_ui(g,1) < 1)
        {
            f(x,n);//x is changed
            f(y,n);//y is going through the sequence twice as fast
            f(y,n);
    
            if(count == nextTerm)//calculate gcd every fibonacci number
            {
                mpz_sub(temp,x,y);
                mpz_gcd(g , temp, n);
    
                t1 = t2;
                t2 = nextTerm;
                nextTerm = t1 + t2;//calculate next fibonacci number
            }
    
            count ++;
        }
    
        return;
    }
    
    int main()
    {
        mpz_t x;
        mpz_t g;
    
        //intialize g and x
        mpz_init(g);
        mpz_init_set_str(x,"167698757698757868925234234253423",10);
    
    
        rho(g , x);
    
        //output the factor, it will output 1 if algorithm fails
        mpz_out_str(NULL, 10, g);
    
        return 0;
    }
    

    Outputs - 353 Execution time - 0.003s

提交回复
热议问题