Example #1
0
        /*************************************************************************
        This subroutine executes FFT/FHT plan.

        If Plan is a:
        * complex FFT plan  -   sizeof(A)=2*N,
                                A contains interleaved real/imaginary values
        * real FFT plan     -   sizeof(A)=2*N,
                                A contains real values interleaved with zeros
        * real FHT plan     -   sizeof(A)=2*N,
                                A contains real values interleaved with zeros

          -- ALGLIB --
             Copyright 01.05.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void ftbaseexecuteplan(ref double[] a,
            int aoffset,
            int n,
            ref ftplan plan)
        {
            int stackptr = 0;

            stackptr = 0;
            ftbaseexecuteplanrec(ref a, aoffset, ref plan, 0, stackptr);
        }
Example #2
0
        /*************************************************************************
        Recurrent subroutine for the FTBaseExecutePlan

        Parameters:
            A           FFT'ed array
            AOffset     offset of the FFT'ed part (distance is measured in doubles)

          -- ALGLIB --
             Copyright 01.05.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void ftbaseexecuteplanrec(ref double[] a,
            int aoffset,
            ftplan plan,
            int entryoffset,
            int stackptr)
        {
            int i = 0;
            int j = 0;
            int k = 0;
            int n1 = 0;
            int n2 = 0;
            int n = 0;
            int m = 0;
            int offs = 0;
            int offs1 = 0;
            int offs2 = 0;
            int offsa = 0;
            int offsb = 0;
            int offsp = 0;
            double hk = 0;
            double hnk = 0;
            double x = 0;
            double y = 0;
            double bx = 0;
            double by = 0;
            double[] emptyarray = new double[0];
            double a0x = 0;
            double a0y = 0;
            double a1x = 0;
            double a1y = 0;
            double a2x = 0;
            double a2y = 0;
            double a3x = 0;
            double a3y = 0;
            double v0 = 0;
            double v1 = 0;
            double v2 = 0;
            double v3 = 0;
            double t1x = 0;
            double t1y = 0;
            double t2x = 0;
            double t2y = 0;
            double t3x = 0;
            double t3y = 0;
            double t4x = 0;
            double t4y = 0;
            double t5x = 0;
            double t5y = 0;
            double m1x = 0;
            double m1y = 0;
            double m2x = 0;
            double m2y = 0;
            double m3x = 0;
            double m3y = 0;
            double m4x = 0;
            double m4y = 0;
            double m5x = 0;
            double m5y = 0;
            double s1x = 0;
            double s1y = 0;
            double s2x = 0;
            double s2y = 0;
            double s3x = 0;
            double s3y = 0;
            double s4x = 0;
            double s4y = 0;
            double s5x = 0;
            double s5y = 0;
            double c1 = 0;
            double c2 = 0;
            double c3 = 0;
            double c4 = 0;
            double c5 = 0;
            double[] tmp = new double[0];
            int i_ = 0;
            int i1_ = 0;

            if( plan.plan[entryoffset+3]==fftemptyplan )
            {
                return;
            }
            if( plan.plan[entryoffset+3]==fftcooleytukeyplan )
            {
                
                //
                // Cooley-Tukey plan
                // * transposition
                // * row-wise FFT
                // * twiddle factors:
                //   - TwBase is a basis twiddle factor for I=1, J=1
                //   - TwRow is a twiddle factor for a second element in a row (J=1)
                //   - Tw is a twiddle factor for a current element
                // * transposition again
                // * row-wise FFT again
                //
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                internalcomplexlintranspose(ref a, n1, n2, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n2-1; i++)
                {
                    ftbaseexecuteplanrec(ref a, aoffset+i*n1*2, plan, plan.plan[entryoffset+5], stackptr);
                }
                ffttwcalc(ref a, aoffset, n1, n2);
                internalcomplexlintranspose(ref a, n2, n1, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n1-1; i++)
                {
                    ftbaseexecuteplanrec(ref a, aoffset+i*n2*2, plan, plan.plan[entryoffset+6], stackptr);
                }
                internalcomplexlintranspose(ref a, n1, n2, aoffset, ref plan.tmpbuf);
                return;
            }
            if( plan.plan[entryoffset+3]==fftrealcooleytukeyplan )
            {
                
                //
                // Cooley-Tukey plan
                // * transposition
                // * row-wise FFT
                // * twiddle factors:
                //   - TwBase is a basis twiddle factor for I=1, J=1
                //   - TwRow is a twiddle factor for a second element in a row (J=1)
                //   - Tw is a twiddle factor for a current element
                // * transposition again
                // * row-wise FFT again
                //
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                internalcomplexlintranspose(ref a, n2, n1, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n1/2-1; i++)
                {
                    
                    //
                    // pack two adjacent smaller real FFT's together,
                    // make one complex FFT,
                    // unpack result
                    //
                    offs = aoffset+2*i*n2*2;
                    for(k=0; k<=n2-1; k++)
                    {
                        a[offs+2*k+1] = a[offs+2*n2+2*k+0];
                    }
                    ftbaseexecuteplanrec(ref a, offs, plan, plan.plan[entryoffset+6], stackptr);
                    plan.tmpbuf[0] = a[offs+0];
                    plan.tmpbuf[1] = 0;
                    plan.tmpbuf[2*n2+0] = a[offs+1];
                    plan.tmpbuf[2*n2+1] = 0;
                    for(k=1; k<=n2-1; k++)
                    {
                        offs1 = 2*k;
                        offs2 = 2*n2+2*k;
                        hk = a[offs+2*k+0];
                        hnk = a[offs+2*(n2-k)+0];
                        plan.tmpbuf[offs1+0] = 0.5*(hk+hnk);
                        plan.tmpbuf[offs2+1] = -(0.5*(hk-hnk));
                        hk = a[offs+2*k+1];
                        hnk = a[offs+2*(n2-k)+1];
                        plan.tmpbuf[offs2+0] = 0.5*(hk+hnk);
                        plan.tmpbuf[offs1+1] = 0.5*(hk-hnk);
                    }
                    i1_ = (0) - (offs);
                    for(i_=offs; i_<=offs+2*n2*2-1;i_++)
                    {
                        a[i_] = plan.tmpbuf[i_+i1_];
                    }
                }
                if( n1%2!=0 )
                {
                    ftbaseexecuteplanrec(ref a, aoffset+(n1-1)*n2*2, plan, plan.plan[entryoffset+6], stackptr);
                }
                ffttwcalc(ref a, aoffset, n2, n1);
                internalcomplexlintranspose(ref a, n1, n2, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n2-1; i++)
                {
                    ftbaseexecuteplanrec(ref a, aoffset+i*n1*2, plan, plan.plan[entryoffset+5], stackptr);
                }
                internalcomplexlintranspose(ref a, n2, n1, aoffset, ref plan.tmpbuf);
                return;
            }
            if( plan.plan[entryoffset+3]==fhtcooleytukeyplan )
            {
                
                //
                // Cooley-Tukey FHT plan:
                // * transpose                    \
                // * smaller FHT's                |
                // * pre-process                  |
                // * multiply by twiddle factors  | corresponds to multiplication by H1
                // * post-process                 |
                // * transpose again              /
                // * multiply by H2 (smaller FHT's)
                // * final transposition
                //
                // For more details see Vitezslav Vesely, "Fast algorithms
                // of Fourier and Hartley transform and their implementation in MATLAB",
                // page 31.
                //
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                n = n1*n2;
                internalreallintranspose(ref a, n1, n2, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n2-1; i++)
                {
                    ftbaseexecuteplanrec(ref a, aoffset+i*n1, plan, plan.plan[entryoffset+5], stackptr);
                }
                for(i=0; i<=n2-1; i++)
                {
                    for(j=0; j<=n1-1; j++)
                    {
                        offsa = aoffset+i*n1;
                        hk = a[offsa+j];
                        hnk = a[offsa+(n1-j)%n1];
                        offs = 2*(i*n1+j);
                        plan.tmpbuf[offs+0] = -(0.5*(hnk-hk));
                        plan.tmpbuf[offs+1] = 0.5*(hk+hnk);
                    }
                }
                ffttwcalc(ref plan.tmpbuf, 0, n1, n2);
                for(j=0; j<=n1-1; j++)
                {
                    a[aoffset+j] = plan.tmpbuf[2*j+0]+plan.tmpbuf[2*j+1];
                }
                if( n2%2==0 )
                {
                    offs = 2*(n2/2)*n1;
                    offsa = aoffset+n2/2*n1;
                    for(j=0; j<=n1-1; j++)
                    {
                        a[offsa+j] = plan.tmpbuf[offs+2*j+0]+plan.tmpbuf[offs+2*j+1];
                    }
                }
                for(i=1; i<=(n2+1)/2-1; i++)
                {
                    offs = 2*i*n1;
                    offs2 = 2*(n2-i)*n1;
                    offsa = aoffset+i*n1;
                    for(j=0; j<=n1-1; j++)
                    {
                        a[offsa+j] = plan.tmpbuf[offs+2*j+1]+plan.tmpbuf[offs2+2*j+0];
                    }
                    offsa = aoffset+(n2-i)*n1;
                    for(j=0; j<=n1-1; j++)
                    {
                        a[offsa+j] = plan.tmpbuf[offs+2*j+0]+plan.tmpbuf[offs2+2*j+1];
                    }
                }
                internalreallintranspose(ref a, n2, n1, aoffset, ref plan.tmpbuf);
                for(i=0; i<=n1-1; i++)
                {
                    ftbaseexecuteplanrec(ref a, aoffset+i*n2, plan, plan.plan[entryoffset+6], stackptr);
                }
                internalreallintranspose(ref a, n1, n2, aoffset, ref plan.tmpbuf);
                return;
            }
            if( plan.plan[entryoffset+3]==fhtn2plan )
            {
                
                //
                // Cooley-Tukey FHT plan
                //
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                n = n1*n2;
                reffht(ref a, n, aoffset);
                return;
            }
            if( plan.plan[entryoffset+3]==fftcodeletplan )
            {
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                n = n1*n2;
                if( n==2 )
                {
                    a0x = a[aoffset+0];
                    a0y = a[aoffset+1];
                    a1x = a[aoffset+2];
                    a1y = a[aoffset+3];
                    v0 = a0x+a1x;
                    v1 = a0y+a1y;
                    v2 = a0x-a1x;
                    v3 = a0y-a1y;
                    a[aoffset+0] = v0;
                    a[aoffset+1] = v1;
                    a[aoffset+2] = v2;
                    a[aoffset+3] = v3;
                    return;
                }
                if( n==3 )
                {
                    offs = plan.plan[entryoffset+7];
                    c1 = plan.precomputed[offs+0];
                    c2 = plan.precomputed[offs+1];
                    a0x = a[aoffset+0];
                    a0y = a[aoffset+1];
                    a1x = a[aoffset+2];
                    a1y = a[aoffset+3];
                    a2x = a[aoffset+4];
                    a2y = a[aoffset+5];
                    t1x = a1x+a2x;
                    t1y = a1y+a2y;
                    a0x = a0x+t1x;
                    a0y = a0y+t1y;
                    m1x = c1*t1x;
                    m1y = c1*t1y;
                    m2x = c2*(a1y-a2y);
                    m2y = c2*(a2x-a1x);
                    s1x = a0x+m1x;
                    s1y = a0y+m1y;
                    a1x = s1x+m2x;
                    a1y = s1y+m2y;
                    a2x = s1x-m2x;
                    a2y = s1y-m2y;
                    a[aoffset+0] = a0x;
                    a[aoffset+1] = a0y;
                    a[aoffset+2] = a1x;
                    a[aoffset+3] = a1y;
                    a[aoffset+4] = a2x;
                    a[aoffset+5] = a2y;
                    return;
                }
                if( n==4 )
                {
                    a0x = a[aoffset+0];
                    a0y = a[aoffset+1];
                    a1x = a[aoffset+2];
                    a1y = a[aoffset+3];
                    a2x = a[aoffset+4];
                    a2y = a[aoffset+5];
                    a3x = a[aoffset+6];
                    a3y = a[aoffset+7];
                    t1x = a0x+a2x;
                    t1y = a0y+a2y;
                    t2x = a1x+a3x;
                    t2y = a1y+a3y;
                    m2x = a0x-a2x;
                    m2y = a0y-a2y;
                    m3x = a1y-a3y;
                    m3y = a3x-a1x;
                    a[aoffset+0] = t1x+t2x;
                    a[aoffset+1] = t1y+t2y;
                    a[aoffset+4] = t1x-t2x;
                    a[aoffset+5] = t1y-t2y;
                    a[aoffset+2] = m2x+m3x;
                    a[aoffset+3] = m2y+m3y;
                    a[aoffset+6] = m2x-m3x;
                    a[aoffset+7] = m2y-m3y;
                    return;
                }
                if( n==5 )
                {
                    offs = plan.plan[entryoffset+7];
                    c1 = plan.precomputed[offs+0];
                    c2 = plan.precomputed[offs+1];
                    c3 = plan.precomputed[offs+2];
                    c4 = plan.precomputed[offs+3];
                    c5 = plan.precomputed[offs+4];
                    t1x = a[aoffset+2]+a[aoffset+8];
                    t1y = a[aoffset+3]+a[aoffset+9];
                    t2x = a[aoffset+4]+a[aoffset+6];
                    t2y = a[aoffset+5]+a[aoffset+7];
                    t3x = a[aoffset+2]-a[aoffset+8];
                    t3y = a[aoffset+3]-a[aoffset+9];
                    t4x = a[aoffset+6]-a[aoffset+4];
                    t4y = a[aoffset+7]-a[aoffset+5];
                    t5x = t1x+t2x;
                    t5y = t1y+t2y;
                    a[aoffset+0] = a[aoffset+0]+t5x;
                    a[aoffset+1] = a[aoffset+1]+t5y;
                    m1x = c1*t5x;
                    m1y = c1*t5y;
                    m2x = c2*(t1x-t2x);
                    m2y = c2*(t1y-t2y);
                    m3x = -(c3*(t3y+t4y));
                    m3y = c3*(t3x+t4x);
                    m4x = -(c4*t4y);
                    m4y = c4*t4x;
                    m5x = -(c5*t3y);
                    m5y = c5*t3x;
                    s3x = m3x-m4x;
                    s3y = m3y-m4y;
                    s5x = m3x+m5x;
                    s5y = m3y+m5y;
                    s1x = a[aoffset+0]+m1x;
                    s1y = a[aoffset+1]+m1y;
                    s2x = s1x+m2x;
                    s2y = s1y+m2y;
                    s4x = s1x-m2x;
                    s4y = s1y-m2y;
                    a[aoffset+2] = s2x+s3x;
                    a[aoffset+3] = s2y+s3y;
                    a[aoffset+4] = s4x+s5x;
                    a[aoffset+5] = s4y+s5y;
                    a[aoffset+6] = s4x-s5x;
                    a[aoffset+7] = s4y-s5y;
                    a[aoffset+8] = s2x-s3x;
                    a[aoffset+9] = s2y-s3y;
                    return;
                }
            }
            if( plan.plan[entryoffset+3]==fhtcodeletplan )
            {
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                n = n1*n2;
                if( n==2 )
                {
                    a0x = a[aoffset+0];
                    a1x = a[aoffset+1];
                    a[aoffset+0] = a0x+a1x;
                    a[aoffset+1] = a0x-a1x;
                    return;
                }
                if( n==3 )
                {
                    offs = plan.plan[entryoffset+7];
                    c1 = plan.precomputed[offs+0];
                    c2 = plan.precomputed[offs+1];
                    a0x = a[aoffset+0];
                    a1x = a[aoffset+1];
                    a2x = a[aoffset+2];
                    t1x = a1x+a2x;
                    a0x = a0x+t1x;
                    m1x = c1*t1x;
                    m2y = c2*(a2x-a1x);
                    s1x = a0x+m1x;
                    a[aoffset+0] = a0x;
                    a[aoffset+1] = s1x-m2y;
                    a[aoffset+2] = s1x+m2y;
                    return;
                }
                if( n==4 )
                {
                    a0x = a[aoffset+0];
                    a1x = a[aoffset+1];
                    a2x = a[aoffset+2];
                    a3x = a[aoffset+3];
                    t1x = a0x+a2x;
                    t2x = a1x+a3x;
                    m2x = a0x-a2x;
                    m3y = a3x-a1x;
                    a[aoffset+0] = t1x+t2x;
                    a[aoffset+1] = m2x-m3y;
                    a[aoffset+2] = t1x-t2x;
                    a[aoffset+3] = m2x+m3y;
                    return;
                }
                if( n==5 )
                {
                    offs = plan.plan[entryoffset+7];
                    c1 = plan.precomputed[offs+0];
                    c2 = plan.precomputed[offs+1];
                    c3 = plan.precomputed[offs+2];
                    c4 = plan.precomputed[offs+3];
                    c5 = plan.precomputed[offs+4];
                    t1x = a[aoffset+1]+a[aoffset+4];
                    t2x = a[aoffset+2]+a[aoffset+3];
                    t3x = a[aoffset+1]-a[aoffset+4];
                    t4x = a[aoffset+3]-a[aoffset+2];
                    t5x = t1x+t2x;
                    v0 = a[aoffset+0]+t5x;
                    a[aoffset+0] = v0;
                    m2x = c2*(t1x-t2x);
                    m3y = c3*(t3x+t4x);
                    s3y = m3y-c4*t4x;
                    s5y = m3y+c5*t3x;
                    s1x = v0+c1*t5x;
                    s2x = s1x+m2x;
                    s4x = s1x-m2x;
                    a[aoffset+1] = s2x-s3y;
                    a[aoffset+2] = s4x-s5y;
                    a[aoffset+3] = s4x+s5y;
                    a[aoffset+4] = s2x+s3y;
                    return;
                }
            }
            if( plan.plan[entryoffset+3]==fftbluesteinplan )
            {
                
                //
                // Bluestein plan:
                // 1. multiply by precomputed coefficients
                // 2. make convolution: forward FFT, multiplication by precomputed FFT
                //    and backward FFT. backward FFT is represented as
                //
                //        invfft(x) = fft(x')'/M
                //
                //    for performance reasons reduction of inverse FFT to
                //    forward FFT is merged with multiplication of FFT components
                //    and last stage of Bluestein's transformation.
                // 3. post-multiplication by Bluestein factors
                //
                n = plan.plan[entryoffset+1];
                m = plan.plan[entryoffset+4];
                offs = plan.plan[entryoffset+7];
                for(i=stackptr+2*n; i<=stackptr+2*m-1; i++)
                {
                    plan.stackbuf[i] = 0;
                }
                offsp = offs+2*m;
                offsa = aoffset;
                offsb = stackptr;
                for(i=0; i<=n-1; i++)
                {
                    bx = plan.precomputed[offsp+0];
                    by = plan.precomputed[offsp+1];
                    x = a[offsa+0];
                    y = a[offsa+1];
                    plan.stackbuf[offsb+0] = x*bx-y*-by;
                    plan.stackbuf[offsb+1] = x*-by+y*bx;
                    offsp = offsp+2;
                    offsa = offsa+2;
                    offsb = offsb+2;
                }
                ftbaseexecuteplanrec(ref plan.stackbuf, stackptr, plan, plan.plan[entryoffset+5], stackptr+2*2*m);
                offsb = stackptr;
                offsp = offs;
                for(i=0; i<=m-1; i++)
                {
                    x = plan.stackbuf[offsb+0];
                    y = plan.stackbuf[offsb+1];
                    bx = plan.precomputed[offsp+0];
                    by = plan.precomputed[offsp+1];
                    plan.stackbuf[offsb+0] = x*bx-y*by;
                    plan.stackbuf[offsb+1] = -(x*by+y*bx);
                    offsb = offsb+2;
                    offsp = offsp+2;
                }
                ftbaseexecuteplanrec(ref plan.stackbuf, stackptr, plan, plan.plan[entryoffset+5], stackptr+2*2*m);
                offsb = stackptr;
                offsp = offs+2*m;
                offsa = aoffset;
                for(i=0; i<=n-1; i++)
                {
                    x = plan.stackbuf[offsb+0]/m;
                    y = -(plan.stackbuf[offsb+1]/m);
                    bx = plan.precomputed[offsp+0];
                    by = plan.precomputed[offsp+1];
                    a[offsa+0] = x*bx-y*-by;
                    a[offsa+1] = x*-by+y*bx;
                    offsp = offsp+2;
                    offsa = offsa+2;
                    offsb = offsb+2;
                }
                return;
            }
        }
Example #3
0
        /*************************************************************************
        Generates real FHT plan
        *************************************************************************/
        public static void ftbasegeneraterealfhtplan(int n,
            ftplan plan)
        {
            int planarraysize = 0;
            int plansize = 0;
            int precomputedsize = 0;
            int tmpmemsize = 0;
            int stackmemsize = 0;
            int stackptr = 0;

            planarraysize = 1;
            plansize = 0;
            precomputedsize = 0;
            stackmemsize = 0;
            stackptr = 0;
            tmpmemsize = n;
            plan.plan = new int[planarraysize];
            ftbasegenerateplanrec(n, ftbaserfhttask, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
            ap.assert(stackptr==0, "Internal error in FTBaseGenerateRealFHTPlan: stack ptr!");
            plan.stackbuf = new double[Math.Max(stackmemsize, 1)];
            plan.tmpbuf = new double[Math.Max(tmpmemsize, 1)];
            plan.precomputed = new double[Math.Max(precomputedsize, 1)];
            stackptr = 0;
            ftbaseprecomputeplanrec(plan, 0, stackptr);
            ap.assert(stackptr==0, "Internal error in FTBaseGenerateRealFHTPlan: stack ptr!");
        }
Example #4
0
        /*************************************************************************
        Recurrent subroutine for precomputing FFT plans

          -- ALGLIB --
             Copyright 01.05.2009 by Bochkanov Sergey
        *************************************************************************/
        private static void ftbaseprecomputeplanrec(ftplan plan,
            int entryoffset,
            int stackptr)
        {
            int i = 0;
            int n1 = 0;
            int n2 = 0;
            int n = 0;
            int m = 0;
            int offs = 0;
            double v = 0;
            double[] emptyarray = new double[0];
            double bx = 0;
            double by = 0;

            if( (plan.plan[entryoffset+3]==fftcooleytukeyplan | plan.plan[entryoffset+3]==fftrealcooleytukeyplan) | plan.plan[entryoffset+3]==fhtcooleytukeyplan )
            {
                ftbaseprecomputeplanrec(plan, plan.plan[entryoffset+5], stackptr);
                ftbaseprecomputeplanrec(plan, plan.plan[entryoffset+6], stackptr);
                return;
            }
            if( plan.plan[entryoffset+3]==fftcodeletplan | plan.plan[entryoffset+3]==fhtcodeletplan )
            {
                n1 = plan.plan[entryoffset+1];
                n2 = plan.plan[entryoffset+2];
                n = n1*n2;
                if( n==3 )
                {
                    offs = plan.plan[entryoffset+7];
                    plan.precomputed[offs+0] = Math.Cos(2*Math.PI/3)-1;
                    plan.precomputed[offs+1] = Math.Sin(2*Math.PI/3);
                    return;
                }
                if( n==5 )
                {
                    offs = plan.plan[entryoffset+7];
                    v = 2*Math.PI/5;
                    plan.precomputed[offs+0] = (Math.Cos(v)+Math.Cos(2*v))/2-1;
                    plan.precomputed[offs+1] = (Math.Cos(v)-Math.Cos(2*v))/2;
                    plan.precomputed[offs+2] = -Math.Sin(v);
                    plan.precomputed[offs+3] = -(Math.Sin(v)+Math.Sin(2*v));
                    plan.precomputed[offs+4] = Math.Sin(v)-Math.Sin(2*v);
                    return;
                }
            }
            if( plan.plan[entryoffset+3]==fftbluesteinplan )
            {
                ftbaseprecomputeplanrec(plan, plan.plan[entryoffset+5], stackptr);
                n = plan.plan[entryoffset+1];
                m = plan.plan[entryoffset+4];
                offs = plan.plan[entryoffset+7];
                for(i=0; i<=2*m-1; i++)
                {
                    plan.precomputed[offs+i] = 0;
                }
                for(i=0; i<=n-1; i++)
                {
                    bx = Math.Cos(Math.PI*math.sqr(i)/n);
                    by = Math.Sin(Math.PI*math.sqr(i)/n);
                    plan.precomputed[offs+2*i+0] = bx;
                    plan.precomputed[offs+2*i+1] = by;
                    plan.precomputed[offs+2*m+2*i+0] = bx;
                    plan.precomputed[offs+2*m+2*i+1] = by;
                    if( i>0 )
                    {
                        plan.precomputed[offs+2*(m-i)+0] = bx;
                        plan.precomputed[offs+2*(m-i)+1] = by;
                    }
                }
                ftbaseexecuteplanrec(ref plan.precomputed, offs, plan, plan.plan[entryoffset+5], stackptr);
                return;
            }
        }
Example #5
0
        /*************************************************************************
        Recurrent subroutine for the FFTGeneratePlan:

        PARAMETERS:
            N                   plan size
            IsReal              whether input is real or not.
                                subroutine MUST NOT ignore this flag because real
                                inputs comes with non-initialized imaginary parts,
                                so ignoring this flag will result in corrupted output
            HalfOut             whether full output or only half of it from 0 to
                                floor(N/2) is needed. This flag may be ignored if
                                doing so will simplify calculations
            Plan                plan array
            PlanSize            size of used part (in integers)
            PrecomputedSize     size of precomputed array allocated yet
            PlanArraySize       plan array size (actual)
            TmpMemSize          temporary memory required size
            BluesteinMemSize    temporary memory required size

          -- ALGLIB --
             Copyright 01.05.2009 by Bochkanov Sergey
        *************************************************************************/
        private static void ftbasegenerateplanrec(int n,
            int tasktype,
            ftplan plan,
            ref int plansize,
            ref int precomputedsize,
            ref int planarraysize,
            ref int tmpmemsize,
            ref int stackmemsize,
            int stackptr)
        {
            int k = 0;
            int m = 0;
            int n1 = 0;
            int n2 = 0;
            int esize = 0;
            int entryoffset = 0;

            
            //
            // prepare
            //
            if( plansize+ftbaseplanentrysize>planarraysize )
            {
                fftarrayresize(ref plan.plan, ref planarraysize, 8*planarraysize);
            }
            entryoffset = plansize;
            esize = ftbaseplanentrysize;
            plansize = plansize+esize;
            
            //
            // if N=1, generate empty plan and exit
            //
            if( n==1 )
            {
                plan.plan[entryoffset+0] = esize;
                plan.plan[entryoffset+1] = -1;
                plan.plan[entryoffset+2] = -1;
                plan.plan[entryoffset+3] = fftemptyplan;
                plan.plan[entryoffset+4] = -1;
                plan.plan[entryoffset+5] = -1;
                plan.plan[entryoffset+6] = -1;
                plan.plan[entryoffset+7] = -1;
                return;
            }
            
            //
            // generate plans
            //
            ftbasefactorize(n, tasktype, ref n1, ref n2);
            if( tasktype==ftbasecffttask | tasktype==ftbaserffttask )
            {
                
                //
                // complex FFT plans
                //
                if( n1!=1 )
                {
                    
                    //
                    // Cooley-Tukey plan (real or complex)
                    //
                    // Note that child plans are COMPLEX
                    // (whether plan itself is complex or not).
                    //
                    tmpmemsize = Math.Max(tmpmemsize, 2*n1*n2);
                    plan.plan[entryoffset+0] = esize;
                    plan.plan[entryoffset+1] = n1;
                    plan.plan[entryoffset+2] = n2;
                    if( tasktype==ftbasecffttask )
                    {
                        plan.plan[entryoffset+3] = fftcooleytukeyplan;
                    }
                    else
                    {
                        plan.plan[entryoffset+3] = fftrealcooleytukeyplan;
                    }
                    plan.plan[entryoffset+4] = 0;
                    plan.plan[entryoffset+5] = plansize;
                    ftbasegenerateplanrec(n1, ftbasecffttask, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
                    plan.plan[entryoffset+6] = plansize;
                    ftbasegenerateplanrec(n2, ftbasecffttask, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
                    plan.plan[entryoffset+7] = -1;
                    return;
                }
                else
                {
                    if( ((n==2 | n==3) | n==4) | n==5 )
                    {
                        
                        //
                        // hard-coded plan
                        //
                        plan.plan[entryoffset+0] = esize;
                        plan.plan[entryoffset+1] = n1;
                        plan.plan[entryoffset+2] = n2;
                        plan.plan[entryoffset+3] = fftcodeletplan;
                        plan.plan[entryoffset+4] = 0;
                        plan.plan[entryoffset+5] = -1;
                        plan.plan[entryoffset+6] = -1;
                        plan.plan[entryoffset+7] = precomputedsize;
                        if( n==3 )
                        {
                            precomputedsize = precomputedsize+2;
                        }
                        if( n==5 )
                        {
                            precomputedsize = precomputedsize+5;
                        }
                        return;
                    }
                    else
                    {
                        
                        //
                        // Bluestein's plan
                        //
                        // Select such M that M>=2*N-1, M is composite, and M's
                        // factors are 2, 3, 5
                        //
                        k = 2*n2-1;
                        m = ftbasefindsmooth(k);
                        tmpmemsize = Math.Max(tmpmemsize, 2*m);
                        plan.plan[entryoffset+0] = esize;
                        plan.plan[entryoffset+1] = n2;
                        plan.plan[entryoffset+2] = -1;
                        plan.plan[entryoffset+3] = fftbluesteinplan;
                        plan.plan[entryoffset+4] = m;
                        plan.plan[entryoffset+5] = plansize;
                        stackptr = stackptr+2*2*m;
                        stackmemsize = Math.Max(stackmemsize, stackptr);
                        ftbasegenerateplanrec(m, ftbasecffttask, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
                        stackptr = stackptr-2*2*m;
                        plan.plan[entryoffset+6] = -1;
                        plan.plan[entryoffset+7] = precomputedsize;
                        precomputedsize = precomputedsize+2*m+2*n;
                        return;
                    }
                }
            }
            if( tasktype==ftbaserfhttask )
            {
                
                //
                // real FHT plans
                //
                if( n1!=1 )
                {
                    
                    //
                    // Cooley-Tukey plan
                    //
                    //
                    tmpmemsize = Math.Max(tmpmemsize, 2*n1*n2);
                    plan.plan[entryoffset+0] = esize;
                    plan.plan[entryoffset+1] = n1;
                    plan.plan[entryoffset+2] = n2;
                    plan.plan[entryoffset+3] = fhtcooleytukeyplan;
                    plan.plan[entryoffset+4] = 0;
                    plan.plan[entryoffset+5] = plansize;
                    ftbasegenerateplanrec(n1, tasktype, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
                    plan.plan[entryoffset+6] = plansize;
                    ftbasegenerateplanrec(n2, tasktype, plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
                    plan.plan[entryoffset+7] = -1;
                    return;
                }
                else
                {
                    
                    //
                    // N2 plan
                    //
                    plan.plan[entryoffset+0] = esize;
                    plan.plan[entryoffset+1] = n1;
                    plan.plan[entryoffset+2] = n2;
                    plan.plan[entryoffset+3] = fhtn2plan;
                    plan.plan[entryoffset+4] = 0;
                    plan.plan[entryoffset+5] = -1;
                    plan.plan[entryoffset+6] = -1;
                    plan.plan[entryoffset+7] = -1;
                    if( ((n==2 | n==3) | n==4) | n==5 )
                    {
                        
                        //
                        // hard-coded plan
                        //
                        plan.plan[entryoffset+0] = esize;
                        plan.plan[entryoffset+1] = n1;
                        plan.plan[entryoffset+2] = n2;
                        plan.plan[entryoffset+3] = fhtcodeletplan;
                        plan.plan[entryoffset+4] = 0;
                        plan.plan[entryoffset+5] = -1;
                        plan.plan[entryoffset+6] = -1;
                        plan.plan[entryoffset+7] = precomputedsize;
                        if( n==3 )
                        {
                            precomputedsize = precomputedsize+2;
                        }
                        if( n==5 )
                        {
                            precomputedsize = precomputedsize+5;
                        }
                        return;
                    }
                    return;
                }
            }
        }
 public override alglib.apobject make_copy()
 {
     ftplan _result = new ftplan();
     _result.plan = (int[])plan.Clone();
     _result.precomputed = (double[])precomputed.Clone();
     _result.tmpbuf = (double[])tmpbuf.Clone();
     _result.stackbuf = (double[])stackbuf.Clone();
     return _result;
 }
Example #7
0
        /*************************************************************************
        This subroutine generates FFT plan - a decomposition of a N-length FFT to
        the more simpler operations. Plan consists of the root entry and the child
        entries.

        Subroutine parameters:
            N               task size

        Output parameters:
            Plan            plan

          -- ALGLIB --
             Copyright 01.05.2009 by Bochkanov Sergey
        *************************************************************************/
        public static void ftbasegeneratecomplexfftplan(int n,
            ref ftplan plan)
        {
            int planarraysize = 0;
            int plansize = 0;
            int precomputedsize = 0;
            int tmpmemsize = 0;
            int stackmemsize = 0;
            int stackptr = 0;

            planarraysize = 1;
            plansize = 0;
            precomputedsize = 0;
            stackmemsize = 0;
            stackptr = 0;
            tmpmemsize = 2*n;
            plan.plan = new int[planarraysize];
            ftbasegenerateplanrec(n, ftbasecffttask, ref plan, ref plansize, ref precomputedsize, ref planarraysize, ref tmpmemsize, ref stackmemsize, stackptr);
            System.Diagnostics.Debug.Assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
            plan.stackbuf = new double[Math.Max(stackmemsize, 1)];
            plan.tmpbuf = new double[Math.Max(tmpmemsize, 1)];
            plan.precomputed = new double[Math.Max(precomputedsize, 1)];
            stackptr = 0;
            ftbaseprecomputeplanrec(ref plan, 0, stackptr);
            System.Diagnostics.Debug.Assert(stackptr==0, "Internal error in FTBaseGenerateComplexFFTPlan: stack ptr!");
        }