/// <summary>
		/// Calculate the square root of a complex number
		/// </summary>
		/// <param name="c"></param>
		/// <returns></returns>
		static public ComplexF	Sqrt( ComplexF c ) {
			double	x	= c.Re;
			double	y	= c.Im;

			double	modulus	= Math.Sqrt( x*x + y*y );
			int		sign	= ( y < 0 ) ? -1 : 1;

			c.Re		= (float)( _halfOfRoot2 * Math.Sqrt( modulus + x ) );
			c.Im	= (float)( _halfOfRoot2 * sign * Math.Sqrt( modulus - x ) );

			return	c;
		}
        //---------------------------------------------------------------------------------------------------
        /// <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;
        }
Exemple #3
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 );
			}
		}
Exemple #4
0
    void InitWaveGenerator()
    {
        // Wind restricted to one direction, reduces calculations
        Vector2 wind = new Vector2 (windx, 0.0f);

        // Initialize wave generator
        for (int y=0; y<height; y++) {
            for (int x=0; x<width; x++) {
                float yc = y < height / 2f ? y : -height + y;
                float xc = x < width / 2f ? x : -width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);
                h0 [width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, wind));
            }
        }

        for (int y=0; y<n_height; y++) {
            for (int x=0; x<n_width; x++) {
                float yc = y < n_height / 2f ? y : -n_height + y;
                float xc = x < n_width / 2f ? x : -n_width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / (size.x / normal_scale), 2.0f * Mathf.PI * yc / (size.z / normal_scale));
                n0 [n_width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, wind));
            }
        }
    }
Exemple #5
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];
			}
		}
Exemple #6
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];
			}
		}
Exemple #7
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 );
		}
Exemple #8
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 );
		}
Exemple #9
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;
			}
		}
		static private void		LockBufferCF( int length, ref ComplexF[] buffer ) {
			
			if( length != _bufferCF.Length ) {
				_bufferCF	= new ComplexF[ length ];
			}
			buffer =	_bufferCF;
		}
		//-------------------------------------------------------------------------------------



		static private void ReorderArray( ComplexF[] data ) {

			int length = data.Length;

			int[] reversedBits = GetReversedBits( 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;
				}
			}
		}
		/// <summary>
		/// Swap two complex numbers
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		static public void Swap( ref ComplexF a, ref ComplexF b ) {
			ComplexF temp = a;
			a = b;
			b = temp;
		}
Exemple #13
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 );
		}
Exemple #14
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;
					}
				}
			}

		}
Exemple #15
0
		static private void Swap( ref ComplexF a, ref ComplexF b ) {
			ComplexF temp = a;
			a = b;
			b = temp;
		}
Exemple #16
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;
		}
Exemple #17
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;
			}
		}
		static private void		UnlockBufferCF( ref ComplexF[] buffer ) {
			buffer = null;
		}
Exemple #19
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;
			}
		}
		private static void	LinearFFT_Quick( ComplexF[] data, int start, int inc, int length, FourierDirection direction ) {
			
			// 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 );
		}
Exemple #21
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];
			}
		}
		//======================================================================================
		 

		/// <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( ComplexF[] data, int length, FourierDirection direction ) {

			SyncLookupTableLength( length );

			int ln = Log2( length );
			
			// reorder array
			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;
					}
				}
			}

		}
Exemple #23
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;
				}
			}
		}
		/// <summary>
		/// Compute a 2D 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="direction"></param>
		public static void	FFT2( ComplexF[] data, int xLength, int yLength, FourierDirection direction ) {

		int xInc = 1;
			int yInc = xLength;

			if( xLength > 1 ) {
				SyncLookupTableLength( xLength );
				for( int y = 0; y < yLength; y ++ ) {
					int xStart = y * yInc;
					LinearFFT_Quick( data, xStart, xInc, xLength, direction );
				}
			}
		
			if( yLength > 1 ) {
				SyncLookupTableLength( yLength );
				for( int x = 0; x < xLength; x ++ ) {
					int yStart = x * xInc;
					LinearFFT_Quick( data, yStart, yInc, yLength, direction );
				}
			}
		}
Exemple #25
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 ) ) );
		}
Exemple #26
0
		static private void		UnlockWorkspaceF( ref ComplexF[] workspace ) {
			Debug.Assert( _workspaceF == workspace );
			//Debug.Assert( _workspaceFLocked == true );
			//_workspaceFLocked = false;
			workspace = null;
		}
Exemple #27
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;
		}
Exemple #28
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 );
		}
Exemple #29
0
    void Update()
    {
        //If player null, search for player by Player tag
        if(player == null)
            player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();

        //Get sun reflection dir from sun object
        if(sun != null){
            SunDir = sun.transform.forward;
            material.SetVector ("_SunDir", SunDir);
        }

        if (this.renderReflection)
            RenderObject ();

        if (followMainCamera) {

            Vector3 centerOffset;

            //centerOffset.x = Mathf.Floor (player.position.x / size.x) * size.x;
            //centerOffset.z = Mathf.Floor (player.position.z / size.z) * size.z;
            centerOffset.y = transform.position.y;
            //centerOffset.x =  (((int)player.position.x + 64) & ~127);
            //centerOffset.z =  (((int)player.position.z + 64) & ~127);

            //Optimized ocean tiles movement
            centerOffset.x = Mathf.Floor( (player.position.x + size.x * 0.5f)  * sizeInv.x )   *  size.x;
            centerOffset.z = Mathf.Floor( (player.position.z + size.z * 0.5f)  * sizeInv.y )   *  size.z;
            if(transform.position != centerOffset)
                transform.position = centerOffset;

        }

        float hhalf=height/2f;
        float whalf=width/2f;
        float time=Time.time;
        for (int y = 0; y<height; y++) {
            for (int x = 0; x<width; x++) {
                int idx = width * y + x;
                float yc = y < hhalf ? y : -height + y;
                float xc = x < whalf ? x : -width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);

                float sqrtMagnitude=(float)System.Math.Sqrt((vec_k.x * vec_k.x) + (vec_k.y * vec_k.y));
                float iwkt = (float)System.Math.Sqrt(9.81f * sqrtMagnitude) * time * speed;
                ComplexF coeffA = new ComplexF ((float)System.Math.Cos(iwkt), (float)System.Math.Sin(iwkt));
                ComplexF coeffB;
                coeffB.Re = coeffA.Re;
                coeffB.Im = -coeffA.Im;

                int ny = y > 0 ? height - y : 0;
                int nx = x > 0 ? width - x : 0;

                data [idx] = h0 [idx] * coeffA + h0[width * ny + nx].GetConjugate() * coeffB;
                t_x [idx] = data [idx] * new ComplexF (0.0f, vec_k.x) - data [idx] * vec_k.y;

                // Choppy wave calculations
                if (x + y > 0)
                    data [idx] += data [idx] * vec_k.x / sqrtMagnitude;
            }
        }

        Fourier.FFT2 (data, width, height, FourierDirection.Backward);
        Fourier.FFT2 (t_x, width, height, FourierDirection.Backward);

        // Get base values for vertices and uv coordinates.
        if (baseHeight == null) {
            baseHeight = baseMesh.vertices;
            vertices = new Vector3[baseHeight.Length];
            normals = new Vector3[baseHeight.Length];
            tangents = new Vector4[baseHeight.Length];
        }

        int wh=width*height;
        float scaleA = choppy_scale / wh;
        float scaleB = scale / wh;
        float scaleBinv = 1.0f / scaleB;

        for (int i=0; i<wh; i++) {
            int iw = i + i / width;
            vertices [iw] = baseHeight [iw];
            vertices [iw].x += data [i].Im * scaleA;
            vertices [iw].y = data [i].Re * scaleB;

            normals [iw] = Vector3.Normalize(new Vector3 (t_x [i].Re, scaleBinv, t_x [i].Im));

            if (((i + 1) % width)==0) {
                int iwi=iw+1;
                int iwidth=i+1-width;
                vertices [iwi] = baseHeight [iwi];
                vertices [iwi].x += data [iwidth].Im * scaleA;
                vertices [iwi].y = data [iwidth].Re * scaleB;

                normals [iwi] = Vector3.Normalize(new Vector3 (t_x [iwidth].Re, scaleBinv, t_x [iwidth].Im));

            }
        }

        int offset = g_width * (g_height - 1);

        for (int i=0; i<g_width; i++) {
            int io=i+offset;
            int mod=i % width;
            vertices [io] = baseHeight [io];
            vertices [io].x += data [mod].Im * scaleA;
            vertices [io].y = data [mod].Re * scaleB;

            normals [io] = Vector3.Normalize(new Vector3 (t_x [mod].Re, scaleBinv, t_x [mod].Im));
        }

        int gwgh=g_width*g_height-1;
        for (int i=0; i<gwgh; i++) {

            //Need to preserve w in refraction/reflection mode
            if (!reflectionRefractionEnabled) {
                if (((i + 1) % g_width) == 0) {
                    tangents [i] = Vector3.Normalize((vertices [i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]));
                } else {
                    tangents [i] = Vector3.Normalize((vertices [i + 1] - vertices [i]));
                }

                tangents [i].w = 1.0f;
            } else {
                Vector3 tmp;// = Vector3.zero;

                if (((i + 1) % g_width) == 0) {
                    tmp = Vector3.Normalize(vertices[i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]);
                } else {
                    tmp = Vector3.Normalize(vertices [i + 1] - vertices [i]);
                }

                tangents [i] = new Vector4 (tmp.x, tmp.y, tmp.z, tangents [i].w);
            }
        }

        //Vector3 playerRelPos =  player.position - transform.position;

        //In reflection mode, use tangent w for foam strength
        if (reflectionRefractionEnabled) {
            for (int y = 0; y < g_height; y++) {
                for (int x = 0; x < g_width; x++) {
                    int item=x + g_width * y;
                    if (x + 1 >= g_width) {
                        tangents [item].w = tangents [g_width * y].w;

                        continue;
                    }

                    if (y + 1 >= g_height) {
                        tangents [item].w = tangents [x].w;

                        continue;
                    }

                    float right = vertices[(x + 1) + g_width * y].x - vertices[item].x;

                    float foam = right/(size.x / g_width);

                    if (foam < 0.0f)
                        tangents [item].w = 1f;
                    else if (foam < 0.5f)
                        tangents [item].w += 3.0f * Time.deltaTime;
                    else
                        tangents [item].w -= 0.4f * Time.deltaTime;

                    if (player != null )
                    {
                        Vector3 player2Vertex = (player.position - vertices[item] - transform.position);
                        // foam around boat
                        if (player2Vertex.x >= size.x)
                            player2Vertex.x -= size.x;

                        if (player2Vertex.x<= -size.x)
                            player2Vertex.x += size.x;

                        if (player2Vertex.z >= size.z)
                            player2Vertex.z -= size.z;

                        if (player2Vertex.z<= -size.z)
                            player2Vertex.z += size.z;
                        player2Vertex.y = 0;

                        if (player2Vertex.sqrMagnitude < wakeDistance * wakeDistance)
                            tangents[item].w += 3.0f * Time.deltaTime;
                    }

                    tangents [item].w = Mathf.Clamp (tangents[item].w, 0.0f, 2.0f);
                }
            }
        }

        tangents [gwgh] = Vector4.Normalize(vertices [gwgh] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [1]);

        for (int L0D=0; L0D<max_LOD; L0D++) {
            int den = (int)System.Math.Pow (2f, L0D);
            int itemcount = (int)((height / den + 1) * (width / den + 1));

            Vector4[] tangentsLOD = new Vector4[itemcount];
            Vector3[] verticesLOD = new Vector3[itemcount];
            Vector3[] normalsLOD = new Vector3[itemcount];

            int idx = 0;

            for (int y=0; y<g_height; y+=den) {
                for (int x=0; x<g_width; x+=den) {
                    int idx2 = g_width * y + x;
                    verticesLOD [idx] = vertices [idx2];
                    tangentsLOD [idx] = tangents [idx2];
                    normalsLOD [idx++] = normals [idx2];
                }
            }
            for (int k=0; k< tiles_LOD[L0D].Count; k++) {
                Mesh meshLOD = tiles_LOD [L0D][k];
                meshLOD.vertices = verticesLOD;
                meshLOD.normals = normalsLOD;
                meshLOD.tangents = tangentsLOD;
            }
        }
    }
Exemple #30
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 );
			}
		}