Пример #1
0
		static private 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 );
			}
		}
Пример #2
0
		static private void		UnlockBufferCF( ref ComplexF[] buffer ) {
			Debug.Assert( _bufferCF == buffer );
			Debug.Assert( _bufferCFLocked == true );
			
			_bufferCFLocked = false;
			buffer = null;
		}
Пример #3
0
		//---------------------------------------------------------------------------------------------
		//--------------------------------------------------------------------------------------------

		/// <summary>
		/// Calculate the sum
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		static public  ComplexF		Sum( ComplexF[] data ) {
			Debug.Assert( data != null );
			return	SumRecursion( data, 0, data.Length );
		}
Пример #4
0
		//--------------------------------------------------------------------------------------------
		//--------------------------------------------------------------------------------------------

		/// <summary>
		/// Calculate the root mean squared (RMS) error between two sets of data.
		/// </summary>
		/// <param name="alpha"></param>
		/// <param name="beta"></param>
		/// <returns></returns>
		static public 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 ) );
		}
Пример #5
0
		/// <summary>
		/// Calculate the variance
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		static public 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 );
		}
Пример #6
0
		static private void		LockWorkspaceF( int length, ref ComplexF[] workspace ) {
			Debug.Assert( _workspaceFLocked == false );
			_workspaceFLocked = true;
			if( length >= _workspaceF.Length ) {
				_workspaceF	= new ComplexF[ length ];
			}
			workspace =	_workspaceF;
		}
Пример #7
0
		/// <summary>
		/// Scale and offset the elements in the array so that the
		/// overall range is [0, 1]
		/// </summary>
		/// <param name="array"></param>
		static public 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 ) ) );
		}
Пример #8
0
		/// <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>
		static public 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;
				}
			}
		}
Пример #9
0
		static private void		UnlockWorkspaceF( ref ComplexF[] workspace ) {
			Debug.Assert( _workspaceF == workspace );
			Debug.Assert( _workspaceFLocked == true );
			_workspaceFLocked = false;
			workspace = null;
		}
Пример #10
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;
		}
Пример #11
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 );

		}
Пример #12
0
		/// <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 );
		}
Пример #13
0
		/// <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;
					}
				}
			}

		}
Пример #14
0
		static private void Swap( ref ComplexF a, ref ComplexF b ) {
			ComplexF temp = a;
			a = b;
			b = temp;
		}
Пример #15
0
		private static void	LinearFFT_Quick( 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 );
		}
Пример #16
0
		/// <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>
		static public 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
		/// <summary>
		/// Divide each element in target array with corresponding element in rhs array
		/// </summary>
		/// <param name="target"></param>
		/// <param name="rhs"></param>
		static public void Divide( ComplexF[] target, ComplexF[] rhs ) {
			ComplexArray.Divide( target, rhs, target );
		}
Пример #18
0
		/// <summary>
		/// Shift (offset) the elements in the array
		/// </summary>
		/// <param name="array"></param>
		/// <param name="offset"></param>
		static public 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 );
		}
Пример #19
0
		/// <summary>
		/// Copy an array
		/// </summary>
		/// <param name="dest"></param>
		/// <param name="source"></param>
		static public void Copy( ComplexF[] dest, ComplexF[] source ) {
			Debug.Assert( dest != null );
			Debug.Assert( source != null );
			Debug.Assert( dest.Length == source.Length );
			for( int i = 0; i < dest.Length; i ++ ) {
				dest[i] = source[i];
			}
		}
Пример #20
0
		/// <summary>
		/// Get the range of element lengths
		/// </summary>
		/// <param name="array"></param>
		/// <param name="minimum"></param>
		/// <param name="maximum"></param>
		static public 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 );
			}
		}
Пример #21
0
		/// <summary>
		/// Invert each element in the array
		/// </summary>
		/// <param name="array"></param>
		static public void Invert( ComplexF[] array ) {
			for( int i = 0; i < array.Length; i ++ ) {
				array[i] = ((ComplexF) 1 ) / array[i];
			}
		}
Пример #22
0
		/// <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>
		static public 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;
		}
Пример #23
0
		//--------------------------------------------------------------------------------------------
		//--------------------------------------------------------------------------------------------

		/// <summary>
		/// Calculate the mean (average)
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		static public ComplexF		Mean( ComplexF[] data ) {
			return	ComplexStats.Sum( data ) / data.Length;
		}
Пример #24
0
		/// <summary>
		/// Add a specific value to each element in the array
		/// </summary>
		/// <param name="array"></param>
		/// <param name="offset"></param>
		static public void Offset( ComplexF[] array, ComplexF offset ) {
			int length = array.Length;
			for( int i = 0; i < length; i ++ ) {
				array[i] += offset;
			}
		}
Пример #25
0
		/// <summary>
		/// Calculate the standard deviation
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		static public 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 ) );
		}
Пример #26
0
		/// <summary>
		/// Multiply each element in the array by a specific value
		/// </summary>
		/// <param name="array"></param>
		/// <param name="scale"></param>
		static public void Scale( ComplexF[] array, ComplexF scale ) {
			Debug.Assert( array != null );

			int length = array.Length;
			for( int i = 0; i < length; i ++ ) {
				array[i] *= scale;
			}
		}
Пример #27
0
		static private 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 );
			}
		}
Пример #28
0
		/// <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>
		static public 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;
			}
		}
Пример #29
0
		/// <summary>
		/// Multiply each element in target array with corresponding element in rhs array
		/// </summary>
		/// <param name="target"></param>
		/// <param name="rhs"></param>
		static public void Multiply( ComplexF[] target, ComplexF[] rhs ) {
			ComplexArray.Multiply( target, rhs, target );
		}
Пример #30
0
		static private 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;
		}