C++ Pollard Rho在输入不太大时崩溃

C++ Pollard Rho在输入不太大时崩溃,c++,algorithm,math,gmp,C++,Algorithm,Math,Gmp,我实现了上给出的Pollard Rho算法 较大的输入会导致错误: GNU MP:无法分配内存(大小=4294950944) 这是我的实现 mpz_class factor(mpz_class num) { mpz_class x(2), y(2), d(1); while(d == 1) { x = polynomial(x); y = polynomial(polynomial(y)); mpz_class diff =

我实现了上给出的Pollard Rho算法

较大的输入会导致错误:

GNU MP:无法分配内存(大小=4294950944)

这是我的实现

mpz_class factor(mpz_class num)
{
    mpz_class x(2), y(2), d(1);
    while(d == 1)
    {
        x = polynomial(x);
        y = polynomial(polynomial(y));
        mpz_class diff = x - y;
        if(diff < 0)
        {
            diff *= -1;
        }
        mpz_gcd(d.get_mpz_t(), diff.get_mpz_t(), num.get_mpz_t());
    }
    if(d == num)
    {
        return -1;//failure
    }
    else
    {
        return d;//found factor
    }
}

mpz_class polynomial (mpz_class x)
{
    return ((x * x) + 1);
}
mpz_类系数(mpz_类数值)
{
mpz_类x(2)、y(2)、d(1);
而(d==1)
{
x=多项式(x);
y=多项式(多项式(y));
mpz_类差异=x-y;
如果(差异<0)
{
差异*=-1;
}
mpz_gcd(d.get_mpz_t(),diff.get_mpz_t(),num.get_mpz_t());
}
如果(d==num)
{
返回-1;//失败
}
其他的
{
返回d;//找到的因子
}
}
mpz_类多项式(mpz_类x)
{
返回((x*x)+1);
}
它在121这样的输入上工作,但在5540987上崩溃。我做错什么了吗?有没有办法改进这一点,以便将这些数字考虑在内?我看到它似乎使用了多项式
((x*x)%N+c)%N
(注意额外的mod N)。这是因为任何多项式都可以使用吗?

有两个模运算是多余的,但有一个模运算可以精确地解决这个问题,即除非算法很早终止(这是针对121的)

这是因为任何多项式都可以使用吗

这有点微妙,在混合中加入模运算并不是真正的“任何多项式”。关键是算法所寻找的是某个序列中的两个值
x[i]
x[j]
i!=j
使得
abs(x[i]-x[j])
p
的倍数(其中
N=pq
p
q
都不是1),或者换句话说,
abs(x[i]-x[j])mod p=0
x[i]≡ x[j]模块p
。在这一点上,当以模
p
查看时,在序列中发现了一个循环,重要的是如果
x[i]!=x[j]
那么它们的差值是
p
的非零倍数,这就有机会从
N
中提取一个因子。。至少,如果它们的差异不是
N
的倍数(在这种情况下,GCD的结果将是
N
本身,并且没有因子出来)

因此,纯粹从数学角度来看,模
N
步骤在理论上是不必要的,循环模
p
在没有这种“帮助”的情况下发生。但是这是可能的,
N=pq
因此,如果我们减少序列模
N
,那么它的模
p
属性不会受到干扰,算法仍然有效。除此之外,约化模
N
在实际中非常重要,因为它可以阻止所涉及的数字变得不切实际的大,否则不仅会减慢算法的速度,而且最终会在实际(有限大小)硬件上失败

这是很多理论上的论证,实现起来非常简单

mpz_class polynomial (mpz_class x, mpz_class num)
{
    return ((x * x) + 1) % num;
}

谢谢既然您似乎知道这一点,为什么有些实现使用随机值而不是从x=2和c=1开始?@northerner当找到一个循环,但它产生的“因子”是
N
本身时,算法可能会“失败”。使用多项式中的随机起始点或偏移量,您可以重试,并获得另一个查找因子的机会
mpz_class polynomial (mpz_class x, mpz_class num)
{
    return ((x * x) + 1) % num;
}