Ejemplo n.º 1
0
            /*************************************************************************
            Recurrent function called by FTComplexFFTPlan() and other functions. It
            recursively builds transformation plan

            INPUT PARAMETERS:
                N           -   FFT length (in complex numbers), N>=1
                K           -   number of repetitions, K>=1
                ChildPlan   -   if True, plan generator inserts OpStart/opEnd in the
                                plan header/footer.
                TopmostPlan -   if True, plan generator assumes that it is topmost plan:
                                * it may use global buffer for transpositions
                                and there is no other plan which executes in parallel
                RowPtr      -   index which points to past-the-last entry generated so far
                BluesteinSize-  amount of storage (in real numbers) required for Bluestein buffer
                PrecRPtr    -   pointer to unused part of precomputed real buffer (Plan.PrecR):
                                * when this function stores some data to precomputed buffer,
                                  it advances pointer.
                                * it is responsibility of the function to assert that
                                  Plan.PrecR has enough space to store data before actually
                                  writing to buffer.
                                * it is responsibility of the caller to allocate enough
                                  space before calling this function
                PrecIPtr    -   pointer to unused part of precomputed integer buffer (Plan.PrecI):
                                * when this function stores some data to precomputed buffer,
                                  it advances pointer.
                                * it is responsibility of the function to assert that
                                  Plan.PrecR has enough space to store data before actually
                                  writing to buffer.
                                * it is responsibility of the caller to allocate enough
                                  space before calling this function
                Plan        -   plan (generated so far)
            
            OUTPUT PARAMETERS:
                RowPtr      -   updated pointer (advanced by number of entries generated
                                by function)
                BluesteinSize-  updated amount
                                (may be increased, but may never be decreased)
                
            NOTE: in case TopmostPlan is True, ChildPlan is also must be True.
            
              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftcomplexfftplanrec(int n,
                int k,
                bool childplan,
                bool topmostplan,
                ref int rowptr,
                ref int bluesteinsize,
                ref int precrptr,
                ref int preciptr,
                fasttransformplan plan)
            {
                apserv.srealarray localbuf = new apserv.srealarray();
                int m = 0;
                int n1 = 0;
                int n2 = 0;
                int gq = 0;
                int giq = 0;
                int row0 = 0;
                int row1 = 0;
                int row2 = 0;
                int row3 = 0;

                alglib.ap.assert(n > 0, "FTComplexFFTPlan: N<=0");
                alglib.ap.assert(k > 0, "FTComplexFFTPlan: K<=0");
                alglib.ap.assert(!topmostplan || childplan, "FTComplexFFTPlan: ChildPlan is inconsistent with TopmostPlan");

                //
                // Try to generate "topmost" plan
                //
                if (topmostplan && n > recursivethreshold)
                {
                    ftfactorize(n, false, ref n1, ref n2);
                    if (n1 * n2 == 0)
                    {

                        //
                        // Handle prime-factor FFT with Bluestein's FFT.
                        // Determine size of Bluestein's buffer.
                        //
                        m = ftbasefindsmooth(2 * n - 1);
                        bluesteinsize = Math.Max(2 * m, bluesteinsize);

                        //
                        // Generate plan
                        //
                        ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                        ftpushentry4(plan, ref rowptr, opbluesteinsfft, k, n, 2, m, 2, precrptr, 0);
                        row0 = rowptr;
                        ftpushentry(plan, ref rowptr, opjmp, 0, 0, 0, 0);
                        ftcomplexfftplanrec(m, 1, true, true, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                        row1 = rowptr;
                        plan.entries[row0, colparam0] = row1 - row0;
                        ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);

                        //
                        // Fill precomputed buffer
                        //
                        ftprecomputebluesteinsfft(n, m, plan.precr, precrptr);

                        //
                        // Update pointer to the precomputed area
                        //
                        precrptr = precrptr + 4 * m;
                    }
                    else
                    {

                        //
                        // Handle composite FFT with recursive Cooley-Tukey which
                        // uses global buffer instead of local one.
                        //
                        ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                        ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                        row0 = rowptr;
                        ftpushentry2(plan, ref rowptr, opparallelcall, k * n2, n1, 2, 0, ftoptimisticestimate(n));
                        ftpushentry(plan, ref rowptr, opcomplexfftfactors, k, n, 2, n1);
                        ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n2);
                        row2 = rowptr;
                        ftpushentry2(plan, ref rowptr, opparallelcall, k * n1, n2, 2, 0, ftoptimisticestimate(n));
                        ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                        ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                        row1 = rowptr;
                        ftcomplexfftplanrec(n1, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                        plan.entries[row0, colparam0] = row1 - row0;
                        row3 = rowptr;
                        ftcomplexfftplanrec(n2, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                        plan.entries[row2, colparam0] = row3 - row2;
                    }
                    return;
                }

                //
                // Prepare "non-topmost" plan:
                // * calculate factorization
                // * use local (shared) buffer
                // * update buffer size - ANY plan will need at least
                //   2*N temporaries, additional requirements can be
                //   applied later
                //
                ftfactorize(n, false, ref n1, ref n2);

                //
                // Handle FFT's with N1*N2=0: either small-N or prime-factor
                //
                if (n1 * n2 == 0)
                {
                    if (n <= maxradix)
                    {

                        //
                        // Small-N FFT
                        //
                        if (childplan)
                        {
                            ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                        }
                        ftpushentry(plan, ref rowptr, opcomplexcodeletfft, k, n, 2, 0);
                        if (childplan)
                        {
                            ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                        }
                        return;
                    }
                    if (n <= raderthreshold)
                    {

                        //
                        // Handle prime-factor FFT's with Rader's FFT
                        //
                        m = n - 1;
                        if (childplan)
                        {
                            ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                        }
                        ntheory.findprimitiverootandinverse(n, ref gq, ref giq);
                        ftpushentry4(plan, ref rowptr, opradersfft, k, n, 2, 2, gq, giq, precrptr);
                        ftprecomputeradersfft(n, gq, giq, plan.precr, precrptr);
                        precrptr = precrptr + 2 * (n - 1);
                        row0 = rowptr;
                        ftpushentry(plan, ref rowptr, opjmp, 0, 0, 0, 0);
                        ftcomplexfftplanrec(m, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                        row1 = rowptr;
                        plan.entries[row0, colparam0] = row1 - row0;
                        if (childplan)
                        {
                            ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                        }
                    }
                    else
                    {

                        //
                        // Handle prime-factor FFT's with Bluestein's FFT
                        //
                        m = ftbasefindsmooth(2 * n - 1);
                        bluesteinsize = Math.Max(2 * m, bluesteinsize);
                        if (childplan)
                        {
                            ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                        }
                        ftpushentry4(plan, ref rowptr, opbluesteinsfft, k, n, 2, m, 2, precrptr, 0);
                        ftprecomputebluesteinsfft(n, m, plan.precr, precrptr);
                        precrptr = precrptr + 4 * m;
                        row0 = rowptr;
                        ftpushentry(plan, ref rowptr, opjmp, 0, 0, 0, 0);
                        ftcomplexfftplanrec(m, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                        row1 = rowptr;
                        plan.entries[row0, colparam0] = row1 - row0;
                        if (childplan)
                        {
                            ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                        }
                    }
                    return;
                }

                //
                // Handle Cooley-Tukey FFT with small N1
                //
                if (n1 <= maxradix)
                {

                    //
                    // Specialized transformation for small N1:
                    // * N2 short inplace FFT's, each N1-point, with integrated twiddle factors
                    // * N1 long FFT's
                    // * final transposition
                    //
                    if (childplan)
                    {
                        ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                    }
                    ftpushentry(plan, ref rowptr, opcomplexcodelettwfft, k, n1, 2 * n2, 0);
                    ftcomplexfftplanrec(n2, k * n1, false, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                    if (childplan)
                    {
                        ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                    }
                    return;
                }

                //
                // Handle general Cooley-Tukey FFT, either "flat" or "recursive"
                //
                if (n <= recursivethreshold)
                {

                    //
                    // General code for large N1/N2, "flat" version without explicit recurrence
                    // (nested subplans are inserted directly into the body of the plan)
                    //
                    if (childplan)
                    {
                        ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                    }
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                    ftcomplexfftplanrec(n1, k * n2, false, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                    ftpushentry(plan, ref rowptr, opcomplexfftfactors, k, n, 2, n1);
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n2);
                    ftcomplexfftplanrec(n2, k * n1, false, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                    if (childplan)
                    {
                        ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                    }
                }
                else
                {

                    //
                    // General code for large N1/N2, "recursive" version - nested subplans
                    // are separated from the plan body.
                    //
                    // Generate parent plan.
                    //
                    if (childplan)
                    {
                        ftpushentry2(plan, ref rowptr, opstart, k, n, 2, -1, ftoptimisticestimate(n));
                    }
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                    row0 = rowptr;
                    ftpushentry2(plan, ref rowptr, opparallelcall, k * n2, n1, 2, 0, ftoptimisticestimate(n));
                    ftpushentry(plan, ref rowptr, opcomplexfftfactors, k, n, 2, n1);
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n2);
                    row2 = rowptr;
                    ftpushentry2(plan, ref rowptr, opparallelcall, k * n1, n2, 2, 0, ftoptimisticestimate(n));
                    ftpushentry(plan, ref rowptr, opcomplextranspose, k, n, 2, n1);
                    if (childplan)
                    {
                        ftpushentry(plan, ref rowptr, opend, k, n, 2, 0);
                    }

                    //
                    // Generate child subplans, insert refence to parent plans
                    //
                    row1 = rowptr;
                    ftcomplexfftplanrec(n1, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                    plan.entries[row0, colparam0] = row1 - row0;
                    row3 = rowptr;
                    ftcomplexfftplanrec(n2, 1, true, false, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                    plan.entries[row2, colparam0] = row3 - row2;
                }
            }
Ejemplo n.º 2
0
            /*************************************************************************
            This subroutine generates FFT plan for K complex FFT's with length N each.

            INPUT PARAMETERS:
                N           -   FFT length (in complex numbers), N>=1
                K           -   number of repetitions, K>=1
            
            OUTPUT PARAMETERS:
                Plan        -   plan

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            public static void ftcomplexfftplan(int n,
                int k,
                fasttransformplan plan)
            {
                apserv.srealarray bluesteinbuf = new apserv.srealarray();
                int rowptr = 0;
                int bluesteinsize = 0;
                int precrptr = 0;
                int preciptr = 0;
                int precrsize = 0;
                int precisize = 0;


                //
                // Initial check for parameters
                //
                alglib.ap.assert(n > 0, "FTComplexFFTPlan: N<=0");
                alglib.ap.assert(k > 0, "FTComplexFFTPlan: K<=0");

                //
                // Determine required sizes of precomputed real and integer
                // buffers. This stage of code is highly dependent on internals
                // of FTComplexFFTPlanRec() and must be kept synchronized with
                // possible changes in internals of plan generation function.
                //
                // Buffer size is determined as follows:
                // * N is factorized
                // * we factor out anything which is less or equal to MaxRadix
                // * prime factor F>RaderThreshold requires 4*FTBaseFindSmooth(2*F-1)
                //   real entries to store precomputed Quantities for Bluestein's
                //   transformation
                // * prime factor F<=RaderThreshold does NOT require
                //   precomputed storage
                //
                precrsize = 0;
                precisize = 0;
                ftdeterminespacerequirements(n, ref precrsize, ref precisize);
                if (precrsize > 0)
                {
                    plan.precr = new double[precrsize];
                }
                if (precisize > 0)
                {
                    plan.preci = new double[precisize];
                }

                //
                // Generate plan
                //
                rowptr = 0;
                precrptr = 0;
                preciptr = 0;
                bluesteinsize = 1;
                plan.buffer = new double[2 * n * k];
                ftcomplexfftplanrec(n, k, true, true, ref rowptr, ref bluesteinsize, ref precrptr, ref preciptr, plan);
                bluesteinbuf.val = new double[bluesteinsize];
                alglib.smp.ae_shared_pool_set_seed(plan.bluesteinpool, bluesteinbuf);

                //
                // Check that actual amount of precomputed space used by transformation
                // plan is EXACTLY equal to amount of space allocated by us.
                //
                alglib.ap.assert(precrptr == precrsize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)");
                alglib.ap.assert(preciptr == precisize, "FTComplexFFTPlan: internal error (PrecRPtr<>PrecRSize)");
            }