Exemple #1
0
        public void Transform2D()
        {
            // Transform forward and inverse and compare with initial values.
            var random = new Random(1234567);

            var s = new Vector2F[16, 8];
            var t = new Vector2F[16, 8];

            for (int i = 0; i < s.GetLength(0); i++)
            {
                for (int j = 0; j < s.GetLength(1); j++)
                {
                    s[i, j] = random.NextVector2F(-10, 10);
                    t[i, j] = s[i, j];
                }
            }

            var fft = new FastFourierTransformF(16);

            fft.Transform2D(t, true);

            Assert.IsFalse(Vector2F.AreNumericallyEqual(s[0, 0], t[0, 0]));

            fft.Transform2D(t, false);

            for (int i = 0; i < s.GetLength(0); i++)
            {
                for (int j = 0; j < s.GetLength(1); j++)
                {
                    Assert.IsTrue(Vector2F.AreNumericallyEqual(s[i, j], t[i, j]));
                }
            }
        }
Exemple #2
0
        public void Transform2DArguments()
        {
            var fft = new FastFourierTransformF(16);

            Assert.Throws <ArgumentNullException>(() => fft.Transform2D(null, true));

            // Senseless.
            Assert.Throws <ArgumentException>(() => fft.Transform2D(new Vector2F[0, 0], true));

            // Not POT.
            Assert.Throws <ArgumentException>(() => fft.Transform2D(new Vector2F[13, 2], true));
            Assert.Throws <ArgumentException>(() => fft.Transform2D(new Vector2F[2, 6], true));

            // Too large for capacity.
            Assert.Throws <ArgumentException>(() => fft.Transform2D(new Vector2F[32, 6], true));

            fft.Transform2D(new Vector2F[1, 1], true);

            // This is ok.
            fft.Transform2D(new Vector2F[2, 4], true);
            fft.Transform2D(new Vector2F[16, 1], false);
        }
        public void Transform1DAs2DColumn()
        {
            // Result of 2D with one row/column must be the same as 1D.
              var fft = new FastFourierTransformF(16);

              var random = new Random(1234567);

              var s1D = new Vector2F[16];
              var s2D = new Vector2F[16, 1];

              for (int i = 0; i < s1D.Length; i++)
              {
            s1D[i] = random.NextVector2F(-10, 10);
            s2D[i, 0] = s1D[i];
              }

              FastFourierTransformF.Transform1D(s1D, true);
              fft.Transform2D(s2D, true);

              for (int i = 0; i < s1D.Length; i++)
            Assert.AreEqual(s1D[i], s2D[i, 0]);
        }
Exemple #4
0
        public void Transform1DAs2DRow()
        {
            // Result of 2D with one row/column must be the same as 1D.
            var fft = new FastFourierTransformF(16);

            var random = new Random(1234567);

            var s1D = new Vector2F[8];
            var s2D = new Vector2F[1, 8];

            for (int i = 0; i < s1D.Length; i++)
            {
                s1D[i]    = random.NextVector2F(-10, 10);
                s2D[0, i] = s1D[i];
            }

            FastFourierTransformF.Transform1D(s1D, true);
            fft.Transform2D(s2D, true);

            for (int i = 0; i < s1D.Length; i++)
            {
                Assert.AreEqual(s1D[i], s2D[0, i]);
            }
        }
Exemple #5
0
    private void PerformCpuFft(float time)
    {
      // Compute _h.
      int n = CpuSize;
      for (int x = -n / 2; x < n / 2; x++)
      {
        for (int y = -n / 2; y < n / 2; y++)
        {
          var indexX = GetIndex(x, n);
          var indexY = GetIndex(y, n);

          // The frequency domain images have a different order:
          var fftIndexX = x & (n - 1);
          var fftIndexY = y & (n - 1);

          var k = new Vector2F(GetKx(x), GetKy(y));

          //float omega = GetOmega(water, k.Length);
          float omega = _omega[indexX, indexY];

          // h = h0(x, y) * e^(i * omega * t) + conj(h0(-x, -y)) * e^(-i * omega * t).
          float cos = (float)Math.Cos(omega * time);
          float sin = (float)Math.Sin(omega * time);

          // conj(Z) = Z.Re - i * Z.Im.
          // e^(ix) = cos(x) + i * sin(x)
          // e^(-ix) = cos(x) - i * sin(x)
          // Multiplication of two complex: (a + ib) *  (c + id) = (ac - bd) + i(ad + bc)
          // --> h.Re = h0(x, y).Re * cos - h0(x, y).Im *sin + h0(-x, -y).Re * cos - h0(-x, -y).Im * sin
          //     h.Im = h0(x, y).Re * sin + h0(x, y).Im * cos  - h0(-x, -y).Re * sin - h0(-x, -y).Im * cos
          var h0XY = _h0[indexX, indexY] * HeightScale;
          var h0NegXNegY = _h0[GetIndex(-x, n), GetIndex(-y, n)] * HeightScale;
          var h = new Vector2F((h0XY.X + h0NegXNegY.X) * cos - (h0XY.Y + h0NegXNegY.Y) * sin,
                               (h0XY.X - h0NegXNegY.X) * sin + (h0XY.Y - h0NegXNegY.Y) * cos);
          _h[fftIndexX, fftIndexY] = h;

          // For normals, we have to perform inverse FFT for normal.X and normal.Y.
          // normal.x = InverseFFT(-i * k.x / kLength * h).Re
          // normal.y = InverseFFT(-i * k.y / kLength * h).Re
          // However, since FFT is linear and normal.X/Y are real (imaginary values are 0),
          // we can combine them into a single FFT:
          // FFT(Nx) = SpectrumNx, FFT(Ny) = SpectrumNy
          // Add and multiply by any constant, e.g. i!
          // FFT(Nx + i * Ny) = SpectrumNx + i * SpectrumNy
          // Nx + i * Ny = InverseFFT(SpectrumNx + i * SpectrumNy)
          // SpectrumNx = i * k.X * h = i * (k.X * h.Re + i * k.X * h.Im) = -k.X * h.Im + i * k.X * h.Re
          // i * SpectrumNy = i * i * k.Y * h = -1 * (k.Y * h.Re + i * k.Y * h.Im)
          _N[fftIndexX, fftIndexY] = new Vector2F(-k.X * h.Y - k.Y * h.X,
                                                  k.X * h.X - k.Y * h.Y);

          // Horizontal displacements for choppy waves:
          // Again we combine the x and y displacement into one FFT.
          // D.x = InverseFFT(-i * k.x / kLength * h).Re
          // D.y = InverseFFT(-i * k.y / kLength * h).Re
          k *= _oneOverKLength[indexX, indexY];
          _D[fftIndexX, fftIndexY] = new Vector2F(k.X * h.Y + k.Y * h.X,
                                                  -k.X * h.X + k.Y * h.Y);
        }
      }

      // Transform data from frequency domain to spatial domain.
      if (_fft == null)
        _fft = new FastFourierTransformF(n);
      else if (_fft.Capacity < n)
        _fft.Capacity = n;

      _fft.Transform2D(_h, false);
      _fft.Transform2D(_D, false);
      _fft.Transform2D(_N, false);
    }
        public void Transform2DArguments()
        {
            var fft = new FastFourierTransformF(16);

              Assert.Throws<ArgumentNullException>(() => fft.Transform2D(null, true));

              // Senseless.
              Assert.Throws<ArgumentException>(() => fft.Transform2D(new Vector2F[0, 0], true));

              // Not POT.
              Assert.Throws<ArgumentException>(() => fft.Transform2D(new Vector2F[13, 2], true));
              Assert.Throws<ArgumentException>(() => fft.Transform2D(new Vector2F[2, 6], true));

              // Too large for capacity.
              Assert.Throws<ArgumentException>(() => fft.Transform2D(new Vector2F[32, 6], true));

              fft.Transform2D(new Vector2F[1, 1], true);

              // This is ok.
              fft.Transform2D(new Vector2F[2, 4], true);
              fft.Transform2D(new Vector2F[16, 1], false);
        }
        public void Transform2D()
        {
            // Transform forward and inverse and compare with initial values.
              var random = new Random(1234567);

              var s = new Vector2F[16, 8];
              var t = new Vector2F[16, 8];
              for (int i = 0; i < s.GetLength(0); i++)
              {
            for (int j = 0; j < s.GetLength(1); j++)
            {
              s[i, j] = random.NextVector2F(-10, 10);
              t[i, j] = s[i, j];
            }
              }

              var fft = new FastFourierTransformF(16);
              fft.Transform2D(t, true);

              Assert.IsFalse(Vector2F.AreNumericallyEqual(s[0, 0], t[0, 0]));

              fft.Transform2D(t, false);

              for (int i = 0; i < s.GetLength(0); i++)
            for (int j = 0; j < s.GetLength(1); j++)
              Assert.IsTrue(Vector2F.AreNumericallyEqual(s[i, j], t[i, j]));
        }