init concurrency

This commit is contained in:
Alexander Kozachenko 2024-05-08 22:38:42 +03:00
commit b73cb00e1f
1692 changed files with 431225 additions and 0 deletions

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7DD5E681-8526-470B-8550-8F28A657269D}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Appendix.A</RootNamespace>
<AssemblyName>Appendix.A</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Listings.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Appendix.A
{
public static class Listings
{
public static void HigherOrderFunctios()
{
Func<int, double> fCos = n => Math.Cos((double)n);
double x = fCos(5);
IEnumerable<double> values = Enumerable.Range(1, 10).Select(fCos);
}
public static void HigherOrderFunctiosAndLambda(string path)
{
string text;
using (var stream = new StreamReader(path))
{
text = stream.ReadToEnd();
}
}
public static R Using<T, R>(this T item, Func<T, R> func) where T : IDisposable
{
using (item)
return func(item);
}
public static void HigherOrderFunctiosAndLambdaReusableCode(string path)
{
string text = new StreamReader(path).Using(stream => stream.ReadToEnd());
}
public static void LambdaExpressionWithSameBehavior()
{
Func<int, int, int> add1 = delegate (int x, int y) { return x + y; };
Func<int, int, int> add2 = (int x, int y) => { return x + y; };
Func<int, int, int> add3 = (x, y) => x + y;
}
public static void CurringFunctions()
{
Func<int, int, int> add = (x, y) => x + y;
Func<int, Func<int, int>> curriedAdd = x => y => x + y;
Func<int, int> increament = curriedAdd(1);
int a = increament(30);
int b = increament(41);
Func<int, int> add30 = curriedAdd(30);
int c = add30(12);
}
public static Func<A, Func<B, R>> Curry<A, B, R>(this Func<A, B, R> function)
{
return a => b => function(a, b);
}
public static void CurryingHelperExtenion()
{
Func<int, int, int> add = (x, y) => x + y;
Func<int, Func<int, int>> curriedAdd = add.Curry();
}
public static Func<A, B, R> Uncurry<A, B, R>(Func<A, Func<B, R>> function)
=> (x, y) => function(x)(y);
static Func<B, R> Partial<A, B, R>(this Func<A, B, R> function, A argument)
=> argument2 => function(argument, argument2);
public static void PartiallyAppliedFunctions()
{
Func<int, int, int> add = (x, y) => x + y;
Func<int, int, int> max = Math.Max;
Func<int, int> max5 = max.Partial(5);
int a = max5(8);
int b = max5(2);
int c = max5(12);
}
static string ReadText(string filePath) => File.ReadAllText(filePath);
public static void PartiallyAppliedFunctionExample()
{
string filePath = "TextFile.txt";
Func<string> readText = () => ReadText(filePath);
string text = readText.Retry();
}
public static void PartiallyAppliedExtensionMethodExample(string filePath)
{
Func<string, string> readText = (path) => ReadText(path);
// string text = readText.Retry(); Error!!
// string text = readText(filePath).Retry(); Error!!
string text = readText.Partial("TextFile.txt").Retry();
Func<string, Func<string>> curriedReadText = readText.Curry();
text = curriedReadText("TextFile.txt").Retry();
}
public static Func<R> Partial<T, R>(this Func<T, R> function, T arg)
{
return () => function(arg);
}
public static Func<T, Func<R>> Curry<T, R>(this Func<T, R> function)
{
return arg => () => function(arg);
}
}
public static class PartiallyAppliedRetryFunction
{
public static T Retry<T>(this Func<T> function)
{
int retry = 0;
T result = default(T);
bool success = false;
do
{
try
{
result = function();
success = true;
}
catch
{
retry++;
}
} while (!success && retry < 3);
return result;
}
}
}

View file

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Appendix.A
{
class Program
{
static void Main(string[] args)
{
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 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("Appendix.A")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Appendix.A")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7dd5e681-8526-470b-8550-8f28a657269d")]
// 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 Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,41 @@
namespace FSharp.Tutorial.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
// 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("FSharp.Tutorial")>]
[<assembly: AssemblyDescription("")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("")>]
[<assembly: AssemblyProduct("FSharp.Tutorial")>]
[<assembly: AssemblyCopyright("Copyright © 2018")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[<assembly: ComVisible(false)>]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[<assembly: Guid("41f033c7-f85b-4bd5-af28-66810b0e1110")>]
// 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 Build and Revision Numbers
// by using the '*' as shown below:
// [<assembly: AssemblyVersion("1.0.*")>]
[<assembly: AssemblyVersion("1.0.0.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>41f033c7-f85b-4bd5-af28-66810b0e1110</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>FSharp.Tutorial</RootNamespace>
<AssemblyName>FSharp.Tutorial</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<UseStandardResourceNames>true</UseStandardResourceNames>
<Name>FSharp.Tutorial</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\$(Configuration)\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\$(Configuration)\$(AssemblyName).XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\$(Configuration)\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\$(Configuration)\$(AssemblyName).XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(FSharpTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets') ">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Program.fs" />
<None Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.ValueTuple">
<HintPath>..\..\packages\System.ValueTuple.4.4.0\lib\net47\System.ValueTuple.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,295 @@
open System
// let binding
module binding =
let myInt = 42
let myFloat = 3.14
let myString = "hello functional programming"
let myFunction = fun number -> number * number
// Create mutable types mutable and ref
let mutable myNumber = 42
myNumber <- 51
let myRefVar = ref 42
myRefVar := 53
printfn "%d" !myRefVar
// Functions as first class types
module FunctionFirstClass =
let square x = x * x
let plusOne x = x + 1
let isEven x = x % 2 = 0
// Composition - Pipe and Composition operators
let inline (|>) x f = f x
let inline (>>) f g x = g(f x)
let squarePlusOne x = x |> square |> plusOne
let plusOneIsEven = plusOne >> isEven
// Delegates
module Delegates =
// type delegate typename = delegate of typeA -> typeB
type MyDelegate = delegate of (int * int) -> int
let add (a, b) = a + b
let addDelegate = MyDelegate(add)
let result = addDelegate.Invoke(33, 9)
// Comments
(* This is block comment *)
// Single line comments use a double forward slash
/// This comment can be used to generate documentation.
// Special String definition
module Strings =
let verbatimHtml = @"<input type=\""submit\"" value=\""Submit\"">"
let tripleHTML = """<input type="submit" value="Submit">"""
// Tuple
module Tuple =
let tuple = (1, "Hello")
let tripleTuple = ("one", "two", "three")
let tupleStruct = struct (1, "Hello")
let (a, b) = tuple
let swap (a, b) = (b, a)
let one = fst tuple
let hello = snd tuple
// Record-Types
module RecordTypes =
type Person = { FirstName : string; LastName : string; Age : int }
let fred = { FirstName = "Fred"; LastName = "Flintstone"; Age = 42 }
type Person with
member this.FullName = sprintf "%s %s" this.FirstName this.LastName
let olderFred = { fred with Age = fred.Age + 1 }
[<Struct>]
type Person_Struct = { FirstName : string; LastName : string; Age : int }
// Discriminated Unions
module Discriminated_Unions =
type Suit = Hearts | Clubs | Diamonds | Spades
type Rank =
| Value of int
| Ace
| King
| Queen
| Jack
static member GetAllRanks() =
[ yield Ace
for i in 2 .. 10 do yield Value i
yield Jack
yield Queen
yield King ]
type Card = { Suit:Suit; Rank:Rank }
let fullDeck =
[ for suit in [ Hearts; Diamonds; Clubs; Spades] do
for rank in Rank.GetAllRanks() do
yield { Suit=suit; Rank=rank } ]
// Pattern matching
module Pattern_matching =
let fizzBuzz n =
let divisibleBy m = n % m = 0
match divisibleBy 3,divisibleBy 5 with
| true, false -> "Fizz"
| false, true -> "Buzz"
| true, true -> "FizzBuzz"
| false, false -> sprintf "%d" n
let fizzBuzz' n =
match n with
| _ when (n % 15) = 0 -> "FizzBuzz"
| _ when (n % 3) = 0 -> "Fizz"
| _ when (n % 5) = 0 -> "Buzz"
| _ -> sprintf "%d" n
[1..20] |> List.iter(fun s -> printfn "%s" (fizzBuzz' s))
// Active patterns
let (|DivisibleBy|_|) divideBy n =
if n % divideBy = 0 then Some DivisibleBy else None
let fizzBuzz'' n =
match n with
| DivisibleBy 3 & DivisibleBy 5 -> "FizzBuzz"
| DivisibleBy 3 -> "Fizz"
| DivisibleBy 5 -> "Buzz"
| _ -> sprintf "%d" n
[1..20] |> List.iter(fun s -> printfn "%s" (fizzBuzz'' s))
let (|Fizz|Buzz|FizzBuzz|Val|) n =
match n % 3, n % 5 with
| 0, 0 -> FizzBuzz
| 0, _ -> Fizz
| _, 0 -> Buzz
| _ -> Val n
// Arrays
module Arrays =
let emptyArray1 = Array.empty
let emptyArray2 = [| |]
let arrayOfFiveElements = [| 1; 2; 3; 4; 5 |]
let arrayFromTwoToTen= [| 2..10 |]
let appendTwoArrays = emptyArray1 |> Array.append arrayFromTwoToTen
let evenNumbers = arrayFromTwoToTen |> Array.filter(fun n -> n % 2 = 0)
let squareNumbers = evenNumbers |> Array.map(fun n -> n * n)
let arr = Array.init 10 (fun i -> i * i)
arr.[1] <- 42
arr.[7] <- 91
let arrOfBytes = Array.create 42 0uy
let arrOfSquare = Array.init 42 (fun i -> i * i)
let arrOfIntegers = Array.zeroCreate<int> 42
// Sequences
module Sequences =
let emptySeq = Seq.empty
let seqFromTwoToFive = seq { yield 2; yield 3; yield 4; yield 5 }
let seqOfFiveElements = seq { 1 .. 5 }
let concatenateTwoSeqs = emptySeq |> Seq.append seqOfFiveElements
let oddNumbers = seqFromTwoToFive |> Seq.filter(fun n -> n % 2 <> 0)
let doubleNumbers = oddNumbers |> Seq.map(fun n -> n + n)
// Lists
module Lists =
let emptyList1 = List.empty
let emptyList2 = [ ]
let listOfFiveElements = [ 1; 2; 3; 4; 5 ]
let listFromTwoToTen = [ 2..10 ]
let appendOneToEmptyList = 1::emptyList1
let concatenateTwoLists = listOfFiveElements @ listFromTwoToTen
let evenNumbers = listOfFiveElements |> List.filter(fun n -> n % 2 = 0)
let squareNumbers = evenNumbers |> List.map(fun n -> n * n)
// Sets
module Sets =
let emptySet = Set.empty<int>
let setWithOneItem = emptySet.Add 8
let setFromList = [ 1..10 ] |> Set.ofList
// Maps
module Maps =
let emptyMap = Map.empty<int, string>
let mapWithOneItem = emptyMap.Add(42, "the answer to the meaning of life")
let mapFromList = [ (1, "Hello"), (2, "World") ] |> Map.ofSeq
// Loops
module Loops =
let mutable a = 10
while (a < 20) do
printfn "value of a: %d" a
a <- a + 1
for i = 1 to 10 do
printf "%d " i
for i in [1..10] do
printfn "%d" i
// Class and inheritance
module Class_and_inheritance =
type Person(firstName, lastName, age) =
member this.FirstName = firstName
member this.LastName = lastName
member this.Age = age
member this.UpdateAge(n:int) =
Person(firstName, lastName, age + n)
override this.ToString() =
sprintf "%s %s" firstName lastName
type Student(firstName, lastName, age, grade) =
inherit Person(firstName, lastName, age)
member this.Grade = grade
// Abstract classes and inheritance
module Abstract_class_and_inheritance =
[<AbstractClass>]
type Shape(weight :float, height :float) =
member this.Weight = weight
member this.Height = height
abstract member Area : unit -> float
default this.Area() = weight * height
type Rectangle(weight :float, height :float) =
inherit Shape(weight, height)
type Circle(radius :float) =
inherit Shape(radius, radius)
override this.Area() = radius * radius * Math.PI
// Interfaces
module Interfaces =
type IPerson =
abstract FirstName : string
abstract LastName : string
abstract FullName : unit -> string
type Person(firstName : string, lastName : string) =
interface IPerson with
member this.FirstName = firstName
member this.LastName = lastName
member this.FullName() = sprintf "%s %s" firstName lastName
let fred = Person("Fred", "Flintstone")
(fred :> IPerson).FullName()
|> ignore
// Object expressions
module Object_expressions =
let print color =
let current = Console.ForegroundColor
Console.ForegroundColor <- color
{ new IDisposable with
member x.Dispose() =
Console.ForegroundColor <- current
}
using(print ConsoleColor.Red) (fun _ -> printf "Hello in red!!")
using(print ConsoleColor.Blue) (fun _ -> printf "Hello in blue!!")
// Casting
module Castings =
open Interfaces
let testPersonType (o:obj) =
match o with
| :? IPerson as person -> printfn "this object is an IPerson"
| _ -> printfn "this is not an IPerson"
// Units of Measure
module Measure =
[<Measure>]
type m
[<Measure>]
type sec
let distance = 25.0<m>
let time = 10.0<sec>
let speed = distance / time
[<EntryPoint>]
let main argv =
printfn "%A" argv
0

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1F277609-5767-4E49-B243-35B3139E4B98}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>AsyncInterop.CS</RootNamespace>
<AssemblyName>AsyncInterop.CS</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AsyncInteroperability\AsyncInteroperability.fsproj">
<Project>{9336b874-f0b2-4923-8f4b-a0753b9eb0ba}</Project>
<Name>AsyncInteroperability</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AsyncInterop;
using static AsyncInterop.AsyncInteropDownload;
namespace AsyncInterop.CS
{
class Program
{
static async Task DownloadMediaAsync()
{
var cts = new CancellationToken();
var images = await downloadMediaAsyncParallel("MyMedia").AsTask(cts);
}
static void Main(string[] args)
{
}
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 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("AsyncInterop.CS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AsyncInterop.CS")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1f277609-5767-4e49-b243-35b3139e4b98")]
// 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 Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,41 @@
namespace AsyncInteroperability.AssemblyInfo
open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices
// 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("AsyncInteroperability")>]
[<assembly: AssemblyDescription("")>]
[<assembly: AssemblyConfiguration("")>]
[<assembly: AssemblyCompany("")>]
[<assembly: AssemblyProduct("AsyncInteroperability")>]
[<assembly: AssemblyCopyright("Copyright © 2018")>]
[<assembly: AssemblyTrademark("")>]
[<assembly: AssemblyCulture("")>]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[<assembly: ComVisible(false)>]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[<assembly: Guid("9336b874-f0b2-4923-8f4b-a0753b9eb0ba")>]
// 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 Build and Revision Numbers
// by using the '*' as shown below:
// [<assembly: AssemblyVersion("1.0.*")>]
[<assembly: AssemblyVersion("1.0.0.0")>]
[<assembly: AssemblyFileVersion("1.0.0.0")>]
do
()

View file

@ -0,0 +1,56 @@
namespace AsyncInterop
open System
open System.Threading
open System.Threading.Tasks
open System.Runtime.CompilerServices
module private AsyncInterop =
let asTask(async: Async<'T>, token: CancellationToken option) =
let tcs = TaskCompletionSource<'T>()
let token = defaultArg token Async.DefaultCancellationToken
Async.StartWithContinuations(async,
tcs.SetResult,
tcs.SetException,
tcs.SetException, token)
tcs.Task
let asAsync(task: Task, token: CancellationToken option) =
Async.FromContinuations( //
fun (completed, caught, canceled) ->
let token = defaultArg token Async.DefaultCancellationToken
task.ContinueWith(new Action<Task>(fun _ ->
if task.IsFaulted then caught(task.Exception)
else if task.IsCanceled then
canceled(new OperationCanceledException(token)|>raise)
else completed()), token)
|> ignore)
let asAsyncT(task: Task<'T>, token: CancellationToken option) =
Async.FromContinuations(
fun (completed, caught, canceled) ->
let token = defaultArg token Async.DefaultCancellationToken
task.ContinueWith(new Action<Task<'T>>(fun _ ->
if task.IsFaulted then caught(task.Exception)
else if task.IsCanceled then
canceled(OperationCanceledException(token) |> raise)
else completed(task.Result)), token)
|> ignore)
[<Extension>]
type AsyncInteropExtensions =
[<Extension>]
static member AsAsync (task: Task<'T>) = AsyncInterop.asAsyncT (task, None)
[<Extension>]
static member AsAsync (task: Task<'T>, token: CancellationToken) =
AsyncInterop.asAsyncT (task, Some token)
[<Extension>]
static member AsTask (async: Async<'T>) = AsyncInterop.asTask (async, None)
[<Extension>]
static member AsTask (async: Async<'T>, token: CancellationToken) =
AsyncInterop.asTask (async, Some token)

View file

@ -0,0 +1,30 @@
namespace AsyncInterop
open System
open System.Threading
open System.Threading.Tasks
open System.Runtime.CompilerServices
open AsyncInterop
open Microsoft.WindowsAzure.Storage
open System.IO
module AsyncInteropDownload =
let azureConnection = "< AZURE CONNECTION >"
let downloadMediaAsyncParallel containerName = async {
let storageAccount = CloudStorageAccount.Parse(azureConnection)
let blobClient = storageAccount.CreateCloudBlobClient()
let container = blobClient.GetContainerReference(containerName)
let computations =
container.ListBlobs()
|> Seq.map(fun blobMedia -> async {
let blobName = blobMedia.Uri.Segments.
[blobMedia.Uri.Segments.Length - 1]
let blockBlob = container.GetBlockBlobReference(blobName)
use stream = new MemoryStream()
do! blockBlob.DownloadToStreamAsync(stream) |> Async.AwaitTask
let image = System.Drawing.Bitmap.FromStream(stream)
return image })
return! Async.Parallel computations }

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>9336b874-f0b2-4923-8f4b-a0753b9eb0ba</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>AsyncInteroperability</RootNamespace>
<AssemblyName>AsyncInteroperability</AssemblyName>
<UseStandardResourceNames>true</UseStandardResourceNames>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Name>AsyncInteroperability</Name>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\$(Configuration)\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\$(Configuration)\$(AssemblyName).XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\$(Configuration)\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\$(Configuration)\$(AssemblyName).XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(FSharpTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets') ">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="AsyncInterop,fs.fs" />
<Compile Include="AsyncInteropDownload.fs" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Data.Edm">
<HintPath>..\..\packages\Microsoft.Data.Edm.5.6.0\lib\net40\Microsoft.Data.Edm.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Data.OData">
<HintPath>..\..\packages\Microsoft.Data.OData.5.6.0\lib\net40\Microsoft.Data.OData.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Data.Services.Client">
<HintPath>..\..\packages\Microsoft.Data.Services.Client.5.6.0\lib\net40\Microsoft.Data.Services.Client.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Configuration">
<HintPath>..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Storage">
<HintPath>..\..\packages\WindowsAzure.Storage.4.0.1\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\packages\Newtonsoft.Json.5.0.6\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Numerics" />
<Reference Include="System.Spatial">
<HintPath>..\..\packages\System.Spatial.5.6.0\lib\net40\System.Spatial.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple">
<HintPath>..\..\packages\System.ValueTuple.4.4.0\lib\net47\System.ValueTuple.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
<package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net47" />
<package id="Microsoft.Data.OData" version="5.8.4" targetFramework="net47" />
<package id="Microsoft.Data.Services.Client" version="5.6.0" targetFramework="net47" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.8.0.0" targetFramework="net47" />
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net47" />
<package id="System.Spatial" version="5.6.0" targetFramework="net47" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="net47" />
<package id="WindowsAzure.Storage" version="4.0.1" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
</startup>
</configuration>

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace QuickSort.cs
{
class Program
{
static void Main(string[] args)
{
Random rand = new Random((int) DateTime.Now.Ticks);
int attempts = 5;
int[][] dataSamples =
Enumerable.Range(0, attempts)
.Select(x =>
{
var A = new int[1000000];
for (int i = 0; i < 1000000; ++i)
A[i] = rand.Next();
return A;
}).ToArray();
Func<Action<int[]>, Action[]> run = (sortFunc) =>
dataSamples.Select(data => (Action)(() => sortFunc(data))).ToArray();
var implementations =
new[]
{
new Tuple<String, Action[]>(
"Sequential", run(QuickSort.QuickSort_Sequential)),
new Tuple<String, Action[]>(
"Parallel", run(QuickSort.QuickSort_Parallel)),
new Tuple<String, Action[]>(
"ParallelWithDepth", run(QuickSort.QuickSort_Parallel_Threshold)),
};
Application.Run(
PerfVis.toChart("C# QuickSort")
.Invoke(PerfVis.fromTuples(implementations)));
}
}
}

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QuickSort.cs
{
public class QuickSort
{
public static void QuickSort_Sequential<T>(T[] items) where T : IComparable<T>
=> QuickSort_Sequential(items, 0, items.Length);
private static void QuickSort_Sequential<T>(T[] items, int left, int right) where T : IComparable<T>
{
if (left == right) return;
int pivot = Partition(items, left, right);
QuickSort_Sequential(items, left, pivot);
QuickSort_Sequential(items, pivot + 1, right);
}
private static int Partition<T>(T[] items, int left, int right) where T : IComparable<T>
{
int pivotPos = (right + left) / 2; // often a random index between left and right is used
T pivotValue = items[pivotPos];
Swap(ref items[right - 1], ref items[pivotPos]);
int store = left;
for (int i = left; i < right - 1; ++i)
{
if (items[i].CompareTo(pivotValue) < 0)
{
Swap(ref items[i], ref items[store]);
++store;
}
}
Swap(ref items[right - 1], ref items[store]);
return store;
}
private static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
public static void QuickSort_Parallel<T>(T[] items) where T : IComparable<T>
=> QuickSort_Parallel(items, 0, items.Length);
private static void QuickSort_Parallel<T>(T[] items, int left, int right) where T : IComparable<T>
{
if (right - left < 2)
{
if (left+1 == right &&
items[left].CompareTo(items[right-1]) > 0)
Swap(ref items[left], ref items[right-1]);
return;
}
int pivot = Partition(items, left, right);
Task leftTask = Task.Run(() => QuickSort_Parallel(items, left, pivot));
Task rightTask = Task.Run(() => QuickSort_Parallel(items, pivot + 1, right));
Task.WaitAll(leftTask, rightTask);
}
public static void QuickSort_Parallel_Threshold<T>(T[] items) where T : IComparable<T>
{
int maxDepth = (int) Math.Log(Environment.ProcessorCount, 2.0);
QuickSort_Parallel_Threshold(items, 0, items.Length, maxDepth);
}
private static void QuickSort_Parallel_Threshold<T>(T[] items, int left, int right, int depth) where T : IComparable<T>
{
if (right - left < 2)
{
if (left + 1 == right &&
items[left].CompareTo(items[right-1]) > 0)
Swap(ref items[left], ref items[right-1]);
return;
}
int pivot = Partition(items, left, right);
if (depth >= 0)
{
Parallel.Invoke(
() => QuickSort_Parallel_Threshold(items, left, pivot, depth - 1),
() => QuickSort_Parallel_Threshold(items, pivot + 1, right, depth - 1)
);
}
else
{
QuickSort_Parallel_Threshold(items, left, pivot, depth);
QuickSort_Parallel_Threshold(items, pivot + 1, right, depth);
}
}
}
}

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BB41293F-CA44-4AE9-8198-AB1F2A0D71A5}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>QuickSort.cs</RootNamespace>
<AssemblyName>QuickSort.cs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="QuickSort.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Name>Utilities</Name>
</ProjectReference>
</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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,26 @@
open System
open System.Windows.Forms
[<EntryPoint>]
let main argv =
let rand = Random(int(DateTime.Now.Ticks))
let attempts = 5
let dataSamples =
List.init attempts (fun _ ->
List.init 1000000 (fun i -> rand.Next()))
let run sort =
dataSamples
|> List.map (fun data ->
fun () -> sort data |> ignore
)
[
"Sequential" , run QuickSort.quicksortSequential
"Parallel" , run QuickSort.quicksortParallel
"ParallelWithDepth" , run (QuickSort.quicksortParallelWithDepth QuickSort.ParallelismHelpers.MaxDepth)
]
|> PerfVis.toChart "F# QuickSort"
|> Application.Run
0

View file

@ -0,0 +1,50 @@
module QuickSort
open System
open System.Threading.Tasks
type ParallelismHelpers =
static member MaxDepth =
int (Math.Log(float Environment.ProcessorCount, 2.0))
static member TotalWorkers =
int (2.0 ** float (ParallelismHelpers.MaxDepth))
// Listing 1.1 A simple Quick-sort Algorithm
let rec quicksortSequential aList =
match aList with
| [] -> []
| firstElement :: restOfList ->
let smaller, larger =
List.partition (fun number -> number > firstElement) restOfList
quicksortSequential smaller @ (firstElement :: quicksortSequential larger)
// Listing 1.2 A parallel Quick-Sort Algorithm using the TPL library
let rec quicksortParallel aList =
match aList with
| [] -> []
| firstElement :: restOfList ->
let smaller, larger =
List.partition (fun number -> number > firstElement) restOfList
let left = Task.Run(fun () -> quicksortParallel smaller) // #A
let right = Task.Run(fun () -> quicksortParallel larger) // #A
left.Result @ (firstElement :: right.Result) // #B
// Listing 1.3 A better parallel Quick-Sort Algorithm using the TPL library
let rec quicksortParallelWithDepth depth aList = // #A
match aList with
| [] -> []
| firstElement :: restOfList ->
let smaller, larger =
List.partition (fun number -> number > firstElement) restOfList
if depth < 0 then // #B
let left = quicksortParallelWithDepth depth smaller //#C
let right = quicksortParallelWithDepth depth larger //#C
left @ (firstElement :: right)
else
let left = Task.Run(fun () -> quicksortParallelWithDepth (depth - 1) smaller) // #D
let right = Task.Run(fun () -> quicksortParallelWithDepth (depth - 1) larger) // #D
left.Result @ (firstElement :: right.Result)

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>85d58f6a-d2ee-4b6f-a19a-3f9cc1babf6a</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>QuickSort.fs</RootNamespace>
<AssemblyName>QuickSort.fs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFSharpCoreVersion>4.4.3.0</TargetFSharpCoreVersion>
<Name>QuickSort.fs</Name>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Debug\QuickSort.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Release\QuickSort.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="QuickSort.fs" />
<Compile Include="Program.fs" />
<None Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<Reference Include="System.Windows.Forms" />
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Name>Utilities</Name>
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
</startup>
</configuration>

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
namespace FunctionalTechniques.cs
{
class Closure
{
// Listing 2.5 Closure defined in C# using an anonymous method
public void FreeVariable()
{
string freeVariable = "I am a free variable"; //#A
Func<string, string> lambda = value => freeVariable + " " + value; //#B
}
System.Windows.Controls.Image img;
// Listing 2.6 Event register with lambda expression capturing local variable
void UpdateImage(string url)
{
System.Windows.Controls.Image image = img; //#A
var client = new WebClient();
client.DownloadDataCompleted += (o, e) => //#B
{
if (image != null)
using (var ms = new MemoryStream(e.Result))
{
var imageConverter = new ImageSourceConverter();
image.Source = (ImageSource) imageConverter.ConvertFrom(ms);
}
};
client.DownloadDataAsync(new Uri(url)); //#C
// image = null; //#A from Listing 2.7
}
// Listing 2.8 Closure capturing variables in a multi-threaded environment
public void Closure_Strange_Behavior()
{
int iterations = 10;
for (int i = 1; i <= iterations; i++)
{
Task.Factory.StartNew(() =>
Console.WriteLine("{0} - {1}", Thread.CurrentThread.ManagedThreadId, i));
}
}
public void Closure_Correct_Behavior()
{
int iterations = 10;
for (int i = 1; i <= iterations; i++)
{
var index = i;
Task.Factory.StartNew(() =>
Console.WriteLine("{0} - {1}", Thread.CurrentThread.ManagedThreadId, index));
}
}
// Listing 2.9 Function to calculate the area of a triangle
void CalcluateAreaFunction()
{
Action<int> displayNumber = n => Console.WriteLine(n);
int i = 5;
Task taskOne = Task.Factory.StartNew(() => displayNumber(i));
i = 7;
Task taskTwo = Task.Factory.StartNew(() => displayNumber(i));
Task.WaitAll(taskOne, taskTwo);
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunctionalTechniques.cs
{
static class Composition
{
// Listing 2.3 Compose function in C#
static Func<A, C> Compose<A, B, C>(this Func<A, B> f, Func<B, C> g) => (n) => g(f(n));
}
}

View file

@ -0,0 +1,101 @@
using FuzzyMatch;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace FunctionalTechniques.cs
{
struct Temperature
{
Temperature(float temperature)
{
Temp = temperature;
}
public float Temp { get; }
}
class ConcurrentSpeculation
{
// Listing 2.22 A fuzzy match
public static string FuzzyMatch(List<string> words, string word)
{
var wordSet = new HashSet<string>(words); //#A
string bestMatch =
(from w in wordSet.AsParallel() //#B
select JaroWinklerModule.Match(w, word))
.OrderByDescending(w => w.Distance)
.Select(w => w.Word)
.FirstOrDefault();
return bestMatch; //#C
}
// Listing 2.23 Fast Fuzzy Match using precomputation
public static Func<string, string> PartialFuzzyMatch(List<string> words) //#A
{
var wordSet = new HashSet<string>(words); //#B
return word =>
(from w in wordSet.AsParallel()
select JaroWinklerModule.Match(w, word))
.OrderByDescending(w => w.Distance)
.Select(w => w.Word)
.FirstOrDefault(); //#C
}
public static void FuzzyMatchDemo()
{
List<string> words =
System.IO.File
.ReadAllLines("google-10000-english/google-10000-english.txt")
.Where(x=>
!(x.Equals("magic", StringComparison.InvariantCultureIgnoreCase)) &&
!(x.Equals("light", StringComparison.InvariantCultureIgnoreCase)))
.ToList();
// Listing 2.22 A fuzzy match
Demo.Benchmark("Listing 2.22 A fuzzy match", () =>
{
string fuzzyMatch = ConcurrentSpeculation.FuzzyMatch(words, "magic"); //#D
Console.WriteLine($"FuzzyMatch for 'magic' = {fuzzyMatch}");
});
Demo.Benchmark("Listing 2.23 Fast Fuzzy Match using precomputation", () =>
{
Func<string, string> fastFuzzyMatch = PartialFuzzyMatch(words); //#D
string magicFuzzyMatch = fastFuzzyMatch("magic");
string lightFuzzyMatch = fastFuzzyMatch("light"); //#E
Console.WriteLine($"FastFuzzyMatch for 'magic' = {magicFuzzyMatch}");
Console.WriteLine($"FastFuzzyMatch for 'light' = {lightFuzzyMatch}");
});
}
// Listing 2.25 Fastest weather task
public Temperature SpeculativeTempCityQuery(string city, params Uri[] weatherServices)
{
var cts = new CancellationTokenSource(); //#A
var tasks =
(from uri in weatherServices
select Task.Factory.StartNew<Temperature>(() =>
queryService(uri, city), cts.Token)).ToArray(); //#B
int taskIndex = Task.WaitAny(tasks); //#C
Temperature tempCity = tasks[taskIndex].Result;
cts.Cancel(); //#D
return tempCity;
}
private Temperature queryService(Uri uri, string city)
{
throw new NotImplementedException();
}
}
}

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{22D90FF3-0F4D-468B-ABA1-1CD6A82D16DA}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FunctionalTechniques.cs</RootNamespace>
<AssemblyName>FunctionalTechniques.cs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Common\Functional.cs\Memoize.cs">
<Link>Memoize.cs</Link>
</Compile>
<Compile Include="Closure.cs" />
<Compile Include="Composition.cs" />
<Compile Include="Laziness.cs" />
<Compile Include="Program.cs" />
<Compile Include="ConcurrentSpeculation.cs" />
<Compile Include="WeakMemoization.cs" />
<Compile Include="WebCrawler.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="google-10000-english\LICENSE.md" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Name>Utilities</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Content Include="google-10000-english\google-10000-english.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</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>

View file

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FunctionalTechniques.cs
{
// Listing 2.26 Lazy initialization of the Person object
public class Person //#A
{
public readonly string FullName; //#B
public Person(string firstName, string lastName)
{
FullName = firstName + " " + lastName;
Console.WriteLine(FullName);
}
public static void RunDemo()
{
Console.WriteLine("Listing 2.26 Lazy initialization of the Person object");
Lazy<Person> fredFlintstone =
new Lazy<Person>(() => new Person("Fred", "Flintstone"), true); //#B
Person[] freds = new Person[5]; //#C
for (int i = 0; i < freds.Length; i++) //#D
{
freds[i] = fredFlintstone.Value; //#E
}
}
}
// Listing 2.27 Singleton pattern using Lazy<T>
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton(), true); //#A
public static Singleton Instance => lazy.Value;
private Singleton()
{ }
}
class Laziness
{
static string cmdText = null;
static SqlConnection conn = null;
// Listing 2.29 Lazy asynchronous operation to initialize the Person object
Lazy<Task<Person>> person =
new Lazy<Task<Person>>(async () => // #A
{
using (var cmd = new SqlCommand(cmdText, conn))
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
string firstName = reader["first_name"].ToString();
string lastName = reader["last_name"].ToString();
return new Person(firstName, lastName);
}
}
throw new Exception("Failed to fetch Person");
});
async Task<Person> FetchPerson()
{
return await person.Value; // #B
}
}
}

View file

@ -0,0 +1,52 @@
using System;
namespace FunctionalTechniques.cs
{
class Program
{
// Listing 2.14 Greeting example in C#
public static string Greeting(string name)
{
return $"Warm greetings {name}, the time is {DateTime.Now.ToString("hh:mm:ss")}";
}
public static void RunDemoMemoization()
{
Console.WriteLine("Listing 2.14 Greeting example in C#");
Console.WriteLine(Greeting("Richard"));
System.Threading.Thread.Sleep(2000);
Console.WriteLine(Greeting("Paul"));
System.Threading.Thread.Sleep(2000);
Console.WriteLine(Greeting("Richard"));
Console.WriteLine("\nListing 2.15 Greeting example using memoized function");
var greetingMemoize = Memoization.Memoize<string, string>(Greeting); //#A
Console.WriteLine(greetingMemoize("Richard")); //#B
System.Threading.Thread.Sleep(2000);
Console.WriteLine(greetingMemoize("Paul"));
System.Threading.Thread.Sleep(2000);
Console.WriteLine(greetingMemoize("Richard")); //#B
}
static void Main(string[] args)
{
Closure closure = new Closure();
closure.Closure_Strange_Behavior();
Demo.PrintSeparator();
closure.Closure_Correct_Behavior();
Demo.PrintSeparator();
RunDemoMemoization();
Demo.PrintSeparator();
WebCrawlerExample.RunDemo();
Demo.PrintSeparator();
ConcurrentSpeculation.FuzzyMatchDemo();
Demo.PrintSeparator();
Person.RunDemo();
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace FunctionalTechniques.cs
{
public static partial class Memoization
{
public static Func<T, R> MemoizeWeakWithTtl<T, R>(Func<T, R> func, TimeSpan ttl)
where T : class, IEquatable<T>
where R : class
{
var keyStore = new ConcurrentDictionary<int, T>();
T ReduceKey(T obj)
{
var oldObj = keyStore.GetOrAdd(obj.GetHashCode(), obj);
return obj.Equals(oldObj) ? oldObj : obj;
}
var cache = new ConditionalWeakTable<T, Tuple<R, DateTime>>();
Tuple<R, DateTime> FactoryFunc(T key) =>
new Tuple<R, DateTime>(func(key), DateTime.Now + ttl);
return arg =>
{
var key = ReduceKey(arg);
var value = cache.GetValue(key, FactoryFunc);
if (value.Item2 >= DateTime.Now)
return value.Item1;
value = FactoryFunc(key);
cache.Remove(key);
cache.Add(key, value);
return value.Item1;
};
}
public static void Example()
{
string Greeting(String name)
{
return $"Warm greetings {name}, the time is {DateTime.Now:hh:mm:ss}";
}
var greetingMemoize = MemoizeWeakWithTtl<string, string>(Greeting, TimeSpan.FromDays(1.0));
Console.WriteLine(greetingMemoize("Richard"));
System.Threading.Thread.Sleep(1500);
Console.WriteLine(greetingMemoize("_Richard".Substring(1)));
}
}
}

View file

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace FunctionalTechniques.cs
{
// Listing 2.16 Web crawler in C#
public class WebCrawlerExample
{
// Listing 2.18 Web crawler execution using memoization
// Listing 2.18 Web crawler execution using memoization
public static Func<string, IEnumerable<string>> WebCrawlerMemoized =
Memoization.Memoize<string, IEnumerable<string>>(WebCrawler); // #A
// Listing 2.20 Thread-safe memoization function
public static Func<string, IEnumerable<string>> WebCrawlerMemoizedThreadSafe =
Memoization.MemoizeThreadSafe<string, IEnumerable<string>>(WebCrawler);
public static IEnumerable<string> WebCrawler(string url) //#A
{
IEnumerable<string> WebCrawler(string webUrl)
{
var content = GetWebContent(webUrl);
yield return content;
foreach (var item in AnalyzeHtmlContent(content))
yield return GetWebContent(item);
}
return WebCrawler(url).ToList();
}
private static string GetWebContent(string url)
{
using (var wc = new WebClient())
return wc.DownloadString(new Uri(url));
}
private static readonly Regex regexLink = new Regex(@"(?<=href=('|""))https?://.*?(?=\1)");
private static IEnumerable<string> AnalyzeHtmlContent(string text)
{
foreach (var url in regexLink.Matches(text))
yield return url.ToString();
}
private static readonly Regex regexTitle = new Regex("<title>(?<title>.*?)<\\/title>", RegexOptions.Compiled);
public static string ExtractWebPageTitle(string textPage) //#D
{
if (regexTitle.IsMatch(textPage))
return regexTitle.Match(textPage).Groups["title"].Value;
return "No Page Title Found!";
}
public static void RunDemo()
{
List<string> urls = new List<string>
{
//#A
@"http://www.google.com",
@"http://www.microsoft.com",
@"http://www.bing.com",
@"http://www.google.com"
};
Demo.Benchmark("Listing 2.17 Web crawler execution", () =>
{
var webPageTitles = from url in urls //#B
from pageContent in WebCrawler(url)
select ExtractWebPageTitle(pageContent);
Console.WriteLine($"Crawled {webPageTitles.Count()} page titles");
});
Demo.Benchmark("Listing 2.18 Web crawler execution using memoization", () =>
{
var webPageTitles = from url in urls //#B
from pageContent in WebCrawlerMemoized(url)
select ExtractWebPageTitle(pageContent);
Console.WriteLine($"Crawled {webPageTitles.Count()} page titles");
});
Demo.Benchmark("Listing 2.19 Web crawler query using PLINQ", () =>
{
var webPageTitles = from url in urls.AsParallel() //#A
from pageContent in WebCrawlerMemoized(url)
select ExtractWebPageTitle(pageContent);
Console.WriteLine($"Crawled {webPageTitles.Count()} page titles");
});
Demo.Benchmark("Listing 2.20 Thread-safe memoization function", () =>
{
var webPageTitles = from url in urls.AsParallel()
from pageContent in WebCrawlerMemoizedThreadSafe(url) //#B
select ExtractWebPageTitle(pageContent); //#C
Console.WriteLine($"Crawled {webPageTitles.Count()} page titles");
});
}
}
}

View file

@ -0,0 +1,3 @@
Downloaded from https://github.com/first20hours/google-10000-english
Data files are derived from the *Google Web Trillion Word Corpus*, as described by [Thorsten Brants and Alex Franz](http://googleresearch.blogspot.com/2006/08/all-our-n-gram-are-belong-to-you.html), and distributed by the [Linguistic Data Consortium](http://www.ldc.upenn.edu/Catalog/CatalogEntry.jsp?catalogId=LDC2006T13). Subsets of this corpus distributed by [Peter Novig](http://norvig.com/ngrams/). Corpus editing and cleanup by Josh Kaufman.

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,77 @@
module FunctionalTechniques
open System
open System.Threading.Tasks
open System.Collections.Generic
open System.Collections.Concurrent
open FSharp.Collections.ParallelSeq
open FuzzyMatch
open System.Linq
// Listing 2.4 F# support for function composition
module Composition =
let add4 x = x + 4 //#A
let multiplyBy3 x = x * 3 //#B
let list = [0..10] //#C
let newList = List.map(fun x -> multiplyBy3(add4(x))) list //#D
let newList' = list |> List.map(add4 >> multiplyBy3) //#E
// Listing 2.10 Closure capturing variables in a multithreaded environment in F#
module Closure =
let tasks = Array.zeroCreate<Task> 10
for index = 1 to 10 do
tasks.[index - 1] <- Task.Factory.StartNew(fun () -> Console.WriteLine index)
module Memoization =
// Listing 2.13 Memoize function in F#
let memoize func =
let table = Dictionary<_,_>()
fun x -> if table.ContainsKey(x) then table.[x]
else
let result = func x
table.[x] <- result
result
let memoizeThreadSafe (func: 'a -> 'b) =
let table = ConcurrentDictionary<'a,'b>()
fun x -> table.GetOrAdd(x, func)
module ConsurrentSpeculation =
// Listing 2.24 Fast fuzzy match in F#
let fuzzyMatch (words:string list) =
let wordSet = new HashSet<string>(words) //#A
let partialFuzzyMatch word = //#B
query { for w in wordSet.AsParallel() do
select (JaroWinkler.getMatch w word) }
|> Seq.sortBy(fun x -> -x.Distance)
|> Seq.head
fun word -> partialFuzzyMatch word //#C
let words = [] // TODO: Fill the list
let fastFuzzyMatch = fuzzyMatch words //#D
let magicFuzzyMatch = fastFuzzyMatch "magic"
let lightFuzzyMatch = fastFuzzyMatch "light”" //#E
let fuzzyMatchPSeq (words:string list) =
let wordSet = new HashSet<string>(words)
fun word ->
wordSet
|> PSeq.map(fun w -> JaroWinkler.bestMatch word w)
|> PSeq.sortBy(fun x -> -x.Distance)
|> Seq.head
module Laziness =
open FunctionalTechniques.cs
// Listing 2.28 Lazy initialization of the Person object with F#
let barneyRubble = lazy( Person("barney", "rubble") ) //#A
printfn "%s" (barneyRubble.Force().FullName) //#B

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>224cf699-2662-4159-a0e8-ec40324e6d04</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>FunctionalTechniques.fs</RootNamespace>
<AssemblyName>FunctionalTechniques.fs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFSharpCoreVersion>4.4.3.0</TargetFSharpCoreVersion>
<Name>FunctionalTechniques.fs</Name>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Debug\FunctionalTechniques.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Release\FunctionalTechniques.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="FunctionalTechniques.fs" />
<None Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Name>Utilities</Name>
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\FunctionalTechniques.cs\FunctionalTechniques.cs.csproj">
<Name>FunctionalTechniques.cs</Name>
<Project>{22d90ff3-0f4d-468b-aba1-1cd6a82d16da}</Project>
<Private>True</Private>
</ProjectReference>
<Reference Include="FSharp.Collections.ParallelSeq">
<HintPath>..\..\packages\FSharp.Collections.ParallelSeq.1.0.2\lib\net40\FSharp.Collections.ParallelSeq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Collections.ParallelSeq" version="1.0.2" targetFramework="net46" />
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PersistentDataStructures
{
// Listing 3.16 Immutable B-tree representation in C#
public class BinaryTree<T>
{
public BinaryTree(T value, BinaryTree<T> left, BinaryTree<T> right)
{
Value = value;
Left = left;
Right = right;
}
public T Value { get; }
public BinaryTree<T> Left { get; }
public BinaryTree<T> Right { get; }
}
public static class BinaryTreeExtension
{
// Listing 3.17 B-tree helper recursive functions
public static bool Contains<T>(this BinaryTree<T> tree, T value)
{
if (tree == null) return false;
var compare = Comparer<T>.Default.Compare(value, tree.Value);
if (compare == 0) return true;
if (compare < 0)
return tree.Left != null && tree.Left.Contains(value);
return tree.Right != null && tree.Right.Contains(value);
}
public static BinaryTree<T> Insert<T>(this BinaryTree<T> tree, T value)
{
if (tree == null)
return new BinaryTree<T>(value, null, null);
var compare = Comparer<T>.Default.Compare(value, tree.Value);
if (compare == 0) return tree;
if (compare < 0)
return new BinaryTree<T>(tree.Value,
tree.Left.Insert(value), tree.Right);
return new BinaryTree<T>(tree.Value,
tree.Left, tree.Right.Insert(value));
}
// Listing 3.18 In-Order navigation function
public static void InOrder<T>(this BinaryTree<T> tree, Action<T> action)
{
if (tree == null)
return;
tree.Left.InOrder(action);
action(tree.Value);
tree.Right.InOrder(action);
}
}
}

View file

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PersistentDataStructures
{
// Listing 3.14 A functional list in C#
public sealed class FList<T>
{
private FList(T head, FList<T> tail)//#A
{
Head = head;
Tail = tail.IsEmpty
? FList<T>.Empty : tail;
IsEmpty = false;
}
private FList() { //#B
IsEmpty = true;
}
public T Head { get; } //#C
public FList<T> Tail { get; } //#D
public bool IsEmpty { get; } //#E
public static FList<T> Cons(T head, FList<T> tail) //#F
{
return tail.IsEmpty
? new FList<T>(head, Empty)
: new FList<T>(head, tail);
}
public FList<T> Cons(T element) //#G
{
return FList<T>.Cons(element, this);
}
public static readonly FList<T> Empty = new FList<T>(); //#H
}
public static class FListExtensions
{
public static FList<TOut> Select<TIn,TOut>
(this FList<TIn> list, Func<TIn, TOut> selector)
{
return list.IsEmpty
? FList<TOut>.Empty
: list.Tail.Select<TIn, TOut>(selector).Cons(selector(list.Head));
}
public static FList<T> Where<T>
(this FList<T> list, Func<T, bool> predicate)
{
if (list.IsEmpty) return list;
var newTail = list.Tail.Where(predicate);
return predicate(list.Head)
? newTail.Cons(list.Head)
: newTail;
}
}
}

View file

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8FB29F53-63C2-44B7-BC08-49A24A055E06}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PersistentDataStructures</RootNamespace>
<AssemblyName>PersistentDataStructures</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Collections.Immutable.1.3.1\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Common\Functional.cs\Concurrency\Atom.cs">
<Link>Atom.cs</Link>
</Compile>
<Compile Include="BinaryTree.cs" />
<Compile Include="FList.cs" />
<Compile Include="LazyList.cs" />
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Functional.cs\Functional.cs.csproj">
<Project>{24d84c19-b173-4635-91a6-42328bc694ce}</Project>
<Name>Functional.cs</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Name>Utilities</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</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>
-->
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')" />
</Choose>
<Choose>
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2' Or $(TargetFrameworkVersion) == 'v4.6.3')">
<ItemGroup>
<Reference Include="System.Collections.Immutable">
<HintPath>..\..\..\packages\System.Collections.Immutable\lib\netstandard1.0\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
<Paket>True</Paket>
</Reference>
</ItemGroup>
</When>
</Choose>
</Project>

View file

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PersistentDataStructures
{
// Listing 3.15 Lazy list implementation using C#
public sealed class LazyList<T>
{
public LazyList(T head, Lazy<LazyList<T>> tail)
{
Head = head;
Tail = tail;
IsEmpty = false;
}
private LazyList()
{
IsEmpty = true;
}
public T Head { get; }
public Lazy<LazyList<T>> Tail { get; }
public bool IsEmpty { get; }
public static readonly Lazy<LazyList<T>> Empty =
new Lazy<LazyList<T>>(() => new LazyList<T>());
}
public static class LazyListExtensions
{
public static LazyList<T> Append<T>
(this LazyList<T> list, LazyList<T> items)
{
if (items.IsEmpty) return list;
return new LazyList<T>(items.Head,
new Lazy<LazyList<T>>(() =>
list.Append(items.Tail.Value)));
}
public static void Iterate<T>
(this LazyList<T> list, Action<T> action)
{
if (list.IsEmpty)
return;
action(list.Head);
list.Tail.Value.Iterate(action);
}
}
}

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Immutable;
namespace PersistentDataStructures
{
class Program
{
// Listing 3.1 SignalR hub in C# that registers connections in context
class Listing31
{
static ConcurrentDictionary<Guid, string> onlineUsers = new ConcurrentDictionary<Guid, string>(); //#A
// public override Task OnConnected()
// {
// string connectionId = new Guid(Context.ConnectionId); //#B
// System.Security.Principal.IPrincipal user = Context.User;
// string userName;
// if (!onlineUsers.TryGetValue(connectionId, out userName))
// { //#C
// RegisterUserConnection(connectionId, user.Identity.Name);
// onlineUsers.Add(connectionId, user.Identity.Name); //#D
// }
// return base.OnConnected();
// }
// public override Task OnDisconnected()
// {
// string connectionId = new Guid(Context.ConnectionId);
// string userName;
// if (onlineUsers.TryGetValue(connectionId, out userName))
// { //#C
// DeregisterUserConnection(connectionId, userName);
// onlineUsers.Remove(connectionId); //#D
// }
// return base.OnDisconnected();
}
static void Main(string[] args)
{
// Listing 3.2 Constructing BCL immutable collections
var list = ImmutableList.Create<int>(); //#A
list = list.Add(1); //#B
list = list.Add(2);
list = list.Add(3);
var builder = ImmutableList.CreateBuilder<int>(); //#C
builder.Add(1); //#D
builder.Add(2);
builder.Add(3);
list = builder.ToImmutable(); //#E
// Listing 3.14 A functional list in C#
FList<int> list1 = FList<int>.Empty;
FList<int> list2 = list1.Cons(1).Cons(2).Cons(3);
FList<int> list3 = FList<int>.Cons(1, FList<int>.Empty);
FList<int> list4 = list2.Cons(2).Cons(3);
Demo.PrintSeparator();
Console.WriteLine("Listing 3.15 Lazy list implementation");
var lazyList1 =
new LazyList<int>(42, new Lazy<LazyList<int>>(()=>
new LazyList<int>(21, LazyList<int>.Empty)));
var lazyList =
lazyList1.Append(
new LazyList<int>(3, LazyList<int>.Empty));
lazyList.Iterate(Console.WriteLine);
Demo.PrintSeparator();
Console.WriteLine("Listing 3.16 Immutable B-tree representation");
var tree =
new BinaryTree<int>(20,
new BinaryTree<int>(9,
new BinaryTree<int>(4,
new BinaryTree<int>(2, null, null),
null),
new BinaryTree<int>(10, null, null)),
null);
var exist9 = tree.Contains(9);
Console.WriteLine($"Tree contains 9 : {exist9}");
var tree21 = tree.Insert(21);
var exist21 = tree21.Contains(21);
Console.WriteLine($"Tree21 contains 21 : {exist21}\n");
tree.InOrder(Console.WriteLine);
Console.ReadLine();
}
}
}

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Linq" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.Collections.Immutable" version="1.3.1" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,26 @@
module Atom
open System.Threading
let eq a b = obj.ReferenceEquals(a,b)
let neq a b = eq a b |> not
type Atom<'T when 'T : not struct>(value : 'T) =
let cell = ref value
let spinner = lazy (new SpinWait())
let rec swap f =
let tempValue = !cell
if Interlocked.CompareExchange<'T>(cell, f tempValue, tempValue) |> neq tempValue then
spinner.Value.SpinOnce()
swap f
member x.Value with get() = !cell
member x.Swap (f : 'T -> 'T) = swap f
[<RequireQualifiedAccess>]
module Atom =
let atom value = new Atom<_>(value)
let swap (atom : Atom<_>) (f : _ -> _) = atom.Swap f

View file

@ -0,0 +1,46 @@
module BTree
// Listing 3.16 Immutable B-tree representation in F#
type Tree<'a> = //#A
| Empty //#B
| Node of leaf:'a * left:Tree<'a> * right:Tree<'a> //#C
let tree = //#D
Node (20,
Node (9, Node (4, Node (2, Empty, Empty), Empty),
Node (10, Empty, Empty)),
Empty)
// Listing 3.17 B-tree helper recursive functions
let rec contains item tree = //#A
match tree with
| Empty -> false
| Node(leaf, left, right) ->
if leaf = item then true
elif item < leaf then contains item left
else contains item right
let rec insert item tree = //#A
match tree with
| Empty -> Node(item, Empty, Empty)
| Node(leaf, left, right) as node ->
if leaf = item then node
elif item < leaf then Node(leaf, insert item left, right)
else Node(leaf, left, insert item right)
let ``exist 9`` = tree |> contains 9
let ``tree 21`` = tree |> insert 21
let ``exist 21`` = ``tree 21`` |> contains 21
// Listing 3.18 In-Order navigation function
let rec inorder action tree = //#A
seq {
match tree with
| Node(leaf, left, right) ->
yield! inorder action left
yield action leaf
yield! inorder action right
| Empty -> ()
}
tree |> inorder (fun n -> printfn "%d" n) |> ignore //#B

View file

@ -0,0 +1,19 @@
module FList
// Listing 3.13 Representation of a list in F# using discriminated unions
type FList<'a> =
| Empty //#A
| Cons of head:'a * tail:FList<'a> //#B
let rec map f (list:FList<'a>) = //#C
match list with
| Empty -> Empty
| Cons(hd,tl) -> Cons(f hd, map f tl)
let rec filter p (list:FList<'a>) =
match list with
| Empty -> Empty
| Cons(hd,tl) when p hd = true -> Cons(hd, filter p tl)
| Cons(hd,tl) -> filter p tl
let list = Cons(5, Cons(4, Cons(3, Empty)))

View file

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>832224d4-d636-430f-ab7f-fcb02603be51</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DataStructures</RootNamespace>
<AssemblyName>DataStructures</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFSharpCoreVersion>4.4.3.0</TargetFSharpCoreVersion>
<Name>FunctionalDataStructures.fs</Name>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Debug\DataStructures.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Release\DataStructures.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="Atom.fs" />
<Compile Include="FList.fs" />
<Compile Include="LazyList.fs" />
<Compile Include="BTree.fs" />
<Compile Include="ParallelDownloadImages.fs" />
<Compile Include="WeakMemoization.fs" />
<Compile Include="TCO_CPS.fs" />
<Compile Include="ParallelCalculator.fs" />
<None Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
<ProjectReference Include="..\..\Chapter.02\FunctionalTechniques.cs\FunctionalTechniques.cs.csproj">
<Name>FunctionalTechniques.cs</Name>
<Project>{22d90ff3-0f4d-468b-aba1-1cd6a82d16da}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,29 @@
module LazyList
// Listing 3.15 Lazy list implementation using F#
type LazyList<'a> =
| Cons of head:'a * tail:Lazy<'a LazyList> //#A
| Empty
let empty = lazy(Empty) //#B
let rec append items list = //#C
match items with
| Cons(head, Lazy(tail)) ->
Cons(head, lazy(append tail list)) //#D
| Empty -> list
let list1 = Cons(42, lazy(Cons(21, empty))) //#E
// val list1: LazyList<int> = Cons (42,Value is not created.)
let list = append (Cons(3, empty)) list1 //#F
// val list : LazyList<int> = Cons (3,Value is not created.)
let rec iter action list = //#G
match list with
| Cons(head, Lazy(tail)) ->
action(head)
iter action tail
| Empty -> ()
list |> iter (printf "%d .. ") //#H
// 3 .. 42 .. 21 ..

View file

@ -0,0 +1,37 @@
module ParallelCalculator
open System.Threading.Tasks
// Listing 3.23 Parallel Calculator
type Operation = Add | Sub | Mul | Div | Pow
and Calculator =
| Value of double
| Expr of Operation * Calculator * Calculator
let spawn (op:unit->double) = Task.Run(op) //#A
let rec eval expr =
match expr with //#B
| Value(value) -> value //#C
| Expr(op, lExpr, rExpr) -> //#D
let op1 = spawn(fun () -> eval lExpr) //#E
let op2 = spawn(fun () -> eval rExpr) //#E
let apply = Task.WhenAll([op1;op2]) //#F
let lRes, rRes = apply.Result.[0], apply.Result.[1]
match op with //#G
| Add -> lRes + rRes
| Sub -> lRes - rRes
| Mul -> lRes * rRes
| Div -> lRes / rRes
| Pow -> System.Math.Pow(lRes, rRes)
let operations = // 2^10 / 2^9 + 2*2
Expr(Add,
Expr(Div,
Expr(Pow, Value(2.0), Value(10.0)),
Expr(Pow, Value(2.0), Value(9.0))),
Expr(Mul, Value(2.0), Value(2.0)))
let value = eval operations

View file

@ -0,0 +1,32 @@
module ParallelDownloadImages
open BTree
open FunctionalTechniques.cs
open System
open System.IO
open System.Threading.Tasks
//Listing 3.22 Parallel recursive divide-and-conquer function
let maxDepth = int <| Math.Log(float System.Environment.ProcessorCount, 2.)+4. //#A
let webSites : Tree<string> =
WebCrawlerExample.WebCrawler("http://www.foxnews.com")
|> Seq.fold(fun tree site -> insert site tree ) Empty //#B
let downloadImage (url:string) =
use client = new System.Net.WebClient()
let fileName = Path.GetFileName(url)
client.DownloadFile(url, @"c:\Images\" + fileName) //#C
let rec parallelDownloadImages tree depth = //#D
match tree with
| _ when depth = maxDepth ->
tree |> inorder downloadImage |> ignore
| Node(leaf, left, right) ->
let taskLeft = Task.Run(fun() ->
parallelDownloadImages left (depth + 1))
let taskRight = Task.Run(fun() ->
parallelDownloadImages right (depth + 1))
let taskLeaf = Task.Run(fun() -> downloadImage leaf)
Task.WaitAll([|taskLeft;taskRight;taskLeaf|]) //#E
| Empty -> ()

View file

@ -0,0 +1,17 @@
module TCO_CPS
// Listing 3.19 Tail recursive implementation of factorial in F#
let rec factorialTCO (n:int) (acc:int) =
if n <= 1 then acc
else factorialTCO (n-1) (acc * n) //#A
let factorial n = factorialTCO n 1
// Listing 3.21 Recursive implementation of factorial using CPS
let rec factorialCPS x continuation =
if x <= 1 then continuation()
else factorialCPS (x - 1) (fun () -> x * continuation())
let result = factorialCPS 4 (fun () -> 1) //#A

View file

@ -0,0 +1,46 @@
module WeakMemoization
open System
open System.Collections.Concurrent
open System.Runtime.CompilerServices
let memoizeWeakWithTtl (func :'a->'b) ttl =
let keyStore = ConcurrentDictionary<int, 'a>()
let reduceKey (obj: 'a) =
let oldObj = keyStore.GetOrAdd(obj.GetHashCode(), obj)
if obj.Equals(oldObj) then oldObj else obj
let cache = ConditionalWeakTable<'a, 'b * DateTime>()
let factoryFunc =
ConditionalWeakTable<'a, 'b * DateTime>
.CreateValueCallback(
fun key -> func key, DateTime.Now + ttl)
fun (arg:'a) ->
let key = reduceKey arg
let (value, due) = cache.GetValue(key, factoryFunc)
if (due < DateTime.Now)
then
let newValue = factoryFunc.Invoke(key)
cache.Remove(key) |> ignore
cache.Add(key, newValue)
fst newValue
else value
let example() =
let greating name =
sprintf "Warm greetings %s, the time is %s"
name (DateTime.Now.ToString("hh:mm:ss"))
let greetingMemoize =
memoizeWeakWithTtl greating (TimeSpan.FromSeconds(2.0))
printfn "%s" <| greetingMemoize("Richard")
System.Threading.Thread.Sleep(1500)
printfn "%s" <| greetingMemoize("_Richard".Substring(1))
System.Threading.Thread.Sleep(1500)
printfn "%s" <| greetingMemoize("_Richard".Substring(1))

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
</startup>
</configuration>

View file

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DataParallelism.cs
{
public static class ArraySum
{
public static int SequentialSum(int[] data)
{
//Listing 4.6 Common For loop
int sum = 0;
for (int i = 0; i < data.Length; i++)
{
sum += data[i]; //#A
}
return sum;
}
public static int SequentialSumLINQ(int[] data)
{
return data.Sum();
}
}
}

View file

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataParallelism.cs
{
// Listing 4.1 Complex number object
class Complex
{
public Complex(float real, float imaginary)
{
Real = real;
Imaginary = imaginary;
}
public float Imaginary { get; } //#A
public float Real { get; } //#A
public float Magnitude
=> (float)Math.Sqrt(Real * Real + Imaginary * Imaginary); //#B
public static Complex operator +(Complex c1, Complex c2)
=> new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary); //#C
public static Complex operator *(Complex c1, Complex c2)
=> new Complex(c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
c1.Real * c2.Imaginary + c1.Imaginary * c2.Real); //#C
}
struct ComplexStruct
{
public ComplexStruct(float real, float imaginary)
{
Real = real;
Imaginary = imaginary;
}
public float Imaginary { get; }
public float Real { get; }
public float Magnitude
=> (float)Math.Sqrt(Real * Real + Imaginary * Imaginary);
public static ComplexStruct operator +(ComplexStruct c1, ComplexStruct c2)
=> new ComplexStruct(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
public static ComplexStruct operator *(ComplexStruct c1, ComplexStruct c2)
=> new ComplexStruct(c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
c1.Real * c2.Imaginary + c1.Imaginary * c2.Real);
}
}

View file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B3777684-C6FA-4011-AC1B-04C810E11F14}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataParallelism.cs</RootNamespace>
<AssemblyName>DataParallelism.cs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArraySum.cs" />
<Compile Include="Complex.cs" />
<Compile Include="Mandelbrot.cs" />
<Compile Include="PrimeNumbers.cs" />
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Name>Utilities</Name>
</ProjectReference>
</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>

View file

@ -0,0 +1,211 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace DataParallelism.cs
{
public class Mandelbrot
{
private const int Rows = 2000;
private const int Cols = 2000;
private static readonly Complex Center = new Complex(-0.75f, 0.0f);
private const float Width = 2.5f;
private const float Height = 2.5f;
private static float ComputeRow(int col)
=> Center.Real - Width / 2.0f + (float)col * Width / (float)Cols;
private static float ComputeColumn(int row)
=> Center.Imaginary - Height / 2.0f + (float)row * Height / (float)Rows;
public static Bitmap SequentialMandelbrot()
{
var bitmap = new Bitmap(Rows, Cols, PixelFormat.Format24bppRgb);
var bitmapData =
bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var pixels = new byte[bitmapData.Stride * bitmap.Height];
var ptrFirstPixel = bitmapData.Scan0;
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
// Listing 4.2 Sequential Mandelbrot
Func<Complex, int, bool> isMandelbrot = (complex, iterations) => //#A
{
var z = new Complex(0.0f, 0.0f);
int acc = 0;
while (acc < iterations && z.Magnitude < 2.0)
{
z = z * z + complex;
acc += 1;
}
return acc == iterations;
};
for (int col = 0; col < Cols; col++) //#B
{
for (int row = 0; row < Rows; row++) //#B
{
var x = ComputeRow(row); //#C
var y = ComputeColumn(col); //#C
var c = new Complex(x, y);
var color = isMandelbrot(c, 100) ? Color.Black : Color.White; //#D
var offset = (col * bitmapData.Stride) + (3 * row);
pixels[offset + 0] = color.B; // Blue component //#E
pixels[offset + 1] = color.G; // Green component //#E
pixels[offset + 2] = color.R; // Red component //#E
}
}
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
bitmap.UnlockBits(bitmapData);
var image = (Bitmap)bitmap.Clone();
return image;
}
public static Bitmap ParallelMandelbrot()
{
var bitmap = new Bitmap(Rows, Cols, PixelFormat.Format24bppRgb);
var bitmapData =
bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var pixels = new byte[bitmapData.Stride * bitmap.Height];
var ptrFirstPixel = bitmapData.Scan0;
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
// Listing 4.3 Parallel Mandelbrot
Func<Complex, int, bool> isMandelbrot = (complex, iterations) =>
{
var z = new Complex(0.0f, 0.0f);
int acc = 0;
while (acc < iterations && z.Magnitude < 2.0)
{
z = z * z + complex;
acc += 1;
}
return acc == iterations;
};
Parallel.For(0, Cols - 1, col =>
{ //#A
for (int row = 0; row < Rows; row++)
{
var x = ComputeRow(row);
var y = ComputeColumn(col);
var c = new Complex(x, y);
var color = isMandelbrot(c, 100) ? Color.DarkBlue : Color.White;
var offset = (col * bitmapData.Stride) + (3 * row);
pixels[offset + 0] = color.B; // Blue component
pixels[offset + 1] = color.G; // Green component
pixels[offset + 2] = color.R; // Red component
}
});
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
bitmap.UnlockBits(bitmapData);
var image = (Bitmap)bitmap.Clone();
return image;
}
public static Bitmap ParallelMandelbrotOversaturation()
{
var bitmap = new Bitmap(Rows, Cols, PixelFormat.Format24bppRgb);
var bitmapData =
bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var pixels = new byte[bitmapData.Stride * bitmap.Height];
var ptrFirstPixel = bitmapData.Scan0;
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
Func<Complex, int, bool> isMandelbrot = (complex, iterations) =>
{
var z = new Complex(0.0f, 0.0f);
int acc = 0;
while (acc < iterations && z.Magnitude < 2.0)
{
z = z * z + complex;
acc += 1;
}
return acc == iterations;
};
Parallel.For(0, Cols - 1, col =>
{
Parallel.For(0, Rows - 1, row =>
{
var x = ComputeRow(row);
var y = ComputeColumn(col);
var c = new Complex(x, y);
var color = isMandelbrot(c, 100) ? Color.DarkBlue : Color.White;
var offset = (col * bitmapData.Stride) + (3 * row);
pixels[offset + 0] = color.B; // Blue component
pixels[offset + 1] = color.G; // Green component
pixels[offset + 2] = color.R; // Red component
});
});
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
bitmap.UnlockBits(bitmapData);
var image = (Bitmap)bitmap.Clone();
return image;
}
private static ComplexStruct _centerStruct = new ComplexStruct(-0.75f, 0.0f);
private static float ComputeRowStruct(int col)
=> _centerStruct.Real - Width / 2.0f + (float)col * Width / (float)Cols;
private static float ComputeColumnStruct(int row)
=> _centerStruct.Imaginary - Height / 2.0f + (float)row * Height / (float)Rows;
public static Bitmap ParallelStructMandelbrot()
{
var bitmap = new Bitmap(Rows, Cols, PixelFormat.Format24bppRgb);
var bitmapData =
bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
var pixels = new byte[bitmapData.Stride * bitmap.Height];
var ptrFirstPixel = bitmapData.Scan0;
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
Func<ComplexStruct, int, bool> isMandelbrot = (complex, iterations) =>
{
var z = new ComplexStruct(0.0f, 0.0f);
int acc = 0;
while (acc < iterations && z.Magnitude < 2.0)
{
z = z * z + complex;
acc += 1;
}
return acc == iterations;
};
Parallel.For(0, Cols - 1, col =>
{
for (int row = 0; row < Rows; row++)
{
var x = ComputeRowStruct(row);
var y = ComputeColumnStruct(col);
var c = new ComplexStruct(x, y);
var color = isMandelbrot(c, 100) ? Color.DarkBlue : Color.White;
var offset = (col * bitmapData.Stride) + (3 * row);
pixels[offset + 0] = color.B; // Blue component
pixels[offset + 1] = color.G; // Green component
pixels[offset + 2] = color.R; // Red component
}
});
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
bitmap.UnlockBits(bitmapData);
var image = (Bitmap)bitmap.Clone();
return image;
}
}
}

View file

@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DataParallelism.cs
{
public static class PrimeNumbers
{
public static long PrimeSumSequential()
{
int len = 10000000;
long total = 0;
Func<int, bool> isPrime = n =>
{
if (n == 1) return false;
if (n == 2) return true;
var boundary = (int)Math.Floor(Math.Sqrt(n));
for (int i = 2; i <= boundary; ++i)
if (n % i == 0) return false;
return true;
};
for (var i=1; i<=len; ++i)
{
if (isPrime(i))
total += i;
}
return total;
}
public static long PrimeSumParallel()
{
// Listing 4.4 Parallel sum of prime numbers in a collection using Parallel.For loop construct
int len = 10000000;
long total = 0; //#A
Func<int, bool> isPrime = n => //#B
{
if (n == 1) return false;
if (n == 2) return true;
var boundary = (int) Math.Floor(Math.Sqrt(n));
for (int i = 2; i <= boundary; ++i)
if (n%i == 0) return false;
return true;
};
Parallel.For(0, len, i => //#C
{
if (isPrime(i)) //#D
total += i; //#D
});
return total;
}
public static long PrimeSumParallelThreadLocal()
{
int len = 10000000;
long total = 0;
Func<int, bool> isPrime = n =>
{
if (n == 1) return false;
if (n == 2) return true;
var boundary = (int)Math.Floor(Math.Sqrt(n));
for (int i = 2; i <= boundary; ++i)
if (n % i == 0) return false;
return true;
};
// Listing 4.5 Thread-safe parallel sum using Parallel.For and ThreadLocal
Parallel.For(0, len,
() => 0, //#A
(int i, ParallelLoopState loopState, long tlsValue) //#B
=> isPrime(i) ? tlsValue += i : tlsValue,
value => Interlocked.Add(ref total, value)); //#C
return total;
}
public static long PrimeSumParallelLINQ()
{
int len = 10000000;
Func<int, bool> isPrime = n =>
{
if (n == 1) return false;
if (n == 2) return true;
var boundary = (int)Math.Floor(Math.Sqrt(n));
for (int i = 2; i <= boundary; ++i)
if (n % i == 0) return false;
return true;
};
// Listing 4.7 Parallel sum of a collection using declarative PLINQ
long total = Enumerable.Range(0, len).AsParallel().Where(isPrime).Sum(x => (long)x); //#B
return total;
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DataParallelism.cs
{
class Program
{
static void Mandelbrot_Performance_Comparison()
{
Demo.PrintSeparator();
Console.WriteLine("Mandelbrot Performance Comparison");
Func<Func<Bitmap>, Action[]> run = (func) =>
new Action[] { () => { func(); } };
var implementations =
new[]
{
new Tuple<String, Action[]>(
"C# Sequential", run(Mandelbrot.SequentialMandelbrot)),
new Tuple<String, Action[]>(
"C# Parallel.For", run(Mandelbrot.ParallelMandelbrot)),
new Tuple<String, Action[]>(
"C# Parallel.For Saturated", run(Mandelbrot.ParallelMandelbrotOversaturation)),
new Tuple<String, Action[]>(
"C# Parallel.For Struct", run(Mandelbrot.ParallelStructMandelbrot))
};
Application.Run(
PerfVis.toChart("C# Mandelbrot")
.Invoke(PerfVis.fromTuples(implementations)));
}
static void Prime_Sum()
{
Demo.PrintSeparator();
Console.WriteLine("Prime Sum [0..10^7]");
Func<Func<long>, Action[]> runSum = (func) =>
new Action[]
{
() =>
{
var result = func();
Console.WriteLine($"Sum = {result}");
}
};
var sumImplementations =
new[]
{
new Tuple<String, Action[]>(
"C# Sequential", runSum(PrimeNumbers.PrimeSumSequential)),
new Tuple<String, Action[]>(
"C# Parallel.For", runSum(PrimeNumbers.PrimeSumParallel)),
new Tuple<String, Action[]>(
"C# Parallel.For ThreadLocal", runSum(PrimeNumbers.PrimeSumParallelThreadLocal)),
new Tuple<String, Action[]>(
"C# Parallel LINQ", runSum(PrimeNumbers.PrimeSumParallelLINQ))
};
Application.Run(
PerfVis.toChart("C# Prime Sum")
.Invoke(PerfVis.fromTuples(sumImplementations)));
}
[STAThread]
static void Main(string[] args)
{
Mandelbrot_Performance_Comparison();
// Prime_Sum();
Console.ReadLine();
}
}
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
</configuration>

View file

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>80404a98-4757-4a1e-861b-03fcf4fdd4ab</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>DataParallelism.fs</RootNamespace>
<AssemblyName>DataParallelism.fs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFSharpCoreVersion>4.4.3.0</TargetFSharpCoreVersion>
<Name>DataParallelism.Part1.fs</Name>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Debug\DataParallelism.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
<DocumentationFile>bin\Release\DataParallelism.fs.XML</DocumentationFile>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<ItemGroup>
<Compile Include="Mandelbrot.fs" />
<Compile Include="PrimeNumbers.fs" />
<Compile Include="Program.fs" />
<None Include="App.config" />
<Content Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Collections.ParallelSeq">
<HintPath>..\..\packages\FSharp.Collections.ParallelSeq.1.0.2\lib\net40\FSharp.Collections.ParallelSeq.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FSharp.Core">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Numerics" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Name>Utilities</Name>
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<!-- 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>

View file

@ -0,0 +1,137 @@
module Mandelbrot
open System
open System.IO
open System.Linq
open System.Drawing
open System.Drawing.Imaging
open System.Collections.Concurrent
open System.Runtime.InteropServices
open FSharp.Collections.ParallelSeq
// Listing 4.1 Complex number object
type Complex(real : float, imaginary : float) =
member this.Real = real
member this.Imaginary = imaginary
member this.Magnitude =
sqrt(this.Real * this.Real + this.Imaginary * this.Imaginary)
static member (+) (c1 : Complex, c2 : Complex) =
new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary)
static member (*) (c1 : Complex, c2 : Complex) =
new Complex(c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
c1.Real * c2.Imaginary + c1.Imaginary * c2.Real)
let parallelMandelbrot() =
let rows, cols = 2000, 2000
let center = Complex(-0.75, 0.0)
let width, height = 2.5, 2.5
let colToX col = center.Real - width / 2.0 +
float(col) * width / float(cols)
let rowToY row = center.Imaginary - height / 2.0 +
float(row) * height / float(rows)
let isMandelbrot c iterations =
let rec isMandelbrot (z:Complex) (rep:int) =
if rep < iterations && z.Magnitude < 2.0 then
isMandelbrot (z * z + c) (rep + 1)
else rep = iterations
isMandelbrot c 0
let bitmap = new Bitmap(rows, cols, PixelFormat.Format24bppRgb)
let width, height = bitmap.Width, bitmap.Height
let bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
let byteCount = bitmapData.Stride * height
let pixels : byte[] = Array.zeroCreate<byte> byteCount
let ptrFirstPixel = bitmapData.Scan0
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length)
Partitioner.Create(0, cols - 1).AsParallel()
|> PSeq.withDegreeOfParallelism(Environment.ProcessorCount)
|> PSeq.withMergeOptions(ParallelMergeOptions.FullyBuffered)
|> PSeq.iter(fun (s,e) ->
for col = s to e - 1 do
for row = 0 to rows - 1 do
let x,y = colToX row, rowToY col
let c = Complex(x, y)
let color = if isMandelbrot c 100 then Color.Black else Color.White
let offset = (col * bitmapData.Stride) + (3 * row)
pixels.[offset + 0] <- color.B; // Red component
pixels.[offset + 1] <- color.G; // Green component
pixels.[offset + 2] <- color.R; // Blue component
)
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length)
bitmap.UnlockBits(bitmapData)
bitmap.Clone() :?> Bitmap
[<Struct>]
type ComplexStruct(real : float, imaginary : float) =
member this.Real = real
member this.Imaginary = imaginary
member this.Magnitude =
sqrt(this.Real * this.Real + this.Imaginary * this.Imaginary)
static member (+) (c1 : ComplexStruct, c2 : ComplexStruct) =
new ComplexStruct(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary)
static member (*) (c1 : ComplexStruct, c2 : ComplexStruct) =
new ComplexStruct(c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
c1.Real * c2.Imaginary + c1.Imaginary * c2.Real)
let parallelMandelbrotStruct() =
let rows, cols = 2000, 2000
let center = ComplexStruct(-0.75, 0.0)
let width, height = 2.5, 2.5
let colToX col = center.Real - width / 2.0 +
float(col) * width / float(cols)
let rowToY row = center.Imaginary - height / 2.0 +
float(row) * height / float(rows)
let isMandelbrot c iterations =
let rec isMandelbrot (z:ComplexStruct) (rep:int) =
if rep < iterations && z.Magnitude < 2.0 then
isMandelbrot (z * z + c) (rep + 1)
else rep = iterations
isMandelbrot c 0
let bitmap = new Bitmap(rows, cols, PixelFormat.Format24bppRgb)
let width, height = bitmap.Width, bitmap.Height
let bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
let byteCount = bitmapData.Stride * height
let pixels : byte[] = Array.zeroCreate<byte> byteCount
let ptrFirstPixel = bitmapData.Scan0
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length)
Partitioner.Create(0, cols - 1).AsParallel()
|> PSeq.withDegreeOfParallelism(Environment.ProcessorCount)
|> PSeq.withMergeOptions(ParallelMergeOptions.FullyBuffered)
|> PSeq.iter(fun (s,e) ->
for col = s to e - 1 do
for row = 0 to rows - 1 do
let x,y = colToX row, rowToY col
let c = ComplexStruct(x, y)
let color = if isMandelbrot c 100 then Color.Blue else Color.White
let offset = (col * bitmapData.Stride) + (3 * row)
pixels.[offset + 0] <- color.B; // Red component
pixels.[offset + 1] <- color.G; // Green component
pixels.[offset + 2] <- color.R; // Blue component
)
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length)
bitmap.UnlockBits(bitmapData)
bitmap.Clone() :?> Bitmap

View file

@ -0,0 +1,31 @@
module PrimeNumbers
open System
open System.Linq
open System.Collections.Concurrent
open FSharp.Collections.ParallelSeq
let len = 1000000//0
let isPrime n =
if n < 2 then false
elif n = 2 then true
else
let boundary = int(Math.Floor(Math.Sqrt(float(n))))
[2..boundary]
|> Seq.exists (fun i-> (n%i)=0)
|> not
let sequentialSum () =
Seq.init len id
|> Seq.filter (isPrime)
|> Seq.sumBy (fun x-> int64(x))
let parallelSum () =
Seq.init len id
|> PSeq.withDegreeOfParallelism(Environment.ProcessorCount)
|> PSeq.withMergeOptions(ParallelMergeOptions.FullyBuffered)
|> PSeq.filter (isPrime)
|> Seq.sumBy (fun x-> int64(x))
let parallelLinqSum () =
(Seq.init len id).AsParallel().Where(isPrime).Sum(fun x -> int64(x))

View file

@ -0,0 +1,53 @@
open System.Windows.Forms
open System.Drawing
open System
let ``run Mandelbrot Performance Comparison``() =
Demo.printSeparator()
printfn "Mandelbrot Performance Comparison"
let run func = [func >> ignore]
[
"F# Parallel" , run Mandelbrot.parallelMandelbrot
"F# Parallel Struct" , run Mandelbrot.parallelMandelbrotStruct
]
|> PerfVis.toChart "F# Mandelbrot"
|> Application.Run
let ``run Draw Mandelbrot``() =
Demo.printSeparator()
printfn "Draw Mandelbrot"
let image = Mandelbrot.parallelMandelbrotStruct()
let form = new Form(Visible = true, Text = "Mandelbrot",
TopMost = true, Size = Size(800,800))
new PictureBox(Dock = DockStyle.Fill, Image = image,
SizeMode = PictureBoxSizeMode.StretchImage)
|> form.Controls.Add
Application.Run(form)
let ``run Prime Sum [0..10^7]``() =
Demo.printSeparator()
printfn "Prime Sum [0..10^7]"
let runSum func =
[fun() ->
let res = func()
printfn "Sum = %d" res
]
[
"F# Sequential" , runSum PrimeNumbers.sequentialSum
"F# Parallel" , runSum PrimeNumbers.parallelSum
"F# Parallel LINQ" , runSum PrimeNumbers.parallelLinqSum
]
|> PerfVis.toChart "F# Prime Sum"
|> Application.Run
[<EntryPoint>]
let main argv =
``run Mandelbrot Performance Comparison``()
//``run Draw Mandelbrot``()
//``run Prime Sum [0..10^7]``()
Console.ReadLine() |> ignore
0

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FSharp.Collections.ParallelSeq" version="1.0.2" targetFramework="net461" />
<package id="FSharp.Core" version="4.3.4" targetFramework="net47" />
</packages>

View file

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D1CD7806-99BF-463D-807D-AF5DE50EA49C}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DataParallelism.Part2</RootNamespace>
<AssemblyName>DataParallelism.Part2.cs</AssemblyName>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>DataParallelism.Part2.CSharp.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=4.4.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FSharp.Core.4.3.4\lib\net45\FSharp.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="KMeans.cs" />
<Compile Include="MapReduce.PLINQ.cs" />
<Compile Include="MapReduce.PLINQPartitioner.cs" />
<Compile Include="ParalellReduce.cs" />
<Compile Include="Program.cs" />
<Compile Include="WordsCounter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Functional.cs\Functional.cs.csproj">
<Project>{24d84c19-b173-4635-91a6-42328bc694ce}</Project>
<Name>Functional.cs</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\Utilities\Utilities.fsproj">
<Project>{2c133fbd-c138-43bb-9066-a9fecb1abe86}</Project>
<Name>Utilities</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Content Include="Shakespeare\allswellthatendswell.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\amsnd.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\antandcleo.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\asyoulikeit.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\comedyoferrors.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\cymbeline.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\hamlet.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryiv1.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryiv2.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryv.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryvi1.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryvi2.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryvi3.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\henryviii.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\juliuscaesar.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\kingjohn.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\kinglear.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\loveslobourslost.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\maan.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\macbeth.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\measureformeasure.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\merchantofvenice.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\othello.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\richardii.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\richardiii.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\romeoandjuliet.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\tamingoftheshrew.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\tempest.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\themwofw.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\thetgofv.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\timon.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\titus.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\troilusandcressida.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\twelfthnight.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Shakespeare\winterstale.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</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>

View file

@ -0,0 +1,170 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DataParallelism.Part2.CSharp
{
public class KMeans
{
public KMeans(double[][] data)
{
this.data = data;
this.N = data[0].Length;
}
protected int N;
protected double[][] data;
private double Dist(double[] u, double[] v)
{
double results = 0.0;
for (var i = 0; i < u.Length; i++)
results += Math.Pow(u[i] - v[i], 2.0);
return results;
}
//Listing 5.8 Function to find the closest centroid(used to update the clusters)
protected double[] GetNearestCentroid(double[][] centroids, double[] center)
{
return centroids.Aggregate((centroid1, centroid2) => //#A
Dist(center, centroid2) < Dist(center, centroid1)
? centroid2
: centroid1);
}
//Listing 5.9 Update the location of the centroids according to the center of the cluster
protected virtual double[][] UpdateCentroids(double[][] centroids)
{
var partitioner = Partitioner.Create(data, true); //#A
var result = partitioner.AsParallel() //#B
.WithExecutionMode(ParallelExecutionMode.ForceParallelism) //#C
.GroupBy(u => GetNearestCentroid(centroids, u))
.Select(points =>
points
.Aggregate(new double[N], //#D
(acc, item) => acc.Zip(item, (a, b) => a + b).ToArray()) //#E
.Select(items => items / points.Count())
.ToArray())
.ToArray();
Array.Sort(result, (a, b) => {
for (var i = 0; i < N; i++)
if (a[i] != b[i])
return a[i].CompareTo(b[i]);
return 0;
});
return result;
}
//Listing 5.10 UpdateCentroids function implemented without Aggregate
double[][] UpdateCentroidsWithMutableState(double[][] centroids)
{
var result = data.AsParallel()
.GroupBy(u => GetNearestCentroid(centroids, u))
.Select(points => {
var res = new double[N];
foreach (var x in points) //#A
for (var i = 0; i < N; i++)
res[i] += x[i]; //#B
var count = points.Count();
for (var i = 0; i < N; i++)
res[i] /= count; //#B
return res;
});
return result.ToArray();
}
public double[][] Run(double[][] initialCentroids)
{
var centroids = initialCentroids;
for (int i = 0; i <= 1000; i++)
{
var newCentroids = UpdateCentroids(centroids);
var error = double.MaxValue;
if (centroids.Length == newCentroids.Length)
{
error = 0;
for (var j = 0; j < centroids.Length; j++)
error += Dist(centroids[j], newCentroids[j]);
}
if (error < 1e-9)
{
Console.WriteLine($"Iterations {i}");
return newCentroids;
}
centroids = newCentroids;
}
Console.WriteLine($"Iterations 1000");
return centroids;
}
}
public class KMeansLinq : KMeans
{
public KMeansLinq(double[][] data) : base(data)
{ }
protected override double[][] UpdateCentroids(double[][] centroids)
{
var result =
data
.GroupBy(u => GetNearestCentroid(centroids, u))
.Select(elements => {
var res = new double[N];
foreach (var x in elements)
for (var i = 0; i < N; i++)
res[i] += x[i];
var M = elements.Count();
for (var i = 0; i < N; i++)
res[i] /= M;
return res;
})
.ToArray();
Array.Sort(result, (a, b) => {
for (var i = 0; i < N; i++)
if (a[i] != b[i])
return a[i].CompareTo(b[i]);
return 0;
});
return result;
}
}
public class KMeansPLinq : KMeans
{
public KMeansPLinq(double[][] data) : base(data)
{ }
protected override double[][] UpdateCentroids(double[][] centroids)
{
var result =
data.AsParallel()
.GroupBy(u => GetNearestCentroid(centroids, u))
.Select(elements => {
var res = new double[N];
foreach (var x in elements)
for (var i = 0; i < N; i++)
res[i] += x[i];
var M = elements.Count();
for (var i = 0; i < N; i++)
res[i] /= M;
return res;
})
.ToArray();
Array.Sort(result, (a, b) => {
for (var i = 0; i < N; i++)
if (a[i] != b[i])
return a[i].CompareTo(b[i]);
return 0;
});
return result;
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace DataParallelism.Part2.CSharp
{
using static Functional.Functional;
public static class MapReducePLINQ
{
public static TResult[] MapReduce<TSource, TMapped, TKey, TResult>(
this IList<TSource> source,
Func<TSource, IEnumerable<TMapped>> map,
Func<TMapped, TKey> keySelector,
Func<IGrouping<TKey, TMapped>, TResult> reduce,
int M, int R)
{
return source.AsParallel()
.WithDegreeOfParallelism(M)
.SelectMany(map)
.GroupBy(keySelector)
.ToList().AsParallel()
.WithDegreeOfParallelism(R)
.Select(reduce)
.ToArray();
}
public static IEnumerable<IGrouping<TKey, TMapped>> Map<TSource, TKey, TMapped>(this IList<TSource> source, Func<TSource, IEnumerable<TMapped>> map, Func<TMapped, TKey> keySelector) =>
source.AsParallel()
.WithDegreeOfParallelism(Environment.ProcessorCount)
.SelectMany(map)
.GroupBy(keySelector)
.ToList();
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace DataParallelism.Part2.CSharp
{
public static class MapReducePLINQPartitioner
{
public static TResult[] MapReduce<TSource, TMapped, TKey, TResult>(
this IList<TSource> source,
Func<TSource, IEnumerable<TMapped>> map,
Func<TMapped, TKey> keySelector,
Func<IGrouping<TKey, TMapped>, TResult> reduce,
int M, int R)
{
var partitioner = Partitioner.Create(source, true);
var mapResults =
partitioner.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithDegreeOfParallelism(M)
.SelectMany(map)
.GroupBy(keySelector)
.ToList().AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithDegreeOfParallelism(R)
.Select(reduce)
.ToArray();
return mapResults;
}
}
}

View file

@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DataParallelism.Part2.CSharp
{
using static Functional.Functional;
public static class ParalellMapReduce
{
// Listing 5.11 A parallel Reduce function implementation using Aggregate
public static TValue Reduce<TValue>(this ParallelQuery<TValue> source, Func<TValue, TValue, TValue> reduce) =>
ParallelEnumerable.Aggregate(source, //#A
(item1, item2) => reduce(item1, item2)); //#B
public static TValue Reduce<TValue>(this IEnumerable<TValue> source, TValue seed,
Func<TValue, TValue, TValue> reduce) =>
source.AsParallel()
.Aggregate(
seed: seed,
updateAccumulatorFunc: (local, value) => reduce(local, value),
combineAccumulatorsFunc: (overall, local) => reduce(overall, local),
resultSelector: overall => overall);
public static Func<Func<TSource, TSource, TSource>, TSource> Reduce<TSource>(this IEnumerable<TSource> source)
=> func => source.AsParallel().Aggregate((item1, item2) => func(item1, item2));
public static IEnumerable<IGrouping<TKey, TMapped>> Map<TSource, TKey, TMapped>(this IList<TSource> source, Func<TSource, IEnumerable<TMapped>> map, Func<TMapped, TKey> keySelector) =>
source.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithDegreeOfParallelism(Environment.ProcessorCount)
.SelectMany(map)
.GroupBy(keySelector)
.ToList();
public static TResult[] Reduce<TSource, TKey, TMapped, TResult>(this IEnumerable<IGrouping<TKey, TMapped>> source, Func<IGrouping<TKey, TMapped>, TResult> reduce) =>
source.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithDegreeOfParallelism(Environment.ProcessorCount)
.Select(reduce).ToArray();
}
}

View file

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DataParallelism.Part2.CSharp
{
public static class Program
{
public static void Main(string[] args)
{
Console.WriteLine("WordCount");
WordsCounterDemo.Demo();
Demo.PrintSeparator();
Console.WriteLine("Listing 5.11 A parallel Reduce function implementation using Aggregate");
int[] source = Enumerable.Range(0, 100000).ToArray();
int result = source.AsParallel()
.Reduce((value1, value2) => value1 + value2);
}
}
}

Some files were not shown because too many files have changed in this diff Show more