public LargeArray <WWComplex> ForwardFft(LargeArray <WWComplex> aFrom)
        {
            if (aFrom == null || aFrom.LongLength != mNumPoints)
            {
                throw new ArgumentOutOfRangeException("aFrom");
            }
            var aTo = new LargeArray <WWComplex>(aFrom.LongLength);

            var aTmp0 = new LargeArray <WWComplex>(mNumPoints);

            for (int i = 0; i < aTmp0.LongLength; ++i)
            {
                aTmp0.Set(i, aFrom.At((long)mBitReversalTable.At(i)));
            }
            var aTmp1 = new LargeArray <WWComplex>(mNumPoints);

            for (int i = 0; i < aTmp1.LongLength; ++i)
            {
                aTmp1.Set(i, WWComplex.Zero());
            }

            var aTmps = new LargeArray <WWComplex> [2];

            aTmps[0] = aTmp0;
            aTmps[1] = aTmp1;

            for (int i = 0; i < mNumStage - 1; ++i)
            {
                FftStageN(i, aTmps[((i & 1) == 1) ? 1 : 0], aTmps[((i & 1) == 0) ? 1 : 0]);
            }
            FftStageN(mNumStage - 1, aTmps[(((mNumStage - 1) & 1) == 1) ? 1 : 0], aTo);

            return(aTo);
        }
        public WWComplex Evaluate(WWComplex x)
        {
            WWComplex n = WWComplex.Zero();
            {
                WWComplex xN = WWComplex.Unity();
                for (int i = 0; i < numer.Length; ++i)
                {
                    n  = WWComplex.Add(n, WWComplex.Mul(numer[i], xN));
                    xN = WWComplex.Mul(xN, x);
                }
            }

            WWComplex d = WWComplex.Zero();

            {
                WWComplex xN = WWComplex.Unity();
                for (int i = 0; i < denom.Length; ++i)
                {
                    d  = WWComplex.Add(d, WWComplex.Mul(denom[i], xN));
                    xN = WWComplex.Mul(xN, x);
                }
            }

            return(WWComplex.Div(n, d));
        }
示例#3
0
        /// <summary>
        /// Linear Convolution x ** h を計算。
        /// </summary>
        /// <param name="h">コンボリューションカーネル。左右反転される。</param>
        /// <param name="x">入力数列。</param>
        public WWComplex[] ConvolutionFft(WWComplex[] h, WWComplex[] x) {
            var r = new WWComplex[h.Length + x.Length - 1];
            int fftSize = Functions.NextPowerOf2(r.Length);
            
            var h2 = new WWComplex[fftSize];
            Array.Copy(h, 0, h2, 0, h.Length);
            for (int i = h.Length; i < h2.Length; ++i) {
                h2[i] = WWComplex.Zero();
            }

            var x2 = new WWComplex[fftSize];
            Array.Copy(x, 0, x2, 0, x.Length);
            for (int i = x.Length; i < x2.Length; ++i) {
                x2[i] = WWComplex.Zero();
            }

            var fft = new WWRadix2Fft(fftSize);
            var H = fft.ForwardFft(h2);
            var X = fft.ForwardFft(x2);

            var Y = WWComplex.Mul(H, X);

            var y = fft.InverseFft(Y);

            Array.Copy(y, 0, r, 0, r.Length);
            return r;
        }
        Add(ComplexPolynomial lhs, ComplexPolynomial rhs)
        {
            int order = lhs.Degree;

            if (order < rhs.Degree)
            {
                order = rhs.Degree;
            }

            var rv = new WWComplex[order + 1];

            for (int i = 0; i <= order; ++i)
            {
                WWComplex ck = WWComplex.Zero();
                if (i <= lhs.Degree)
                {
                    ck = WWComplex.Add(ck, lhs.C(i));
                }
                if (i <= rhs.Degree)
                {
                    ck = WWComplex.Add(ck, rhs.C(i));
                }
                rv[i] = ck;
            }

            // 最高次の項が0のとき削除して次数を減らす。
            return(new ComplexPolynomial(rv).ReduceDegree());
        }
 static WWComplex Get(WWComplex[] v, int pos)
 {
     if (pos < 0 || v.Length <= pos)
     {
         return(WWComplex.Zero());
     }
     return(v[pos]);
 }
        MultiplyX(ComplexPolynomial p)
        {
            var rv = new WWComplex [p.Degree + 2];

            rv[0] = WWComplex.Zero();
            for (int i = 0; i <= p.Degree; ++i)
            {
                rv[i + 1] = p.C(i);
            }
            return(new ComplexPolynomial(rv));
        }
示例#7
0
        PartialFractionDecomposition(
            WWComplex [] nCoeffs, WWComplex [] dRoots)
        {
            var result = new List <FirstOrderComplexRationalPolynomial>();

            if (dRoots.Length == 1 && nCoeffs.Length == 1)
            {
                result.Add(new FirstOrderComplexRationalPolynomial(WWComplex.Zero(),
                                                                   nCoeffs[0], WWComplex.Unity(), WWComplex.Minus(dRoots[0])));
                return(result);
            }

            if (dRoots.Length < 2)
            {
                throw new ArgumentException("denomR");
            }
            if (dRoots.Length < nCoeffs.Length)
            {
                throw new ArgumentException("nCoeffs");
            }

            for (int k = 0; k < dRoots.Length; ++k)
            {
                // cn = ... + nCoeffs[2]s^2 + nCoeffs[1]s + nCoeffs[0]
                // 係数c[0]は、s==denomR[0]としたときの、cn/(s-denomR[1])(s-denomR[2])(s-denomR[3])…(s-denomR[p-1])
                // 係数c[1]は、s==denomR[1]としたときの、cn/(s-denomR[0])(s-denomR[2])(s-denomR[3])…(s-denomR[p-1])
                // 係数c[2]は、s==denomR[2]としたときの、cn/(s-denomR[0])(s-denomR[1])(s-denomR[3])…(s-denomR[p-1])

                // 分子の値c。
                var c = WWComplex.Zero();
                var s = WWComplex.Unity();
                for (int j = 0; j < nCoeffs.Length; ++j)
                {
                    c = WWComplex.Add(c, WWComplex.Mul(nCoeffs[j], s));
                    s = WWComplex.Mul(s, dRoots[k]);
                }

                for (int i = 0; i < dRoots.Length; ++i)
                {
                    if (i == k)
                    {
                        continue;
                    }

                    c = WWComplex.Div(c, WWComplex.Sub(dRoots[k], dRoots[i]));
                }

                result.Add(new FirstOrderComplexRationalPolynomial(
                               WWComplex.Zero(), c,
                               WWComplex.Unity(), WWComplex.Minus(dRoots[k])));
            }

            return(result);
        }
示例#8
0
        /// <summary>
        /// 連続FFT オーバーラップアド法でLinear convolution x ** hする。
        /// </summary>
        /// <param name="h">コンボリューションカーネル。左右反転される。</param>
        /// <param name="x">入力数列。</param>
        /// <param name="fragmentSz">個々のFFTに入力するxの断片サイズ。</param>
        public WWComplex[] ConvolutionContinuousFft(WWComplex[] h, WWComplex[] x, int fragmentSz) {
            System.Diagnostics.Debug.Assert(2 <= fragmentSz);

            if (x.Length < h.Length) {
                // swap x and h
                var tmp = h;
                h = x;
                x = tmp;
            }

            // h.Len <= x.Len

            int fullConvLen = h.Length + x.Length - 1;

            var r = new WWComplex[fullConvLen];
            for (int i = 0; i < r.Length; ++i) {
                r[i] = WWComplex.Zero();
            }

            // hをFFTしてHを得る。
            int fragConvLen = h.Length + fragmentSz - 1;
            int fftSize = Functions.NextPowerOf2(fragConvLen);
            var h2 = new WWComplex[fftSize];
            Array.Copy(h, 0, h2, 0, h.Length);
            for (int i = h.Length; i < h2.Length; ++i) {
                h2[i] = WWComplex.Zero();
            }
            var fft = new WWRadix2Fft(fftSize);
            var H = fft.ForwardFft(h2);

            for (int offs = 0; offs < x.Length; offs += fragmentSz) {
                // xFをFFTしてXを得る。
                var xF = WWComplex.ZeroArray(fftSize);
                for (int i=0; i<fragmentSz; ++i) {
                    if (i + offs < x.Length) {
                        xF[i] = x[offs + i];
                    } else {
                        break;
                    }
                }
                var X = fft.ForwardFft(xF);

                var Y = WWComplex.Mul(H, X);
                var y = fft.InverseFft(Y);

                // オーバーラップアド法。FFT結果を足し合わせる。
                for (int i = 0; i <fragConvLen; ++i) {
                    r[offs + i] = WWComplex.Add(r[offs + i], y[i]);
                }
            }

            return r;
        }
示例#9
0
        /// <summary>
        /// 注:compensationが指定しないとき、結果をNで割りません。
        /// </summary>
        /// <param name="aFrom">時間ドメイン値x[n] 0≦n<N</param>
        /// <param name="compensation">倍率。指定しないとき1.0倍となる。</param>
        /// <returns>周波数ドメイン値X^m(q)</returns>
        public WWComplex[] ForwardFft(WWComplex[] aFrom, double?compensation = null)
        {
            if (aFrom == null || aFrom.Length != mNumPoints)
            {
                throw new ArgumentOutOfRangeException("aFrom");
            }
            var aTo = new WWComplex[aFrom.Length];

            var aTmp0 = new WWComplex[mNumPoints];

            for (int i = 0; i < aTmp0.Length; ++i)
            {
                aTmp0[i] = aFrom[mBitReversalTable[i]];
            }
            var aTmp1 = new WWComplex[mNumPoints];

            for (int i = 0; i < aTmp1.Length; ++i)
            {
                aTmp1[i] = WWComplex.Zero();
            }

            var aTmps = new WWComplex[2][];

            aTmps[0] = aTmp0;
            aTmps[1] = aTmp1;

            for (int i = 0; i < mNumStage - 1; ++i)
            {
                FftStageN(i, aTmps[((i & 1) == 1) ? 1 : 0], aTmps[((i & 1) == 0) ? 1 : 0]);
            }
            FftStageN(mNumStage - 1, aTmps[(((mNumStage - 1) & 1) == 1) ? 1 : 0], aTo);

            double c = 1.0;

            if (compensation != null)
            {
                c = (double)compensation;
            }

            if (c != 1.0)
            {
                var aToC = new WWComplex[aTo.Length];
                for (int i = 0; i < aTo.Length; ++i)
                {
                    aToC[i] = new WWComplex(aTo[i].real * c, aTo[i].imaginary * c);
                }
                return(aToC);
            }
            else
            {
                return(aTo);
            }
        }
示例#10
0
        Reduction(WWComplex [] aNumerCoeffList, WWComplex [] aDenomRootList)
        {
            var rv = new PolynomialAndRationalPolynomial();

            rv.coeffList      = new WWComplex[0];
            rv.numerCoeffList = new WWComplex[aNumerCoeffList.Length];
            Array.Copy(aNumerCoeffList, rv.numerCoeffList, aNumerCoeffList.Length);
            rv.denomRootList = new WWComplex[aDenomRootList.Length];
            Array.Copy(aDenomRootList, rv.denomRootList, aDenomRootList.Length);

            if (rv.numerCoeffList.Length - 1 < rv.denomRootList.Length)
            {
                // 既に分子の多項式の次数が分母の多項式の次数よりも低い。
                return(rv);
            }

            // 分母の根のリスト⇒分母の多項式の係数のリストに変換。
            var denomCoeffList = RootListToCoeffList(aDenomRootList, new WWComplex(1, 0));

            var quotient = new List <WWComplex>();

            while (denomCoeffList.Length <= rv.numerCoeffList.Length)
            {
                // denomの最も次数が高い項の係数がcdn、numerの最も次数が高い項の係数がcnnとすると
                // denomiCoeffListを-cnn/cdn * s^(numerの次数-denomの次数)倍してnumerCoeffListと足し合わせてnumerの次数を1下げる。
                // このときrv.coeffListにc == cnn/cdnを足す。
                var c = WWComplex.Div(rv.numerCoeffList[rv.numerCoeffList.Length - 1],
                                      denomCoeffList[denomCoeffList.Length - 1]);
                quotient.Insert(0, c);
                var denomMulX = new ComplexPolynomial(denomCoeffList);
                while (denomMulX.Degree + 1 < rv.numerCoeffList.Length)
                {
                    denomMulX = ComplexPolynomial.MultiplyX(denomMulX);
                }
                denomMulX = ComplexPolynomial.MultiplyC(denomMulX, WWComplex.Mul(c, -1));

                // ここで引き算することで分子の多項式の次数が1減る。
                int expectedOrder = rv.numerCoeffList.Length - 2;
                rv.numerCoeffList = ComplexPolynomial.TrimPolynomialOrder(
                    ComplexPolynomial.Add(denomMulX, new ComplexPolynomial(rv.numerCoeffList)),
                    expectedOrder).ToArray();

                // 引き算によって一挙に2以上次数が減った場合coeffListに0を足す。
                int actualOrder = rv.numerCoeffList.Length - 1;
                for (int i = 0; i < expectedOrder - actualOrder; ++i)
                {
                    quotient.Insert(0, WWComplex.Zero());
                }
            }

            rv.coeffList = quotient.ToArray();
            return(rv);
        }
示例#11
0
        /// <summary>
        /// Calculate poly value at position z
        /// </summary>
        /// <param name="p">z position</param>
        /// <returns>y</returns>
        public WWComplex Evaluate(WWComplex z)
        {
            WWComplex y      = WWComplex.Zero();
            WWComplex zPower = WWComplex.Unity();

            for (int i = 0; i < mCoeff.Length; ++i)
            {
                y      = WWComplex.Add(y, WWComplex.Mul(mCoeff[i], zPower));
                zPower = WWComplex.Mul(zPower, z);
            }

            return(y);
        }
示例#12
0
        /// <summary>
        /// この多項式が位置zで取る値を戻す。
        /// </summary>
        /// <param name="z">ガウス平面上の座標(p,y)</param>
        /// <returns>多項式が位置zで取る値。</returns>
        public WWComplex Evaluate(WWComplex z)
        {
            WWComplex w      = WWComplex.Zero();
            WWComplex zPower = WWComplex.Unity();

            for (int i = 0; i < mCoeff.Length; ++i)
            {
                w      = WWComplex.Add(w, zPower.Scale(mCoeff[i]));
                zPower = WWComplex.Mul(zPower, z);
            }

            return(w);
        }
示例#13
0
        /// <summary>
        /// 時間ドメイン値xを入力すると、N点DFTの周波数ドメイン値Xのm番目の周波数binの値を戻す。
        /// </summary>
        /// <param name="m">周波数binの番号。0≦m<N</param>
        /// <param name="N">DFTサイズN。</param>
        public WWGoertzel(int m, int N)
        {
            if (N <= 0)
            {
                throw new ArgumentOutOfRangeException("N");
            }

            mN     = N;
            mDelay = new DelayT <WWComplex>(1);
            mDelay.Fill(WWComplex.Zero());

            mOsc = new WWQuadratureOscillatorInt(-m, N);
        }
示例#14
0
        /// <summary>
        /// Linear Convolution x ** h を計算。
        /// </summary>
        /// <param name="h">コンボリューションカーネル。左右反転される。</param>
        /// <param name="x">入力数列。</param>
        public WWComplex[] ConvolutionBruteForce(WWComplex[] h, WWComplex[] x) {
            var r = new WWComplex[h.Length + x.Length - 1];

            Parallel.For(0, r.Length, i => {
                WWComplex v = WWComplex.Zero();

                for (int j = 0; j < h.Length; ++j) {
                    int hPos = h.Length - j - 1;
                    int xPos = i + j - (h.Length - 1);
                    v = WWComplex.Add(v, WWComplex.Mul(Get(h, hPos), Get(x, xPos)));
                }
                r[i] = v;
            });

            return r;
        }
        /// <summary>
        /// 1次多項式を作る。
        /// mCoeffs[0] + p * mCoeffs[1]
        /// </summary>
        public static List <FirstOrderComplexRationalPolynomial> CreateFromCoeffList(WWComplex [] coeffList)
        {
            var p = new List <FirstOrderComplexRationalPolynomial>();

            if (coeffList.Length == 0)
            {
                return(p);
            }
            if (coeffList.Length == 1)
            {
                // 定数を追加。
                p.Add(new FirstOrderComplexRationalPolynomial(WWComplex.Zero(), coeffList[0], WWComplex.Zero(), WWComplex.Unity()));
            }
            if (coeffList.Length == 2)
            {
                // 1次式を追加。
                p.Add(new FirstOrderComplexRationalPolynomial(coeffList[1], coeffList[0], WWComplex.Zero(), WWComplex.Unity()));
            }

            return(p);
        }
示例#16
0
            public SlidingDFTbin(int m, int N, double compensation)
            {
                if (N <= 0)
                {
                    throw new ArgumentOutOfRangeException("N");
                }
                if (m < 0 || N <= m)
                {
                    throw new ArgumentOutOfRangeException("m");
                }

                mN            = N;
                mCompensation = compensation;
                mM            = m;

                double θ = 2.0 * Math.PI * m / N;

                mE = new WWComplex(Math.Cos(θ), Math.Sin(θ));

                mDelay = new DelayT <WWComplex>(1);
                mDelay.Fill(WWComplex.Zero());
            }
示例#17
0
        public WWComplex Evaluate(WWComplex x)
        {
            WWComplex n  = WWComplex.Zero();
            WWComplex xN = WWComplex.Unity();

            for (int i = 0; i < numer.Length; ++i)
            {
                n  = WWComplex.Add(n, WWComplex.Mul(xN, numer[i]));
                xN = WWComplex.Mul(xN, x);
            }

            WWComplex d = WWComplex.Zero();

            xN = WWComplex.Unity();
            for (int i = 0; i < denom.Length; ++i)
            {
                d  = WWComplex.Add(d, WWComplex.Mul(xN, denom[i]));
                xN = WWComplex.Mul(xN, x);
            }

            WWComplex y = WWComplex.Div(n, d);

            return(y);
        }
        private void FftStageN(int stageNr, LargeArray <WWComplex> x, LargeArray <WWComplex> y)
        {
            /*
             * stage0: 2つの入力データにバタフライ演算 (length=8の時) 4回 (nRepeat=4, nSubRepeat=2)
             * y[0] = x[0] + w_n^(0*4) * x[1]
             * y[1] = x[0] + w_n^(1*4) * x[1]
             *
             * y[2] = x[2] + w_n^(0*4) * x[3]
             * y[3] = x[2] + w_n^(1*4) * x[3]
             *
             * y[4] = x[4] + w_n^(0*4) * x[5]
             * y[5] = x[4] + w_n^(1*4) * x[5]
             *
             * y[6] = x[6] + w_n^(0*4) * x[7]
             * y[7] = x[6] + w_n^(1*4) * x[7]
             */

            /*
             * stage1: 4つの入力データにバタフライ演算 (length=8の時) 2回 (nRepeat=2, nSubRepeat=4)
             * y[0] = x[0] + w_n^(0*2) * x[2]
             * y[1] = x[1] + w_n^(1*2) * x[3]
             * y[2] = x[0] + w_n^(2*2) * x[2]
             * y[3] = x[1] + w_n^(3*2) * x[3]
             *
             * y[4] = x[4] + w_n^(0*2) * x[6]
             * y[5] = x[5] + w_n^(1*2) * x[7]
             * y[6] = x[4] + w_n^(2*2) * x[6]
             * y[7] = x[5] + w_n^(3*2) * x[7]
             */

            /*
             * stage2: 8つの入力データにバタフライ演算 (length=8の時) 1回 (nRepeat=1, nSubRepeat=8)
             * y[0] = x[0] + w_n^(0*1) * x[4]
             * y[1] = x[1] + w_n^(1*1) * x[5]
             * y[2] = x[2] + w_n^(2*1) * x[6]
             * y[3] = x[3] + w_n^(3*1) * x[7]
             * y[4] = x[0] + w_n^(4*1) * x[4]
             * y[5] = x[1] + w_n^(5*1) * x[5]
             * y[6] = x[2] + w_n^(6*1) * x[6]
             * y[7] = x[3] + w_n^(7*1) * x[7]
             */

            /*
             * stageN:
             */

            long nRepeat    = Pow2(mNumStage - stageNr - 1);
            long nSubRepeat = mNumPoints / nRepeat;

            for (long i = 0; i < nRepeat; ++i)
            {
                long offsBase = i * nSubRepeat;

                bool allZero = true;
                for (long j = 0; j < nSubRepeat / 2; ++j)
                {
                    long offs = offsBase + (j % (nSubRepeat / 2));
                    if (Double.Epsilon < x.At(offs).Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                    if (Double.Epsilon < x.At(offs + nSubRepeat / 2).Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                }

                if (allZero)
                {
                    for (long j = 0; j < nSubRepeat; ++j)
                    {
                        y.Set(j + offsBase, WWComplex.Zero());
                    }
                }
                else
                {
                    for (long j = 0; j < nSubRepeat; ++j)
                    {
                        long offs = offsBase + (j % (nSubRepeat / 2));
                        var  t    = x.At(offs);

                        var t2 = WWComplex.Mul(mWn.At(j * nRepeat), x.At(offs + nSubRepeat / 2));
                        var t3 = WWComplex.Add(t, t2);

                        y.Set(j + offsBase, t3);
                    }
                }
            }
        }
示例#19
0
        public static void Test()
        {
            {
                /*
                 * 部分分数分解のテスト。
                 *           s + 3
                 * X(s) = -------------
                 *         (s+1)s(s-2)
                 *
                 * 部分分数分解すると
                 *
                 *          2/3      -3/2      5/6
                 * X(s) = ------- + ------ + -------
                 *         s + 1       s      s - 2
                 */
                var numerCoeffs = new WWComplex [] {
                    new WWComplex(3, 0),
                    new WWComplex(1, 0)
                };

                var dRoots = new WWComplex [] {
                    new WWComplex(-1, 0),
                    WWComplex.Zero(),
                    new WWComplex(2, 0)
                };

                var p = WWPolynomial.PartialFractionDecomposition(numerCoeffs, dRoots);

                for (int i = 0; i < p.Count; ++i)
                {
                    Console.WriteLine(p[i].ToString("s"));
                    if (i != p.Count - 1)
                    {
                        Console.WriteLine(" + ");
                    }
                }

                Console.WriteLine("");
            }

            {
                // 約分のテスト
                //  p-1        (p+1) -(p+1) + (p-1)            -2
                // ─────  ⇒  ──────────────────────  ⇒  1 + ─────
                //  p+1                  p+1                   p+1

                var numerC = new List <WWComplex>();
                numerC.Add(new WWComplex(-1, 0)); // 定数項。
                numerC.Add(WWComplex.Unity());    // 1乗の項。

                var denomR = new List <WWComplex>();
                denomR.Add(new WWComplex(-1, 0));

                var r = Reduction(numerC.ToArray(), denomR.ToArray());
                r.Print("p");
            }

            {
                // 約分のテスト
                //  p^2+3x+2            (p^2+3x+2) -(p^2+7x+12)            -4x-10
                // ────────────  ⇒ 1+ ─────────────────────────  ⇒  1 + ────────────
                //  (p+3)(p+4)           p^2+7x+12                         (p+3)(p+4)

                var numerC = new WWComplex [] {
                    new WWComplex(2, 0), // 定数項。
                    new WWComplex(3, 0), // 1乗の項。
                    WWComplex.Unity()
                };                       // 2乗の項。

                var denomR = new WWComplex [] {
                    new WWComplex(-3, 0),
                    new WWComplex(-4, 0)
                };

                var r = Reduction(numerC, denomR);
                r.Print("p");
            }
            {
                // 部分分数分解。
                //  -4x-10             2      -6
                // ────────────  ⇒  ───── + ─────
                //  (p+3)(p+4)        p+3     p+4

                var numerC = new WWComplex [] {
                    new WWComplex(-10, 0),
                    new WWComplex(-4, 0)
                };

                var denomR = new WWComplex [] {
                    new WWComplex(-3, 0),
                    new WWComplex(-4, 0)
                };

                var p = WWPolynomial.PartialFractionDecomposition(numerC, denomR);

                for (int i = 0; i < p.Count; ++i)
                {
                    Console.WriteLine(p[i].ToString("s"));
                    if (i != p.Count - 1)
                    {
                        Console.WriteLine(" + ");
                    }
                }

                Console.WriteLine("");
            }

            {
                var deriv = new RealPolynomial(new double[] { 1, 1, 1, 1 }).Derivative();
                Console.WriteLine("derivative of p^3+p^2+p+1={0}",
                                  deriv.ToString("p"));
            }

            {
                var r2 = AlgebraicLongDivision(new RealPolynomial(new double[] { 6, 3, 1 }),
                                               new RealPolynomial(new double[] { 1, 1 }));
                Console.WriteLine("(p^2+3x+6)/(p+1) = {0} r {1}",
                                  r2.quotient.ToString(), r2.remainder.ToString());
            }
        }
示例#20
0
        private void FftStageN(int stageNr, WWComplex[] x, WWComplex[] y)
        {
            /*
             * stage0: 2つの入力データにバタフライ演算 (length=8の時) 4回 (nRepeat=4, nSubRepeat=2)
             * y[0] = x[0] + w_n^(0*4) * x[1]
             * y[1] = x[0] + w_n^(1*4) * x[1]
             *
             * y[2] = x[2] + w_n^(0*4) * x[3]
             * y[3] = x[2] + w_n^(1*4) * x[3]
             *
             * y[4] = x[4] + w_n^(0*4) * x[5]
             * y[5] = x[4] + w_n^(1*4) * x[5]
             *
             * y[6] = x[6] + w_n^(0*4) * x[7]
             * y[7] = x[6] + w_n^(1*4) * x[7]
             */

            /*
             * stage1: 4つの入力データにバタフライ演算 (length=8の時) 2回 (nRepeat=2, nSubRepeat=4)
             * y[0] = x[0] + w_n^(0*2) * x[2]
             * y[1] = x[1] + w_n^(1*2) * x[3]
             * y[2] = x[0] + w_n^(2*2) * x[2]
             * y[3] = x[1] + w_n^(3*2) * x[3]
             *
             * y[4] = x[4] + w_n^(0*2) * x[6]
             * y[5] = x[5] + w_n^(1*2) * x[7]
             * y[6] = x[4] + w_n^(2*2) * x[6]
             * y[7] = x[5] + w_n^(3*2) * x[7]
             */

            /*
             * stage2: 8つの入力データにバタフライ演算 (length=8の時) 1回 (nRepeat=1, nSubRepeat=8)
             * y[0] = x[0] + w_n^(0*1) * x[4]
             * y[1] = x[1] + w_n^(1*1) * x[5]
             * y[2] = x[2] + w_n^(2*1) * x[6]
             * y[3] = x[3] + w_n^(3*1) * x[7]
             * y[4] = x[0] + w_n^(4*1) * x[4]
             * y[5] = x[1] + w_n^(5*1) * x[5]
             * y[6] = x[2] + w_n^(6*1) * x[6]
             * y[7] = x[3] + w_n^(7*1) * x[7]
             */

            /*
             * stageN:
             */

            int nRepeat    = Pow2(mNumStage - stageNr - 1);
            int nSubRepeat = mNumPoints / nRepeat;
            var t          = WWComplex.Zero();

            for (int i = 0; i < nRepeat; ++i)
            {
                int offsBase = i * nSubRepeat;

                bool allZero = true;
                for (int j = 0; j < nSubRepeat / 2; ++j)
                {
                    int offs = offsBase + (j % (nSubRepeat / 2));
                    if (Double.Epsilon < x[offs].Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                    if (Double.Epsilon < x[offs + nSubRepeat / 2].Magnitude())
                    {
                        allZero = false;
                        break;
                    }
                }

                if (allZero)
                {
                    for (int j = 0; j < nSubRepeat; ++j)
                    {
                        y[j + offsBase] = WWComplex.Zero();
                    }
                }
                else
                {
                    for (int j = 0; j < nSubRepeat; ++j)
                    {
                        int offs = offsBase + (j % (nSubRepeat / 2));

                        var v1 = x[offs];
                        var v2 = WWComplex.Mul(mWn[j * nRepeat], x[offs + nSubRepeat / 2]);
                        y[j + offsBase] = WWComplex.Add(v1, v2);
                    }
                }
            }
        }