English 中文(简体)
利用Finite Field FFT进行多彩的推广——选择最原始的团结根基
原标题:Polynomial multiplication using Finite Field FFT - the selection of nth primitive root of unity
  • 时间:2012-01-14 15:54:39
  •  标签:
  • c#
  • fft

As a school assignment, I am supposed to create a program in C# that multiplies two polynomials using FFT over a finite field.
My finite field of choice would be Zp (all operations modulo p, the elements are {0,...,p - 1} ). I realized the p has to be large enough so that the factors in the resulting polynomial are not changed by the modulo operation.
Finding the nth primitive root of unity is easy for small n(in a corresponding finite field). However, I needed to find it for n = 220. I practically needed only this one as computing it for all the lower powers of 2 is done by squaring. I tried to write a simple program that would compute it(using the fact that there is 2r th root of unity in the finite field Zc*2r + 1), ran it for a pretty long time and it didn t finish. So I tried to Google something and only found a table of primitive nth roots for n = 2k for k = 0..30 in the field Z70383776563201 and used it. Of course when I used longint, it resulted in overflow and therefore, wrong answers. So I started using the BigInteger structure from the System.Numerics namespace. This is where I am, having a correct algorithm that is extremely slow:

private static List<BigInteger> FFT(List<BigInteger> input, BigInteger Omega)
            {
                if (input.Count == 1)
                {
                    return new List<BigInteger>() { input[0] };
                }
                else
                {
                    List<BigInteger> evenInput = new List<BigInteger>();
                    for (int i = 0; i < input.Count; i += 2)
                    {
                        evenInput.Add(input[i]);
                    }
                    List<BigInteger> oddInput = new List<BigInteger>();
                    for (int i = 1; i < input.Count; i += 2)
                    {
                        oddInput.Add(input[i]);
                    }
                    List<BigInteger> even = FFT(evenInput, (Omega * Omega));
                    List<BigInteger> odd = FFT(oddInput, (Omega * Omega));
                    BigInteger[] outputArr = new BigInteger[input.Count];
                    int count = 0;
                    for (int i = 0; i < input.Count / 2; i++)
                    {
                        outputArr[i] = (even[i] + BigInteger.Pow(Omega, i) * odd[i]);
                        outputArr[i + input.Count / 2] = (even[i] - BigInteger.Pow(Omega, i) * odd[i]);
                        count += 2;
                    }
                    List<BigInteger> output = new List<BigInteger>();
                    for (int i = 0; i < count; i++)
                    {
                        output.Add(outputArr[i] % finiteField);
                    }
                    return output;
                }
            }

I know that creating all the lists doesn t help the speed, but the main problem is the BigInteger structure of course.(I tried basically the same code with System.Numerics.Complex structure and it was as fast as it should be) The modulo operation takes extremely long, so I know I have to go back to longint. The problem is finding the primitive nth root of unity. I don t know if it s even possible to use the 220 th primitive root of unity with longint without having to worry about overflow. If not, for which n can I use longint and thus have a fast algorithm?
Is there a way of computing the primitive roots for large n faster? Maybe someone knows of a table of precomputed primitive roots in finite fields? Or should I consider using other finite fields? This is the only kind I know of. I have been searching for quite a long time and didn t come across anything useful. I have been told by the teacher that this area is well documented, but it doesn t seem to be the case.

最佳回答

我完全不认为它,但你似乎不认为,在转向“大负债”时,这种差别很大——10x可能? 你的算术为2^20,因此,你的人数应该仍然很少。 我想到的是你们的问题:Omega * Omega,特别是even[i] + BigInteger。 Pow(Omega, i) * odd[i]。 这将使你们的人数比他们所需要的要大得多。

Biginteger。 Pow在花费时间的长短方面有相当的运行时间。 你再做模块数学,这样你就能够减少模块化。 更经常的领域:Omega * Omega % finite Fieldeven [i] + BigInteger。 ModPow(Omega, i, finite Field) * odd[i]

问题回答

You can work in the ring modulo 2n+1, i.e. the numbers from 0 ... 2n inclusive. Since 2n == -1 (mod 2n+1) and the square of -1 is 1, 2 is the primitive (2*n)th root of unity in this ring.

What s more, modulo operations mod 2n+1 are easy to implement with shifts, adds and subs. That s very cheap even with bignums. Likewise, multiplications by powers of 2 are naturally only shifts (plus the mod operation).

这是。 Wikipedia的文章是一个良好的开端。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签