コード例 #1
0
ファイル: ComplexMath.cs プロジェクト: rikkit/exocortex-dsp
        //---------------------------------------------------------------------------------------------------
        /// <summary>
        /// Calculate the power of a complex number
        /// </summary>
        /// <param name="c"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        public static ComplexF Pow( ComplexF c, double exponent )
        {
            double	x	= c.Re;
            double	y	= c.Im;

            double	modulus		= Math.Pow( x*x + y*y, exponent * 0.5 );
            double	argument	= Math.Atan2( y, x ) * exponent;

            c.Re		= (float)( modulus * System.Math.Cos( argument ) );
            c.Im = (float)( modulus * System.Math.Sin( argument ) );

            return	c;
        }
コード例 #2
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="length"></param>
        /// <param name="direction"></param>
        public static void FFT_Quick( ComplexF[] data, int length, FourierDirection direction )
        {
            /*if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < length ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
            }
            if( Fourier.IsPowerOf2( length ) == false ) {
                throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
            }

            Fourier.SyncLookupTableLength( length );*/

            int ln = Fourier.Log2( length );

            // reorder array
            Fourier.ReorderArray( data );

            // successive doubling
            int N = 1;
            int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;

            for( int level = 1; level <= ln; level ++ ) {
                int M = N;
                N <<= 1;

                float[] uRLookup = _uRLookupF[ level, signIndex ];
                float[] uILookup = _uILookupF[ level, signIndex ];

                for( int j = 0; j < M; j ++ ) {
                    float uR = uRLookup[j];
                    float uI = uILookup[j];

                    for( int even = j; even < length; even += N ) {
                        int odd	 = even + M;

                        float	r = data[ odd ].Re;
                        float	i = data[ odd ].Im;

                        float	odduR = r * uR - i * uI;
                        float	odduI = r * uI + i * uR;

                        r = data[ even ].Re;
                        i = data[ even ].Im;

                        data[ even ].Re	= r + odduR;
                        data[ even ].Im	= i + odduI;

                        data[ odd ].Re	= r - odduR;
                        data[ odd ].Im	= i - odduI;
                    }
                }
            }
        }
コード例 #3
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Compute a 1D fast Fourier transform of a dataset of complex numbers.
 /// </summary>
 /// <param name="data"></param>
 /// <param name="direction"></param>
 public static void FFT( ComplexF[] data, FourierDirection direction )
 {
     if( data == null ) {
         throw new ArgumentNullException( "data" );
     }
     Fourier.FFT( data, data.Length, direction );
 }
コード例 #4
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
 private static void Swap( ref ComplexF a, ref ComplexF b )
 {
     ComplexF temp = a;
     a = b;
     b = temp;
 }
コード例 #5
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        private static void LockBufferCF( int length, ref ComplexF[] buffer )
        {
            Debug.Assert( length >= 0 );
            Debug.Assert( _bufferCFLocked == false );

            _bufferCFLocked = true;
            if( length != _bufferCF.Length ) {
                _bufferCF	= new ComplexF[ length ];
            }
            buffer =	_bufferCF;
        }
コード例 #6
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
 //--------------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------------
 /// <summary>
 /// Calculate the mean (average)
 /// </summary>
 /// <param name="data"></param>
 /// <returns></returns>
 public static ComplexF Mean( ComplexF[] data )
 {
     return	ComplexStats.Sum( data ) / data.Length;
 }
コード例 #7
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
        private static float SumOfSquaredErrorRecursion( ComplexF[] alpha, ComplexF[] beta, int start, int end )
        {
            Debug.Assert( 0 <= start, "start = " + start );
            Debug.Assert( start < end, "start = " + start + " and end = " + end );
            Debug.Assert( end <= alpha.Length, "end = " + end + " and alpha.Length = " + alpha.Length );
            Debug.Assert( beta.Length == alpha.Length );
            if( ( end - start ) <= 1000 ) {
                float sumOfSquaredError = 0;
                for( int i = start; i < end; i ++ ) {
                    ComplexF delta = beta[ i ] - alpha[ i ];
                    sumOfSquaredError += ( delta.Re * delta.Re ) + ( delta.Im * delta.Im );

                }
                return	sumOfSquaredError;
            }
            else {
                int middle = ( start + end ) >> 1;
                return	SumOfSquaredErrorRecursion( alpha, beta, start, middle ) + SumOfSquaredErrorRecursion( alpha, beta, middle, end );
            }
        }
コード例 #8
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
 //--------------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------------
 /// <summary>
 /// Calculate the sum of squares
 /// </summary>
 /// <param name="data"></param>
 /// <returns></returns>
 public static ComplexF SumOfSquares( ComplexF[] data )
 {
     Debug.Assert( data != null );
     return	SumOfSquaresRecursion( data, 0, data.Length );
 }
コード例 #9
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Multiply each element in target array with corresponding element in rhs array
 /// </summary>
 /// <param name="target"></param>
 /// <param name="rhs"></param>
 public static void Multiply( ComplexF[] target, ComplexF[] rhs )
 {
     ComplexArray.Multiply( target, rhs, target );
 }
コード例 #10
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 ///  Determine whether the elements in the two arrays are the same
 /// </summary>
 /// <param name="array1"></param>
 /// <param name="array2"></param>
 /// <param name="tolerance"></param>
 /// <returns></returns>
 public static bool IsEqual( ComplexF[] array1, ComplexF[] array2, float tolerance )
 {
     if ( array1.Length != array2.Length ) {
         return false;
     }
     for( int i = 0; i < array1.Length; i ++ ) {
         if( ComplexF.IsEqual( array1[i], array2[i], tolerance ) == false ) {
             return false;
         }
     }
     return true;
 }
コード例 #11
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Invert each element in the array
 /// </summary>
 /// <param name="array"></param>
 public static void Invert( ComplexF[] array )
 {
     for( int i = 0; i < array.Length; i ++ ) {
         array[i] = ((ComplexF) 1 ) / array[i];
     }
 }
コード例 #12
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Get the range of element lengths
 /// </summary>
 /// <param name="array"></param>
 /// <param name="minimum"></param>
 /// <param name="maximum"></param>
 public static void GetLengthRange( ComplexF[] array, ref float minimum, ref float maximum )
 {
     minimum = +float.MaxValue;
     maximum = -float.MaxValue;
     for( int i = 0; i < array.Length; i ++ ) {
         float temp = array[i].GetModulus();
         minimum = Math.Min( temp, minimum );
         maximum = Math.Max( temp, maximum );
     }
 }
コード例 #13
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Divide each element in lhs array with corresponding element in rhs array and
        /// put product in result array
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <param name="result"></param>
        public static void Divide( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result )
        {
            Debug.Assert( lhs != null );
            Debug.Assert( rhs != null );
            Debug.Assert( result != null );
            Debug.Assert( lhs.Length == rhs.Length );
            Debug.Assert( lhs.Length == result.Length );

            ComplexF zero = ComplexF.Zero;
            int length = lhs.Length;
            for( int i = 0; i < length; i ++ ) {
                if( rhs[i] != zero ) {
                    result[i] = lhs[i] / rhs[i];
                }
                else {
                    result[i] = zero;
                }
            }
        }
コード例 #14
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Divide each element in target array with corresponding element in rhs array
 /// </summary>
 /// <param name="target"></param>
 /// <param name="rhs"></param>
 public static void Divide( ComplexF[] target, ComplexF[] rhs )
 {
     ComplexArray.Divide( target, rhs, target );
 }
コード例 #15
0
 /// <summary>
 /// Create a complex number based on an existing complex number
 /// </summary>
 /// <param name="c"></param>
 public ComplexF(ComplexF c)
 {
     this.Re = c.Re;
     this.Im = c.Im;
 }
コード例 #16
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Multiply each element in lhs array with corresponding element in rhs array and
        /// put product in result array
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <param name="result"></param>
        public static void Multiply( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result )
        {
            Debug.Assert( lhs != null );
            Debug.Assert( rhs != null );
            Debug.Assert( result != null );
            Debug.Assert( lhs.Length == rhs.Length );
            Debug.Assert( lhs.Length == result.Length );

            int length = lhs.Length;
            for( int i = 0; i < length; i ++ ) {
                result[i] = lhs[i] * rhs[i];
            }
        }
コード例 #17
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Calculate the standard deviation
 /// </summary>
 /// <param name="data"></param>
 /// <returns></returns>
 public static ComplexF StdDev( ComplexF[] data )
 {
     Debug.Assert( data != null );
     if( data.Length == 0 ) {
         throw new DivideByZeroException( "length of data is zero" );
     }
     return	ComplexMath.Sqrt( ComplexStats.Variance( data ) );
 }
コード例 #18
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Scale and offset the elements in the array so that the
 /// overall range is [0, 1]
 /// </summary>
 /// <param name="array"></param>
 public static void Normalize( ComplexF[] array )
 {
     float min = 0, max = 0;
     GetLengthRange( array, ref min, ref max );
     Scale( array, ( 1 / ( max - min ) ) );
     Offset( array, ( - min / ( max - min ) ) );
 }
コード例 #19
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Calculate the variance
 /// </summary>
 /// <param name="data"></param>
 /// <returns></returns>
 public static ComplexF Variance( ComplexF[] data )
 {
     Debug.Assert( data != null );
     if( data.Length == 0 ) {
         throw new DivideByZeroException( "length of data is zero" );
     }
     return	ComplexStats.SumOfSquares( data ) / data.Length - ComplexStats.Sum( data );
 }
コード例 #20
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 /// <summary>
 /// Add a specific value to each element in the array
 /// </summary>
 /// <param name="array"></param>
 /// <param name="offset"></param>
 public static void Offset( ComplexF[] array, ComplexF offset )
 {
     int length = array.Length;
     for( int i = 0; i < length; i ++ ) {
         array[i] += offset;
     }
 }
コード例 #21
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
        private static ComplexF SumRecursion( ComplexF[] data, int start, int end )
        {
            Debug.Assert( 0 <= start, "start = " + start );
            Debug.Assert( start < end, "start = " + start + " and end = " + end );
            Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
            if( ( end - start ) <= 1000 ) {
                ComplexF sum = ComplexF.Zero;
                for( int i = start; i < end; i ++ ) {
                    sum += data[ i ];

                }
                return	sum;
            }
            else {
                int middle = ( start + end ) >> 1;
                return	SumRecursion( data, start, middle ) + SumRecursion( data, middle, end );
            }
        }
コード例 #22
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Multiply each element in the array by a specific value
        /// </summary>
        /// <param name="array"></param>
        /// <param name="scale"></param>
        public static void Scale( ComplexF[] array, ComplexF scale )
        {
            Debug.Assert( array != null );

            int length = array.Length;
            for( int i = 0; i < length; i ++ ) {
                array[i] *= scale;
            }
        }
コード例 #23
0
ファイル: ComplexStats.cs プロジェクト: rikkit/exocortex-dsp
        //--------------------------------------------------------------------------------------------
        //--------------------------------------------------------------------------------------------
        /// <summary>
        /// Calculate the root mean squared (RMS) error between two sets of data.
        /// </summary>
        /// <param name="alpha"></param>
        /// <param name="beta"></param>
        /// <returns></returns>
        public static float RMSError( ComplexF[] alpha, ComplexF[] beta )
        {
            Debug.Assert( alpha != null );
            Debug.Assert( beta != null );
            Debug.Assert( beta.Length == alpha.Length );

            return (float) Math.Sqrt( SumOfSquaredErrorRecursion( alpha, beta, 0, alpha.Length ) );
        }
コード例 #24
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Multiply each element in the array by a specific value 
        /// </summary>
        /// <param name="array"></param>
        /// <param name="scale"></param>
        /// <param name="start"></param>
        /// <param name="length"></param>
        public static void Scale( ComplexF[] array, ComplexF scale, int start, int length )
        {
            Debug.Assert( array != null );
            Debug.Assert( start >= 0 );
            Debug.Assert( length >= 0 );
            Debug.Assert( ( start + length ) < array.Length );

            for( int i = 0; i < length; i ++ ) {
                array[i + start] *= scale;
            }
        }
コード例 #25
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        private static void ReorderArray( ComplexF[] data )
        {
            Debug.Assert( data != null );

            int length = data.Length;

            Debug.Assert( Fourier.IsPowerOf2( length ) == true );
            Debug.Assert( length >= cMinLength );
            Debug.Assert( length <= cMaxLength );

            int[] reversedBits = Fourier.GetReversedBits( Fourier.Log2( length ) );
            for( int i = 0; i < length; i ++ ) {
                int swap = reversedBits[ i ];
                if( swap > i ) {
                    ComplexF temp = data[ i ];
                    data[ i ] = data[ swap ];
                    data[ swap ] = temp;
                }
            }
        }
コード例 #26
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Shift (offset) the elements in the array
        /// </summary>
        /// <param name="array"></param>
        /// <param name="offset"></param>
        public static void Shift( ComplexF[] array, int offset )
        {
            Debug.Assert( array != null );
            Debug.Assert( offset >= 0 );
            Debug.Assert( offset < array.Length );

            if( offset == 0 ) {
                return;
            }

            int			length		= array.Length;
            ComplexF[]	workspace	= null;
            ComplexArray.LockWorkspaceF( length, ref workspace );

            for( int i = 0; i < length; i ++ ) {
                workspace[ ( i + offset ) % length ] = array[ i ];
            }
            for( int i = 0; i < length; i ++ ) {
                array[ i ] = workspace[ i ];
            }

            ComplexArray.UnlockWorkspaceF( ref workspace );
        }
コード例 #27
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        private static void UnlockBufferCF( ref ComplexF[] buffer )
        {
            Debug.Assert( _bufferCF == buffer );
            Debug.Assert( _bufferCFLocked == true );

            _bufferCFLocked = false;
            buffer = null;
        }
コード例 #28
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 private static void LockWorkspaceF( int length, ref ComplexF[] workspace )
 {
     Debug.Assert( _workspaceFLocked == false );
     _workspaceFLocked = true;
     if( length >= _workspaceF.Length ) {
         _workspaceF	= new ComplexF[ length ];
     }
     workspace =	_workspaceF;
 }
コード例 #29
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        /// <summary>
        /// Compute a 3D fast fourier transform on a data set of complex numbers
        /// </summary>
        /// <param name="data"></param>
        /// <param name="xLength"></param>
        /// <param name="yLength"></param>
        /// <param name="zLength"></param>
        /// <param name="direction"></param>
        public static void FFT3( ComplexF[] data, int xLength, int yLength, int zLength, FourierDirection direction )
        {
            if( data == null ) {
                throw new ArgumentNullException( "data" );
            }
            if( data.Length < xLength*yLength*zLength ) {
                throw new ArgumentOutOfRangeException( "data.Length", data.Length, "must be at least as large as 'xLength * yLength * zLength' parameter" );
            }
            if( Fourier.IsPowerOf2( xLength ) == false ) {
                throw new ArgumentOutOfRangeException( "xLength", xLength, "must be a power of 2" );
            }
            if( Fourier.IsPowerOf2( yLength ) == false ) {
                throw new ArgumentOutOfRangeException( "yLength", yLength, "must be a power of 2" );
            }
            if( Fourier.IsPowerOf2( zLength ) == false ) {
                throw new ArgumentOutOfRangeException( "zLength", zLength, "must be a power of 2" );
            }

            int xInc = 1;
            int yInc = xLength;
            int zInc = xLength * yLength;

            if( xLength > 1 ) {
                Fourier.SyncLookupTableLength( xLength );
                for( int z = 0; z < zLength; z ++ ) {
                    for( int y = 0; y < yLength; y ++ ) {
                        int xStart = y * yInc + z * zInc;
                        Fourier.LinearFFT_Quick( data, xStart, xInc, xLength, direction );
                    }
                }
            }

            if( yLength > 1 ) {
                Fourier.SyncLookupTableLength( yLength );
                for( int z = 0; z < zLength; z ++ ) {
                    for( int x = 0; x < xLength; x ++ ) {
                        int yStart = z * zInc + x * xInc;
                        Fourier.LinearFFT_Quick( data, yStart, yInc, yLength, direction );
                    }
                }
            }

            if( zLength > 1 ) {
                Fourier.SyncLookupTableLength( zLength );
                for( int y = 0; y < yLength; y ++ ) {
                    for( int x = 0; x < xLength; x ++ ) {
                        int zStart = y * yInc + x * xInc;
                        Fourier.LinearFFT_Quick( data, zStart, zInc, zLength, direction );
                    }
                }
            }
        }
コード例 #30
0
ファイル: ComplexArray.cs プロジェクト: rikkit/exocortex-dsp
 private static void UnlockWorkspaceF( ref ComplexF[] workspace )
 {
     Debug.Assert( _workspaceF == workspace );
     Debug.Assert( _workspaceFLocked == true );
     _workspaceFLocked = false;
     workspace = null;
 }
コード例 #31
0
ファイル: Fourier.cs プロジェクト: rikkit/exocortex-dsp
        private static void LinearFFT( ComplexF[] data, int start, int inc, int length, FourierDirection direction )
        {
            Debug.Assert( data != null );
            Debug.Assert( start >= 0 );
            Debug.Assert( inc >= 1 );
            Debug.Assert( length >= 1 );
            Debug.Assert( ( start + inc * ( length - 1 ) ) < data.Length );

            // copy to buffer
            ComplexF[]	buffer = null;
            LockBufferCF( length, ref buffer );
            int j = start;
            for( int i = 0; i < length; i ++ ) {
                buffer[ i ] = data[ j ];
                j += inc;
            }

            FFT( buffer, length, direction );

            // copy from buffer
            j = start;
            for( int i = 0; i < length; i ++ ) {
                data[ j ] = buffer[ i ];
                j += inc;
            }
            UnlockBufferCF( ref buffer );
        }
コード例 #32
0
        //-----------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------

        /// <summary>
        /// Determine whether two complex numbers are almost (i.e. within the tolerance) equivalent.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        static public bool IsEqual(ComplexF a, ComplexF b, float tolerance)
        {
            return
                ((Math.Abs(a.Re - b.Re) < tolerance) &&
                 (Math.Abs(a.Im - b.Im) < tolerance));
        }