在Schönhage–Strassen算法中如何选择内环?


9

我一直在尝试实现Schönhage–Strassen整数乘法算法,但是在递归步骤中遇到了绊脚石。

我有一个位的值,我想计算。我最初以为是选择一个k,使4 ^ k \ geq 2n,将x分成2 ^ k个,每个具有2 ^ {k-1}位,在对2 ^ {2 ^ k}进行模运算时应用SSA的卷积+1,即每个值具有2 ^ k位容量的环,然后将碎片放回原处。但是,卷积的输出略大于2n位(即> 2 ^ kXnx2(mod2n+1)k4k2nx2k2k122k+12k2n>2k每个输出值的位数大于环的容量,这是因为每个输出值是多个乘积之和),所以这是行不通的。我必须添加2的额外因素。

填充中的额外2因子破坏了复杂性。这使我的递归步骤太昂贵了。代替了F(n)=nlgn+nF(2n)=Θ(nlgnlglgn)算法用F(n)=nlgn+nF(4n)=Θ(nlg2n)算法。

我阅读了一些来自维基百科的链接,但它们似乎都掩盖了如何解决此问题的细节。例如,我可以通过工作模避免额外的填充开销的,这不是2的幂......但后来的事情后来才破的时候我只有非功率剩下2个因素,并且在不加倍数量的情况下不能应用Cooley-Tukey。而且,可能不具有模的乘法逆。因此,仍然存在2的强制因素。2p2k+1pp2p+1个

如何在递归步骤中选择要使用的环,而又不增加渐近复杂性?

或者,以伪代码形式:

multiply_in_ring(a, b, n):
  ...
  // vvv                          vvv //
  // vvv HOW DOES THIS PART WORK? vvv //
  // vvv                          vvv //
  let inner_ring = convolution_ring_for_values_of_size(n);
  // ^^^                          ^^^ //
  // ^^^ HOW DOES THIS PART WORK? ^^^ //
  // ^^^                          ^^^ //

  let input_bits_per_piece = ceil(n / inner_ring.order);
  let piecesA = a.splitIntoNPiecesOfSize(inner_ring.order, input_bits_per_piece);
  let piecesB = b.splitIntoNPiecesOfSize(inner_ring.order, input_bits_per_piece);

  let piecesC = inner_ring.negacyclic_convolution(piecesA, piecesB);
  ...

不要在多个站点上发布相同的问题。每个社区都应该诚实地回答,而不会浪费任何时间。我建议您删除两个副本之一。
DW

@DW完成。在cs一个星期没有给出任何答案之后,我交叉张贴了文章,认为那对于该网站来说太难了。显然要链接回任何答案。
Craig Gidney

我明白。如果将来出现这种情况,您可以随时标记您的帖子以引起版主注意,并要求将其迁移,我们可以为您将其移至CSTheory。感谢您的理解!
DW

3
该算法有一个版本,其形式为以下形式的模数 2ν2n:A.Schönhage。具有复杂系数的多项式的数值乘法和除法的渐近快速算法。在EUROCAM '82:欧洲计算机代数会议,Lect。Notes Comp。科学 144,3-15。iai.uni-bonn.de/~schoe/publi39.dvi
MarkusBläser2016年

IIRC您对现在删除的CS问题有部分自我解答。失去这一点似乎很可耻。您可以在这里添加它吗(在问题中,这样就不会将问题标记为已回答)?
彼得·泰勒

Answers:


4

该答案摘自Markus在评论中链接的论文“渐近快速算法,用于对具有复杂系数的多项式进行数值乘法和除法”


你想平方 ñ位数,模 2ñ+1个。这是您的工作:

  • ps 满足 ñ=p-1个2ssp2s

  • 挑选件数 2 分割 ñ 位,以及相应的件数参数:

    =s/2+1个s2=s/2+1个p2=p/2+1个

    注意 s2p2 继续满足 s2p22s2不变的 另请注意22s2p22ñ++1个 满足,因此输入内容适合携带。

  • 像往常一样,在片段上执行基于FFT的负循环卷积,其余部分执行。

这就是最主要的思想:对数填充因子 p。现在进行复杂性分析。FFT将ñ 工作要做,我们继续 2 大小 p2-1个2s2,因此我们现在可以使用递归关系wrt进行极其粗略的数学运算 s

F(s)()(p1)2sm+2mF(s/2+1)()2s2s(s/2+1)+2s/2+1F(s/2+1)()s22s+22s/2F(s/2+1)()s22s+4(s/2)22s+16(s/4)22s+...()2ss2lg(s)()nlgn(lgnlgn)2lglgnlgn()nlgn(lg2n)lglgn()n(lgn)lglgn

尽管我在这些步骤中作弊很多,但这似乎是对的。

“把戏”似乎是我们最终得到的事实 s2 代替 s基本费用。每个递归级别仍然有两个乘以2的乘积,就像我在问题中抱怨的那样,但是现在减半s付出了双倍的红利,所以一切顺利。然后,最后,我们取消了s (实际上是 logn)多亏了 p 相对于 s 原来。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.