public static Complex[,] fft2d(Complex[,] input) { Complex[,] output = (Complex[,])input.Clone(); // Rows first: Complex[] x = new Complex[output.GetLength(1)]; for (int h = 0; h < output.GetLength(0); h++) { for (int i = 0; i < output.GetLength(1); i++) { x[i] = output[h, i]; } x = fft(x); for (int i = 0; i < output.GetLength(1); i++) { output[h, i] = x[i]; } } //Columns last Complex[] y = new Complex[output.GetLength(0)]; for (int h = 0; h < output.GetLength(1); h++) { for (int i = 0; i < output.GetLength(0); i++) { y[i] = output[i, h]; } y = fft(y); for (int i = 0; i < output.GetLength(0); i++) { output[i, h] = y[i]; } } return output; }
public Complex[] ComputeSpectrum(Complex[] srcData) { var data = srcData.Clone() as Complex[]; ComputeSpectrumInPlace(data); return data; }
private static (Complex Zero, bool converge, Complex[] qp) Vrshft(Complex z, Complex[] p, Complex[] h) { double relstp = 0; var b = 0; var s = z.Clone(); _ = new Complex[p.Length]; Complex pv; Complex[] qp; (pv, qp) = p.Deflate(s); var mp = pv.Modulus(); if (mp <= 20 * ErrorEvaluation(qp, s.Modulus(), mp)) { return(s, true, qp); } double omp = mp; LastPart(); for (int i = 2; i <= 10; i++) { (pv, qp) = p.Deflate(s); mp = pv.Modulus(); if (mp <= 20 * ErrorEvaluation(qp, s.Modulus(), mp)) { return(s, true, qp); } var pumasa = b == 1 || mp < omp || relstp >= 0.05; if (pumasa && mp * 0.1 > omp) { return(z, false, qp); } if (!pumasa) { b = 1; s *= SMultiplier(relstp); (pv, qp) = p.Deflate(s); for (var j = 1; j <= 5; j++) { h = CalcTH(h, s, qp, pv); } } omp = pumasa ? mp : DblMax; LastPart(); } return(z, false, qp); void LastPart() { h = CalcTH(h, s, qp, pv); var(t1, _) = Calct(s, pv, h); if (t1 != new Complex(0, 0)) { relstp = t1.Modulus() / s.Modulus(); s += t1; } } }
public Term(Complex coefficient, Indeterminate[] variables) { CoEfficient = coefficient.Clone(); Variables = CloneHelper <Indeterminate> .CloneCollection(variables).ToArray(); }
/// <summary> /// Performs the Fast Hilbert Transform over a complex[] array. /// </summary> /// public static void FHT(Complex[] data, FourierTransform.Direction direction) { int N = data.Length; // Forward operation if (direction == FourierTransform.Direction.Forward) { // Makes a copy of the data so we don't lose the // original information to build our final signal Complex[] shift = (Complex[])data.Clone(); // Perform FFT FourierTransform.FFT(shift, FourierTransform.Direction.Backward); //double positive frequencies for (int i = 1; i < (N / 2); i++) { shift[i] *= 2.0; } // zero out negative frequencies // (leaving out the dc component) for (int i = (N / 2) + 1; i < N; i++) { shift[i] = Complex.Zero; } // Reverse the FFT FourierTransform.FFT(shift, FourierTransform.Direction.Forward); // Put the Hilbert transform in the Imaginary part // of the input signal, creating a Analytic Signal for (int i = 0; i < N; i++) data[i] = new Complex(data[i].Real, shift[i].Imaginary); } else // Backward operation { // Just discard the imaginary part for (int i = 0; i < data.Length; i++) data[i] = new Complex(data[i].Real, 0.0); } }
/// <summary> /// Removes unnecessary zero terms. /// </summary> public void Clean() { int i; for (i = Degree; i >= 0 && Coefficients[i] == 0; i--) ; Complex[] coeffs = new Complex[i + 1]; for (int k = 0; k <= i; k++) coeffs[k] = Coefficients[k]; Coefficients = (Complex[])coeffs.Clone(); }
/// <summary> /// 一维频率抽取基2快速傅里叶变换 /// 频率抽取:输入为自然顺序,输出为码位倒置顺序 /// 基2:待变换的序列长度必须为2的整数次幂 /// </summary> /// <param name="sourceData">待变换的序列(复数数组)</param> /// <param name="countN">序列长度,可以指定[0,sourceData.Length-1]区间内的任意数值</param> /// <returns>返回变换后的序列(复数数组)</returns> private Complex[] fft_frequency(Complex[] sourceData, int countN) { if (countN == 0) return null; if (sourceData == null) return null; //2的r次幂为N,求出r.r能代表fft算法的迭代次数 double dr = Math.Log(countN, 2); //int r = Convert.ToInt32(dr); int r = (int)Math.Ceiling(dr); //向上取整 Complex[] resultData = new Complex[sourceData.Length]; if (dr - r != 0) { countN = (int)Math.Pow(2, r); } //分别存储蝶形运算过程中左右两列的结果 Complex[] interVar1 = new Complex[countN]; Complex[] interVar2 = new Complex[countN]; //interVar1 = (Complex[])sourceData.Clone(); int index = 0; for (; index < sourceData.Length; index++) { interVar1[index] = sourceData[index]; } if (sourceData.Length < countN) { while (index < countN) { interVar1[index] = new Complex(); index++; } } //w代表旋转因子 Complex[] w = new Complex[countN / 2]; //为旋转因子赋值。(在蝶形运算中使用的旋转因子是已经确定的,提前求出以便调用) //旋转因子公式 \ /\ /k __ // \/ \/N -- exp(-j*2πk/N) //这里还用到了欧拉公式 for (int i = 0; i < countN / 2; i++) { double angle = -i * Math.PI * 2 / countN; w[i] = new Complex(Math.Cos(angle), Math.Sin(angle)); } //蝶形运算 for (int i = 0; i < r; i++) { //i代表当前的迭代次数,r代表总共的迭代次数. //i记录着迭代的重要信息.通过i可以算出当前迭代共有几个分组,每个分组的长度 //interval记录当前有几个组 // <<是左移操作符,左移一位相当于*2 //多使用位运算符可以人为提高算法速率^_^ int interval = 1 << i; //halfN记录当前循环每个组的长度N int halfN = 1 << (r - i); //循环,依次对每个组进行蝶形运算 for (int j = 0; j < interval; j++) { //j代表第j个组 //gap=j*每组长度,代表着当前第j组的首元素的下标索引 int gap = j * halfN; //进行蝶形运算 for (int k = 0; k < halfN / 2; k++) { interVar2[k + gap] = interVar1[k + gap] + interVar1[k + gap + halfN / 2]; interVar2[k + (halfN / 2) + gap] = (interVar1[k + gap] - interVar1[k + gap + (halfN / 2)]) * w[k * interval]; } } //将结果拷贝到输入端,为下次迭代做好准备 interVar1 = (Complex[])interVar2.Clone(); } //将输出码位倒置 for (uint j = 0; j < countN; j++) { //j代表自然顺序的数组元素的下标索引 //用rev记录j码位倒置后的结果 uint rev = 0; //num作为中间变量 uint num = j; //码位倒置(通过将j的最右端一位最先放入rev右端,然后左移,然后将j的次右端一位放入rev右端,然后左移...) //由于2的r次幂=N,所以任何j可由r位二进制数组表示,循环r次即可 for (int i = 0; i < r; i++) { rev <<= 1; rev |= num & 1; num >>= 1; } interVar2[rev] = interVar1[j]; } for (int i = 0; i < resultData.Length; i++) resultData[i] = interVar2[i]; return resultData; }
void FFT(double[] sourceData, double[] spectrumData) { int N = spectrumData.Length; int r = Convert.ToInt32(Math.Log(N, 2)); Complex[] interVar1 = new Complex[N]; Complex[] interVar2 = new Complex[N]; for (int i = 0; i < N; i++) { interVar1[i] = new Complex(sourceData[i], 0); } //interVar1 = (Complex[])sourceData.Clone(); Complex[] w = new Complex[N / 2]; for (int i = 0; i < N / 2; i++) { double angle = -i * Math.PI * 2 / N; w[i] = new Complex(Math.Cos(angle), Math.Sin(angle)); } for (int i = 0; i < r; i++) { int interval = 1 << i; int halfN = 1 << (r - i); for (int j = 0; j < interval; j++) { int gap = j * halfN; for (int k = 0; k < halfN / 2; k++) { interVar2[k + gap] = interVar1[k + gap] + interVar1[k + gap + halfN / 2]; interVar2[k + halfN / 2 + gap] = (interVar1[k + gap] - interVar1[k + gap + halfN / 2]) * w[k * interval]; } } interVar1 = (Complex[])interVar2.Clone(); } for (uint j = 0; j < N; j++) { uint rev = 0; uint num = j; for (int i = 0; i < r; i++) { rev <<= 1; rev |= num & 1; num >>= 1; } interVar2[rev] = interVar1[j]; } for (int i = 0; i < N; i++) { spectrumData[i] = Complex.Abs(interVar2[i]); } }