Esempio n. 1
0
 public kiss_fft_cpx <double> Multiply(kiss_fft_cpx <double> a, kiss_fft_cpx <double> b)
 {
     return(new kiss_fft_cpx <double>(
                a.r * b.r - a.i * b.i,
                a.r * b.i + a.i * b.r
                ));
 }
Esempio n. 2
0
 public kiss_fft_cpx <float> Multiply(kiss_fft_cpx <float> a, kiss_fft_cpx <float> b)
 {
     return(new kiss_fft_cpx <float>(
                a.r * b.r - a.i * b.i,
                a.r * b.i + a.i * b.r
                ));
 }
Esempio n. 3
0
        protected void kf_bfly4(Array <kiss_fft_cpx <kiss_fft_scalar> > Fout, int fstride, int m)
        {
            Array <kiss_fft_cpx <kiss_fft_scalar> > tw1, tw2, tw3;

            kiss_fft_cpx <kiss_fft_scalar>[] scratch = new kiss_fft_cpx <kiss_fft_scalar> [6];
            int k  = m;
            int m2 = 2 * m;
            int m3 = 3 * m;

            tw1 = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);
            tw2 = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);
            tw3 = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);

            do
            {
                Fout[0]  = A.FixDivide(Fout[0], 4);
                Fout[m]  = A.FixDivide(Fout[m], 4);
                Fout[m2] = A.FixDivide(Fout[m2], 4);
                Fout[m3] = A.FixDivide(Fout[m3], 4);

                scratch[0] = A.Multiply(Fout[m], tw1[0]);
                scratch[1] = A.Multiply(Fout[m2], tw2[0]);
                scratch[2] = A.Multiply(Fout[m3], tw3[0]);

                scratch[5] = A.Subtract(Fout[0], scratch[1]);
                Fout[0]    = A.Add(Fout[0], scratch[1]);
                scratch[3] = A.Add(scratch[0], scratch[2]);
                scratch[4] = A.Subtract(scratch[0], scratch[2]);
                Fout[m2]   = A.Subtract(Fout[0], scratch[3]);
                tw1       += fstride;
                tw2       += fstride * 2;
                tw3       += fstride * 3;
                Fout[0]    = A.Add(Fout[0], scratch[3]);

                if (Inverse)
                {
                    Fout[m].r  = A.Subtract(scratch[5].r, scratch[4].i);
                    Fout[m].i  = A.Add(scratch[5].i, scratch[4].r);
                    Fout[m3].r = A.Add(scratch[5].r, scratch[4].i);
                    Fout[m3].i = A.Subtract(scratch[5].i, scratch[4].r);
                }
                else
                {
                    Fout[m].r  = A.Add(scratch[5].r, scratch[4].i);
                    Fout[m].i  = A.Subtract(scratch[5].i, scratch[4].r);
                    Fout[m3].r = A.Subtract(scratch[5].r, scratch[4].i);
                    Fout[m3].i = A.Add(scratch[5].i, scratch[4].r);
                }
                ++Fout;
            } while (--k != 0);
        }
Esempio n. 4
0
        /*
         * This works by tackling one dimension at a time.
         *
         * In effect,
         * Each stage starts out by reshaping the matrix into a DixSi 2d matrix.
         * A Di-sized fft is taken of each column, transposing the matrix as it goes.
         *
         * Here's a 3-d example:
         * Take a 2x3x4 matrix, laid out in memory as a contiguous buffer
         * [ [ [ a b c d ] [ e f g h ] [ i j k l ] ]
         * [ [ m n o p ] [ q r s t ] [ u v w x ] ] ]
         *
         * Stage 0 ( D=2): treat the buffer as a 2x12 matrix
         * [ [a b ... k l]
         *       [m n ... w x] ]
         *
         * FFT each column with size 2.
         * Transpose the matrix at the same time using kiss_fft_stride.
         *
         * [ [ a+m a-m ]
         *       [ b+n b-n]
         *       ...
         *       [ k+w k-w ]
         *       [ l+x l-x ] ]
         *
         * Note fft([x y]) == [x+y x-y]
         *
         * Stage 1 ( D=3) treats the buffer (the output of stage D=2) as an 3x8 matrix,
         * [ [ a+m a-m b+n b-n c+o c-o d+p d-p ]
         *       [ e+q e-q f+r f-r g+s g-s h+t h-t ]
         *       [ i+u i-u j+v j-v k+w k-w l+x l-x ] ]
         *
         * And perform FFTs (size=3) on each of the columns as above, transposing
         * the matrix as it goes.  The output of stage 1 is
         *         (Legend: ap = [ a+m e+q i+u ]
         *                              am = [ a-m e-q i-u ] )
         *
         * [ [ sum(ap) fft(ap)[0] fft(ap)[1] ]
         *       [ sum(am) fft(am)[0] fft(am)[1] ]
         *       [ sum(bp) fft(bp)[0] fft(bp)[1] ]
         *       [ sum(bm) fft(bm)[0] fft(bm)[1] ]
         *       [ sum(cp) fft(cp)[0] fft(cp)[1] ]
         *       [ sum(cm) fft(cm)[0] fft(cm)[1] ]
         *       [ sum(dp) fft(dp)[0] fft(dp)[1] ]
         *       [ sum(dm) fft(dm)[0] fft(dm)[1] ]  ]
         *
         * Stage 2 ( D=4) treats this buffer as a 4*6 matrix,
         * [ [ sum(ap) fft(ap)[0] fft(ap)[1] sum(am) fft(am)[0] fft(am)[1] ]
         *       [ sum(bp) fft(bp)[0] fft(bp)[1] sum(bm) fft(bm)[0] fft(bm)[1] ]
         *       [ sum(cp) fft(cp)[0] fft(cp)[1] sum(cm) fft(cm)[0] fft(cm)[1] ]
         *       [ sum(dp) fft(dp)[0] fft(dp)[1] sum(dm) fft(dm)[0] fft(dm)[1] ]  ]
         *
         * Then FFTs each column, transposing as it goes.
         *
         * The resulting matrix is the 3d FFT of the 2x3x4 input matrix.
         *
         * Note as a sanity check that the first element of the final
         * stage's output (DC term) is
         * sum( [ sum(ap) sum(bp) sum(cp) sum(dp) ] )
         * , i.e. the summation of all 24 input elements.
         *
         */
        public void kiss_fftnd(Array <kiss_fft_cpx <kiss_fft_scalar> > fin, Array <kiss_fft_cpx <kiss_fft_scalar> > fout)
        {
            Array <kiss_fft_cpx <kiss_fft_scalar> > bufin = new Array <kiss_fft_cpx <kiss_fft_scalar> >(fin);
            Array <kiss_fft_cpx <kiss_fft_scalar> > bufout;

            /*arrange it so the last bufout == fout*/
            if ((Ndims & 1) != 0)
            {
                bufout = new Array <kiss_fft_cpx <kiss_fft_scalar> >(fout);
                if (fin == fout)
                {
                    for (int i = 0; i < Tmpbuf.Length; ++i)
                    {
                        Tmpbuf[i] = new kiss_fft_cpx <kiss_fft_scalar>(fin[i]);
                    }
                    bufin = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Tmpbuf);
                }
            }
            else
            {
                bufout = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Tmpbuf);
            }

            for (int k = 0; k < Ndims; ++k)
            {
                int curdim = Dims[k];
                int stride = Dimprod / curdim;

                for (int i = 0; i < stride; ++i)
                {
                    States[k].kiss_fft_stride(bufin + i, bufout + i * curdim, stride);
                }

                /*toggle back and forth between the two buffers*/
                if (bufout == Tmpbuf)
                {
                    bufout = new Array <kiss_fft_cpx <kiss_fft_scalar> >(fout);
                    bufin  = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Tmpbuf);
                }
                else
                {
                    bufout = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Tmpbuf);
                    bufin  = new Array <kiss_fft_cpx <kiss_fft_scalar> >(fout);
                }
            }
        }
Esempio n. 5
0
 public void kiss_fft_stride(Array <kiss_fft_cpx <kiss_fft_scalar> > fin, Array <kiss_fft_cpx <kiss_fft_scalar> > fout, int in_stride)
 {
     if (fin == fout)
     {
         //NOTE: this is not really an in-place FFT algorithm.
         //It just performs an out-of-place FFT into a temp buffer
         kiss_fft_cpx <kiss_fft_scalar>[] tmpbuf = new kiss_fft_cpx <kiss_fft_scalar> [Nfft];
         kf_work(new Array <kiss_fft_cpx <kiss_fft_scalar> >(tmpbuf), fin, 1, in_stride, new Array <int>(Factors));
         for (int i = 0; i < Nfft; ++i)
         {
             fout[i] = new kiss_fft_cpx <kiss_fft_scalar>(tmpbuf[i]);
         }
     }
     else
     {
         kf_work(fout, fin, 1, in_stride, new Array <int>(Factors));
     }
 }
Esempio n. 6
0
        protected void kf_bfly3(Array <kiss_fft_cpx <kiss_fft_scalar> > Fout, int fstride, int m)
        {
            int k = m;
            int m2 = 2 * m;
            Array <kiss_fft_cpx <kiss_fft_scalar> > tw1, tw2;

            kiss_fft_cpx <kiss_fft_scalar>[] scratch = new kiss_fft_cpx <kiss_fft_scalar> [5];
            kiss_fft_cpx <kiss_fft_scalar>   epi3;

            epi3 = Twiddles[fstride * m];

            tw1 = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);
            tw2 = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);

            do
            {
                Fout[0]  = A.FixDivide(Fout[0], 3);
                Fout[m]  = A.FixDivide(Fout[m], 3);
                Fout[m2] = A.FixDivide(Fout[m2], 3);

                scratch[1] = A.Multiply(Fout[m], tw1[0]);
                scratch[2] = A.Multiply(Fout[m2], tw2[0]);

                scratch[3] = A.Add(scratch[1], scratch[2]);
                scratch[0] = A.Subtract(scratch[1], scratch[2]);
                tw1       += fstride;
                tw2       += fstride * 2;

                Fout[m].r = A.Subtract(Fout[0].r, A.Half(scratch[3].r));
                Fout[m].i = A.Subtract(Fout[0].i, A.Half(scratch[3].i));

                scratch[0] = A.Multiply(scratch[0], epi3.i);

                Fout[0] = A.Add(Fout[0], scratch[3]);

                Fout[m2].r = A.Add(Fout[m].r, scratch[0].i);
                Fout[m2].i = A.Subtract(Fout[m].i, scratch[0].r);

                Fout[m].r = A.Subtract(Fout[m].r, scratch[0].i);
                Fout[m].i = A.Add(Fout[m].i, scratch[0].r);

                ++Fout;
            } while (--k != 0);
        }
Esempio n. 7
0
        /* perform the butterfly for one stage of a mixed radix FFT */
        protected void kf_bfly_generic(Array <kiss_fft_cpx <kiss_fft_scalar> > Fout, int fstride, int m, int p)
        {
            int u, k, q1, q;
            Array <kiss_fft_cpx <kiss_fft_scalar> > twiddles = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);
            kiss_fft_cpx <kiss_fft_scalar>          t;
            int Norig = Nfft;

            kiss_fft_cpx <kiss_fft_scalar>[] scratch = new kiss_fft_cpx <kiss_fft_scalar> [p];

            for (u = 0; u < m; ++u)
            {
                k = u;
                for (q1 = 0; q1 < p; ++q1)
                {
                    scratch[q1] = new kiss_fft_cpx <kiss_fft_scalar>(Fout[k]);
                    scratch[q1] = A.FixDivide(scratch[q1], p);
                    k          += m;
                }

                k = u;
                for (q1 = 0; q1 < p; ++q1)
                {
                    int twidx = 0;
                    Fout[k] = new kiss_fft_cpx <kiss_fft_scalar>(scratch[0]);
                    for (q = 1; q < p; ++q)
                    {
                        twidx += fstride * k;
                        if (twidx >= Norig)
                        {
                            twidx -= Norig;
                        }
                        t       = A.Multiply(scratch[q], twiddles[twidx]);
                        Fout[k] = A.Add(Fout[k], t);
                    }
                    k += m;
                }
            }
        }
Esempio n. 8
0
 public kiss_fft_cpx <float> Add(kiss_fft_cpx <float> a, kiss_fft_cpx <float> b)
 {
     return(new kiss_fft_cpx <float>(a.r + b.r, a.i + b.i));
 }
Esempio n. 9
0
 public kiss_fft_cpx(kiss_fft_cpx <kiss_fft_scalar> other)
 {
     r = other.r;
     i = other.i;
 }
Esempio n. 10
0
 public kiss_fft_cpx <double> FixDivide(kiss_fft_cpx <double> a, int b)
 {
     return(a);
 }
Esempio n. 11
0
 public kiss_fft_cpx <double> Multiply(kiss_fft_cpx <double> a, double b)
 {
     return(new kiss_fft_cpx <double>(a.r * b, a.i * b));
 }
Esempio n. 12
0
 public kiss_fft_cpx <float> Multiply(kiss_fft_cpx <float> a, float b)
 {
     return(new kiss_fft_cpx <float>(a.r * b, a.i * b));
 }
Esempio n. 13
0
 public kiss_fft_cpx <double> Subtract(kiss_fft_cpx <double> a, kiss_fft_cpx <double> b)
 {
     return(new kiss_fft_cpx <double>(a.r - b.r, a.i - b.i));
 }
Esempio n. 14
0
 public kiss_fft_cpx <double> Add(kiss_fft_cpx <double> a, kiss_fft_cpx <double> b)
 {
     return(new kiss_fft_cpx <double>(a.r + b.r, a.i + b.i));
 }
Esempio n. 15
0
 public kiss_fft_cpx <float> Subtract(kiss_fft_cpx <float> a, kiss_fft_cpx <float> b)
 {
     return(new kiss_fft_cpx <float>(a.r - b.r, a.i - b.i));
 }
Esempio n. 16
0
        protected void kf_work(Array <kiss_fft_cpx <kiss_fft_scalar> > Fout, Array <kiss_fft_cpx <kiss_fft_scalar> > f, int fstride, int in_stride, Array <int> factors)
        {
            Array <kiss_fft_cpx <kiss_fft_scalar> > Fout_beg = Fout;
            int p = factors++[0];             /* the radix  */
            int m = factors++[0];             /* stage's fft length/p */
            Array <kiss_fft_cpx <kiss_fft_scalar> > Fout_end = Fout + p * m;

            // OpenMP

            /*
             * // use openmp extensions at the
             * // top-level (not recursive)
             * if (fstride == 1 && p <= 5)
             * {
             *      int k;
             *
             *      // execute the p different work units in different threads
             #pragma omp parallel for
             *      for (k = 0; k < p; ++k)
             *              kf_work(Fout + k * m, f + fstride * in_stride * k, fstride * p, in_stride, factors, st);
             *      // all threads have joined by this point
             *
             *      switch (p)
             *      {
             *              case 2:
             *                      kf_bfly2(Fout, fstride, st, m);
             *                      break;
             *              case 3:
             *                      kf_bfly3(Fout, fstride, st, m);
             *                      break;
             *              case 4:
             *                      kf_bfly4(Fout, fstride, st, m);
             *                      break;
             *              case 5:
             *                      kf_bfly5(Fout, fstride, st, m);
             *                      break;
             *              default:
             *                      kf_bfly_generic(Fout, fstride, st, m, p);
             *                      break;
             *      }
             *      return;
             * }
             */

            if (m == 1)
            {
                do
                {
                    Fout[0] = new kiss_fft_cpx <kiss_fft_scalar>(f[0]);
                    f      += fstride * in_stride;
                } while (++Fout != Fout_end);
            }
            else
            {
                do
                {
                    // recursive call:
                    // DFT of size m*p performed by doing
                    // p instances of smaller DFTs of size m,
                    // each one takes a decimated version of the input
                    kf_work(Fout, f, fstride * p, in_stride, factors);
                    f += fstride * in_stride;
                } while ((Fout += m) != Fout_end);
            }

            Fout = Fout_beg;

            // recombine the p smaller DFTs
            switch (p)
            {
            case 2:
                kf_bfly2(Fout, fstride, m);
                break;

            case 3:
                kf_bfly3(Fout, fstride, m);
                break;

            case 4:
                kf_bfly4(Fout, fstride, m);
                break;

            case 5:
                kf_bfly5(Fout, fstride, m);
                break;

            default:
                kf_bfly_generic(Fout, fstride, m, p);
                break;
            }
        }
Esempio n. 17
0
        protected void kf_bfly5(Array <kiss_fft_cpx <kiss_fft_scalar> > Fout, int fstride, int m)
        {
            Array <kiss_fft_cpx <kiss_fft_scalar> > Fout0, Fout1, Fout2, Fout3, Fout4;
            int u;

            kiss_fft_cpx <kiss_fft_scalar>[]        scratch  = new kiss_fft_cpx <kiss_fft_scalar> [13];
            Array <kiss_fft_cpx <kiss_fft_scalar> > twiddles = new Array <kiss_fft_cpx <kiss_fft_scalar> >(Twiddles);
            Array <kiss_fft_cpx <kiss_fft_scalar> > tw;
            kiss_fft_cpx <kiss_fft_scalar>          ya, yb;

            ya = twiddles[fstride * m];
            yb = twiddles[fstride * 2 * m];

            Fout0 = Fout;
            Fout1 = Fout0 + m;
            Fout2 = Fout0 + 2 * m;
            Fout3 = Fout0 + 3 * m;
            Fout4 = Fout0 + 4 * m;

            tw = new Array <kiss_fft_cpx <kiss_fft_scalar> >(twiddles);
            for (u = 0; u < m; ++u)
            {
                Fout[0]    = A.FixDivide(Fout[0], 5);
                Fout1[0]   = A.FixDivide(Fout1[0], 5);
                Fout2[0]   = A.FixDivide(Fout2[0], 5);
                Fout3[0]   = A.FixDivide(Fout3[0], 5);
                Fout4[0]   = A.FixDivide(Fout4[0], 5);
                scratch[0] = new kiss_fft_cpx <kiss_fft_scalar>(Fout[0]);

                scratch[1] = A.Multiply(Fout1[0], tw[u * fstride]);
                scratch[2] = A.Multiply(Fout2[0], tw[2 * u * fstride]);
                scratch[3] = A.Multiply(Fout3[0], tw[3 * u * fstride]);
                scratch[4] = A.Multiply(Fout4[0], tw[4 * u * fstride]);

                scratch[7]  = A.Add(scratch[1], scratch[4]);
                scratch[10] = A.Subtract(scratch[1], scratch[4]);
                scratch[8]  = A.Add(scratch[2], scratch[3]);
                scratch[9]  = A.Subtract(scratch[2], scratch[3]);

                Fout[0].r = A.Add(Fout[0].r, A.Add(scratch[7].r, scratch[8].r));
                Fout[0].i = A.Add(Fout[0].i, A.Add(scratch[7].i, scratch[8].i));

                scratch[5].r = A.Add(scratch[0].r, A.Add(A.Multiply(scratch[7].r, ya.r), A.Multiply(scratch[8].r, yb.r)));
                scratch[5].i = A.Add(scratch[0].i, A.Add(A.Multiply(scratch[7].i, ya.r), A.Multiply(scratch[8].i, yb.r)));

                scratch[6].r = A.Add(A.Multiply(scratch[10].i, ya.i), A.Multiply(scratch[9].i, yb.i));
                scratch[6].r = A.Negate(A.Add(A.Multiply(scratch[10].r, ya.i), A.Multiply(scratch[9].r, yb.i)));

                Fout1[0] = A.Subtract(scratch[5], scratch[6]);
                Fout4[0] = A.Add(scratch[5], scratch[6]);

                scratch[11].r = A.Add(scratch[0].r, A.Add(A.Multiply(scratch[7].r, yb.r), A.Multiply(scratch[8].r, ya.r)));
                scratch[11].i = A.Add(scratch[0].i, A.Add(A.Multiply(scratch[7].i, yb.r), A.Multiply(scratch[8].i, ya.r)));
                scratch[12].r = A.Subtract(A.Multiply(scratch[9].i, ya.i), A.Multiply(scratch[10].i, yb.i));
                scratch[12].i = A.Subtract(A.Multiply(scratch[10].r, yb.i), A.Multiply(scratch[9].r, ya.i));

                Fout2[0] = A.Add(scratch[11], scratch[12]);
                Fout3[0] = A.Subtract(scratch[11], scratch[12]);

                ++Fout0;
                ++Fout1;
                ++Fout2;
                ++Fout3;
                ++Fout4;
            }
        }
Esempio n. 18
0
 public kiss_fft_cpx <float> FixDivide(kiss_fft_cpx <float> a, int b)
 {
     return(a);
 }