Browse Source

using common parallel class for both silverlight and .NET 4.0

pull/36/head
Marcus Cuda 17 years ago
parent
commit
fe5147fcda
  1. 1
      src/FSharpExamples/Apply.fs
  2. 1
      src/FSharpExamples/FSharpExamples.fsproj
  3. 10
      src/MathNet.Numerics.sln
  4. 635
      src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs
  5. 31
      src/Numerics/Control.cs
  6. 6
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs
  7. 33
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs
  8. 17
      src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs
  9. 27
      src/Numerics/IntegralTransforms/Algorithms/DiscreteHartleyTransform.Naive.cs
  10. 1
      src/Numerics/Numerics.csproj
  11. 147
      src/Numerics/Threading/CommonParallel.cs
  12. 2
      src/Silverlight/Properties/AssemblyInfo.cs
  13. 115
      src/Silverlight/Silverlight.csproj
  14. 65
      src/Silverlight/Threading/AggregateException.cs
  15. 485
      src/Silverlight/Threading/Parallel.cs
  16. 128
      src/Silverlight/Threading/Task.cs
  17. 79
      src/Silverlight/Threading/TaskOfT.cs
  18. 258
      src/Silverlight/Threading/ThreadQueue.cs

1
src/FSharpExamples/Apply.fs

@ -27,6 +27,7 @@
// </copyright> // </copyright>
module MathNet.Numerics.FSharp.Examples.Apply module MathNet.Numerics.FSharp.Examples.Apply
open System.Numerics
open MathNet.Numerics open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra.Double open MathNet.Numerics.LinearAlgebra.Double

1
src/FSharpExamples/FSharpExamples.fsproj

@ -37,6 +37,7 @@
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Numerics" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FSharp\FSharp.fsproj"> <ProjectReference Include="..\FSharp\FSharp.fsproj">

10
src/MathNet.Numerics.sln

@ -13,7 +13,7 @@ Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpExamples", "FSharpExa
EndProject EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests", "FSharpUnitTests\FSharpUnitTests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}" Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests", "FSharpUnitTests\FSharpUnitTests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silverlight", "Silverlight\Silverlight.csproj", "{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silverlight", "Silverlight\Silverlight.csproj", "{793E332F-E2B1-4D1D-9B2E-27E90B99BF93}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -45,10 +45,10 @@ Global
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.Build.0 = Release|Any CPU {F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.Build.0 = Release|Any CPU
{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {793E332F-E2B1-4D1D-9B2E-27E90B99BF93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}.Debug|Any CPU.Build.0 = Debug|Any CPU {793E332F-E2B1-4D1D-9B2E-27E90B99BF93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}.Release|Any CPU.ActiveCfg = Release|Any CPU {793E332F-E2B1-4D1D-9B2E-27E90B99BF93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}.Release|Any CPU.Build.0 = Release|Any CPU {793E332F-E2B1-4D1D-9B2E-27E90B99BF93}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

635
src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs

File diff suppressed because it is too large

31
src/Numerics/Control.cs

@ -28,6 +28,7 @@
namespace MathNet.Numerics namespace MathNet.Numerics
{ {
using System;
using Algorithms.LinearAlgebra; using Algorithms.LinearAlgebra;
/// <summary> /// <summary>
@ -35,6 +36,13 @@ namespace MathNet.Numerics
/// </summary> /// </summary>
public static class Control public static class Control
{ {
#if !SILVERLIGHT
/// <summary>
/// Initial number of threads to use;
/// </summary>
private static int _numberOfThreads = Environment.ProcessorCount;
#endif
/// <summary> /// <summary>
/// Initializes static members of the Control class. /// Initializes static members of the Control class.
/// </summary> /// </summary>
@ -75,5 +83,28 @@ namespace MathNet.Numerics
{ {
get; set; get; set;
} }
/// <summary>
/// Gets or sets a value indicating how many parallel worker threads shall be used
/// when parallelization is applicable.
/// </summary>
/// <remarks>The Silverlight version of the library defaults to one thread.</remarks>
public static int NumberOfParallelWorkerThreads
{
#if SILVERLIGHT
get { return ThreadQueue.ThreadCount; }
set { ThreadQueue.Start(value); }
#else
get
{
return _numberOfThreads;
}
set
{ // instead of throwing an out of range exception, simply normalize
_numberOfThreads = Math.Max(1, Math.Min(1024, value));
}
#endif
}
} }
} }

6
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs

@ -30,9 +30,9 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
using System; using System;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks;
using NumberTheory; using NumberTheory;
using Threading;
/// <summary> /// <summary>
/// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT).
/// </summary> /// </summary>
@ -71,7 +71,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
Complex[] b = new Complex[m]; Complex[] b = new Complex[m];
Complex[] a = new Complex[m]; Complex[] a = new Complex[m];
Parallel.Invoke( CommonParallel.Invoke(
() => () =>
{ {
// Build and transform padded sequence b_k = exp(I*Pi*k^2/N) // Build and transform padded sequence b_k = exp(I*Pi*k^2/N)

33
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs

@ -25,9 +25,8 @@
namespace MathNet.Numerics.IntegralTransforms.Algorithms namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
using System; using System;
using System.Collections.Concurrent;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks; using Threading;
/// <summary> /// <summary>
/// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT).
@ -45,23 +44,21 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
var w0 = exponentSign * Constants.Pi2 / samples.Length; var w0 = exponentSign * Constants.Pi2 / samples.Length;
var spectrum = new Complex[samples.Length]; var spectrum = new Complex[samples.Length];
Parallel.ForEach( CommonParallel.For(
Partitioner.Create(0, samples.Length), 0,
(range, loopState) => samples.Length,
{ index =>
for (var k = range.Item1; k < range.Item2; k++) {
{ var wk = w0 * index;
var wk = w0 * k; var sum = Complex.Zero;
var sum = Complex.Zero; for (var n = 0; n < samples.Length; n++)
for (var n = 0; n < samples.Length; n++) {
{ var w = n * wk;
var w = n * wk; sum += samples[n] * new Complex(Math.Cos(w), Math.Sin(w));
sum += samples[n] * new Complex(Math.Cos(w), Math.Sin(w)); }
}
spectrum[k] = sum; spectrum[index] = sum;
} });
});
return spectrum; return spectrum;
} }

17
src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs

@ -25,11 +25,10 @@
namespace MathNet.Numerics.IntegralTransforms.Algorithms namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
using System; using System;
using System.Collections.Concurrent;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks;
using NumberTheory; using NumberTheory;
using Properties; using Properties;
using Threading;
/// <summary> /// <summary>
/// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT).
@ -127,15 +126,11 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2) for (var levelSize = 1; levelSize < samples.Length; levelSize *= 2)
{ {
var size = levelSize; var size = levelSize;
Parallel.ForEach(
Partitioner.Create(0, size), CommonParallel.For(
(range, loopState) => 0,
{ size,
for (var k = range.Item1; k < range.Item2; k++) index => Radix2Step(samples, exponentSign, size, index));
{
Radix2Step(samples, exponentSign, size, k);
}
});
} }
} }

27
src/Numerics/IntegralTransforms/Algorithms/DiscreteHartleyTransform.Naive.cs

@ -25,8 +25,7 @@
namespace MathNet.Numerics.IntegralTransforms.Algorithms namespace MathNet.Numerics.IntegralTransforms.Algorithms
{ {
using System; using System;
using System.Collections.Concurrent; using Threading;
using System.Threading.Tasks;
/// <summary> /// <summary>
/// Fast (FHT) Implementation of the Discrete Hartley Transform (DHT). /// Fast (FHT) Implementation of the Discrete Hartley Transform (DHT).
@ -43,22 +42,20 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms
var w0 = Constants.Pi2 / samples.Length; var w0 = Constants.Pi2 / samples.Length;
var spectrum = new double[samples.Length]; var spectrum = new double[samples.Length];
Parallel.ForEach( CommonParallel.For(
Partitioner.Create(0, samples.Length), 0,
(range, loopState) => samples.Length,
index =>
{ {
for (var k = range.Item1; k < range.Item2; k++) var wk = w0 * index;
var sum = 0.0;
for (var n = 0; n < samples.Length; n++)
{ {
var wk = w0 * k; var w = n * wk;
var sum = 0.0; sum += samples[n] * Constants.Sqrt2 * Math.Cos(w - Constants.PiOver4);
for (var n = 0; n < samples.Length; n++)
{
var w = n * wk;
sum += samples[n] * Constants.Sqrt2 * Math.Cos(w - Constants.PiOver4);
}
spectrum[k] = sum;
} }
spectrum[index] = sum;
}); });
return spectrum; return spectrum;

1
src/Numerics/Numerics.csproj

@ -180,6 +180,7 @@
<Compile Include="Statistics\MCMC\RejectionSampler.cs" /> <Compile Include="Statistics\MCMC\RejectionSampler.cs" />
<Compile Include="Statistics\Statistics.cs" /> <Compile Include="Statistics\Statistics.cs" />
<Compile Include="Statistics\MCMC\UnivariateSliceSampler.cs" /> <Compile Include="Statistics\MCMC\UnivariateSliceSampler.cs" />
<Compile Include="Threading\CommonParallel.cs" />
<Compile Include="Trigonometry.cs" /> <Compile Include="Trigonometry.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

147
src/Numerics/Threading/CommonParallel.cs

@ -0,0 +1,147 @@
// <copyright file="CommonParallel.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
// Copyright (c) 2009-2010 Math.NET
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
#if !SILVERLIGHT
using System.Collections.Concurrent;
using System.Threading.Tasks;
#endif
/// <summary>
/// Used to simplify parallel code, particularly between the .NET 4.0 and Silverlight Code.
/// </summary>
internal static class CommonParallel
{
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
/// <param name="fromInclusive">The start index, inclusive.</param>
/// <param name="toExclusive">The end index, exclusive.</param>
/// <param name="body">The body to be invoked for each iteration.</param>
/// <exception cref="ArgumentNullException">The <paramref name="body"/> argument is null.</exception>
/// <exception cref="AggregateException">At least one invocation of the body threw an exception.</exception>
public static void For(int fromInclusive, int toExclusive, Action<int> body)
{
#if SILVERLIGHT
Parallel.For(fromInclusive, toExclusive, body);
#else
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
{
for (var index = fromInclusive; index < toExclusive; index++)
{
body(index);
}
}
else
{
Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive),
new ParallelOptions { MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads },
(range, loopState) =>
{
for (var i = range.Item1; i < range.Item2; i++)
{
body(i);
}
});
}
#endif
}
/// <summary>
/// Aggregates a function over a loop.
/// </summary>
/// <param name="fromInclusive">Starting index of the loop.</param>
/// <param name="toExclusive">Ending index of the loop</param>
/// <param name="body">The function to aggregate.</param>
/// <returns>The sum of the function over the loop.</returns>
public static double Aggregate(int fromInclusive, int toExclusive, Func<int, double> body)
{
var sync = new object();
var sum = 0.0;
#if SILVERLIGHT
Parallel.For(
fromInclusive,
toExclusive,
() => 0.0,
(i, localData) => localData += body(i),
localResult =>
{
lock (sync)
{
sum += localResult;
}
});
#else
if (Control.DisableParallelization || Control.NumberOfParallelWorkerThreads < 2)
{
for (var index = fromInclusive; index < toExclusive; index++)
{
sum += body(index);
}
}
else
{
Parallel.ForEach(
Partitioner.Create(fromInclusive, toExclusive),
new ParallelOptions { MaxDegreeOfParallelism = Control.NumberOfParallelWorkerThreads },
() => 0.0,
(range, loopState, localData) =>
{
for (var i = range.Item1; i < range.Item2; i++)
{
localData += body(i);
}
return localData;
},
localResult =>
{
lock (sync)
{
sum += localResult;
}
});
}
#endif
return sum;
}
/// <summary>
/// Executes each of the provided actions inside a discrete, asynchronous task.
/// </summary>
/// <param name="actions">An array of actions to execute.</param>
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
/// <exception cref="AggregateException">An action threw an exception.</exception>
public static void Invoke(params Action[] actions)
{
Parallel.Invoke(actions);
}
}
}

2
src/Silverlight/Properties/AssemblyInfo.cs

@ -44,4 +44,4 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
[assembly: Guid("7b66646f-f0ee-425d-9065-910d1937a2df")] [assembly: Guid("7b66646f-f0ee-425d-9065-910d1937a2df")]
[assembly: NeutralResourcesLanguage("en")] [assembly: NeutralResourcesLanguage("en")]
[assembly: InternalsVisibleTo("MathNet.Numerics.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100ed2314a577643d859571b8b9307c6ff2670525c4598fbb307e57ea65ebf5d4417284cb3da9181636480b623f4db8cc3c1947244ba069df0df86e2431621f51a488f9929519a1c5d0ae595f6e2d0e4094685f0c1229ff658360acbb9f63f1a0258e984dda00dc7ad4fd16dbb550ec1ef8a11df138402b7c1998ee224e652c839b")] //[assembly: InternalsVisibleTo("MathNet.Numerics.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100ed2314a577643d859571b8b9307c6ff2670525c4598fbb307e57ea65ebf5d4417284cb3da9181636480b623f4db8cc3c1947244ba069df0df86e2431621f51a488f9929519a1c5d0ae595f6e2d0e4094685f0c1229ff658360acbb9f63f1a0258e984dda00dc7ad4fd16dbb550ec1ef8a11df138402b7c1998ee224e652c839b")]

115
src/Silverlight/Silverlight.csproj

@ -1,47 +1,28 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion> <ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0CCA2BA4-9DF2-4E9B-8A77-0A1F61A96A77}</ProjectGuid> <ProjectGuid>{793E332F-E2B1-4D1D-9B2E-27E90B99BF93}</ProjectGuid>
<ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MathNet.Numerics</RootNamespace> <RootNamespace>MathNet.Numerics</RootNamespace>
<AssemblyName>MathNet.Numerics.Silverlight</AssemblyName> <AssemblyName>MathNet.Numerics.Silverlight</AssemblyName>
<TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion>
<SilverlightApplication>false</SilverlightApplication> <SilverlightApplication>false</SilverlightApplication>
<ValidateXaml>true</ValidateXaml> <ValidateXaml>true</ValidateXaml>
<ThrowErrorsInValidation>true</ThrowErrorsInValidation> <ThrowErrorsInValidation>true</ThrowErrorsInValidation>
<SignAssembly>true</SignAssembly> </PropertyGroup>
<AssemblyOriginatorKeyFile>..\MathNet.Numerics.snk</AssemblyOriginatorKeyFile> <!-- This property group is only here to support building this project using the
<TargetFrameworkIdentifier>Silverlight</TargetFrameworkIdentifier> MSBuild 3.5 toolset. In order to work correctly with this older toolset, it needs
<SilverlightVersion>$(TargetFrameworkVersion)</SilverlightVersion> to set the TargetFrameworkVersion to v3.5 -->
<FileUpgradeFlags> <PropertyGroup Condition="'$(MSBuildToolsVersion)' == '3.5'">
</FileUpgradeFlags> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<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>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -53,7 +34,6 @@
<NoConfig>true</NoConfig> <NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
@ -64,12 +44,11 @@
<NoConfig>true</NoConfig> <NoConfig>true</NoConfig>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System.Numerics, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" /> <Reference Include="System.Numerics, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Windows" /> <Reference Include="System.Windows" />
<Reference Include="mscorlib" />
<Reference Include="system" /> <Reference Include="system" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
@ -78,13 +57,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Numerics\Algorithms\LinearAlgebra\ILinearAlgebraProvider.cs"> <Compile Include="..\Numerics\Algorithms\LinearAlgebra\ILinearAlgebraProvider.cs">
<Link>Algorithms\ILinearAlgebraProvider.cs</Link> <Link>Algorithms\LinearAlgebra\ILinearAlgebraProvider.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Algorithms\LinearAlgebra\ILinearAlgebraProviderOfT.cs"> <Compile Include="..\Numerics\Algorithms\LinearAlgebra\ILinearAlgebraProviderOfT.cs">
<Link>Algorithms\ILinearAlgebraProviderOfT.cs</Link> <Link>Algorithms\LinearAlgebra\ILinearAlgebraProviderOfT.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Algorithms\LinearAlgebra\ManagedLinearAlgebraProvider.cs"> <Compile Include="..\Numerics\Algorithms\LinearAlgebra\ManagedLinearAlgebraProvider.cs">
<Link>Algorithms\ManagedLinearAlgebraProvider.cs</Link> <Link>Algorithms\LinearAlgebra\ManagedLinearAlgebraProvider.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Combinatorics.cs"> <Compile Include="..\Numerics\Combinatorics.cs">
<Link>Combinatorics.cs</Link> <Link>Combinatorics.cs</Link>
@ -230,21 +209,6 @@
<Compile Include="..\Numerics\IPrecisionSupport.cs"> <Compile Include="..\Numerics\IPrecisionSupport.cs">
<Link>IPrecisionSupport.cs</Link> <Link>IPrecisionSupport.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\LinearAlgebra\Double\DenseMatrix.cs">
<Link>LinearAlgebra\Double\DenseMatrix.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Double\DenseVector.cs">
<Link>LinearAlgebra\Double\DenseVector.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Double\Matrix.Arithmetic.cs">
<Link>LinearAlgebra\Double\Matrix.Arithmetic.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Double\Matrix.cs">
<Link>LinearAlgebra\Double\Matrix.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Double\Vector.cs">
<Link>LinearAlgebra\Double\Vector.cs</Link>
</Compile>
<Compile Include="..\Numerics\NumberTheory\IntegerTheory.cs"> <Compile Include="..\Numerics\NumberTheory\IntegerTheory.cs">
<Link>NumberTheory\IntegerTheory.cs</Link> <Link>NumberTheory\IntegerTheory.cs</Link>
</Compile> </Compile>
@ -255,7 +219,7 @@
<Link>Precision.cs</Link> <Link>Precision.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Properties\Resources.Designer.cs"> <Compile Include="..\Numerics\Properties\Resources.Designer.cs">
<Link>Properties\Resources.Designer.cs</Link> <Link>Resources.Designer.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Random\AbstractRandomNumberGenerator.cs"> <Compile Include="..\Numerics\Random\AbstractRandomNumberGenerator.cs">
<Link>Random\AbstractRandomNumberGenerator.cs</Link> <Link>Random\AbstractRandomNumberGenerator.cs</Link>
@ -338,49 +302,35 @@
<Compile Include="..\Numerics\Statistics\Statistics.cs"> <Compile Include="..\Numerics\Statistics\Statistics.cs">
<Link>Statistics\Statistics.cs</Link> <Link>Statistics\Statistics.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Threading\CommonParallel.cs">
<Link>Threading\CommonParallel.cs</Link>
</Compile>
<Compile Include="..\Numerics\Trigonometry.cs"> <Compile Include="..\Numerics\Trigonometry.cs">
<Link>Trigonometry.cs</Link> <Link>Trigonometry.cs</Link>
</Compile> </Compile>
<Compile Include="..\Numerics\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Threading\AggregateException.cs" />
<Compile Include="Threading\Parallel.cs" />
<Compile Include="Threading\Task.cs" />
<Compile Include="Threading\TaskOfT.cs" />
<Compile Include="Threading\ThreadQueue.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="..\Numerics\Properties\Resources.resx"> <EmbeddedResource Include="..\Numerics\Properties\Resources.resx">
<Link>Properties\Resources.resx</Link> <Link>Resources.resx</Link>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\MathNet.Numerics.snk"> <None Include="..\Numerics\Version.tt">
<Link>MathNet.Numerics.snk</Link> <Link>Version.tt</Link>
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Version1.cs</LastGenOutput>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
<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>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Silverlight\$(SilverlightVersion)\Microsoft.Silverlight.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>
-->
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}"> <FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
@ -388,4 +338,11 @@
</FlavorProperties> </FlavorProperties>
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<!-- 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> </Project>

65
src/Silverlight/Threading/AggregateException.cs

@ -0,0 +1,65 @@
// <copyright file="AggregateException.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
// Copyright (c) 2009 Math.NET
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
/// <summary>
/// Represents multiple errors that occur during application execution.
/// </summary>
public class AggregateException : Exception
{
/// <summary>
/// List of the aggregated exceptions.
/// </summary>
private readonly IList<Exception> _exceptions = new List<Exception>();
/// <summary>
/// Initializes a new instance of the AggregateException class with a specified error message and references to the inner exceptions that are the cause of this exception.
/// </summary>
/// <param name="exceptions">The exceptions that are the cause of the current exception.</param>
public AggregateException(IEnumerable<Exception> exceptions)
{
foreach (var exception in exceptions)
{
this._exceptions.Add(exception);
}
}
/// <summary>
/// Gets a read-only collection of the Exception instances that caused the current exception.
/// </summary>
/// <value>A read-only collection of the Exception instances that caused the current exception</value>
public ReadOnlyCollection<Exception> InnerExceptions
{
get
{
return new ReadOnlyCollection<Exception>(this._exceptions);
}
}
}
}

485
src/Silverlight/Threading/Parallel.cs

@ -0,0 +1,485 @@
// <copyright file="Parallel.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
using System.Collections.Generic;
using Properties;
/// <summary>
/// Provides support for parallel loops.
/// </summary>
internal static class Parallel
{
/// <summary>
/// The amount to scale the foreach buffer after each iteration.
/// </summary>
private const int ScalingFactor = 2;
/// <summary>
/// The maximum size of the foreach buffer.
/// </summary>
private const int MaxBlockSize = 65536;
/// <summary>
/// The initial size of the for each buffer.
/// </summary>
private const int IntialBlockSize = 1024;
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
/// <param name="fromInclusive">The start index, inclusive.</param>
/// <param name="toExclusive">The end index, exclusive.</param>
/// <param name="body">The body to be invoked for each iteration.</param>
/// <exception cref="ArgumentNullException">The <paramref name="body"/> argument is null.</exception>
/// <exception cref="AggregateException">At least one invocation of the body threw an exception.</exception>
public static void For(int fromInclusive, int toExclusive, Action<int> body)
{
if (body == null)
{
throw new ArgumentNullException("body");
}
// fast forward execution if it's only one or none items
var count = toExclusive - fromInclusive;
if (count <= 1)
{
if (count == 1)
{
body(fromInclusive);
}
return;
}
// fast forward execution in case parallelization is disabled
if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{
for (int i = fromInclusive; i < toExclusive; i++)
{
body(i);
}
return;
}
var actions = new Action[ThreadQueue.ThreadCount];
var size = count / actions.Length;
// partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < actions.Length - 1; i++)
{
var start = fromInclusive + (i * size);
var stop = fromInclusive + ((i + 1) * size);
actions[i] =
() =>
{
for (int j = start; j < stop; j++)
{
body(j);
}
};
}
// add another set for last worker thread
actions[actions.Length - 1] =
() =>
{
for (int i = fromInclusive + ((actions.Length - 1) * size); i < toExclusive; i++)
{
body(i);
}
};
Invoke(actions);
}
/// <summary>
/// Executes a for loop in which iterations may run in parallel.
/// </summary>
/// <typeparam name="T">The type of the thread-local data.</typeparam>
/// <param name="fromInclusive">The start index, inclusive.</param>
/// <param name="toExclusive">The end index, exclusive.</param>
/// <param name="localInit">The function delegate that returns the initial state of the local data for each thread.</param>
/// <param name="body">The delegate that is invoked once per iteration.</param>
/// <param name="localFinally">The delegate that performs a final action on the local state of each thread.</param>
public static void For<T>(int fromInclusive, int toExclusive, Func<T> localInit, Func<int, T, T> body, Action<T> localFinally)
{
var count = toExclusive - fromInclusive;
var tasks = new Task<T>[ThreadQueue.ThreadCount];
var size = count / tasks.Length;
// fast forward execution if it's only one or none items
if (count <= 1)
{
if (count == 1)
{
localFinally(body(fromInclusive, localInit()));
}
return;
}
// fast forward execution in case parallelization is disabled
if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{
var localresult = localInit();
for (var i = fromInclusive; i < toExclusive; i++)
{
localresult = body(i, localresult);
}
localFinally(localresult);
return;
}
// partition the jobs into separate sets for each but the last worked thread
for (var i = 0; i < tasks.Length - 1; i++)
{
var start = fromInclusive + (i * size);
var stop = fromInclusive + ((i + 1) * size);
tasks[i] = new Task<T>(
localData =>
{
var localresult = (T)localData;
for (var j = start; j < stop; j++)
{
localresult = body(j, localresult);
}
return localresult;
},
localInit());
ThreadQueue.Enqueue(tasks[i]);
}
// add another set for last worker thread
tasks[tasks.Length - 1] = new Task<T>(
localData =>
{
var localresult = (T)localData;
for (var i = fromInclusive + ((tasks.Length - 1) * size); i < toExclusive; i++)
{
localresult = body(i, localresult);
}
return localresult;
},
localInit());
ThreadQueue.Enqueue(tasks[tasks.Length - 1]);
if (tasks.Length <= 0)
{
return;
}
WaitForTasksToComplete(tasks);
foreach (var t in tasks)
{
localFinally(t.Result);
}
CollectExceptions(tasks);
}
/// <summary>
/// Executes a for each operation on an IEnumerable{T} in which iterations may run in parallel.
/// </summary>
/// <typeparam name="T">The type of the data in the source.</typeparam>
/// <param name="source">An enumerable data source.</param>
/// <param name="body">The delegate that is invoked once per iteration.</param>
public static void ForEach<T>(IEnumerable<T> source, Action<T> body)
{
if (body == null)
{
throw new ArgumentNullException("body");
}
// fast forward execution in case parallelization is disabled
if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{
foreach (var item in source)
{
body(item);
}
return;
}
// source is a IList, call For instead.
if (source is IList<T>)
{
var list = (IList<T>)source;
For(0, list.Count, i => body(list[i]));
return;
}
var maxBlockSize = IntialBlockSize;
var tasks = new List<Task>();
var enumerator = source.GetEnumerator();
while (enumerator.MoveNext())
{
var pos = 0;
var list = new T[maxBlockSize];
list[pos++] = enumerator.Current;
var count = 1;
while (count < maxBlockSize && enumerator.MoveNext())
{
list[pos++] = enumerator.Current;
count++;
}
var task = new Task(
() =>
{
for (var i = 0; i < pos; i++)
{
body(list[i]);
}
});
ThreadQueue.Enqueue(task);
tasks.Add(task);
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * ScalingFactor);
}
if (tasks.Count > 0)
{
WaitForTasksToComplete(tasks.ToArray());
CollectExceptions(tasks);
}
}
/// <summary>
/// Executes a for each operation on an IEnumerable{TSource in which iterations may run in parallel.
/// </summary>
/// <typeparam name="TSource">The type of the data in the source.</typeparam>
/// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
/// <param name="source">An enumerable data source.</param>
/// <param name="localInit">The function delegate that returns the initial state of the local data for each thread.</param>
/// <param name="body">The delegate that is invoked once per iteration.</param>
/// <param name="localFinally">The delegate that performs a final action on the local state of each thread.</param>
public static void ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit, Func<TSource, TLocal, TLocal> body, Action<TLocal> localFinally)
{
if (body == null)
{
throw new ArgumentNullException("body");
}
// fast forward execution in case parallelization is disabled
if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{
var localResult = localInit();
foreach (var item in source)
{
localResult = body(item, localResult);
}
localFinally(localResult);
return;
}
// source is a IList, call For instead.
if (source is IList<TSource>)
{
var list = (IList<TSource>)source;
For(0, list.Count, localInit, (i, local) => body(list[i], local), localFinally);
return;
}
var maxBlockSize = IntialBlockSize;
var tasks = new List<Task<TLocal>>();
var enumerator = source.GetEnumerator();
while (enumerator.MoveNext())
{
var pos = 0;
var list = new TSource[maxBlockSize];
list[pos++] = enumerator.Current;
var count = 1;
while (count < maxBlockSize && enumerator.MoveNext())
{
list[pos++] = enumerator.Current;
count++;
}
var task = new Task<TLocal>(
localData =>
{
var localresult = localData;
for (var i = 0; i < pos; i++)
{
localresult = body(list[i], (TLocal)localresult);
}
return (TLocal)localresult;
},
localInit());
ThreadQueue.Enqueue(task);
tasks.Add(task);
maxBlockSize = Math.Min(MaxBlockSize, maxBlockSize * ScalingFactor);
}
if (tasks.Count <= 0)
{
return;
}
var taskArray = tasks.ToArray();
WaitForTasksToComplete(taskArray);
for (var i = 0; i < taskArray.Length; i++)
{
localFinally(tasks[i].Result);
}
CollectExceptions(taskArray);
}
/// <summary>
/// Executes each of the provided actions inside a discrete, asynchronous task.
/// </summary>
/// <param name="actions">An array of actions to execute.</param>
/// <exception cref="ArgumentNullException">The <paramref name="actions"/> argument is null.</exception>
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
/// <exception cref="AggregateException">An action threw an exception.</exception>
public static void Run(params Action[] actions)
{
if (actions == null)
{
throw new ArgumentNullException("actions");
}
// fast forward execution if it's only one or none items
if (actions.Length <= 1)
{
if (actions.Length == 1)
{
actions[0]();
}
return;
}
// fast forward execution in case parallelization is disabled
if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{
for (var i = 0; i < actions.Length; i++)
{
actions[i]();
}
return;
}
Invoke(actions);
}
/// <summary>
/// Executes each of the provided actions inside a discrete, asynchronous task.
/// </summary>
/// <param name="actions">An array of actions to execute.</param>
/// <exception cref="ArgumentException">The actions array contains a null element.</exception>
/// <exception cref="AggregateException">An action threw an exception.</exception>
internal static void Invoke(params Action[] actions)
{
// create a job for each action
var tasks = new Task[actions.Length];
for (var i = 0; i < tasks.Length; i++)
{
Action action = actions[i];
if (action == null)
{
throw new ArgumentException(String.Format(Resources.ArgumentItemNull, "actions"), "actions");
}
tasks[i] = new Task(action);
}
// run the jobs
ThreadQueue.Enqueue(tasks);
WaitForTasksToComplete(tasks);
CollectExceptions(tasks);
}
/// <summary>
/// Waits for tasks to complete.
/// </summary>
/// <param name="tasks">The tasks.</param>
private static void WaitForTasksToComplete(Task[] tasks)
{
foreach (var task in tasks)
{
task.Wait();
}
}
/// <summary>
/// Collects the exceptions and dispose tasks.
/// </summary>
/// <param name="tasks">The tasks.</param>
private static void CollectExceptions(IEnumerable<Task> tasks)
{
// collect all thrown exceptions and dispose the jobs
var exceptions = new List<Exception>();
foreach (var task in tasks)
{
if (task.IsFaulted)
{
exceptions.Add(task.Exception);
}
}
// throw the aggregated exceptions, if any
if (exceptions.Count > 0)
{
throw new AggregateException(exceptions);
}
}
}
}

128
src/Silverlight/Threading/Task.cs

@ -0,0 +1,128 @@
// <copyright file="Task.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
using System.Threading;
/// <summary>
/// Internal Parallel Task Handle.
/// </summary>
internal class Task
{
/// <summary>
/// Delegate to the task's action.
/// </summary>
private readonly System.Action _body;
/// <summary>
/// Initializes a new instance of the Task class.
/// </summary>
/// <param name="body">Delegate to the task's action.</param>
public Task(Action body)
{
if (body == null)
{
throw new ArgumentNullException("body");
}
_body = body;
}
/// <summary>
/// Initializes a new instance of the <see cref="Task"/> class.
/// </summary>
protected Task()
{
}
/// <summary>
/// Gets a value indicating whether the task completed due to an unhandled exception.
/// </summary>
/// <value>
/// <c>true</c> if this task completed due to an unhandled exception; otherwise, <c>false</c>.
/// </value>
public bool IsFaulted
{
get { return Exception != null; }
}
/// <summary>
/// Gets a value indicating whether this task has completed.
/// </summary>
/// <value>
/// <c>true</c> if this task has completed; otherwise, <c>false</c>.
/// </value>
public bool IsCompleted
{
get;
private set;
}
/// <summary>
/// Gets or sets the exception thrown by the task, if any.
/// </summary>
public Exception Exception { get; set; }
/// <summary>
/// Run the task.
/// </summary>
public void Compute()
{
try
{
DoCompute();
IsCompleted = true;
}
catch (Exception e)
{
Exception = e;
}
}
/// <summary>
/// Runs the actual task.
/// </summary>
protected virtual void DoCompute()
{
_body();
}
/// <summary>
/// Waits for the task to complete execution.
/// </summary>
public void Wait()
{
while (!IsCompleted && !IsFaulted)
{
Thread.Sleep(0);
}
}
}
}

79
src/Silverlight/Threading/TaskOfT.cs

@ -0,0 +1,79 @@
// <copyright file="TaskOfT.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
/// <summary>
/// Internal Generic Parallel Task Handle.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
internal class Task<TResult> : Task
{
/// <summary>
/// Delegate to the task's action.
/// </summary>
private readonly Func<object, TResult> _body;
/// <summary>
/// Variable used to hold state information between iterations.
/// </summary>
private readonly object _state;
/// <summary>
/// Gets the result of the task.
/// </summary>
/// <value>The result of the task.</value>
public TResult Result { get; private set; }
/// <summary>
/// Initializes a new instance of the Task class.
/// </summary>
/// <param name="body">Delegate to the task's action.</param>
/// <param name="state">An object representing data to be used by the action.</param>
public Task(Func<object, TResult> body, object state)
{
if (body == null)
{
throw new ArgumentNullException("body");
}
_state = state;
_body = body;
}
/// <summary>
/// Runs the actual task.
/// </summary>
protected override void DoCompute()
{
Result = _body(_state);
}
}
}

258
src/Silverlight/Threading/ThreadQueue.cs

@ -0,0 +1,258 @@
// <copyright file="ThreadQueue.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.Threading
{
using System;
using System.Collections.Generic;
using System.Threading;
/// <summary>
/// Internal Parallel Thread Queue.
/// </summary>
internal static class ThreadQueue
{
/// <summary>
/// Sync Object for the thread queue state.
/// </summary>
private static readonly object _stateSync = new object();
/// <summary>
/// Sync Object for queue access (to be sure it's used by us only).
/// </summary>
private static readonly object _queueSync = new object();
/// <summary>
/// Queue holding the pending jobs.
/// </summary>
private static readonly Queue<Task> _queue = new Queue<Task>();
/// <summary>
/// Running flag, used to signal worker threads to stop cleanly.
/// </summary>
private static bool _running = true;
/// <summary>
/// Worker threads
/// </summary>
private static Thread[] _threads;
/// <summary>
/// Gets the number of worker threads.
/// </summary>
internal static int ThreadCount { get; private set; }
/// <summary>
/// Indicating whether the current thread is a parallelized worker thread.
/// </summary>
[ThreadStatic]
private static bool _isInWorkerThread;
/// <summary>
/// Initializes static members of the ThreadQueue class.
/// </summary>
static ThreadQueue()
{
Start(1);
}
/// <summary>
/// Gets a value indicating whether the current thread is a parallelized worker thread.
/// </summary>
public static bool IsInWorkerThread
{
get { return _isInWorkerThread; }
}
/// <summary>
/// Add a job to the queue.
/// </summary>
/// <param name="task">The job to run.</param>
public static void Enqueue(Task task)
{
if (!_running)
{
Start();
}
lock (_queueSync)
{
_queue.Enqueue(task);
Monitor.Pulse(_queueSync);
}
}
/// <summary>
/// Add a set of jobs to the queue.
/// </summary>
/// <param name="tasks">The jobs to run.</param>
public static void Enqueue(IList<Task> tasks)
{
if (!_running)
{
Start();
}
lock (_queueSync)
{
foreach (var task in tasks)
{
_queue.Enqueue(task);
}
Monitor.PulseAll(_queueSync);
}
}
/// <summary>
/// Worker Thread Program
/// </summary>
private static void WorkerThreadStart()
{
_isInWorkerThread = true;
while (_running)
{
// Get the job...
Task task = null;
lock (_queueSync)
{
// Check whether we should shut down
if (!_running)
{
break;
}
if (_queue.Count > 0)
{
task = _queue.Dequeue();
}
else
{
Monitor.Wait(_queueSync);
}
}
if (task == null)
{
continue;
}
// ...and run it
task.Compute();
}
_isInWorkerThread = false;
}
/// <summary>
/// Start or restart the queue with the specified number of worker threads.
/// </summary>
/// <param name="numberOfThreads">Number of worker threads.</param>
public static void Start(int numberOfThreads)
{
lock (_stateSync)
{
// instead of throwing an out of range exception, simply normalize
numberOfThreads = Math.Max(1, Math.Min(1024, numberOfThreads));
if (_threads != null)
{
if (_threads.Length == numberOfThreads)
{
return;
}
Shutdown();
}
ThreadCount = numberOfThreads;
Start();
}
}
/// <summary>
/// Start the thread queue, if it is not already running.
/// </summary>
public static void Start()
{
lock (_stateSync)
{
if (_threads != null)
{
return;
}
_running = true;
_threads = new Thread[ThreadCount];
for (var i = 0; i < _threads.Length; i++)
{
_threads[i] = new Thread(WorkerThreadStart)
{
IsBackground = true
};
_threads[i].Start();
}
}
}
/// <summary>
/// Stop the thread queue, if it is running.
/// </summary>
public static void Shutdown()
{
// try to stop the worker threads cleanly
lock (_stateSync)
{
if (_threads == null)
{
return;
}
_running = false;
lock (_queueSync)
{
Monitor.PulseAll(_queueSync);
}
// wait until all threads have stopped
foreach (var thread in _threads)
{
thread.Join();
}
_threads = null;
}
}
}
}
Loading…
Cancel
Save