Question

Given a set of n particles electric charge carriers founds on the points (1,0), (2,0), .... (n,0) on a plane. The particle charge that found in point (i,0) is noted as Qi. the force that act on the particle is given by the formula:

enter image description here C is a Coulomb's constant.

Give an algorithm to calculate Fi, for all of the particles in total complexity O(nlgn). Hint: use FFT algorithm.

It seems that Fi is already divided to the even and odd points..

I thought about to divide each sum to calculate the FFT (but divide until what..?) and then sum always half of the points (cause this is what FFT cause) and then subtract the result of the sums that given on the formula..

any idea of how to do it better?

Était-ce utile?

La solution

looks like homework so no actual code for your case is provided instead some example and hints.
for FFT-like algorithms:

  1. set the dataset size to power of 2 by zero padding

    so the division to halves is simple (no remainders)

  2. create recursive function to compute your FFT-like stuff

    in it reorder the data set, divide it to two halves and recursively call it self 2 times (each with the different half of data) and add if statement to start. If dataset size<=1 or 2 then return directly computed value to ensure that recursion stops.

    After these two recursion calls reorder data back and combine them to result

  3. remove zero padding from the result if needed

For example this is how mine NTT looks like (Number theoretic transform)

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_fast(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    // recursion stop condition if the data is single number ...
    if (n<=1) { if (n==1) dst[0]=src[0]; return; }
    DWORD i,j,a0,a1,n2=n>>1,w2=modmul(w,w);
    // reorder even,odd to dst array
    for (i=0,j=0;i<n2;i++,j+=2) dst[i]=src[j];
    for (    j=1;i<n ;i++,j+=2) dst[i]=src[j];
    // recursion
    NTT_fast(src   ,dst   ,n2,w2);  // even
    NTT_fast(src+n2,dst+n2,n2,w2);  // odd
    // restore results
    for (w2=1,i=0,j=n2;i<n2;i++,j++,w2=modmul(w2,w))
        {
        a0=src[i];
        a1=modmul(src[j],w2);
        dst[i]=modadd(a0,a1);
        dst[j]=modsub(a0,a1);
        }
    }
//---------------------------------------------------------------------------

Full source code and more info is here.

Always compare Fast implementation results with the slow implementation !!!

A small error in some coefficient or index can lead to huge differences in results with growing dataset size.

This is slow implementation for above NTT function:

//---------------------------------------------------------------------------
void fourier_NTT:: NTT_slow(DWORD *dst,DWORD *src,DWORD n,DWORD w)
    {
    DWORD i,j,wj,wi,a,n2=n>>1;
    for (wj=1,j=0;j<n;j++)
        {
        a=0;
        for (wi=1,i=0;i<n;i++)
            {
            a=modadd(a,modmul(wi,src[i]));
            wi=modmul(wi,wj);
            }
        dst[j]=a;
        wj=modmul(wj,w);
        }
    }
//---------------------------------------------------------------------------

[Notes]

  1. now you have your separation equation

    derive the coefficient difference between directly computed value and value computed by 2x half recursion call and restore your result accordingly so the output match the correct result.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top