Example #1
0
            /*************************************************************************
            This subroutine precomputes data for complex Rader's FFT and  writes  them
            to array PrecR[] at specified offset. It  is  responsibility of the caller
            to make sure that PrecR[] is large enough.

            INPUT PARAMETERS:
                N           -   original size of the transform (before reduction to N-1)
                RQ          -   primitive root modulo N
                RIQ         -   inverse of primitive root modulo N
                PrecR       -   preallocated array
                Offs        -   offset
            
            OUTPUT PARAMETERS:
                PrecR       -   data at Offs:Offs+2*(N-1)-1 store FFT of Rader's factors,
                                other parts of PrecR are unchanged.
                            
            NOTE: this function performs internal (N-1)-point FFT. It allocates temporary
                  plan which is destroyed after leaving this function.

              -- ALGLIB --
                 Copyright 08.05.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftprecomputeradersfft(int n,
                int rq,
                int riq,
                double[] precr,
                int offs)
            {
                int q = 0;
                fasttransformplan plan = new fasttransformplan();
                int kiq = 0;
                double v = 0;


                //
                // Fill PrecR with Rader factors, perform FFT
                //
                kiq = 1;
                for (q = 0; q <= n - 2; q++)
                {
                    v = -(2 * Math.PI * kiq / n);
                    precr[offs + 2 * q + 0] = Math.Cos(v);
                    precr[offs + 2 * q + 1] = Math.Sin(v);
                    kiq = kiq * riq % n;
                }
                ftcomplexfftplan(n - 1, 1, plan);
                ftapplysubplan(plan, 0, precr, offs, 0, plan.buffer, 1);
            }
Example #2
0
            /*************************************************************************
            This subroutine applies complex Rader's FFT to input/output array A.

            INPUT PARAMETERS:
                A           -   array, must be large enough for plan to work
                ABase       -   base offset in array A, this value points to start of
                                subarray whose length is equal to length of the plan
                AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
                                This is an offset within large PlanLength-subarray of
                                the chunk to process.
                OperandsCnt -   number of repeated operands (length N each)
                N           -   original data length (measured in complex numbers)
                SubPlan     -   position of the (N-1)-point FFT subplan which is used
                                by transformation
                RQ          -   primitive root modulo N
                RIQ         -   inverse of primitive root modulo N
                PrecOffs    -   offset of the precomputed data for the plan
                Buf         -   temporary array
            
            OUTPUT PARAMETERS:
                A           -   transformed array

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftradersfft(fasttransformplan plan,
                double[] a,
                int abase,
                int aoffset,
                int operandscnt,
                int n,
                int subplan,
                int rq,
                int riq,
                int precoffs,
                double[] buf)
            {
                int opidx = 0;
                int i = 0;
                int q = 0;
                int kq = 0;
                int kiq = 0;
                double x0 = 0;
                double y0 = 0;
                int p0 = 0;
                int p1 = 0;
                double ax = 0;
                double ay = 0;
                double bx = 0;
                double by = 0;
                double rx = 0;
                double ry = 0;

                alglib.ap.assert(operandscnt >= 1, "FTApplyComplexRefFFT: OperandsCnt<1");

                //
                // Process operands
                //
                for (opidx = 0; opidx <= operandscnt - 1; opidx++)
                {

                    //
                    // fill QA
                    //
                    kq = 1;
                    p0 = abase + aoffset + opidx * n * 2;
                    p1 = aoffset + opidx * n * 2;
                    rx = a[p0 + 0];
                    ry = a[p0 + 1];
                    x0 = rx;
                    y0 = ry;
                    for (q = 0; q <= n - 2; q++)
                    {
                        ax = a[p0 + 2 * kq + 0];
                        ay = a[p0 + 2 * kq + 1];
                        buf[p1 + 0] = ax;
                        buf[p1 + 1] = ay;
                        rx = rx + ax;
                        ry = ry + ay;
                        kq = kq * rq % n;
                        p1 = p1 + 2;
                    }
                    p0 = abase + aoffset + opidx * n * 2;
                    p1 = aoffset + opidx * n * 2;
                    for (q = 0; q <= n - 2; q++)
                    {
                        a[p0] = buf[p1];
                        a[p0 + 1] = buf[p1 + 1];
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                    }

                    //
                    // Convolution
                    //
                    ftapplysubplan(plan, subplan, a, abase, aoffset + opidx * n * 2, buf, 1);
                    p0 = abase + aoffset + opidx * n * 2;
                    p1 = precoffs;
                    for (i = 0; i <= n - 2; i++)
                    {
                        ax = a[p0 + 0];
                        ay = a[p0 + 1];
                        bx = plan.precr[p1 + 0];
                        by = plan.precr[p1 + 1];
                        a[p0 + 0] = ax * bx - ay * by;
                        a[p0 + 1] = -(ax * by + ay * bx);
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                    }
                    ftapplysubplan(plan, subplan, a, abase, aoffset + opidx * n * 2, buf, 1);
                    p0 = abase + aoffset + opidx * n * 2;
                    for (i = 0; i <= n - 2; i++)
                    {
                        a[p0 + 0] = a[p0 + 0] / (n - 1);
                        a[p0 + 1] = -(a[p0 + 1] / (n - 1));
                        p0 = p0 + 2;
                    }

                    //
                    // Result
                    //
                    buf[aoffset + opidx * n * 2 + 0] = rx;
                    buf[aoffset + opidx * n * 2 + 1] = ry;
                    kiq = 1;
                    p0 = aoffset + opidx * n * 2;
                    p1 = abase + aoffset + opidx * n * 2;
                    for (q = 0; q <= n - 2; q++)
                    {
                        buf[p0 + 2 * kiq + 0] = x0 + a[p1 + 0];
                        buf[p0 + 2 * kiq + 1] = y0 + a[p1 + 1];
                        kiq = kiq * riq % n;
                        p1 = p1 + 2;
                    }
                    p0 = abase + aoffset + opidx * n * 2;
                    p1 = aoffset + opidx * n * 2;
                    for (q = 0; q <= n - 1; q++)
                    {
                        a[p0] = buf[p1];
                        a[p0 + 1] = buf[p1 + 1];
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                    }
                }
            }
Example #3
0
            /*************************************************************************
            This subroutine precomputes data for complex Bluestein's  FFT  and  writes
            them to array PrecR[] at specified offset. It  is  responsibility  of  the
            caller to make sure that PrecR[] is large enough.

            INPUT PARAMETERS:
                N           -   original size of the transform
                M           -   size of the "padded" Bluestein's transform
                PrecR       -   preallocated array
                Offs        -   offset
            
            OUTPUT PARAMETERS:
                PrecR       -   data at Offs:Offs+4*M-1 are modified:
                                * PrecR[Offs:Offs+2*M-1] stores Z[k]=exp(i*pi*k^2/N)
                                * PrecR[Offs+2*M:Offs+4*M-1] stores FFT of the Z
                                Other parts of PrecR are unchanged.
                            
            NOTE: this function performs internal M-point FFT. It allocates temporary
                  plan which is destroyed after leaving this function.

              -- ALGLIB --
                 Copyright 08.05.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftprecomputebluesteinsfft(int n,
                int m,
                double[] precr,
                int offs)
            {
                int i = 0;
                double bx = 0;
                double by = 0;
                fasttransformplan plan = new fasttransformplan();


                //
                // Fill first half of PrecR with b[k] = exp(i*pi*k^2/N)
                //
                for (i = 0; i <= 2 * m - 1; i++)
                {
                    precr[offs + i] = 0;
                }
                for (i = 0; i <= n - 1; i++)
                {
                    bx = Math.Cos(Math.PI / n * i * i);
                    by = Math.Sin(Math.PI / n * i * i);
                    precr[offs + 2 * i + 0] = bx;
                    precr[offs + 2 * i + 1] = by;
                    precr[offs + 2 * ((m - i) % m) + 0] = bx;
                    precr[offs + 2 * ((m - i) % m) + 1] = by;
                }

                //
                // Precomputed FFT
                //
                ftcomplexfftplan(m, 1, plan);
                for (i = 0; i <= 2 * m - 1; i++)
                {
                    precr[offs + 2 * m + i] = precr[offs + i];
                }
                ftapplysubplan(plan, 0, precr, offs + 2 * m, 0, plan.buffer, 1);
            }
Example #4
0
            /*************************************************************************
            This subroutine applies complex Bluestein's FFT to input/output array A.

            INPUT PARAMETERS:
                Plan        -   transformation plan
                A           -   array, must be large enough for plan to work
                ABase       -   base offset in array A, this value points to start of
                                subarray whose length is equal to length of the plan
                AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
                                This is an offset within large PlanLength-subarray of
                                the chunk to process.
                OperandsCnt -   number of repeated operands (length N each)
                N           -   original data length (measured in complex numbers)
                M           -   padded data length (measured in complex numbers)
                PrecOffs    -   offset of the precomputed data for the plan
                SubPlan     -   position of the length-M FFT subplan which is used by
                                transformation
                BufA        -   temporary buffer, at least 2*M elements
                BufB        -   temporary buffer, at least 2*M elements
                BufC        -   temporary buffer, at least 2*M elements
                BufD        -   temporary buffer, at least 2*M elements
            
            OUTPUT PARAMETERS:
                A           -   transformed array

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftbluesteinsfft(fasttransformplan plan,
                double[] a,
                int abase,
                int aoffset,
                int operandscnt,
                int n,
                int m,
                int precoffs,
                int subplan,
                double[] bufa,
                double[] bufb,
                double[] bufc,
                double[] bufd)
            {
                int op = 0;
                int i = 0;
                double x = 0;
                double y = 0;
                double bx = 0;
                double by = 0;
                double ax = 0;
                double ay = 0;
                double rx = 0;
                double ry = 0;
                int p0 = 0;
                int p1 = 0;
                int p2 = 0;

                for (op = 0; op <= operandscnt - 1; op++)
                {

                    //
                    // Multiply A by conj(Z), store to buffer.
                    // Pad A by zeros.
                    //
                    // NOTE: Z[k]=exp(i*pi*k^2/N)
                    //
                    p0 = abase + aoffset + op * 2 * n;
                    p1 = precoffs;
                    for (i = 0; i <= n - 1; i++)
                    {
                        x = a[p0 + 0];
                        y = a[p0 + 1];
                        bx = plan.precr[p1 + 0];
                        by = -plan.precr[p1 + 1];
                        bufa[2 * i + 0] = x * bx - y * by;
                        bufa[2 * i + 1] = x * by + y * bx;
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                    }
                    for (i = 2 * n; i <= 2 * m - 1; i++)
                    {
                        bufa[i] = 0;
                    }

                    //
                    // Perform convolution of A and Z (using precomputed
                    // FFT of Z stored in Plan structure).
                    //
                    ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1);
                    p0 = 0;
                    p1 = precoffs + 2 * m;
                    for (i = 0; i <= m - 1; i++)
                    {
                        ax = bufa[p0 + 0];
                        ay = bufa[p0 + 1];
                        bx = plan.precr[p1 + 0];
                        by = plan.precr[p1 + 1];
                        bufa[p0 + 0] = ax * bx - ay * by;
                        bufa[p0 + 1] = -(ax * by + ay * bx);
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                    }
                    ftapplysubplan(plan, subplan, bufa, 0, 0, bufc, 1);

                    //
                    // Post processing:
                    //     A:=conj(Z)*conj(A)/M
                    // Here conj(A)/M corresponds to last stage of inverse DFT,
                    // and conj(Z) comes from Bluestein's FFT algorithm.
                    //
                    p0 = precoffs;
                    p1 = 0;
                    p2 = abase + aoffset + op * 2 * n;
                    for (i = 0; i <= n - 1; i++)
                    {
                        bx = plan.precr[p0 + 0];
                        by = plan.precr[p0 + 1];
                        rx = bufa[p1 + 0] / m;
                        ry = -(bufa[p1 + 1] / m);
                        a[p2 + 0] = rx * bx - ry * -by;
                        a[p2 + 1] = rx * -by + ry * bx;
                        p0 = p0 + 2;
                        p1 = p1 + 2;
                        p2 = p2 + 2;
                    }
                }
            }
Example #5
0
            /*************************************************************************
            Same as FTPushEntry(), but sets Param0, Param1, Param2 and Param3.
            This function pushes one more entry to the plan. It resized Entries matrix
            if needed.

            INPUT PARAMETERS:
                Plan        -   plan (generated so far)
                RowPtr      -   index which points to past-the-last entry generated so far
                EType       -   entry type
                EOpCnt      -   operands count
                EOpSize     -   operand size
                EMcvSize    -   microvector size
                EParam0     -   parameter 0
                EParam1     -   parameter 1
                EParam2     -   parameter 2
                EParam3     -   parameter 3
            
            OUTPUT PARAMETERS:
                Plan        -   updated plan    
                RowPtr      -   updated pointer

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftpushentry4(fasttransformplan plan,
                ref int rowptr,
                int etype,
                int eopcnt,
                int eopsize,
                int emcvsize,
                int eparam0,
                int eparam1,
                int eparam2,
                int eparam3)
            {
                if (rowptr >= alglib.ap.rows(plan.entries))
                {
                    apserv.imatrixresize(ref plan.entries, Math.Max(2 * alglib.ap.rows(plan.entries), 1), colscnt);
                }
                plan.entries[rowptr, coltype] = etype;
                plan.entries[rowptr, coloperandscnt] = eopcnt;
                plan.entries[rowptr, coloperandsize] = eopsize;
                plan.entries[rowptr, colmicrovectorsize] = emcvsize;
                plan.entries[rowptr, colparam0] = eparam0;
                plan.entries[rowptr, colparam1] = eparam1;
                plan.entries[rowptr, colparam2] = eparam2;
                plan.entries[rowptr, colparam3] = eparam3;
                rowptr = rowptr + 1;
            }
Example #6
0
            /*************************************************************************
            This subroutine applies subplan to input/output array A.

            INPUT PARAMETERS:
                Plan        -   transformation plan
                SubPlan     -   subplan index
                A           -   array, must be large enough for plan to work
                ABase       -   base offset in array A, this value points to start of
                                subarray whose length is equal to length of the plan
                AOffset     -   offset with respect to ABase, 0<=AOffset<PlanLength.
                                This is an offset within large PlanLength-subarray of
                                the chunk to process.
                Buf         -   temporary buffer whose length is equal to plan length
                                (without taking into account RepCnt) or larger.
                OffsBuf     -   offset in the buffer array
                RepCnt      -   repetition count (transformation is repeatedly applied
                                to subsequent subarrays)
            
            OUTPUT PARAMETERS:
                Plan        -   plan (temporary buffers can be modified, plan itself
                                is unchanged and can be reused)
                A           -   transformed array

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftapplysubplan(fasttransformplan plan,
                int subplan,
                double[] a,
                int abase,
                int aoffset,
                double[] buf,
                int repcnt)
            {
                int rowidx = 0;
                int i = 0;
                int n1 = 0;
                int n2 = 0;
                int operation = 0;
                int operandscnt = 0;
                int operandsize = 0;
                int microvectorsize = 0;
                int param0 = 0;
                int param1 = 0;
                int parentsize = 0;
                int childsize = 0;
                int chunksize = 0;
                int lastchunksize = 0;
                apserv.srealarray bufa = null;
                apserv.srealarray bufb = null;
                apserv.srealarray bufc = null;
                apserv.srealarray bufd = null;

                alglib.ap.assert(plan.entries[subplan, coltype] == opstart, "FTApplySubPlan: incorrect subplan header");
                rowidx = subplan + 1;
                while (plan.entries[rowidx, coltype] != opend)
                {
                    operation = plan.entries[rowidx, coltype];
                    operandscnt = repcnt * plan.entries[rowidx, coloperandscnt];
                    operandsize = plan.entries[rowidx, coloperandsize];
                    microvectorsize = plan.entries[rowidx, colmicrovectorsize];
                    param0 = plan.entries[rowidx, colparam0];
                    param1 = plan.entries[rowidx, colparam1];
                    apserv.touchint(ref param1);

                    //
                    // Process "jump" operation
                    //
                    if (operation == opjmp)
                    {
                        rowidx = rowidx + plan.entries[rowidx, colparam0];
                        continue;
                    }

                    //
                    // Process "parallel call" operation:
                    // * we perform initial check for consistency between parent and child plans
                    // * we call FTSplitAndApplyParallelPlan(), which splits parallel plan into
                    //   several parallel tasks
                    //
                    if (operation == opparallelcall)
                    {
                        parentsize = operandsize * microvectorsize;
                        childsize = plan.entries[rowidx + param0, coloperandscnt] * plan.entries[rowidx + param0, coloperandsize] * plan.entries[rowidx + param0, colmicrovectorsize];
                        alglib.ap.assert(plan.entries[rowidx + param0, coltype] == opstart, "FTApplySubPlan: incorrect child subplan header");
                        alglib.ap.assert(parentsize == childsize, "FTApplySubPlan: incorrect child subplan header");
                        chunksize = Math.Max(recursivethreshold / childsize, 1);
                        lastchunksize = operandscnt % chunksize;
                        if (lastchunksize == 0)
                        {
                            lastchunksize = chunksize;
                        }
                        i = 0;
                        while (i < operandscnt)
                        {
                            chunksize = Math.Min(chunksize, operandscnt - i);
                            ftapplysubplan(plan, rowidx + param0, a, abase, aoffset + i * childsize, buf, chunksize);
                            i = i + chunksize;
                        }
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process "reference complex FFT" operation
                    //
                    if (operation == opcomplexreffft)
                    {
                        ftapplycomplexreffft(a, abase + aoffset, operandscnt, operandsize, microvectorsize, buf);
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process "codelet FFT" operation
                    //
                    if (operation == opcomplexcodeletfft)
                    {
                        ftapplycomplexcodeletfft(a, abase + aoffset, operandscnt, operandsize, microvectorsize);
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process "integrated codelet FFT" operation
                    //
                    if (operation == opcomplexcodelettwfft)
                    {
                        ftapplycomplexcodelettwfft(a, abase + aoffset, operandscnt, operandsize, microvectorsize);
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process Bluestein's FFT operation
                    //
                    if (operation == opbluesteinsfft)
                    {
                        alglib.ap.assert(microvectorsize == 2, "FTApplySubPlan: microvectorsize!=2 for Bluesteins FFT");
                        alglib.smp.ae_shared_pool_retrieve(plan.bluesteinpool, ref bufa);
                        alglib.smp.ae_shared_pool_retrieve(plan.bluesteinpool, ref bufb);
                        alglib.smp.ae_shared_pool_retrieve(plan.bluesteinpool, ref bufc);
                        alglib.smp.ae_shared_pool_retrieve(plan.bluesteinpool, ref bufd);
                        ftbluesteinsfft(plan, a, abase, aoffset, operandscnt, operandsize, plan.entries[rowidx, colparam0], plan.entries[rowidx, colparam2], rowidx + plan.entries[rowidx, colparam1], bufa.val, bufb.val, bufc.val, bufd.val);
                        alglib.smp.ae_shared_pool_recycle(plan.bluesteinpool, ref bufa);
                        alglib.smp.ae_shared_pool_recycle(plan.bluesteinpool, ref bufb);
                        alglib.smp.ae_shared_pool_recycle(plan.bluesteinpool, ref bufc);
                        alglib.smp.ae_shared_pool_recycle(plan.bluesteinpool, ref bufd);
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process Rader's FFT
                    //
                    if (operation == opradersfft)
                    {
                        ftradersfft(plan, a, abase, aoffset, operandscnt, operandsize, rowidx + plan.entries[rowidx, colparam0], plan.entries[rowidx, colparam1], plan.entries[rowidx, colparam2], plan.entries[rowidx, colparam3], buf);
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process "complex twiddle factors" operation
                    //
                    if (operation == opcomplexfftfactors)
                    {
                        alglib.ap.assert(microvectorsize == 2, "FTApplySubPlan: MicrovectorSize<>1");
                        n1 = plan.entries[rowidx, colparam0];
                        n2 = operandsize / n1;
                        for (i = 0; i <= operandscnt - 1; i++)
                        {
                            ffttwcalc(a, abase + aoffset + i * operandsize * 2, n1, n2);
                        }
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Process "complex transposition" operation
                    //
                    if (operation == opcomplextranspose)
                    {
                        alglib.ap.assert(microvectorsize == 2, "FTApplySubPlan: MicrovectorSize<>1");
                        n1 = plan.entries[rowidx, colparam0];
                        n2 = operandsize / n1;
                        for (i = 0; i <= operandscnt - 1; i++)
                        {
                            internalcomplexlintranspose(a, n1, n2, abase + aoffset + i * operandsize * 2, buf);
                        }
                        rowidx = rowidx + 1;
                        continue;
                    }

                    //
                    // Error
                    //
                    alglib.ap.assert(false, "FTApplySubPlan: unexpected plan type");
                }
            }
Example #7
0
            /*************************************************************************
            This function pushes one more entry to the plan. It resizes Entries matrix
            if needed.

            INPUT PARAMETERS:
                Plan        -   plan (generated so far)
                RowPtr      -   index which points to past-the-last entry generated so far
                EType       -   entry type
                EOpCnt      -   operands count
                EOpSize     -   operand size
                EMcvSize    -   microvector size
                EParam0     -   parameter 0
            
            OUTPUT PARAMETERS:
                Plan        -   updated plan    
                RowPtr      -   updated pointer

            NOTE: Param1 is set to -1.
            
              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            private static void ftpushentry(fasttransformplan plan,
                ref int rowptr,
                int etype,
                int eopcnt,
                int eopsize,
                int emcvsize,
                int eparam0)
            {
                ftpushentry2(plan, ref rowptr, etype, eopcnt, eopsize, emcvsize, eparam0, -1);
            }
Example #8
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;
                }
            }
Example #9
0
            /*************************************************************************
            This subroutine applies transformation plan to input/output array A.

            INPUT PARAMETERS:
                Plan        -   transformation plan
                A           -   array, must be large enough for plan to work
                OffsA       -   offset of the subarray to process
                RepCnt      -   repetition count (transformation is repeatedly applied
                                to subsequent subarrays)
            
            OUTPUT PARAMETERS:
                Plan        -   plan (temporary buffers can be modified, plan itself
                                is unchanged and can be reused)
                A           -   transformed array

              -- ALGLIB --
                 Copyright 05.04.2013 by Bochkanov Sergey
            *************************************************************************/
            public static void ftapplyplan(fasttransformplan plan,
                double[] a,
                int offsa,
                int repcnt)
            {
                int plansize = 0;
                int i = 0;

                plansize = plan.entries[0, coloperandscnt] * plan.entries[0, coloperandsize] * plan.entries[0, colmicrovectorsize];
                for (i = 0; i <= repcnt - 1; i++)
                {
                    ftapplysubplan(plan, 0, a, offsa + plansize * i, 0, plan.buffer, 1);
                }
            }
Example #10
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)");
            }
Example #11
0
 public override alglib.apobject make_copy()
 {
     fasttransformplan _result = new fasttransformplan();
     _result.entries = (int[,])entries.Clone();
     _result.buffer = (double[])buffer.Clone();
     _result.precr = (double[])precr.Clone();
     _result.preci = (double[])preci.Clone();
     _result.bluesteinpool = (alglib.smp.shared_pool)bluesteinpool.make_copy();
     return _result;
 }