init
This commit is contained in:
1
DataPRO/ExocortexDSP/.svn/entries
Normal file
1
DataPRO/ExocortexDSP/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
DataPRO/ExocortexDSP/.svn/format
Normal file
1
DataPRO/ExocortexDSP/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>8.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{1904A41B-D1B8-40E5-ADBB-728DDCF7C816}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ApplicationIcon>
|
||||
</ApplicationIcon>
|
||||
<AssemblyKeyContainerName>
|
||||
</AssemblyKeyContainerName>
|
||||
<AssemblyName>Exocortex.DSP.v1</AssemblyName>
|
||||
<AssemblyOriginatorKeyFile>
|
||||
</AssemblyOriginatorKeyFile>
|
||||
<DefaultClientScript>JScript</DefaultClientScript>
|
||||
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
|
||||
<DefaultTargetSchema>IE50</DefaultTargetSchema>
|
||||
<DelaySign>false</DelaySign>
|
||||
<OutputType>Library</OutputType>
|
||||
<RootNamespace>Exocortex.DSP</RootNamespace>
|
||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DocumentationFile>doc\Exocortex.DSP.xml</DocumentationFile>
|
||||
<Optimize>true</Optimize>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DocumentationFile>doc\Exocortex.DSP.xml</DocumentationFile>
|
||||
<Optimize>true</Optimize>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<Optimize>false</Optimize>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<BaseAddress>285212672</BaseAddress>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<DocumentationFile>doc\Exocortex.DSP.xml</DocumentationFile>
|
||||
<Optimize>true</Optimize>
|
||||
<FileAlignment>4096</FileAlignment>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System">
|
||||
<Name>System</Name>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Complex.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ComplexArray.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ComplexF.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ComplexMath.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ComplexStats.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Fourier.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FourierDirection.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="PassFilter.cs" />
|
||||
<Compile Include="Polynomial.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Design\Exocortex.DSPClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Exocortex.DSP;
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>A set of array utilities for complex number arrays</p>
|
||||
/// </summary>
|
||||
public class ComplexArray
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
private ComplexArray()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Clamp length (modulus) of the elements in the complex array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="fMinimum"></param>
|
||||
/// <param name="fMaximum"></param>
|
||||
static public void ClampLength(Complex[] array, double fMinimum, double fMaximum)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = Complex.FromModulusArgument(Math.Max(fMinimum, Math.Min(fMaximum, array[i].GetModulus())), array[i].GetArgument());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp elements in the complex array to range [minimum,maximum]
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="minimum"></param>
|
||||
/// <param name="maximum"></param>
|
||||
static public void Clamp(Complex[] array, Complex minimum, Complex maximum)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i].Re = Math.Min(Math.Max(array[i].Re, minimum.Re), maximum.Re);
|
||||
array[i].Im = Math.Min(Math.Max(array[i].Re, minimum.Im), maximum.Im);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp elements in the complex array to real unit range (i.e. [0,1])
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
static public void ClampToRealUnit(Complex[] array)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i].Re = Math.Min(Math.Max(array[i].Re, 0), 1);
|
||||
array[i].Im = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
static private bool _workspaceFLocked = false;
|
||||
static private ComplexF[] _workspaceF = new ComplexF[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;
|
||||
}
|
||||
static private void UnlockWorkspaceF(ref ComplexF[] workspace)
|
||||
{
|
||||
Debug.Assert(_workspaceF == workspace);
|
||||
Debug.Assert(_workspaceFLocked == true);
|
||||
_workspaceFLocked = false;
|
||||
workspace = null;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Shift (offset) the elements in the array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="offset"></param>
|
||||
static public void Shift(Complex[] array, int offset)
|
||||
{
|
||||
Debug.Assert(array != null);
|
||||
Debug.Assert(offset >= 0);
|
||||
Debug.Assert(offset < array.Length);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int length = array.Length;
|
||||
Complex[] temp = new Complex[length];
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
temp[(i + offset) % length] = array[i];
|
||||
}
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i] = temp[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Get the range of element lengths
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="minimum"></param>
|
||||
/// <param name="maximum"></param>
|
||||
static public void GetLengthRange(Complex[] array, ref double minimum, ref double maximum)
|
||||
{
|
||||
minimum = +double.MaxValue;
|
||||
maximum = -double.MaxValue;
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
double temp = array[i].GetModulus();
|
||||
minimum = Math.Min(temp, minimum);
|
||||
maximum = Math.Max(temp, maximum);
|
||||
}
|
||||
}
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
// // <summary>
|
||||
// // Conver the complex array to a double array
|
||||
// // </summary>
|
||||
// // <param name="array"></param>
|
||||
// // <param name="style"></param>
|
||||
// // <returns></returns>
|
||||
/* static public double[] ConvertToDoubleArray( Complex[] array, ConversionStyle style ) {
|
||||
double[] newArray = new double[ array.Length ];
|
||||
switch( style ) {
|
||||
case ConversionStyle.Length:
|
||||
for( int i = 0; i < array.Length; i ++ ) {
|
||||
newArray[i] = (double) array[i].GetModulus();
|
||||
}
|
||||
break;
|
||||
case ConversionStyle.Real:
|
||||
for( int i = 0; i < array.Length; i ++ ) {
|
||||
newArray[i] = (double) array[i].Re;
|
||||
}
|
||||
break;
|
||||
case ConversionStyle.Imaginary:
|
||||
for( int i = 0; i < array.Length; i ++ ) {
|
||||
newArray[i] = (double) array[i].Im;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug.Assert( false );
|
||||
break;
|
||||
}
|
||||
return newArray;
|
||||
} */
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <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(Complex[] array1, Complex[] array2, double tolerance)
|
||||
{
|
||||
if (array1.Length != array2.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < array1.Length; i++)
|
||||
{
|
||||
if (Complex.IsEqual(array1[i], array2[i], tolerance) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Add a specific value to each element in the array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="offset"></param>
|
||||
static public void Offset(Complex[] array, double offset)
|
||||
{
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i].Re += offset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a specific value to each element in the array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="offset"></param>
|
||||
static public void Offset(Complex[] array, Complex offset)
|
||||
{
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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, float offset)
|
||||
{
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i].Re += offset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Multiply each element in the array by a specific value
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="scale"></param>
|
||||
static public void Scale(Complex[] array, double scale)
|
||||
{
|
||||
Debug.Assert(array != null);
|
||||
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i] *= scale;
|
||||
}
|
||||
}
|
||||
/// <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(Complex[] array, double 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply each element in the array by a specific value
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="scale"></param>
|
||||
static public void Scale(Complex[] array, Complex scale)
|
||||
{
|
||||
Debug.Assert(array != null);
|
||||
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i] *= scale;
|
||||
}
|
||||
}
|
||||
/// <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(Complex[] array, Complex 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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, float scale)
|
||||
{
|
||||
Debug.Assert(array != null);
|
||||
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
array[i] *= scale;
|
||||
}
|
||||
}
|
||||
/// <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, float 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <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(Complex[] target, Complex[] rhs)
|
||||
{
|
||||
ComplexArray.Multiply(target, rhs, target);
|
||||
}
|
||||
/// <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(Complex[] lhs, Complex[] rhs, Complex[] 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>
|
||||
/// 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);
|
||||
}
|
||||
/// <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>
|
||||
/// 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(Complex[] target, Complex[] rhs)
|
||||
{
|
||||
ComplexArray.Divide(target, rhs, target);
|
||||
}
|
||||
/// <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(Complex[] lhs, Complex[] rhs, Complex[] 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>
|
||||
/// 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);
|
||||
}
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
/*static public void Flip( ComplexF[] array, Size3 size ) {
|
||||
Debug.Assert( array != null );
|
||||
|
||||
ComplexF[] workspace = null;
|
||||
ComplexArray.LockWorkspaceF( size.GetTotalLength(), ref workspace );
|
||||
|
||||
for( int z = 0; z < size.Depth; z ++ ) {
|
||||
for( int y = 0; y < size.Height; y ++ ) {
|
||||
int xyzOffset = 0 + y * size.Width + z * size.Width * size.Height;
|
||||
int abcOffset = size.Width - 1 + ( size.Height - y - 1 ) * size.Width + ( size.Depth - z - 1 ) * size.Width * size.Height;
|
||||
for( int x = 0; x < size.Width; x ++ ) {
|
||||
workspace[ xyzOffset ++ ] = array[ abcOffset -- ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = 0; i < size.GetTotalLength(); i ++ ) {
|
||||
array[ i ] = workspace[ i ];
|
||||
}
|
||||
|
||||
ComplexArray.UnlockWorkspaceF( ref workspace );
|
||||
} */
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Copy an array
|
||||
/// </summary>
|
||||
/// <param name="dest"></param>
|
||||
/// <param name="source"></param>
|
||||
static public void Copy(Complex[] dest, Complex[] 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];
|
||||
}
|
||||
}
|
||||
|
||||
/// <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];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reverse the elements in the array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
static public void Reverse(Complex[] array)
|
||||
{
|
||||
Complex temp;
|
||||
int length = array.Length;
|
||||
for (int i = 0; i < length / 2; i++)
|
||||
{
|
||||
temp = array[i];
|
||||
array[i] = array[length - 1 - i];
|
||||
array[length - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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(Complex[] array)
|
||||
{
|
||||
double min = 0, max = 0;
|
||||
GetLengthRange(array, ref min, ref max);
|
||||
Scale(array, (1 / (max - min)));
|
||||
Offset(array, (-min / (max - min)));
|
||||
}
|
||||
|
||||
/// <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)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invert each element in the array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
static public void Invert(Complex[] array)
|
||||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = ((Complex)1) / array[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// <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];
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
public class SimplePolynomial : Polynomial
|
||||
{
|
||||
public SimplePolynomial(params double[] coefficients) : base(coefficients) { }
|
||||
|
||||
public override double Evaluate(double value)
|
||||
{
|
||||
var retval = coefficients[0];
|
||||
var f = value;
|
||||
|
||||
for (int i = 1; i < coefficients.Length; i++)
|
||||
{
|
||||
retval += coefficients[i] * f;
|
||||
f *= value;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
public abstract class Polynomial
|
||||
{
|
||||
public Polynomial(params double[] coefficients)
|
||||
{
|
||||
this.coefficients = new double[coefficients.Length];
|
||||
|
||||
for (int i = 0; i < coefficients.Length; i++)
|
||||
this.coefficients[i] = coefficients[i];
|
||||
}
|
||||
|
||||
public abstract double Evaluate(double value);
|
||||
|
||||
protected double[] coefficients = null;
|
||||
|
||||
public double GetCoefficient(int index)
|
||||
{
|
||||
if (null == coefficients || index < 0 || index >= coefficients.Length)
|
||||
{
|
||||
return double.NaN;
|
||||
}
|
||||
return coefficients[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>A single-precision complex number representation.</p>
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ComplexF : IComparable, ICloneable
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The real component of the complex number
|
||||
/// </summary>
|
||||
public float Re;
|
||||
|
||||
/// <summary>
|
||||
/// The imaginary component of the complex number
|
||||
/// </summary>
|
||||
public float Im;
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a real and an imaginary component
|
||||
/// </summary>
|
||||
/// <param name="real"></param>
|
||||
/// <param name="imaginary"></param>
|
||||
public ComplexF(float real, float imaginary)
|
||||
{
|
||||
this.Re = real;
|
||||
this.Im = imaginary;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a real and an imaginary component
|
||||
/// </summary>
|
||||
/// <param name="real"></param>
|
||||
/// <param name="imaginary"></param>
|
||||
/// <returns></returns>
|
||||
static public ComplexF FromRealImaginary(float real, float imaginary)
|
||||
{
|
||||
ComplexF c;
|
||||
c.Re = real;
|
||||
c.Im = imaginary;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a modulus (length) and an argument (radian)
|
||||
/// </summary>
|
||||
/// <param name="modulus"></param>
|
||||
/// <param name="argument"></param>
|
||||
/// <returns></returns>
|
||||
static public ComplexF FromModulusArgument(float modulus, float argument)
|
||||
{
|
||||
ComplexF c;
|
||||
c.Re = (float)(modulus * System.Math.Cos(argument));
|
||||
c.Im = (float)(modulus * System.Math.Sin(argument));
|
||||
return c;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new ComplexF(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clone the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ComplexF Clone()
|
||||
{
|
||||
return new ComplexF(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The modulus (length) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public float GetModulus()
|
||||
{
|
||||
float x = this.Re;
|
||||
float y = this.Im;
|
||||
return (float)Math.Sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The squared modulus (length^2) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public float GetModulusSquared()
|
||||
{
|
||||
float x = this.Re;
|
||||
float y = this.Im;
|
||||
return (float)x * x + y * y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The argument (radians) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public float GetArgument()
|
||||
{
|
||||
return (float)Math.Atan2(this.Im, this.Re);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ComplexF GetConjugate()
|
||||
{
|
||||
return FromRealImaginary(this.Re, -this.Im);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Scale the complex number to 1.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
double modulus = this.GetModulus();
|
||||
if (modulus == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Can not normalize a complex number that is zero.");
|
||||
}
|
||||
this.Re = (float)(this.Re / modulus);
|
||||
this.Im = (float)(this.Im / modulus);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Convert to a from double precision complex number to a single precison complex number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator ComplexF(Complex c)
|
||||
{
|
||||
ComplexF cF;
|
||||
cF.Re = (float)c.Re;
|
||||
cF.Im = (float)c.Im;
|
||||
return cF;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert from a single precision real number to a complex number
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator ComplexF(float f)
|
||||
{
|
||||
ComplexF c;
|
||||
c.Re = f;
|
||||
c.Im = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert from a single precision complex to a real number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator float(ComplexF c)
|
||||
{
|
||||
return c.Re;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Are these two complex numbers equivalent?
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(ComplexF a, ComplexF b)
|
||||
{
|
||||
return (a.Re == b.Re) && (a.Im == b.Im);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are these two complex numbers different?
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(ComplexF a, ComplexF b)
|
||||
{
|
||||
return (a.Re != b.Re) || (a.Im != b.Im);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the hash code of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (this.Re.GetHashCode() ^ this.Im.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this complex number equivalent to another object?
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (o is ComplexF)
|
||||
{
|
||||
ComplexF c = (ComplexF)o;
|
||||
return (this == c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Compare to other complex numbers or real numbers
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public int CompareTo(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return 1; // null sorts before current
|
||||
}
|
||||
if (o is ComplexF)
|
||||
{
|
||||
return this.GetModulus().CompareTo(((ComplexF)o).GetModulus());
|
||||
}
|
||||
if (o is float)
|
||||
{
|
||||
return this.GetModulus().CompareTo((float)o);
|
||||
}
|
||||
if (o is Complex)
|
||||
{
|
||||
return this.GetModulus().CompareTo(((Complex)o).GetModulus());
|
||||
}
|
||||
if (o is double)
|
||||
{
|
||||
return this.GetModulus().CompareTo((double)o);
|
||||
}
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// This operator doesn't do much. :-)
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator +(ComplexF a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Negate the complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator -(ComplexF a)
|
||||
{
|
||||
a.Re = -a.Re;
|
||||
a.Im = -a.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a complex number to a real
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator +(ComplexF a, float f)
|
||||
{
|
||||
a.Re = a.Re + f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a real to a complex number
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator +(float f, ComplexF a)
|
||||
{
|
||||
a.Re = a.Re + f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add to complex numbers
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator +(ComplexF a, ComplexF b)
|
||||
{
|
||||
a.Re = a.Re + b.Re;
|
||||
a.Im = a.Im + b.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract a real from a complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator -(ComplexF a, float f)
|
||||
{
|
||||
a.Re = a.Re - f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract a complex number from a real
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator -(float f, ComplexF a)
|
||||
{
|
||||
a.Re = f - a.Re;
|
||||
a.Im = 0 - a.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract two complex numbers
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator -(ComplexF a, ComplexF b)
|
||||
{
|
||||
a.Re = a.Re - b.Re;
|
||||
a.Im = a.Im - b.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a complex number by a real
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator *(ComplexF a, float f)
|
||||
{
|
||||
a.Re = a.Re * f;
|
||||
a.Im = a.Im * f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a real by a complex number
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator *(float f, ComplexF a)
|
||||
{
|
||||
a.Re = a.Re * f;
|
||||
a.Im = a.Im * f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply two complex numbers together
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator *(ComplexF a, ComplexF b)
|
||||
{
|
||||
// (x + yi)(u + vi) = (xu – yv) + (xv + yu)i.
|
||||
double x = a.Re, y = a.Im;
|
||||
double u = b.Re, v = b.Im;
|
||||
a.Re = (float)(x * u - y * v);
|
||||
a.Im = (float)(x * v + y * u);
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a complex number by a real number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator /(ComplexF a, float f)
|
||||
{
|
||||
if (f == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
a.Re = a.Re / f;
|
||||
a.Im = a.Im / f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a complex number by a complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static ComplexF operator /(ComplexF a, ComplexF b)
|
||||
{
|
||||
double x = a.Re, y = a.Im;
|
||||
double u = b.Re, v = b.Im;
|
||||
double denom = u * u + v * v;
|
||||
|
||||
if (denom == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
a.Re = (float)((x * u + y * v) / denom);
|
||||
a.Im = (float)((y * u - x * v) / denom);
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a complex representation in this fashion: "( %f, %f )"
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
static public ComplexF Parse(string s)
|
||||
{
|
||||
throw new NotImplementedException("ComplexF ComplexF.Parse( string s ) is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("( {0}, {1}i )", this.Re, this.Im);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <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);
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Represents zero
|
||||
/// </summary>
|
||||
static public ComplexF Zero
|
||||
{
|
||||
get { return new ComplexF(0, 0); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the result of sqrt( -1 )
|
||||
/// </summary>
|
||||
static public ComplexF I
|
||||
{
|
||||
get { return new ComplexF(0, 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the largest possible value of ComplexF.
|
||||
/// </summary>
|
||||
static public ComplexF MaxValue
|
||||
{
|
||||
get { return new ComplexF(float.MaxValue, float.MaxValue); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the smallest possible value of ComplexF.
|
||||
/// </summary>
|
||||
static public ComplexF MinValue
|
||||
{
|
||||
get { return new ComplexF(float.MinValue, float.MinValue); }
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
public enum PassFilterType
|
||||
{
|
||||
Bessel,
|
||||
Butterworth,
|
||||
Chebyshev,
|
||||
CriticalDamping
|
||||
}
|
||||
public static class PassFilter
|
||||
{
|
||||
public static double[] HighPass(double[] values, double sampleRate, double centerFrequency, PassFilterType type, uint order)
|
||||
{
|
||||
return RunFilter(values, sampleRate, centerFrequency, type, order, false);
|
||||
}
|
||||
public static double[] LowPass(double[] values, double sampleRate, double centerFrequency, PassFilterType type, uint order)
|
||||
{
|
||||
return RunFilter(values, sampleRate, centerFrequency, type, order, true);
|
||||
}
|
||||
private static double[] RunFilter(double[] values, double sampleRate, double centerFrequency, PassFilterType type, uint order, bool lowPass)
|
||||
{
|
||||
Complex[] data = new Complex[values.Length];
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
data[i] = (Complex)values[i];
|
||||
}
|
||||
Complex[] result;
|
||||
switch (type)
|
||||
{
|
||||
case PassFilterType.Bessel:
|
||||
result = BesselFilter(data, sampleRate, centerFrequency, order, lowPass);
|
||||
break;
|
||||
case PassFilterType.Chebyshev:
|
||||
result = ChebyshevFilter(data, sampleRate, centerFrequency, order, 1D, 0.005, lowPass);
|
||||
break;
|
||||
case PassFilterType.Butterworth:
|
||||
default:
|
||||
result = ButterworthFilter(data, sampleRate, centerFrequency, order, 1D, lowPass);
|
||||
break;
|
||||
}
|
||||
return result.Select(c => c.Re).ToArray();
|
||||
}
|
||||
private static Complex[] BesselFilter(Complex[] values, double sampleRate, double centerFrequency, uint order, bool lowPass)
|
||||
{
|
||||
var signal = (Complex[])values.Clone();
|
||||
var N = signal.Length;
|
||||
|
||||
// Get the reverse Bessel polynomial-to-gain function denominator
|
||||
Polynomial B = BesselDenominatorPolynomial((int)order);
|
||||
var numerator = Math.Sqrt(B.GetCoefficient(0));
|
||||
// Apply forward FFT
|
||||
Fourier.FFT(signal, N, FourierDirection.Forward);
|
||||
// Apply gain function
|
||||
if (centerFrequency > 0)
|
||||
{
|
||||
var numBins = N / 2; // Half the length of the FFT by symmetry
|
||||
var binWidth = sampleRate / N; // Hz
|
||||
|
||||
// Filter
|
||||
System.Threading.Tasks.Parallel.For(1, N / 2, i =>
|
||||
{
|
||||
var binFreq = binWidth * i;
|
||||
var gain = BesselGain(numerator, B, binFreq, centerFrequency, lowPass);
|
||||
signal[i] *= gain;
|
||||
signal[N - i] *= gain;
|
||||
});
|
||||
|
||||
}
|
||||
// Reverse filtered signal
|
||||
Fourier.FFT(signal, N, FourierDirection.Backward);
|
||||
signal = signal.Select(n => n / N).ToArray(); // scale result by length
|
||||
|
||||
return signal;
|
||||
}
|
||||
private static double BesselGain(double numerator, Polynomial B, double freq, double centerFreq, bool lowPass)
|
||||
{
|
||||
return numerator / Math.Sqrt(B.Evaluate(lowPass ? freq / centerFreq : centerFreq / freq)); // low-to-high pass is inverting f/fc
|
||||
}
|
||||
|
||||
// uses logic from https://www.centerspace.net/butterworth-filter-csharp
|
||||
private static Complex[] ButterworthFilter(Complex[] values, double sampleRate, double centerFrequency, uint order, double DCGain, bool lowPass)
|
||||
{
|
||||
var signal = (Complex[])values.Clone();
|
||||
var N = signal.Length;
|
||||
|
||||
// Apply forward FFT
|
||||
Fourier.FFT(signal, N, FourierDirection.Forward);
|
||||
// Apply gain function
|
||||
if (centerFrequency > 0)
|
||||
{
|
||||
var numBins = N / 2; // Half the length of the FFT by symmetry
|
||||
var binWidth = sampleRate / N; // Hz
|
||||
|
||||
// Filter
|
||||
System.Threading.Tasks.Parallel.For(1, N / 2, i =>
|
||||
{
|
||||
var binFreq = binWidth * i;
|
||||
var gain = ButterworthGain(DCGain, binFreq, centerFrequency, order, lowPass);
|
||||
signal[i] *= gain;
|
||||
signal[N - i] *= gain;
|
||||
});
|
||||
|
||||
}
|
||||
// Reverse filtered signal
|
||||
Fourier.FFT(signal, N, FourierDirection.Backward);
|
||||
// scale result by length
|
||||
signal = signal.Select(n => n / N).ToArray();
|
||||
return signal;
|
||||
}
|
||||
private static double ButterworthGain(double DCGain, double freq, double centerFreq, uint order, bool lowPass)
|
||||
{
|
||||
return DCGain / Math.Sqrt(1 + Math.Pow(lowPass ? freq / centerFreq : centerFreq / freq, 2.0 * order)); // low-to-high pass is just inverting f/fc
|
||||
}
|
||||
|
||||
// uses logic from https://www.centerspace.net/chebyshev-filter-csharp
|
||||
private static Complex[] ChebyshevFilter(Complex[] values, double sampleRate, double centerFrequency, uint order, double DCGain, double ripple, bool lowPass)
|
||||
{
|
||||
var signal = (Complex[])values.Clone();
|
||||
var N = signal.Length;
|
||||
|
||||
// Get the Chebyshev polynomial
|
||||
Polynomial T = ChebyshevPolynomial((int)order);
|
||||
// Apply forward FFT
|
||||
Fourier.FFT(signal, N, FourierDirection.Forward);
|
||||
// Remove DC offset
|
||||
signal[0] = (Complex)0;
|
||||
|
||||
// Apply gain function
|
||||
if (centerFrequency > 0)
|
||||
{
|
||||
var numBins = N / 2; // Half the length of the FFT by symmetry
|
||||
var binWidth = sampleRate / N; // Hz
|
||||
|
||||
// Filter
|
||||
System.Threading.Tasks.Parallel.For(1, N / 2, i =>
|
||||
{
|
||||
var binFreq = binWidth * i;
|
||||
var gain = ChebyshevGain(DCGain, ripple, T, binFreq, centerFrequency, order, lowPass);
|
||||
signal[i] *= gain;
|
||||
signal[N - i] *= gain;
|
||||
});
|
||||
|
||||
}
|
||||
// Reverse filtered signal
|
||||
Fourier.FFT(signal, N, FourierDirection.Backward);
|
||||
// scale result by length
|
||||
signal = signal.Select(n => n / N).ToArray();
|
||||
|
||||
return signal;
|
||||
}
|
||||
private static double ChebyshevGain(double DCGain, double ripple, Polynomial T, double freq, double centerFreq, uint order, bool lowPass)
|
||||
{
|
||||
return DCGain / Math.Sqrt(1 + ripple * Math.Pow(T.Evaluate(lowPass ? freq / centerFreq : centerFreq / freq), 2.0 * order));
|
||||
}
|
||||
|
||||
private static Polynomial ChebyshevPolynomial(int order)
|
||||
{
|
||||
switch (order)
|
||||
{
|
||||
case 0:
|
||||
return new SimplePolynomial(new double[] { 1 });
|
||||
case 1:
|
||||
return new SimplePolynomial(new double[] { 0, 1 });
|
||||
case 2:
|
||||
return new SimplePolynomial(new double[] { -1, 0, 2 });
|
||||
case 3:
|
||||
return new SimplePolynomial(new double[] { 0, -3, 0, 4 });
|
||||
case 4:
|
||||
return new SimplePolynomial(new double[] { 1, 0, -8, 0, 8 });
|
||||
case 5:
|
||||
return new SimplePolynomial(new double[] { 0, 5, 0, -20, 0, 16 });
|
||||
case 6:
|
||||
return new SimplePolynomial(new double[] { -1, 0, 1, 8, 0, -48, 0, 32 });
|
||||
case 7:
|
||||
return new SimplePolynomial(new double[] { 0, 7, 0, 56, 0, -112, 0, 64 });
|
||||
case 8:
|
||||
return new SimplePolynomial(new double[] { 1, 0, -32, 0, 160, 0, -256, 0, 128 });
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
private static Polynomial BesselDenominatorPolynomial(int order)
|
||||
{
|
||||
// Polynomials in the square-rooted denominator of bessel gain functions
|
||||
// Obtained via magnitude calc of H(iw) of each Bessel H(s): https://en.wikipedia.org/wiki/Bessel_filter#The_transfer_function
|
||||
// at https://www.symbolab.com/solver/complex-numbers-magnitude-calculator/
|
||||
switch (order)
|
||||
{
|
||||
case 2:
|
||||
return new SimplePolynomial(new double[] { 9, 0, 3, 0, 1 });
|
||||
case 3:
|
||||
return new SimplePolynomial(new double[] { 225, 0, 45, 0, 6, 0, 1 });
|
||||
case 4:
|
||||
return new SimplePolynomial(new double[] { 11025, 0, 1575, 0, 135, 0, 10, 0, 1 });
|
||||
case 5:
|
||||
return new SimplePolynomial(new double[] { 893025, 0, 99225, 0, 6300, 0, 315, 0, 15, 0, 1 });
|
||||
case 6:
|
||||
return new SimplePolynomial(new double[] { 108056025, 0, 9823275, 0, 496125, 0, 18900, 0, 630, 0, 21, 0, 1 });
|
||||
case 7:
|
||||
return new SimplePolynomial(new double[] { 18261468225, 0, 1404728325, 0, 58939650, 0, 1819125, 0, 47250, 0, 1134, 0, 28, 0, 1 });
|
||||
case 8:
|
||||
return new SimplePolynomial(new double[] { 4108830350625, 0, 273922023375, 0, 9833098275, 0, 255405150, 0, 5457375, 0, 103950, 0, 1890, 0, 36, 0, 1 });
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>A double-precision complex number representation.</p>
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Complex : IComparable, ICloneable
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The real component of the complex number
|
||||
/// </summary>
|
||||
public double Re;
|
||||
|
||||
/// <summary>
|
||||
/// The imaginary component of the complex number
|
||||
/// </summary>
|
||||
public double Im;
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a real and an imaginary component
|
||||
/// </summary>
|
||||
/// <param name="real"></param>
|
||||
/// <param name="imaginary"></param>
|
||||
public Complex(double real, double imaginary)
|
||||
{
|
||||
this.Re = real;
|
||||
this.Im = imaginary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number based on an existing complex number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
public Complex(Complex c)
|
||||
{
|
||||
this.Re = c.Re;
|
||||
this.Im = c.Im;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a real and an imaginary component
|
||||
/// </summary>
|
||||
/// <param name="real"></param>
|
||||
/// <param name="imaginary"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex FromRealImaginary(double real, double imaginary)
|
||||
{
|
||||
Complex c;
|
||||
c.Re = real;
|
||||
c.Im = imaginary;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a complex number from a modulus (length) and an argument (radian)
|
||||
/// </summary>
|
||||
/// <param name="modulus"></param>
|
||||
/// <param name="argument"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex FromModulusArgument(double modulus, double argument)
|
||||
{
|
||||
Complex c;
|
||||
c.Re = modulus * System.Math.Cos(argument);
|
||||
c.Im = modulus * System.Math.Sin(argument);
|
||||
return c;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
object ICloneable.Clone()
|
||||
{
|
||||
return new Complex(this);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clone the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Complex Clone()
|
||||
{
|
||||
return new Complex(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// The modulus (length) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetModulus()
|
||||
{
|
||||
double x = this.Re;
|
||||
double y = this.Im;
|
||||
return (double)Math.Sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The squared modulus (length^2) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetModulusSquared()
|
||||
{
|
||||
double x = this.Re;
|
||||
double y = this.Im;
|
||||
return (double)x * x + y * y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The argument (radians) of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double GetArgument()
|
||||
{
|
||||
return (double)Math.Atan2(this.Im, this.Re);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Complex GetConjugate()
|
||||
{
|
||||
return FromRealImaginary(this.Re, -this.Im);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Scale the complex number to 1.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
double modulus = this.GetModulus();
|
||||
if (modulus == 0)
|
||||
{
|
||||
throw new DivideByZeroException("Can not normalize a complex number that is zero.");
|
||||
}
|
||||
this.Re = this.Re / modulus;
|
||||
this.Im = this.Im / modulus;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Convert to a from double precision complex number to a single precison complex number
|
||||
/// </summary>
|
||||
/// <param name="cF"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator Complex(ComplexF cF)
|
||||
{
|
||||
Complex c;
|
||||
c.Re = cF.Re;
|
||||
c.Im = cF.Im;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert from a single precision real number to a complex number
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator Complex(double d)
|
||||
{
|
||||
Complex c;
|
||||
c.Re = d;
|
||||
c.Im = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert from a single precision complex to a real number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
public static explicit operator double(Complex c)
|
||||
{
|
||||
return c.Re;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Are these two complex numbers equivalent?
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(Complex a, Complex b)
|
||||
{
|
||||
return (a.Re == b.Re) && (a.Im == b.Im);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are these two complex numbers different?
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(Complex a, Complex b)
|
||||
{
|
||||
return (a.Re != b.Re) || (a.Im != b.Im);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the hash code of the complex number
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (this.Re.GetHashCode() ^ this.Im.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is this complex number equivalent to another object?
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (o is Complex)
|
||||
{
|
||||
Complex c = (Complex)o;
|
||||
return (this == c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Compare to other complex numbers or real numbers
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
/// <returns></returns>
|
||||
public int CompareTo(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return 1; // null sorts before current
|
||||
}
|
||||
if (o is Complex)
|
||||
{
|
||||
return this.GetModulus().CompareTo(((Complex)o).GetModulus());
|
||||
}
|
||||
if (o is double)
|
||||
{
|
||||
return this.GetModulus().CompareTo((double)o);
|
||||
}
|
||||
if (o is ComplexF)
|
||||
{
|
||||
return this.GetModulus().CompareTo(((ComplexF)o).GetModulus());
|
||||
}
|
||||
if (o is float)
|
||||
{
|
||||
return this.GetModulus().CompareTo((float)o);
|
||||
}
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// This operator doesn't do much. :-)
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator +(Complex a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Negate the complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator -(Complex a)
|
||||
{
|
||||
a.Re = -a.Re;
|
||||
a.Im = -a.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a complex number to a real
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator +(Complex a, double f)
|
||||
{
|
||||
a.Re = a.Re + f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a real to a complex number
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator +(double f, Complex a)
|
||||
{
|
||||
a.Re = a.Re + f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add to complex numbers
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator +(Complex a, Complex b)
|
||||
{
|
||||
a.Re = a.Re + b.Re;
|
||||
a.Im = a.Im + b.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract a real from a complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator -(Complex a, double f)
|
||||
{
|
||||
a.Re = a.Re - f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract a complex number from a real
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator -(double f, Complex a)
|
||||
{
|
||||
a.Re = (float)(f - a.Re);
|
||||
a.Im = (float)(0 - a.Im);
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract two complex numbers
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator -(Complex a, Complex b)
|
||||
{
|
||||
a.Re = a.Re - b.Re;
|
||||
a.Im = a.Im - b.Im;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a complex number by a real
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator *(Complex a, double f)
|
||||
{
|
||||
a.Re = a.Re * f;
|
||||
a.Im = a.Im * f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a real by a complex number
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator *(double f, Complex a)
|
||||
{
|
||||
a.Re = a.Re * f;
|
||||
a.Im = a.Im * f;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply two complex numbers together
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator *(Complex a, Complex b)
|
||||
{
|
||||
// (x + yi)(u + vi) = (xu – yv) + (xv + yu)i.
|
||||
double x = a.Re, y = a.Im;
|
||||
double u = b.Re, v = b.Im;
|
||||
|
||||
a.Re = x * u - y * v;
|
||||
a.Im = x * v + y * u;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a complex number by a real number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="f"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator /(Complex a, double f)
|
||||
{
|
||||
if (f == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
|
||||
a.Re = a.Re / f;
|
||||
a.Im = a.Im / f;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a complex number by a complex number
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static Complex operator /(Complex a, Complex b)
|
||||
{
|
||||
double x = a.Re, y = a.Im;
|
||||
double u = b.Re, v = b.Im;
|
||||
double denom = u * u + v * v;
|
||||
|
||||
if (denom == 0)
|
||||
{
|
||||
throw new DivideByZeroException();
|
||||
}
|
||||
|
||||
a.Re = (x * u + y * v) / denom;
|
||||
a.Im = (y * u - x * v) / denom;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a complex representation in this fashion: "( %f, %f )"
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Parse(string s)
|
||||
{
|
||||
throw new NotImplementedException("Complex Complex.Parse( string s ) is not implemented.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the string representation
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("( {0}, {1}i )", this.Re, this.Im);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
/// <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(Complex a, Complex b, double tolerance)
|
||||
{
|
||||
return
|
||||
(Math.Abs(a.Re - b.Re) < tolerance) &&
|
||||
(Math.Abs(a.Im - b.Im) < tolerance);
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Represents zero
|
||||
/// </summary>
|
||||
static public Complex Zero
|
||||
{
|
||||
get { return new Complex(0, 0); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the result of sqrt( -1 )
|
||||
/// </summary>
|
||||
static public Complex I
|
||||
{
|
||||
get { return new Complex(0, 1); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the largest possible value of Complex.
|
||||
/// </summary>
|
||||
static public Complex MaxValue
|
||||
{
|
||||
get { return new Complex(double.MaxValue, double.MaxValue); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the smallest possible value of Complex.
|
||||
/// </summary>
|
||||
static public Complex MinValue
|
||||
{
|
||||
get { return new Complex(double.MinValue, double.MinValue); }
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>A set of statistical utilities for complex number arrays</p>
|
||||
/// </summary>
|
||||
public class ComplexStats
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
private ComplexStats()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
/// <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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the sum
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Sum(Complex[] data)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
return SumRecursion(data, 0, data.Length);
|
||||
}
|
||||
static private Complex SumRecursion(Complex[] 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)
|
||||
{
|
||||
Complex sum = Complex.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);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the sum of squares
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public ComplexF SumOfSquares(ComplexF[] data)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
return SumOfSquaresRecursion(data, 0, data.Length);
|
||||
}
|
||||
static private ComplexF SumOfSquaresRecursion(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 sumOfSquares = ComplexF.Zero;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
sumOfSquares += data[i] * data[i];
|
||||
|
||||
}
|
||||
return sumOfSquares;
|
||||
}
|
||||
else
|
||||
{
|
||||
int middle = (start + end) >> 1;
|
||||
return SumOfSquaresRecursion(data, start, middle) + SumOfSquaresRecursion(data, middle, end);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the sum of squares
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex SumOfSquares(Complex[] data)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
return SumOfSquaresRecursion(data, 0, data.Length);
|
||||
}
|
||||
static private Complex SumOfSquaresRecursion(Complex[] 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)
|
||||
{
|
||||
Complex sumOfSquares = Complex.Zero;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
sumOfSquares += data[i] * data[i];
|
||||
|
||||
}
|
||||
return sumOfSquares;
|
||||
}
|
||||
else
|
||||
{
|
||||
int middle = (start + end) >> 1;
|
||||
return SumOfSquaresRecursion(data, start, middle) + SumOfSquaresRecursion(data, middle, end);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the mean (average)
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public ComplexF Mean(ComplexF[] data)
|
||||
{
|
||||
return ComplexStats.Sum(data) / data.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the mean (average)
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Mean(Complex[] data)
|
||||
{
|
||||
return ComplexStats.Sum(data) / data.Length;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculate the variance
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Variance(Complex[] 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);
|
||||
}
|
||||
|
||||
/// <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));
|
||||
}
|
||||
/// <summary>
|
||||
/// Calculate the standard deviation
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex StdDev(Complex[] data)
|
||||
{
|
||||
Debug.Assert(data != null);
|
||||
if (data.Length == 0)
|
||||
{
|
||||
throw new DivideByZeroException("length of data is zero");
|
||||
}
|
||||
return ComplexMath.Sqrt(ComplexStats.Variance(data));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
//--------------------------------------------------------------------------------------------
|
||||
|
||||
/// <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));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 double RMSError(Complex[] alpha, Complex[] beta)
|
||||
{
|
||||
Debug.Assert(alpha != null);
|
||||
Debug.Assert(beta != null);
|
||||
Debug.Assert(beta.Length == alpha.Length);
|
||||
|
||||
return Math.Sqrt(SumOfSquaredErrorRecursion(alpha, beta, 0, alpha.Length));
|
||||
}
|
||||
static private double SumOfSquaredErrorRecursion(Complex[] alpha, Complex[] 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)
|
||||
{
|
||||
double sumOfSquaredError = 0;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
Complex 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="Exocortex.DSP.ComplexArray" Collapsed="true">
|
||||
<Position X="0.5" Y="1" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAEADAQAAAAgAEQIhACAAAgAAEAAEAAACAAAAgAA=</HashCode>
|
||||
<FileName>ComplexArray.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Exocortex.DSP.ComplexMath" Collapsed="true">
|
||||
<Position X="2.25" Y="1" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAASBAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>ComplexMath.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Exocortex.DSP.ComplexStats" Collapsed="true">
|
||||
<Position X="0.5" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>IAAAAAAAAAAAAAAAAQAAAAABAAABBAAEgAAAAAAAAAQ=</HashCode>
|
||||
<FileName>ComplexStats.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="Exocortex.DSP.Fourier" Collapsed="true">
|
||||
<Position X="2.25" Y="2" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gWgFAKgAgAgQBAICCIAGgBRCABMBAEAABAAAAgAgAKA=</HashCode>
|
||||
<FileName>Fourier.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Struct Name="Exocortex.DSP.Complex" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="0.5" Y="3.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAgAAAQABAABgwM9QUAAAAAAwEAEIAAAAAgACAAAzA=</HashCode>
|
||||
<FileName>Complex.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Struct>
|
||||
<Struct Name="Exocortex.DSP.ComplexF" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="2.25" Y="3.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAgAAAQAAAABgwM9QcAAAAAAwFAEIAAAAAgACAAAzA=</HashCode>
|
||||
<FileName>ComplexF.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Struct>
|
||||
<Enum Name="Exocortex.DSP.FourierDirection" Collapsed="true">
|
||||
<Position X="0.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI=</HashCode>
|
||||
<FileName>FourierDirection.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{5497D233-0E72-45C2-8A2B-9264ECD2AE31}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Exocortex</RootNamespace>
|
||||
<AssemblyName>Exocortex</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Complex.cs" />
|
||||
<Compile Include="ComplexArray.cs" />
|
||||
<Compile Include="ComplexF.cs" />
|
||||
<Compile Include="ComplexMath.cs" />
|
||||
<Compile Include="ComplexStats.cs" />
|
||||
<Compile Include="Fourier.cs" />
|
||||
<Compile Include="FourierDirection.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>The direction of the fourier transform.</p>
|
||||
/// </summary>
|
||||
public enum FourierDirection : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Forward direction. Usually in reference to moving from temporal
|
||||
/// representation to frequency representation
|
||||
/// </summary>
|
||||
Forward = 1,
|
||||
/// <summary>
|
||||
/// Backward direction. Usually in reference to moving from frequency
|
||||
/// representation to temporal representation
|
||||
/// </summary>
|
||||
Backward = -1,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* BSD Licence:
|
||||
* Copyright (c) 2001, 2002 Ben Houston [ ben@exocortex.org ]
|
||||
* Exocortex Technologies [ www.exocortex.org ]
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
namespace Exocortex.DSP
|
||||
{
|
||||
|
||||
// Comments? Questions? Bugs? Tell Ben Houston at ben@exocortex.org
|
||||
// Version: May 4, 2002
|
||||
|
||||
/// <summary>
|
||||
/// <p>Various mathematical functions for complex numbers.</p>
|
||||
/// </summary>
|
||||
public class ComplexMath
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
private ComplexMath()
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Swap two complex numbers
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
static public void Swap(ref Complex a, ref Complex b)
|
||||
{
|
||||
Complex temp = a;
|
||||
a = b;
|
||||
b = 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;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
static private double _halfOfRoot2 = 0.5 * Math.Sqrt(2);
|
||||
|
||||
/// <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 square root of a complex number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Sqrt(Complex 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 = _halfOfRoot2 * Math.Sqrt(modulus + x);
|
||||
c.Im = _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>
|
||||
static public 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the power of a complex number
|
||||
/// </summary>
|
||||
/// <param name="c"></param>
|
||||
/// <param name="exponent"></param>
|
||||
/// <returns></returns>
|
||||
static public Complex Pow(Complex 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 = modulus * System.Math.Cos(argument);
|
||||
c.Im = modulus * System.Math.Sin(argument);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
}
|
||||
BIN
DataPRO/ExocortexDSP/.svn/wc.db
Normal file
BIN
DataPRO/ExocortexDSP/.svn/wc.db
Normal file
Binary file not shown.
0
DataPRO/ExocortexDSP/.svn/wc.db-journal
Normal file
0
DataPRO/ExocortexDSP/.svn/wc.db-journal
Normal file
Reference in New Issue
Block a user