public RealFourierTransform(int length)
    {
      _numberOfData = length;

      if(length<1)
        throw new ArgumentException("length smaller than 1 is not appropriate here.");
      else if(length<3)
      {
        _method = Method.Trivial;
      }
      else if(Calc.BinaryMath.IsPowerOfTwo(length))
      {
        // use Hartley transform
        _method = Method.Hartley;
      }
      else if(Pfa235FFT.CanFactorized(length))
      {
        // use Pfa235 transform
        _method = Method.Pfa235;
        _pfa235 = new Pfa235FFT(_numberOfData);
      }
      else
      {
        // use chirp transform
        _method = Method.Chirp;
      }
    }
Exemple #2
0
		/// <summary>
		///  Copy-Constructor
		/// </summary>
		/// <remarks>
		/// Setup fast Fourier transform / back-transform for one, two or three
		/// dimensions. The dimensions n1,n2,and n3 must be of the form
		///              n = (2**p) * (3**q) * (5**r)
		/// otherwise an error will be generated and the error handler function
		/// Matpack.Error() is called. On instantiation some trigonometric tables
		/// will be allocated and calculated. This approach avoids multiple
		/// twiddle factor recalculations if several FFTs are calculated for data
		/// with the same dimensions. Sometimes it is convenient to define an
		/// "empty" setup (first constructor) and assign a setup later (see
		/// copying and assignment). As default the multi-dimensional data
		/// are expected in row order (C convention). If you want to transform
		/// data stored in column order (Fortran convention) use the member
		/// function SetOrder() to change the order - see below. For optimizations
		/// on vector machines with separate memory banks an extra leading dimension
		/// can be defined to avoid bank conflicts - also see SetOrder().
		/// </remarks>
		public Pfa235FFT(Pfa235FFT fft)
		{
			// copy all elements
			id = fft.id;
			ndim = fft.ndim;
			trisize = fft.trisize;
			row_order = fft.row_order;
			for (int i = 0; i < 3; i++)
			{
				dim[i] = fft.dim[i];
				trindex[i] = fft.trindex[i];
			}

			// allocate and copy trigs
			trigs = new double[trisize];
			Array.Copy(fft.trigs, 0, this.trigs, 0, fft.trigs.Length);
		}
    protected static string TwoDimFFT(Altaxo.AltaxoDocument mainDocument, GUI.WorksheetController dg, out double[] rePart, out double[] imPart)
    {
      int rows = dg.Doc.DataColumns.RowCount;
      int cols = dg.Doc.DataColumns.ColumnCount;

      // reserve two arrays (one for real part, which is filled with the table contents)
      // and the imaginary part - which is left zero here)

      rePart = new double[rows*cols];
      imPart = new double[rows*cols];

      // fill the real part with the table contents
      for(int i=0;i<cols;i++)
      {
        Altaxo.Data.INumericColumn col = dg.Doc[i] as Altaxo.Data.INumericColumn;
        if(null==col)
        {
          return string.Format("Can't apply fourier transform, since column number {0}, name:{1} is not numeric",i,dg.Doc[i].FullName); 
        }

        for(int j=0;j<rows;j++)
        {
          rePart[i*rows+j] = col[j];
        }
      }

      // test it can be done
      if(!Pfa235FFT.CanFactorized(cols))
        return string.Format("Can't apply fourier transform, since the number of cols ({0}) are not appropriate for this kind of fourier transform.",cols);
      if(!Pfa235FFT.CanFactorized(rows))
        return string.Format("Can't apply fourier transform, since the number of rows ({0}) are not appropriate for this kind of fourier transform.",rows);

      // fourier transform
      Pfa235FFT fft = new Pfa235FFT(cols,rows);
      fft.FFT(rePart,imPart,FourierDirection.Forward);

      // replace the real part by the amplitude
      for(int i=0;i<rePart.Length;i++)
      {
        rePart[i] = Math.Sqrt(rePart[i]*rePart[i]+imPart[i]*imPart[i]);
      }

      return null;
    }
		/// <summary>
		/// Executes the fourier transformation itself (without data pretreatment).
		/// </summary>
		/// <exception cref="System.InvalidOperationException">The Fourier transformation was already executed.</exception>
		protected virtual void ExecuteFourierTransformation()
		{
			if (_arraysContainTransformation)
				throw new InvalidOperationException("The Fourier transformation was already executed.");

			var numColumns = NumberOfColumns;
			var numRows = NumberOfRows;

			var rePart = ((IMatrixInArray1DRowMajorRepresentation<double>)_realMatrix).GetArray1DRowMajor();

			_imagMatrix = new DoubleMatrixInArray1DRowMajorRepresentation(numRows, numColumns);
			var imPart = ((IMatrixInArray1DRowMajorRepresentation<double>)_imagMatrix).GetArray1DRowMajor();

			// fourier transform either with Pfa (faster) or with the Chirp-z-transform
			if (Pfa235FFT.CanFactorized(numRows) && Pfa235FFT.CanFactorized(numColumns))
			{
				Pfa235FFT fft = new Pfa235FFT(numRows, numColumns);
				fft.FFT(rePart, imPart, FourierDirection.Forward);
			}
			else
			{
				var matrixRe = new DoubleMatrixInArray1DRowMajorRepresentation(rePart, numRows, numColumns);
				ChirpFFT.FourierTransformation2D(matrixRe, _imagMatrix, FourierDirection.Forward);
			}

			_arraysContainTransformation = true;
		}
Exemple #5
0
		private void MyFFT(double[] real, double[] imag, FourierDirection direction)
		{
			Pfa235FFT fft = new Pfa235FFT(real.Length);
			fft.FFT(real, imag, direction);
		}
Exemple #6
0
		private void MyRoutine2(double[] real1, FourierDirection dir)
		{
			int n = real1.Length;
			System.Random rnd = new System.Random();
			double[] real2 = new double[n];
			for (int i = 0; i < n; i++)
				real2[i] = rnd.NextDouble() / n;

			Pfa235FFT fft = new Pfa235FFT(n);
			fft.RealFFT(real2, real1, dir);
		}
Exemple #7
0
		private static void zzTestImOne_ArbPosBothDim(int u, int v)
		{
			int upos = rnd.Next(u);
			int vpos = rnd.Next(v);

			int n = u * v;
			double[] re = new double[n];
			double[] im = new double[n];

			im[upos * v + vpos] = 1;

			Pfa235FFT fft = new Pfa235FFT(u, v);

			fft.FFT(re, im, FourierDirection.Inverse);

			for (int i = 0; i < u; i++)
			{
				for (int j = 0; j < v; j++)
				{
					Assert.AreEqual(Math.Sin(2 * Math.PI * (((double)i) * upos / u + ((double)j) * vpos / v)), re[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 re[{2},{3}]", u, v, i, j));
					Assert.AreEqual(Math.Cos(2 * Math.PI * (((double)i) * upos / u + ((double)j) * vpos / v)), im[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 im[{2},{3}]", u, v, i, j));
				}
			}
		}
Exemple #8
0
		private static void zzTestReOne_OnePos2ndDim(int u, int v)
		{
			int n = u * v;
			double[] re = new double[n];
			double[] im = new double[n];

			re[1 * v] = 1;

			Pfa235FFT fft = new Pfa235FFT(u, v);

			fft.FFT(re, im, FourierDirection.Inverse);

			for (int i = 0; i < u; i++)
			{
				for (int j = 0; j < v; j++)
				{
					Assert.AreEqual(Math.Cos((2 * Math.PI * i) / u), re[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 re[{2},{3}]", u, v, i, j));
					Assert.AreEqual(-Math.Sin((2 * Math.PI * i) / u), im[i * v + j], n * 1E-15, string.Format("FFT({0},{1}) of re 1 at pos 1 im[{2},{3}]", u, v, i, j));
				}
			}
		}
Exemple #9
0
		private static void zzTestZero(int u, int v)
		{
			int n = u * v;
			double[] re = new double[n];
			double[] im = new double[n];

			Pfa235FFT fft = new Pfa235FFT(u, v);

			fft.FFT(re, im, FourierDirection.Inverse);

			for (int i = 0; i < n; i++)
			{
				Assert.AreEqual(0, re[i], 0, "FFT of zero should give re=0");
				Assert.AreEqual(0, im[i], 0, "FFT of zero should give im=0");
			}
		}