Compare commits
3 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
6f80b6df33 | 13 years ago |
|
|
d08996b6c7 | 13 years ago |
|
|
0fc76027c1 | 13 years ago |
33 changed files with 4441 additions and 1 deletions
@ -0,0 +1,88 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 11.00 |
|||
# Visual Studio 2010 |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples", "src\Examples\Examples.csproj", "{8239A6FF-1EF3-4DA4-A860-95C392DD6899}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "src\Numerics\Numerics.csproj", "{B7CAE5F4-A23F-4438-B5BE-41226618B695}" |
|||
EndProject |
|||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp", "src\FSharp\FSharp.fsproj", "{37E8E802-A354-4114-BFC1-6E1357DA605B}" |
|||
EndProject |
|||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpExamples", "src\FSharpExamples\FSharpExamples.fsproj", "{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}" |
|||
EndProject |
|||
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests", "src\FSharpUnitTests\FSharpUnitTests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{4D50FB34-10BC-495A-8B2F-482E34B4D771}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{49EE74BD-301F-4C3B-B76A-07F90CC88CE7}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "src\UnitTests\UnitTests.csproj", "{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}" |
|||
ProjectSection(SolutionItems) = preProject |
|||
AUTHORS.markdown = AUTHORS.markdown |
|||
COPYRIGHT.markdown = COPYRIGHT.markdown |
|||
README.markdown = README.markdown |
|||
EndProjectSection |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics.IO", "src\Numerics.IO\Numerics.IO.csproj", "{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
Release-Signed|Any CPU = Release-Signed|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{B7CAE5F4-A23F-4438-B5BE-41226618B695}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{37E8E802-A354-4114-BFC1-6E1357DA605B}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU |
|||
{EB1A5D32-F264-4BCE-BEB7-0B97085075BE}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1} = {49EE74BD-301F-4C3B-B76A-07F90CC88CE7} |
|||
{8239A6FF-1EF3-4DA4-A860-95C392DD6899} = {49EE74BD-301F-4C3B-B76A-07F90CC88CE7} |
|||
{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D} = {4D50FB34-10BC-495A-8B2F-482E34B4D771} |
|||
{DAF07AA8-C5C9-4963-98F7-2C3285064DAD} = {4D50FB34-10BC-495A-8B2F-482E34B4D771} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,51 @@ |
|||
// <copyright file="AssemblyInfo.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics |
|||
|
|||
open System.Reflection |
|||
open System.Resources; |
|||
open System.Runtime.CompilerServices |
|||
open System.Runtime.InteropServices |
|||
|
|||
[<assembly: AssemblyTitle("Math.NET Numerics F# Modules")>] |
|||
[<assembly: AssemblyDescription("F# Modules for Math.NET Numerics, providing methods and algorithms for numerical computations in science, engineering and every day use.")>] |
|||
[<assembly: AssemblyConfiguration("")>] |
|||
[<assembly: AssemblyCompany("Math.NET Project")>] |
|||
[<assembly: AssemblyProduct("Math.NET Numerics")>] |
|||
[<assembly: AssemblyCopyright("Copyright © Math.NET Project")>] |
|||
[<assembly: AssemblyTrademark("")>] |
|||
[<assembly: AssemblyCulture("")>] |
|||
[<assembly: ComVisible(false)>] |
|||
[<assembly: Guid("048BC4EB-CE2B-4040-9967-4784F5405B0F")>] |
|||
[<assembly: NeutralResourcesLanguage("en")>] |
|||
[<assembly: AssemblyVersion("1.0.0.0")>] |
|||
[<assembly: AssemblyFileVersion("1.0.0.0")>] |
|||
() |
|||
@ -0,0 +1,101 @@ |
|||
// <copyright file="DenseMatrix.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://mathnet.opensourcedotnet.info |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
/// A module which implements functional dense vector operations. |
|||
module DenseMatrix = |
|||
|
|||
/// Initialize a matrix by calling a construction function for every element. |
|||
let inline init (n: int) (m: int) f = |
|||
let A = new DenseMatrix(n,m) |
|||
for i=0 to n-1 do |
|||
for j=0 to m-1 do |
|||
A.[i,j] <- f i j |
|||
A |
|||
|
|||
/// Create a matrix from a list of float lists. Every list in the master list specifies a row. |
|||
let inline ofList (fll: float list list) = |
|||
let n = List.length fll |
|||
let m = List.length (List.head fll) |
|||
let A = DenseMatrix(n,m) |
|||
fll |> List.iteri (fun i fl -> |
|||
if (List.length fl) <> m then failwith "Each subrow must be of the same length." else |
|||
List.iteri (fun j f -> A.[i,j] <- f) fl) |
|||
A |
|||
|
|||
/// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. |
|||
let inline ofSeq (fss: #seq<#seq<float>>) = |
|||
let n = Seq.length fss |
|||
let m = Seq.length (Seq.head fss) |
|||
let A = DenseMatrix(n,m) |
|||
fss |> Seq.iteri (fun i fs -> |
|||
if (Seq.length fs) <> m then failwith "Each subrow must be of the same length." else |
|||
Seq.iteri (fun j f -> A.[i,j] <- f) fs) |
|||
A |
|||
|
|||
/// Create a matrix from a 2D array of floating point numbers. |
|||
let inline ofArray2 (arr: float[,]) = new DenseMatrix(arr) |
|||
|
|||
/// Create a matrix with the given entries. |
|||
let inline initDense (n: int) (m: int) (es: #seq<int * int * float>) = |
|||
let A = new DenseMatrix(n,m) |
|||
Seq.iter (fun (i,j,f) -> A.[i,j] <- f) es |
|||
A |
|||
|
|||
/// Create a square matrix with constant diagonal entries. |
|||
let inline constDiag (n: int) (f: float) = |
|||
let A = new DenseMatrix(n,n) |
|||
for i=0 to n-1 do |
|||
A.[i,i] <- f |
|||
A |
|||
|
|||
/// Create a square matrix with the vector elements on the diagonal. |
|||
let inline diag (v: #Vector<float>) = |
|||
let n = v.Count |
|||
let A = new DenseMatrix(n,n) |
|||
for i=0 to n-1 do |
|||
A.[i,i] <- v.Item(i) |
|||
A |
|||
|
|||
/// Initialize a matrix by calling a construction function for every row. |
|||
let inline initRow (n: int) (m: int) (f: int -> #Vector<float>) = |
|||
let A = new DenseMatrix(n,m) |
|||
for i=0 to n-1 do A.SetRow(i, f i) |
|||
A |
|||
|
|||
/// Initialize a matrix by calling a construction function for every column. |
|||
let inline initCol (n: int) (m: int) (f: int -> #Vector<float>) = |
|||
let A = new DenseMatrix(n,m) |
|||
for i=0 to m-1 do A.SetColumn(i, f i) |
|||
A |
|||
@ -0,0 +1,69 @@ |
|||
// <copyright file="DenseVector.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
|
|||
open MathNet.Numerics.LinearAlgebra |
|||
|
|||
/// A module which implements functional dense vector operations. |
|||
module DenseVector = |
|||
|
|||
/// Initialize a vector by calling a construction function for every element. |
|||
let inline init (n: int) f = |
|||
let v = new Double.DenseVector(n) |
|||
for i=0 to n-1 do |
|||
v.[i] <- f i |
|||
v |
|||
|
|||
/// Create a vector from a float list. |
|||
let inline ofList (fl: float list) = |
|||
let n = List.length fl |
|||
let v = Double.DenseVector(n) |
|||
fl |> List.iteri (fun i f -> v.[i] <- f) |
|||
v |
|||
|
|||
/// Create a vector from a sequences. |
|||
let inline ofSeq (fs: #seq<float>) = |
|||
let n = Seq.length fs |
|||
let v = DenseVector(n) |
|||
fs |> Seq.iteri (fun i f -> v.[i] <- f) |
|||
v |
|||
|
|||
/// Create a vector with evenly spaced entries: e.g. rangef -1.0 0.5 1.0 = [-1.0 -0.5 0.0 0.5 1.0] |
|||
let inline rangef (start: float) (step: float) (stop: float) = |
|||
let n = (int ((stop - start) / step)) + 1 |
|||
let v = new DenseVector(n) |
|||
for i=0 to n-1 do |
|||
v.[i] <- (float i) * step + start |
|||
v |
|||
|
|||
/// Create a vector with integer entries in the given range. |
|||
let inline range (start: int) (stop: int) = |
|||
new DenseVector([| for i in [start .. stop] -> float i |]) |
|||
@ -0,0 +1,68 @@ |
|||
// <copyright file="Extensions.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
// Module that contains implementation of useful F#-specific |
|||
// extension members for generic Matrix and Vector types |
|||
[<AutoOpen>] |
|||
module FSharpExtensions = |
|||
|
|||
// A type extension for the generic vector type that |
|||
// adds the 'GetSlice' method to allow vec.[a .. b] syntax |
|||
type MathNet.Numerics.LinearAlgebra.Generic. |
|||
Vector<'T when 'T : struct and 'T : (new : unit -> 'T) |
|||
and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable |
|||
and 'T :> System.ValueType> with |
|||
|
|||
/// Gets a slice of a vector starting at a specified index |
|||
/// and ending at a specified index (both indices are optional) |
|||
/// This method can be used via the x.[start .. finish] syntax |
|||
member x.GetSlice(start, finish) = |
|||
let start = defaultArg start 0 |
|||
let finish = defaultArg finish (x.Count - 1) |
|||
x.SubVector(start, finish - start + 1) |
|||
|
|||
// A type extension for the generic matrix type that |
|||
// adds the 'GetSlice' method to allow m.[r1 .. r2, c1 .. c2] syntax |
|||
type MathNet.Numerics.LinearAlgebra.Generic. |
|||
Matrix<'T when 'T : struct and 'T : (new : unit -> 'T) |
|||
and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable |
|||
and 'T :> System.ValueType> with |
|||
|
|||
/// Gets a submatrix using a specified column range and |
|||
/// row range (all indices are optional) |
|||
/// This method can be used via the x.[r1 .. r2, c1 .. c2 ] syntax |
|||
member x.GetSlice(rstart, rfinish, cstart, cfinish) = |
|||
let cstart = defaultArg cstart 0 |
|||
let rstart = defaultArg rstart 0 |
|||
let cfinish = defaultArg cfinish (x.ColumnCount - 1) |
|||
let rfinish = defaultArg rfinish (x.RowCount - 1) |
|||
x.SubMatrix(rstart, rfinish - rstart + 1, cstart, cfinish - cstart + 1) |
|||
@ -0,0 +1,80 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProductVersion>8.0.30703</ProductVersion> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<ProjectGuid>{37e8e802-a354-4114-bfc1-6e1357da605b}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<RootNamespace>FSharp</RootNamespace> |
|||
<AssemblyName>MathNet.Numerics.FSharp</AssemblyName> |
|||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
|||
<Name>FSharp</Name> |
|||
<TargetFrameworkProfile /> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<Tailcalls>false</Tailcalls> |
|||
<OutputPath>..\..\out\debug\Net40\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<Tailcalls>true</Tailcalls> |
|||
<OutputPath>..\..\out\lib\Net40\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
<DocumentationFile>..\..\out\lib\Net40\MathNet.Numerics.FSharp.xml</DocumentationFile> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> |
|||
<DocumentationFile>MathNet.Numerics.FSharp.XML</DocumentationFile> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Signed|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<Tailcalls>true</Tailcalls> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
<DocumentationFile>..\..\out\lib\Net40\MathNet.Numerics.FSharp.xml</DocumentationFile> |
|||
<OutputPath>bin\Release-Signed\</OutputPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<ItemGroup> |
|||
<Compile Include="Extensions.fs" /> |
|||
<Compile Include="DenseVector.fs" /> |
|||
<Compile Include="DenseMatrix.fs" /> |
|||
<Compile Include="SparseMatrix.fs" /> |
|||
<Compile Include="SparseVector.fs" /> |
|||
<Compile Include="Vector.fs" /> |
|||
<Compile Include="Matrix.fs" /> |
|||
<Compile Include="Main.fs" /> |
|||
<Compile Include="AssemblyInfo.fs" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Reference Include="FSharp.Core" /> |
|||
<Reference Include="mscorlib" /> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core"> |
|||
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
|||
</Reference> |
|||
<Reference Include="System.Numerics" /> |
|||
<ProjectReference Include="..\Numerics\Numerics.csproj"> |
|||
<Name>Numerics</Name> |
|||
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</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> |
|||
@ -0,0 +1,43 @@ |
|||
// <copyright file="Main.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics |
|||
|
|||
open MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
/// A module which implements some F# utility functions. |
|||
module FSharp = |
|||
|
|||
/// Construct a dense matrix from a list of floating point numbers. |
|||
let inline matrix (lst: list<list<float>>) = DenseMatrix.ofList lst :> Matrix<float> |
|||
|
|||
/// Construct a dense vector from a list of floating point numbers. |
|||
let inline vector (lst: list<float>) = DenseVector.ofList lst :> Vector<float> |
|||
@ -0,0 +1,243 @@ |
|||
// <copyright file="Matrix.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
|
|||
open MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
/// A module which implements functional matrix operations. |
|||
module Matrix = |
|||
|
|||
/// Fold a function over all matrix elements. |
|||
let inline fold (f: 'a -> float -> 'a) (acc0: 'a) (A: #Matrix<float>) = |
|||
let n = A.RowCount |
|||
let m = A.ColumnCount |
|||
let mutable acc = acc0 |
|||
for i=0 to n-1 do |
|||
for j=0 to m-1 do |
|||
acc <- f acc (A.Item(i,j)) |
|||
acc |
|||
|
|||
/// Fold a function over all matrix elements in reverse order. |
|||
let inline foldBack (f: float -> 'a -> 'a) (acc0: 'a) (A: #Matrix<float>) = |
|||
let n = A.RowCount |
|||
let m = A.ColumnCount |
|||
let mutable acc = acc0 |
|||
for i in n-1 .. -1 .. 0 do |
|||
for j in m-1 .. -1 .. 0 do |
|||
acc <- f (A.Item(i,j)) acc |
|||
acc |
|||
|
|||
/// Fold a matrix by applying a given function to all matrix elements. |
|||
let inline foldi (f: int -> int -> 'a -> float -> 'a) (acc0: 'a) (A: #Matrix<float>) = |
|||
let n = A.RowCount |
|||
let m = A.ColumnCount |
|||
let mutable acc = acc0 |
|||
for i=0 to n-1 do |
|||
for j=0 to m-1 do |
|||
acc <- f i j acc (A.Item(i,j)) |
|||
acc |
|||
|
|||
/// Create a 2D array from a matrix. |
|||
let inline toArray2 (A: #Matrix<float>) = |
|||
let n = A.RowCount |
|||
let m = A.ColumnCount |
|||
Array2D.init n m (fun i j -> (A.Item(i,j))) |
|||
|
|||
/// Checks whether a predicate holds for all elements of a matrix. |
|||
let inline forall (p: float -> bool) (A: #Matrix<float>) = |
|||
let mutable b = true |
|||
let mutable i = 0 |
|||
let mutable j = 0 |
|||
while b && i < A.RowCount do |
|||
b <- b && (p (A.Item(i,j))) |
|||
j <- j+1 |
|||
if j = A.ColumnCount then i <- i+1; j <- 0 |
|||
b |
|||
|
|||
/// Chechks whether a predicate holds for at least one element of a matrix. |
|||
let inline exists (p: float -> bool) (A: #Matrix<float>) = |
|||
let mutable b = false |
|||
let mutable i = 0 |
|||
let mutable j = 0 |
|||
while not(b) && i < A.RowCount do |
|||
b <- b || (p (A.Item(i,j))) |
|||
j <- j+1 |
|||
if j = A.ColumnCount then i <- i+1; j <- 0 |
|||
b |
|||
|
|||
/// Checks whether a position dependent predicate holds for all elements of a matrix. |
|||
let inline foralli (p: int -> int -> float -> bool) (A: #Matrix<float>) = |
|||
let mutable b = true |
|||
let mutable i = 0 |
|||
let mutable j = 0 |
|||
while b && i < A.RowCount do |
|||
b <- b && (p i j (A.Item(i,j))) |
|||
j <- j+1 |
|||
if j = A.ColumnCount then i <- i+1; j <- 0 |
|||
b |
|||
|
|||
/// Checks whether a position dependent predicate holds for at least one element of a matrix. |
|||
let inline existsi (p: int -> int -> float -> bool) (A: #Matrix<float>) = |
|||
let mutable b = false |
|||
let mutable i = 0 |
|||
let mutable j = 0 |
|||
while not(b) && i < A.RowCount do |
|||
b <- b || (p i j (A.Item(i,j))) |
|||
j <- j+1 |
|||
if j = A.ColumnCount then i <- i+1; j <- 0 |
|||
b |
|||
|
|||
/// Map every matrix element using the given function. |
|||
let inline map (f: float -> float) (A: #Matrix<float>) = |
|||
let N = A.RowCount |
|||
let M = A.ColumnCount |
|||
let C = A.Clone() |
|||
for i=0 to N-1 do |
|||
for j=0 to M-1 do |
|||
C.[i,j] <- f (C.Item(i,j)) |
|||
C |
|||
|
|||
/// Map every matrix element using the given position dependent function. |
|||
let inline mapi (f: int -> int -> float -> float) (A: #Matrix<float>) = |
|||
let N = A.RowCount |
|||
let M = A.ColumnCount |
|||
let C = A.Clone() |
|||
for i=0 to N-1 do |
|||
for j=0 to M-1 do |
|||
C.[i,j] <- f i j (C.Item(i,j)) |
|||
C |
|||
|
|||
/// In-place map every matrix column using the given position dependent function. |
|||
let inline inplaceMapCols (f: int -> Vector<float> -> Vector<float>) (A: #Matrix<float>) = |
|||
for j = 0 to A.ColumnCount-1 do |
|||
A.SetColumn(j, f j (A.Column(j))) |
|||
() |
|||
|
|||
/// In-place map every matrix row using the given position dependent function. |
|||
let inline inplaceMapRows (f: int -> Vector<float> -> Vector<float>) (A: #Matrix<float>) = |
|||
for i = 0 to A.RowCount-1 do |
|||
A.SetRow(i, f i (A.Row(i))) |
|||
() |
|||
|
|||
/// Map every matrix column using the given position dependent function. |
|||
let inline mapCols (f: int -> Vector<float> -> Vector<float>) (A: #Matrix<float>) = |
|||
let A = A.Clone() |
|||
inplaceMapCols f A |
|||
A |
|||
|
|||
/// Map every matrix row using the given position dependent function. |
|||
let inline mapRows (f: int -> Vector<float> -> Vector<float>) (A: #Matrix<float>) = |
|||
let A = A.Clone() |
|||
inplaceMapRows f A |
|||
A |
|||
|
|||
/// In-place assignment. |
|||
let inline inplaceAssign (f: int -> int -> float) (A: #Matrix<float>) = |
|||
for i=0 to A.RowCount-1 do |
|||
for j=0 to A.ColumnCount-1 do |
|||
A.Item(i,j) <- f i j |
|||
|
|||
/// In-place map of every matrix element using a position dependent function. |
|||
let inline inplaceMapi (f: int -> int -> float -> float) (A: #Matrix<float>) = |
|||
for i=0 to A.RowCount-1 do |
|||
for j=0 to A.ColumnCount-1 do |
|||
A.Item(i,j) <- f i j (A.Item(i,j)) |
|||
|
|||
/// Creates a sequence that iterates the non-zero entries in the matrix. |
|||
let inline nonZeroEntries (A: #Matrix<float>) = |
|||
seq { for i in 0 .. A.RowCount-1 do |
|||
for j in 0 .. A.ColumnCount-1 do |
|||
if A.Item(i,j) <> 0.0 then yield (i,j, A.Item(i,j)) } |
|||
|
|||
/// Returns the sum of all elements of a matrix. |
|||
let inline sum (A: #Matrix<float>) = |
|||
let mutable f = 0.0 |
|||
for i=0 to A.RowCount-1 do |
|||
for j=0 to A.ColumnCount-1 do |
|||
f <- f + A.Item(i,j) |
|||
f |
|||
|
|||
/// Returns the sum of the results generated by applying a position dependent function to each column of the matrix. |
|||
let inline sumColsBy (f: int -> Vector<float> -> 'a) (A: #Matrix<float>) = |
|||
A.ColumnEnumerator() |> Seq.map (fun (j,col) -> f j col) |> Seq.reduce (+) |
|||
|
|||
/// Returns the sum of the results generated by applying a position dependent function to each row of the matrix. |
|||
let inline sumRowsBy (f: int -> Vector<float> -> 'a) (A: #Matrix<float>) = |
|||
A.RowEnumerator() |> Seq.map (fun (i,row) -> f i row) |> Seq.reduce (+) |
|||
|
|||
/// Iterates over all elements of a matrix. |
|||
let inline iter (f: float -> unit) (A: #Matrix<float>) = |
|||
for i=0 to A.RowCount-1 do |
|||
for j=0 to A.ColumnCount-1 do |
|||
f (A.Item(i,j)) |
|||
() |
|||
|
|||
/// Iterates over all elements of a matrix using the element indices. |
|||
let inline iteri (f: int -> int -> float -> unit) (A: #Matrix<float>) = |
|||
for i=0 to A.RowCount-1 do |
|||
for j=0 to A.ColumnCount-1 do |
|||
f i j (A.Item(i,j)) |
|||
() |
|||
|
|||
/// Fold one column. |
|||
let inline foldCol (f: 'a -> float -> 'a) acc (A: #Matrix<float>) k = |
|||
let mutable macc = acc |
|||
for i=0 to A.RowCount-1 do |
|||
macc <- f macc (A.Item(i,k)) |
|||
macc |
|||
|
|||
/// Fold one row. |
|||
let inline foldRow (f: 'a -> float -> 'a) acc (A: #Matrix<float>) k = |
|||
let mutable macc = acc |
|||
for i=0 to A.ColumnCount-1 do |
|||
macc <- f macc (A.Item(k,i)) |
|||
macc |
|||
|
|||
/// Fold all columns into one row vector. |
|||
let inline foldByCol (f: float -> float -> float) acc (A: #Matrix<float>) = |
|||
let v = new DenseVector(A.ColumnCount) |
|||
for k=0 to A.ColumnCount-1 do |
|||
let mutable macc = acc |
|||
for i=0 to A.RowCount-1 do |
|||
macc <- f macc (A.Item(i,k)) |
|||
v.[k] <- macc |
|||
v :> Vector<float> |
|||
|
|||
/// Fold all rows into one column vector. |
|||
let inline foldByRow (f: float -> float -> float) acc (A: #Matrix<float>) = |
|||
let v = new DenseVector(A.RowCount) |
|||
for k=0 to A.RowCount-1 do |
|||
let mutable macc = acc |
|||
for i=0 to A.ColumnCount-1 do |
|||
macc <- f macc (A.Item(k,i)) |
|||
v.[k] <- macc |
|||
v :> Vector<float> |
|||
@ -0,0 +1,75 @@ |
|||
// <copyright file="SparseMatrix.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
|
|||
open MathNet.Numerics.LinearAlgebra |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
/// A module which implements functional sparse vector operations. |
|||
module SparseMatrix = |
|||
|
|||
/// Create a matrix from a list of float lists. Every list in the master list specifies a row. |
|||
let inline ofList (rows: int) (cols: int) (fll: list<int * int * float>) = |
|||
let A = new Double.SparseMatrix(rows, cols) |
|||
fll |> List.iter (fun (i, j, x) -> A.[i,j] <- x) |
|||
A |
|||
|
|||
/// Create a matrix from a list of sequences. Every sequence in the master sequence specifies a row. |
|||
let inline ofSeq (rows: int) (cols: int) (fss: #seq<int * int * float>) = |
|||
let A = new Double.SparseMatrix(rows, cols) |
|||
fss |> Seq.iter (fun (i, j, x) -> A.[i,j] <- x) |
|||
A |
|||
|
|||
/// Create a square matrix with constant diagonal entries. |
|||
let inline constDiag (n: int) (f: float) = |
|||
let A = new Double.SparseMatrix(n,n) |
|||
for i=0 to n-1 do |
|||
A.[i,i] <- f |
|||
A |
|||
|
|||
/// Create a square matrix with the vector elements on the diagonal. |
|||
let inline diag (v: #Vector<float>) = |
|||
let n = v.Count |
|||
let A = new Double.SparseMatrix(n,n) |
|||
for i=0 to n-1 do |
|||
A.[i,i] <- v.Item(i) |
|||
A |
|||
|
|||
/// Initialize a matrix by calling a construction function for every row. |
|||
let inline initRow (n: int) (m: int) (f: int -> #Vector<float>) = |
|||
let A = new Double.SparseMatrix(n,m) |
|||
for i=0 to n-1 do A.SetRow(i, f i) |
|||
A |
|||
|
|||
/// Initialize a matrix by calling a construction function for every column. |
|||
let inline initCol (n: int) (m: int) (f: int -> #Vector<float>) = |
|||
let A = new Double.SparseMatrix(n,m) |
|||
for i=0 to m-1 do A.SetColumn(i, f i) |
|||
A |
|||
@ -0,0 +1,48 @@ |
|||
// <copyright file="SparseVector.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
|
|||
open MathNet.Numerics.LinearAlgebra |
|||
|
|||
/// A module which implements functional sparse vector operations. |
|||
module SparseVector = |
|||
|
|||
/// Create a sparse vector with a given dimension from a list of entry, value pairs. |
|||
let inline ofList (dim: int) (fl: list<int * float>) = |
|||
let v = new Double.SparseVector(dim) |
|||
fl |> List.iter (fun (i, f) -> v.[i] <- f) |
|||
v |
|||
|
|||
/// Create a sparse vector with a given dimension from a sequence of entry, value pairs. |
|||
let inline ofSeq (dim: int) (fs: #seq<int * float>) = |
|||
let v = new Double.SparseVector(dim) |
|||
fs |> Seq.iter (fun (i, f) -> v.[i] <- f) |
|||
v |
|||
@ -0,0 +1,187 @@ |
|||
// <copyright file="Vector.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://numerics.mathdotnet.com |
|||
// http://github.com/mathnet/mathnet-numerics |
|||
// http://mathnetnumerics.codeplex.com |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
|
|||
open MathNet.Numerics.LinearAlgebra |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
/// A module which implements functional vector operations. |
|||
module Vector = |
|||
|
|||
/// Transform a vector into an array. |
|||
let inline toArray (v: #Vector<float>) = |
|||
let n = v.Count |
|||
Array.init n (fun i -> v.Item(i)) |
|||
|
|||
/// Transform a vector into an array. |
|||
let inline toList (v: #Vector<float>) = |
|||
let n = v.Count |
|||
List.init n (fun i -> v.Item(i)) |
|||
|
|||
/// In-place mutation by applying a function to every element of the vector. |
|||
let inline mapInPlace (f: float -> float) (v: #Vector<float>) = |
|||
for i=0 to v.Count-1 do |
|||
v.Item(i) <- f (v.Item(i)) |
|||
() |
|||
|
|||
/// In-place mutation by applying a function to every element of the vector. |
|||
let inline mapiInPlace (f: int -> float -> float) (v: #Vector<float>) = |
|||
for i=0 to v.Count-1 do |
|||
v.Item(i) <- f i (v.Item(i)) |
|||
() |
|||
|
|||
/// In-place vector addition. |
|||
let inline addInPlace (v: #Vector<float>) (w: #Vector<float>) = v.Add(w, v) |
|||
|
|||
/// In place vector subtraction. |
|||
let inline subInPlace (v: #Vector<float>) (w: #Vector<float>) = v.Subtract(w, v) |
|||
|
|||
/// Functional map operator for vectors. |
|||
/// <include file='../../../../FSharpExamples/DenseVector.xml' path='example'/> |
|||
let inline map f (v: #Vector<float>) = |
|||
let w = v.Clone() |
|||
mapInPlace (fun x -> f x) w |
|||
w |
|||
|
|||
/// Applies a function to all elements of the vector. |
|||
let inline iter (f: float -> unit) (v: #Vector<float>) = |
|||
for i=0 to v.Count-1 do |
|||
f (v.Item i) |
|||
|
|||
/// Applies a function to all elements of the vector. |
|||
let inline iteri (f: int -> float -> unit) (v: #Vector<float>) = |
|||
for i=0 to v.Count-1 do |
|||
f i (v.Item i) |
|||
|
|||
/// Maps a vector to a new vector by applying a function to every element. |
|||
let inline mapi (f: int -> float -> float) (v: #Vector<float>) = |
|||
let w = v.Clone() |
|||
mapiInPlace f w |
|||
w |
|||
|
|||
/// Fold all entries of a vector. |
|||
let inline fold (f: 'a -> float -> 'a) (acc0: 'a) (v: #Vector<float>) = |
|||
let mutable acc = acc0 |
|||
for i=0 to v.Count-1 do |
|||
acc <- f acc (v.Item(i)) |
|||
acc |
|||
|
|||
/// Fold all entries of a vector in reverse order. |
|||
let inline foldBack (f: float -> 'a -> 'a) (acc0: 'a) (v: #Vector<float>) = |
|||
let mutable acc = acc0 |
|||
for i=2 to v.Count do |
|||
acc <- f (v.Item(v.Count - i)) acc |
|||
acc |
|||
|
|||
/// Fold all entries of a vector using a position dependent folding function. |
|||
let inline foldi (f: int -> 'a -> float -> 'a) (acc0: 'a) (v: #Vector<float>) = |
|||
let mutable acc = acc0 |
|||
for i=0 to v.Count-1 do |
|||
acc <- f i acc (v.Item(i)) |
|||
acc |
|||
|
|||
/// Checks whether a predicate is satisfied for every element in the vector. |
|||
let inline forall (p: float -> bool) (v: #Vector<float>) = |
|||
let mutable b = true |
|||
let mutable i = 0 |
|||
while b && i < v.Count do |
|||
b <- b && (p (v.Item(i))) |
|||
i <- i+1 |
|||
b |
|||
|
|||
/// Checks whether there is an entry in the vector that satisfies a given predicate. |
|||
let inline exists (p: float -> bool) (v: #Vector<float>) = |
|||
let mutable b = false |
|||
let mutable i = 0 |
|||
while not(b) && i < v.Count do |
|||
b <- b || (p (v.Item(i))) |
|||
i <- i+1 |
|||
b |
|||
|
|||
/// Checks whether a predicate is true for all entries in a vector. |
|||
let inline foralli (p: int -> float -> bool) (v: #Vector<float>) = |
|||
let mutable b = true |
|||
let mutable i = 0 |
|||
while b && i < v.Count do |
|||
b <- b && (p i (v.Item(i))) |
|||
i <- i+1 |
|||
b |
|||
|
|||
/// Checks whether there is an entry in the vector that satisfies a given position dependent predicate. |
|||
let inline existsi (p: int -> float -> bool) (v: #Vector<float>) = |
|||
let mutable b = false |
|||
let mutable i = 0 |
|||
while not(b) && i < v.Count do |
|||
b <- b || (p i (v.Item(i))) |
|||
i <- i+1 |
|||
b |
|||
|
|||
/// Scans a vector; like fold but returns the intermediate result. |
|||
let inline scan (f: float -> float -> float) (v: #Vector<float>) = |
|||
let w = v.Clone() |
|||
let mutable p = v.Item(0) |
|||
for i=1 to v.Count-1 do |
|||
p <- f p (v.Item(i)) |
|||
w.[i] <- p |
|||
w |
|||
|
|||
/// Scans a vector in reverse order; like foldBack but returns the intermediate result. |
|||
let inline scanBack (f: float -> float -> float) (v: #Vector<float>) = |
|||
let w = v.Clone() |
|||
let mutable p = v.Item(v.Count-1) |
|||
for i=2 to v.Count do |
|||
p <- f (v.Item(v.Count - i)) p |
|||
w.[v.Count - i] <- p |
|||
w |
|||
|
|||
/// Reduces a vector: the result of this function will be f(...f(f(v[0],v[1]), v[2]),..., v[n]). |
|||
let inline reduce (f: float -> float -> float) (v: #Vector<float>) = |
|||
let mutable p = v.Item(0) |
|||
for i=1 to v.Count-1 do |
|||
p <- f p (v.Item(i)) |
|||
p |
|||
|
|||
/// Reduces a vector in reverse order: the result of this function will be f(v[1], ..., f(v[n-2], f(v[n-1],v[n]))...). |
|||
let inline reduceBack (f: float -> float -> float) (v: #Vector<float>) = |
|||
let mutable p = v.Item(v.Count-1) |
|||
for i=2 to v.Count do |
|||
p <- f (v.Item(v.Count - i)) p |
|||
p |
|||
|
|||
/// Creates a new vector and inserts the given value at the given index. |
|||
let inline insert index value (v: #Vector<float>) = |
|||
let newV = new DenseVector(v.Count + 1) |
|||
for i = 0 to index - 1 do |
|||
newV.Item(i) <- v.Item(i) |
|||
newV.Item(index) <- value |
|||
for i = index + 1 to v.Count do |
|||
newV.Item(i) <- v.Item(i - 1) |
|||
newV |
|||
@ -0,0 +1,94 @@ |
|||
// <copyright file="Apply.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://mathnet.opensourcedotnet.info |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
module MathNet.Numerics.FSharp.Examples.Apply |
|||
|
|||
open System.Numerics |
|||
open MathNet.Numerics |
|||
open MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
/// Flag to specify wether we want pretty printing or tab separated output. |
|||
let prettyPrint = false |
|||
|
|||
/// The size of the vector we want to map things for. |
|||
let N = 1000000 |
|||
/// The number of times we repeat a call. |
|||
let T = 10 |
|||
/// The list of all functions we want to test. |
|||
let FunctionList : (string * (float -> float) * (float -> float)) [] = |
|||
[| ("Cosine", cos, System.Math.Cos); |
|||
("Sine", sin, System.Math.Sin); |
|||
("Tangent", tan, System.Math.Tan); |
|||
("Inverse Cosine", acos, System.Math.Acos); |
|||
("Inverse Sine", asin, System.Math.Asin); |
|||
("Inverse Tangent", atan, System.Math.Atan); |
|||
("Hyperbolic Cosine", cosh, System.Math.Cosh); |
|||
("Hyperbolic Sine", sinh, System.Math.Sinh); |
|||
("Hyperbolic Tangent", tanh, System.Math.Tanh); |
|||
("Abs", abs, System.Math.Abs); |
|||
("Exp", exp, System.Math.Exp); |
|||
("Log", log, System.Math.Log); |
|||
("Sqrt", sqrt, System.Math.Sqrt); |
|||
("Error Function", SpecialFunctions.Erf, SpecialFunctions.Erf); |
|||
("Error Function Complement", SpecialFunctions.Erfc, SpecialFunctions.Erfc); |
|||
("Inverse Error Function", SpecialFunctions.ErfInv, SpecialFunctions.ErfInv); |
|||
("Inverse Error Function Complement", SpecialFunctions.ErfcInv, SpecialFunctions.ErfcInv) |] |
|||
|
|||
/// A vector with random entries. |
|||
let w = |
|||
let rnd = new Random.MersenneTwister() |
|||
(new DenseVector(Array.init N (fun _ -> rnd.NextDouble() * 10.0))) :> Vector<float> |
|||
|
|||
/// A stopwatch to time the execution. |
|||
let sw = new System.Diagnostics.Stopwatch() |
|||
|
|||
|
|||
for (name, fs, dotnet) in FunctionList do |
|||
if prettyPrint then printfn "Running %s on an %d dimensional vector for %d iterations:" name N T |
|||
else printf "%s" name |
|||
|
|||
/// Perform the standard F# map function. |
|||
do |
|||
let v = w.Clone() |
|||
sw.Start() |
|||
for t in 1 .. T do Vector.mapInPlace fs v |
|||
sw.Stop() |
|||
if prettyPrint then printfn "\tVector.map (F#): %d milliseconds." sw.ElapsedMilliseconds |
|||
else printf "\t%d" sw.ElapsedMilliseconds |
|||
sw.Reset() |
|||
(* |
|||
/// Perform the Apply.Map function. |
|||
do |
|||
let v = w.Clone() |
|||
sw.Start() |
|||
for t in 1 .. T do v.Map(fun x -> dotnet x) |
|||
sw.Stop() |
|||
if prettyPrint then printfn "\tApply.Map (MKL): %d milliseconds." sw.ElapsedMilliseconds |
|||
else printf "\t%d" sw.ElapsedMilliseconds |
|||
sw.Reset()*) |
|||
|
|||
printfn "" |
|||
@ -0,0 +1,54 @@ |
|||
// <copyright file="DenseVector.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://mathnet.opensourcedotnet.info |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
module MathNet.Numerics.FSharp.Examples.DenseVector |
|||
|
|||
open MathNet.Numerics.FSharp |
|||
open MathNet.Numerics.LinearAlgebra |
|||
|
|||
// Create a new 100 dimensional dense vector. |
|||
let v = Double.DenseVector.init 100 (fun i -> float i / 100.0) |
|||
|
|||
// Another way to create a 100 dimensional dense vector is using the vector function. |
|||
let w = vector (List.init 100 (fun i -> float i ** 2.0)) |
|||
|
|||
// Vectors can also be constructed from sequences. |
|||
let t = Double.DenseVector.ofSeq (seq { for i in 1 .. 100 do yield float i }) |
|||
|
|||
// We can now add two vectors together ... |
|||
let z = v + w |
|||
|
|||
// ... or scale them in the process. |
|||
let x = v + 3.0 * t |
|||
|
|||
|
|||
|
|||
// We can create a vector from an integer range (in this case, 5 and 10 inclusive) ... |
|||
let s = Double.DenseVector.range 5 10 |
|||
|
|||
// ... or we can create a vector from a double range with a particular step size. |
|||
let r = Double.DenseVector.rangef 0.0 0.1 10.0 |
|||
@ -0,0 +1,77 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProductVersion>8.0.30703</ProductVersion> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<ProjectGuid>{bc81ea37-8ee6-4bf9-b8a9-b30497aef8b1}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<RootNamespace>FSharpExamples</RootNamespace> |
|||
<AssemblyName>FSharpExamples</AssemblyName> |
|||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
|||
<Name>FSharpExamples</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> |
|||
</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> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Signed|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<Tailcalls>true</Tailcalls> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
<OutputPath>bin\Release-Signed\</OutputPath> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<Reference Include="FSharp.Core" /> |
|||
<Reference Include="mscorlib" /> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core"> |
|||
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
|||
</Reference> |
|||
<Reference Include="System.Numerics" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\FSharp\FSharp.fsproj"> |
|||
<Name>FSharp</Name> |
|||
<Project>{37e8e802-a354-4114-bfc1-6e1357da605b}</Project> |
|||
<Private>True</Private> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Numerics\Numerics.csproj"> |
|||
<Name>Numerics</Name> |
|||
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project> |
|||
<Private>True</Private> |
|||
</ProjectReference> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="DenseVector.fs" /> |
|||
<Compile Include="Apply.fs" /> |
|||
<Compile Include="Histogram.fs" /> |
|||
<Compile Include="MCMC.fs" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -0,0 +1,44 @@ |
|||
// <copyright file="Histogram.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://mathnet.opensourcedotnet.info |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
module MathNet.Numerics.FSharp.Examples.Histogram |
|||
|
|||
open MathNet.Numerics.Statistics |
|||
|
|||
/// The number of buckets to use in our histogram. |
|||
let B = 9 |
|||
|
|||
/// Create a small dataset. |
|||
let data = [| 0.5; 1.5; 2.5; 3.5; 4.5; 5.5; 6.5; 7.5; 8.5; 9.5 |] |
|||
|
|||
/// A histogram with 9 buckets for this dataset. |
|||
let hist = new Histogram(data, B) |
|||
|
|||
// Print some histogram information. |
|||
printfn "Histogram.ToString(): %O" hist |
|||
for i in 0 .. B-1 do |
|||
printfn "Bucket %d contains %f datapoints." i hist.[i].Count |
|||
@ -0,0 +1,201 @@ |
|||
// <copyright file="MCMC.fs" company="Math.NET"> |
|||
// Math.NET Numerics, part of the Math.NET Project |
|||
// http://mathnet.opensourcedotnet.info |
|||
// |
|||
// Copyright (c) 2009 Math.NET |
|||
// |
|||
// Permission is hereby granted, free of charge, to any person |
|||
// obtaining a copy of this software and associated documentation |
|||
// files (the "Software"), to deal in the Software without |
|||
// restriction, including without limitation the rights to use, |
|||
// copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
// copies of the Software, and to permit persons to whom the |
|||
// Software is furnished to do so, subject to the following |
|||
// conditions: |
|||
// |
|||
// The above copyright notice and this permission notice shall be |
|||
// included in all copies or substantial portions of the Software. |
|||
// |
|||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
// OTHER DEALINGS IN THE SOFTWARE. |
|||
// </copyright> |
|||
module MathNet.Numerics.FSharp.Examples.Mcmc |
|||
|
|||
open MathNet.Numerics.Random |
|||
open MathNet.Numerics.Statistics |
|||
open MathNet.Numerics.Distributions |
|||
open MathNet.Numerics.Statistics.Mcmc |
|||
|
|||
/// The number of samples to gather for each sampler. |
|||
let N = 10000 |
|||
/// The random number generator we use for the examples. |
|||
let rnd = new MersenneTwister() |
|||
|
|||
// |
|||
// Example 1: Sampling a Beta distributed variable through rejection sampling. |
|||
// |
|||
// Target Distribution: Beta(2.7, 6.3) |
|||
// |
|||
// ----------------------------------------------------------------------------- |
|||
do |
|||
printfn "Rejection Sampling Example" |
|||
|
|||
/// The target distribution. |
|||
let beta = new Beta(2.7, 6.3) |
|||
|
|||
/// Samples uniform distributed variables. |
|||
let uniform = new ContinuousUniform(0.0, 1.0, RandomSource = rnd) |
|||
|
|||
/// Implements the rejection sampling procedure. |
|||
let rs = new RejectionSampler<float>( ( fun x -> x**(beta.A-1.0) * (1.0 - x)**(beta.B-1.0) ), |
|||
( fun x -> 0.021 ), |
|||
( fun () -> uniform.Sample()) ) |
|||
|
|||
/// An array of samples from the rejection sampler. |
|||
let arr = rs.Sample(N) |
|||
|
|||
/// The true distribution. |
|||
printfn "\tEmpirical Mean = %f (should be %f)" (Statistics.Mean(arr)) beta.Mean |
|||
printfn "\tEmpirical StdDev = %f (should be %f)" (Statistics.StandardDeviation(arr)) beta.StdDev |
|||
printfn "\tAcceptance rate = %f" rs.AcceptanceRate |
|||
printfn "" |
|||
|
|||
|
|||
|
|||
// |
|||
// Example 2: Sampling a normal distributed variable through Metropolis sampling. |
|||
// |
|||
// Target Distribution: Normal(1.0, 3.5) |
|||
// |
|||
// ----------------------------------------------------------------------------- |
|||
do |
|||
printfn "Metropolis Sampling Example" |
|||
|
|||
let mean, stddev = 1.0, 3.5 |
|||
let normal = new Normal(mean, stddev) |
|||
|
|||
/// Implements the rejection sampling procedure. |
|||
let ms = new MetropolisSampler<float>( 0.1, (fun x -> log(normal.Density(x))), |
|||
(fun x -> Normal.Sample(rnd, x, 0.3)), 20, |
|||
RandomSource = rnd ) |
|||
|
|||
/// An array of samples from the rejection sampler. |
|||
let arr = ms.Sample(N) |
|||
|
|||
/// The true distribution. |
|||
printfn "\tEmpirical Mean = %f (should be %f)" (Statistics.Mean(arr)) normal.Mean |
|||
printfn "\tEmpirical StdDev = %f (should be %f)" (Statistics.StandardDeviation(arr)) normal.StdDev |
|||
printfn "\tAcceptance rate = %f" ms.AcceptanceRate |
|||
printfn "" |
|||
|
|||
|
|||
|
|||
// |
|||
// Example 3: Sampling a normal distributed variable through Metropolis-Hastings sampling |
|||
// with a symmetric proposal distribution. |
|||
// |
|||
// Target Distribution: Normal(1.0, 3.5) |
|||
// |
|||
// ----------------------------------------------------------------------------------------- |
|||
do |
|||
printfn "Metropolis Hastings Sampling Example (Symmetric Proposal)" |
|||
let mean, stddev = 1.0, 3.5 |
|||
let normal = new Normal(mean, stddev) |
|||
|
|||
/// Evaluates the log normal distribution. |
|||
let npdf x m s = -0.5*(x-m)*(x-m)/(s*s) - 0.5 * log(2.0 * System.Math.PI * s * s) |
|||
|
|||
/// Implements the rejection sampling procedure. |
|||
let ms = new MetropolisHastingsSampler<float>( 0.1, (fun x -> log(normal.Density(x))), |
|||
(fun x y -> npdf x y 0.3), (fun x -> Normal.Sample(rnd, x, 0.3)), 10, |
|||
RandomSource = rnd ) |
|||
|
|||
/// An array of samples from the rejection sampler. |
|||
let arr = ms.Sample(N) |
|||
|
|||
/// The true distribution. |
|||
printfn "\tEmpirical Mean = %f (should be %f)" (Statistics.Mean(arr)) normal.Mean |
|||
printfn "\tEmpirical StdDev = %f (should be %f)" (Statistics.StandardDeviation(arr)) normal.StdDev |
|||
printfn "\tAcceptance rate = %f" ms.AcceptanceRate |
|||
printfn "" |
|||
|
|||
|
|||
|
|||
// |
|||
// Example 4: Sampling a normal distributed variable through Metropolis-Hastings sampling |
|||
// with a asymmetric proposal distribution. |
|||
// |
|||
// Target Distribution: Normal(1.0, 3.5) |
|||
// |
|||
// ----------------------------------------------------------------------------------------- |
|||
do |
|||
printfn "Metropolis Hastings Sampling Example (Assymetric Proposal)" |
|||
let mean, stddev = 1.0, 3.5 |
|||
let normal = new Normal(mean, stddev) |
|||
|
|||
/// Evaluates the logarithm of the normal distribution function. |
|||
let npdf x m s = -0.5*(x-m)*(x-m)/(s*s) - 0.5 * log(2.0 * System.Math.PI * s * s) |
|||
|
|||
/// Samples from a mixture that is biased towards samples larger than x. |
|||
let mixSample x = |
|||
if Bernoulli.Sample(rnd, 0.5) = 1 then |
|||
Normal.Sample(rnd, x, 0.3) |
|||
else |
|||
Normal.Sample(rnd, x + 0.1, 0.3) |
|||
|
|||
/// The transition kernel for the proposal above. |
|||
let krnl xnew x = log (0.5 * exp(npdf xnew x 0.3) + 0.5 * exp(npdf xnew (x+0.1) 0.3)) |
|||
|
|||
/// Implements the rejection sampling procedure. |
|||
let ms = new MetropolisHastingsSampler<float>( 0.1, (fun x -> log(normal.Density(x))), |
|||
(fun xnew x -> krnl xnew x), (fun x -> mixSample x), 10, |
|||
RandomSource = rnd ) |
|||
|
|||
/// An array of samples from the rejection sampler. |
|||
let arr = ms.Sample(N) |
|||
|
|||
/// The true distribution. |
|||
printfn "\tEmpirical Mean = %f (should be %f)" (Statistics.Mean(arr)) normal.Mean |
|||
printfn "\tEmpirical StdDev = %f (should be %f)" (Statistics.StandardDeviation(arr)) normal.StdDev |
|||
printfn "\tAcceptance rate = %f" ms.AcceptanceRate |
|||
printfn "" |
|||
|
|||
|
|||
|
|||
// |
|||
// Example 5: Slice sampling a normal distributed random variable. |
|||
// |
|||
// Target Distribution: Normal(1.0, 3.5) |
|||
// |
|||
// ----------------------------------------------------------------------------------------- |
|||
do |
|||
printfn "Slice Sampling Example" |
|||
let mean, stddev = 1.0, 3.5 |
|||
let normal = new Normal(mean, stddev) |
|||
|
|||
/// Evaluates the unnormalized logarithm of the normal distribution function. |
|||
let npdf x m s = -0.5*(x-m)*(x-m)/(s*s) |
|||
|
|||
/// Implements the rejection sampling procedure. |
|||
let ms = new UnivariateSliceSampler( 0.1, (fun x -> npdf x mean stddev), 5, 1.0, RandomSource = rnd ) |
|||
|
|||
/// An array of samples from the rejection sampler. |
|||
let arr = ms.Sample(N) |
|||
|
|||
/// The true distribution. |
|||
printfn "\tEmpirical Mean = %f (should be %f)" (Statistics.Mean(arr)) normal.Mean |
|||
printfn "\tEmpirical StdDev = %f (should be %f)" (Statistics.StandardDeviation(arr)) normal.StdDev |
|||
printfn "" |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
System.Console.ReadLine() |> ignore |
|||
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<startup> |
|||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /> |
|||
</startup> |
|||
</configuration> |
|||
@ -0,0 +1,76 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProductVersion>8.0.30703</ProductVersion> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<ProjectGuid>{f2f8032b-a31d-4e33-a05e-f2cdcbfaa75d}</ProjectGuid> |
|||
<OutputType>Exe</OutputType> |
|||
<RootNamespace>FSharpUnitTests</RootNamespace> |
|||
<AssemblyName>MathNet.Numerics.FSharp.UnitTests</AssemblyName> |
|||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
|||
<Name>FSharpUnitTests</Name> |
|||
<TargetFrameworkProfile /> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<Tailcalls>false</Tailcalls> |
|||
<OutputPath>..\..\out\test\debug\Net40\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<Tailcalls>true</Tailcalls> |
|||
<OutputPath>..\..\out\test\Net40\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Signed|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<Tailcalls>true</Tailcalls> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<WarningLevel>3</WarningLevel> |
|||
<OutputPath>bin\Release-Signed\</OutputPath> |
|||
</PropertyGroup> |
|||
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll')" /> |
|||
<ItemGroup> |
|||
<Compile Include="FsUnit.fs" /> |
|||
<Compile Include="Program.fs" /> |
|||
<None Include="App.config"> |
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
|||
</None> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Reference Include="FSharp.Core" /> |
|||
<Reference Include="mscorlib" /> |
|||
<Reference Include="System" /> |
|||
<Reference Include="System.Core"> |
|||
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
|||
</Reference> |
|||
<ProjectReference Include="..\FSharp\FSharp.fsproj"> |
|||
<Name>FSharp</Name> |
|||
<Project>{37e8e802-a354-4114-bfc1-6e1357da605b}</Project> |
|||
<Private>True</Private> |
|||
</ProjectReference> |
|||
<ProjectReference Include="..\Numerics\Numerics.csproj"> |
|||
<Name>Numerics</Name> |
|||
<Project>{b7cae5f4-a23f-4438-b5be-41226618b695}</Project> |
|||
<Private>True</Private> |
|||
</ProjectReference> |
|||
<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> |
|||
@ -0,0 +1,244 @@ |
|||
(* |
|||
Copyright (c) 2008, Raymond W. Vernagus (R.Vernagus@gmail.com) |
|||
All rights reserved. |
|||
|
|||
Redistribution and use in source and binary forms, with or without modification, |
|||
are permitted provided that the following conditions are met: |
|||
|
|||
* Redistributions of source code must retain the above copyright notice, |
|||
this list of conditions and the following disclaimer. |
|||
* Redistributions in binary form must reproduce the above copyright notice, |
|||
this list of conditions and the following disclaimer in the documentation |
|||
and/or other materials provided with the distribution. |
|||
* Neither the name of Raymond W. Vernagus nor the names of FsUnit's |
|||
contributors may be used to endorse or promote products derived from this |
|||
software without specific prior written permission. |
|||
|
|||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
|||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE |
|||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|||
*) |
|||
namespace FsUnit |
|||
|
|||
open MathNet.Numerics |
|||
open MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
type Result = |
|||
| Pass |
|||
| Fail of string |
|||
| Error of string |
|||
|
|||
type Expectation = |
|||
| True |
|||
| False |
|||
| Empty |
|||
| NullOrEmpty |
|||
| Null |
|||
| SameAs of obj |
|||
|
|||
type Spec = |
|||
abstract Check : unit -> Result |
|||
abstract NegatedMessage : string |
|||
|
|||
[<AutoOpen>] |
|||
module SpecOps = |
|||
let internal safeCheck f = |
|||
try |
|||
f() |
|||
with ex -> Error (ex.ToString()) |
|||
|
|||
let make f nmsg = |
|||
{ new Spec with |
|||
member this.Check() = safeCheck f |
|||
member this.NegatedMessage = nmsg } |
|||
|
|||
let check (s: Spec) = s.Check() |
|||
|
|||
let not' f x = |
|||
let s = f x |
|||
match check s with |
|||
| Pass -> make (fun () -> Fail s.NegatedMessage) "" |
|||
| Fail msg -> make (fun () -> Pass) msg |
|||
| Error msg -> make (fun () -> Error msg) msg |
|||
|
|||
let equal expected actual = |
|||
make (fun () -> |
|||
if actual.Equals(expected) |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
let have n lbl s = |
|||
make (fun() -> |
|||
let len = Seq.length s |
|||
if len = n |
|||
then Pass |
|||
else Fail (sprintf "Expected: %d %s\nActual: %d %s" n lbl len lbl)) |
|||
(sprintf "NOT Expected: %d %s\nActual: %d %s" n lbl n lbl) |
|||
|
|||
let contain x s = |
|||
make (fun () -> |
|||
let exists = s |> Seq.exists (fun x' -> x' = x) |
|||
if exists |
|||
then Pass |
|||
else Fail (sprintf "Expected %A to contain %A" s x)) |
|||
(sprintf "Did NOT expect %A to contain %A" s x) |
|||
|
|||
let raise'<'a when 'a :> System.Exception> f = |
|||
let expType = typeof<'a> |
|||
make (fun () -> |
|||
try |
|||
f() |
|||
Fail (sprintf "Expected %s but no exception was raised" expType.FullName) |
|||
with ex -> |
|||
let actualExType = ex.GetType() |
|||
if expType = actualExType |
|||
then Pass |
|||
else Fail (sprintf "Expected: %s\nActual: %s" expType.FullName actualExType.FullName)) |
|||
(sprintf "Did NOT expect %s to be raised" expType.FullName) |
|||
|
|||
let be expectation x = |
|||
let x = box x |
|||
let msg = sprintf "Expected: %A\nActual: %A" expectation x |
|||
let negmsg = sprintf "NOT Expected: %A\nActual: %A" expectation x |
|||
match expectation with |
|||
| True -> |
|||
make (fun () -> |
|||
if x = box true |
|||
then Pass |
|||
else Fail msg) |
|||
negmsg |
|||
| False -> |
|||
make (fun () -> |
|||
if x = box false |
|||
then Pass |
|||
else Fail msg) |
|||
negmsg |
|||
| Empty -> |
|||
make (fun () -> |
|||
if x = box System.String.Empty |
|||
then Pass |
|||
else Fail msg) |
|||
negmsg |
|||
| NullOrEmpty -> |
|||
make (fun () -> |
|||
if System.String.IsNullOrEmpty(x :?> string) |
|||
then Pass |
|||
else Fail msg) |
|||
negmsg |
|||
| Null -> |
|||
make (fun () -> |
|||
if x = null |
|||
then Pass |
|||
else Fail msg) |
|||
negmsg |
|||
| SameAs other -> |
|||
make (fun () -> |
|||
if System.Object.ReferenceEquals(x, other) |
|||
then Pass |
|||
else Fail (sprintf "Expected actual to be same reference as expected %A" other)) |
|||
(sprintf "Expected %A to have different reference than %A" x other) |
|||
|
|||
let array_equal (expected: float []) (actual: float []) = |
|||
make (fun () -> |
|||
let mutable f = true |
|||
for i=0 to expected.Length-1 do |
|||
f <- f && (expected.[i] = actual.[i]) |
|||
if f |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
let array2_equal (expected: float [,]) (actual: float [,]) = |
|||
make (fun () -> |
|||
let mutable f = true |
|||
for i=0 to expected.GetLength(0)-1 do |
|||
for j=0 to expected.GetLength(1)-1 do |
|||
f <- f && (expected.[i,j] = actual.[i,j]) |
|||
if f |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
let approximately_equal (places : int) (expected: float) (actual: float) = |
|||
make (fun () -> |
|||
if Precision.AlmostEqualInDecimalPlaces(actual, expected, places) |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
let approximately_vector_equal (places : int) (expected: #Vector<float>) (actual: #Vector<float>) = |
|||
make (fun () -> |
|||
let mutable f = true |
|||
for i=0 to expected.Count-1 do |
|||
f <- f && Precision.AlmostEqualInDecimalPlaces(expected.[i], actual.[i], places) |
|||
if f |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
let approximately_matrix_equal (places : int) (expected: #Matrix<float>) (actual: #Matrix<float>) = |
|||
make (fun () -> |
|||
let mutable f = true |
|||
for i=0 to expected.RowCount-1 do |
|||
for j=0 to expected.ColumnCount-1 do |
|||
f <- f && Precision.AlmostEqualInDecimalPlaces(expected.[i,j], actual.[i,j], places) |
|||
if f |
|||
then Pass |
|||
else Fail (sprintf "Expected: %A\nActual: %A" expected actual)) |
|||
(sprintf "NOT Expected: %A\nActual: %A" expected actual) |
|||
|
|||
module Results = |
|||
open Microsoft.FSharp.Text |
|||
|
|||
let internal currentResults = new ResizeArray<string * Result>() |
|||
|
|||
let add = currentResults.Add |
|||
|
|||
let passedCount () = |
|||
currentResults |
|||
|> Seq.filter (function _,Pass -> true | _ -> false) |
|||
|> Seq.length |
|||
|
|||
let failed () = |
|||
currentResults |
|||
|> Seq.filter (function _,Fail _ -> true | _ -> false) |
|||
|
|||
let failedCount () = |
|||
failed() |
|||
|> Seq.length |
|||
|
|||
let erred () = |
|||
currentResults |
|||
|> Seq.filter (function _,Error _ -> true | _ -> false) |
|||
|
|||
let erredCount () = |
|||
erred() |
|||
|> Seq.length |
|||
|
|||
let summary () = |
|||
let buff = new System.Text.StringBuilder() |
|||
buff.AppendFormat("{0} passed.\n{1} failed.\n{2} erred.", passedCount(), failedCount(), erredCount()) |> ignore |
|||
failed() |
|||
|> Seq.iter (function (lbl,Fail msg) -> buff.AppendFormat("\n----\nFailed: {0}\n{1}", lbl, msg) |> ignore | _ -> ()) |
|||
erred() |
|||
|> Seq.iter (function (lbl,Error msg) -> buff.AppendFormat("\n----\nErred: {0}\n{1}", lbl, msg) |> ignore | _ -> ()) |
|||
buff.ToString() |
|||
|
|||
|
|||
[<AutoOpen>] |
|||
module SpecHelpers = |
|||
let spec lbl s = (lbl, check s) |
|||
|
|||
let should f x = f x |
|||
|
|||
let specs lbl (results: seq<string * Result>) = |
|||
results |> Seq.iter (fun x -> Results.add x) |
|||
@ -0,0 +1,224 @@ |
|||
open FsUnit |
|||
open MathNet.Numerics.FSharp |
|||
open MathNet.Numerics.LinearAlgebra.Double |
|||
open MathNet.Numerics.LinearAlgebra.Generic |
|||
|
|||
/// Unit tests for the dense vector type. |
|||
let DenseVectorTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallv = new DenseVector(5, 0.3 ) |
|||
|
|||
/// A large vector with increasingly large entries |
|||
let largev = new DenseVector( Array.init 100 (fun i -> float i / 100.0) ) |
|||
|
|||
specs "DenseVector" [ |
|||
spec "DenseVector.init" |
|||
(DenseVector.init 100 (fun i -> float i / 100.0) |> should equal largev) |
|||
spec "DenseVector.ofList" |
|||
(DenseVector.ofList [ for i in 0 .. 99 -> float i / 100.0 ] |> should equal largev) |
|||
spec "DenseVector.ofSeq" |
|||
(DenseVector.ofSeq (seq { for i in 0 .. 99 -> float i / 100.0 }) |> should equal largev) |
|||
spec "DenseVector.rangef" |
|||
(DenseVector.rangef 0.0 0.01 0.99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> 0.01 * float i |] ) )) |
|||
spec "DenseVector.range" |
|||
(DenseVector.range 0 99 |> should equal (new DenseVector( [| for i in 0 .. 99 -> float i |] ) )) |
|||
] |
|||
|
|||
|
|||
/// Unit tests for the sparse vector type. |
|||
let SparseVectorTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallv = new DenseVector( [|0.0;0.3;0.0;0.0;0.0|] ) :> Vector<float> |
|||
|
|||
specs "SparseVector" [ |
|||
spec "SparseVector.ofList" |
|||
((SparseVector.ofList 5 [ (1,0.3) ] :> Vector<float>) |> should equal smallv) |
|||
spec "SparseVector.ofSeq" |
|||
((SparseVector.ofSeq 5 (List.toSeq [ (1,0.3) ]) :> Vector<float>) |> should equal smallv) |
|||
] |
|||
|
|||
|
|||
/// Unit tests for the vector type. |
|||
let VectorTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallv = new DenseVector( [|0.3;0.3;0.3;0.3;0.3|] ) :> Vector<float> |
|||
|
|||
/// A large vector with increasingly large entries |
|||
let largev = new DenseVector( Array.init 100 (fun i -> float i / 100.0) ) :> Vector<float> |
|||
|
|||
specs "Vector" [ |
|||
spec "Vector.toArray" |
|||
(Vector.toArray smallv |> should array_equal [|0.3;0.3;0.3;0.3;0.3|]) |
|||
spec "Vector.toList" |
|||
(Vector.toList smallv |> should equal [0.3;0.3;0.3;0.3;0.3]) |
|||
spec "Vector.mapInPlace" |
|||
( let w = smallv.Clone() |
|||
Vector.mapInPlace (fun x -> 2.0 * x) w |
|||
w |> should equal (2.0 * smallv)) |
|||
spec "Vector.mapiInPlace" |
|||
( let w = largev.Clone() |
|||
Vector.mapiInPlace (fun i x -> float i / 100.0) w |
|||
w |> should equal (largev)) |
|||
spec "Vector.addInPlace" |
|||
( let w = largev.Clone() |
|||
Vector.addInPlace w largev |
|||
w |> should equal (2.0 * largev)) |
|||
spec "Vector.subInPlace" |
|||
( let w = largev.Clone() |
|||
Vector.subInPlace w largev |
|||
w |> should equal (0.0 * largev)) |
|||
spec "Vector.map" |
|||
(Vector.map (fun x -> 2.0 * x) largev |> should equal (2.0 * largev)) |
|||
spec "Vector.mapi" |
|||
(Vector.mapi (fun i x -> float i / 100.0) largev |> should equal largev) |
|||
spec "Vector.fold" |
|||
(Vector.fold (fun a b -> a - b) 0.0 smallv |> should equal -1.5) |
|||
spec "Vector.foldBack" |
|||
(Vector.foldBack (fun a b -> a - b) 0.0 smallv |> should equal 0.0) |
|||
spec "Vector.foldi" |
|||
(Vector.foldi (fun i a b -> a + b) 0.0 smallv |> should equal 1.5) |
|||
spec "Vector.forall" |
|||
(Vector.forall (fun x -> x = 0.3) smallv |> should equal true) |
|||
spec "Vector.exists" |
|||
(Vector.exists (fun x -> x = 0.3) smallv |> should equal true) |
|||
spec "Vector.foralli" |
|||
(Vector.foralli (fun i x -> x = 0.3 && i < 5) smallv |> should equal true) |
|||
spec "Vector.existsi" |
|||
(Vector.existsi (fun i x -> x = 0.3 && i = 2) smallv |> should equal true) |
|||
spec "Vector.scan" |
|||
(Vector.scan (fun acc x -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|0.3;0.6;0.9;1.2;1.5|] ) :> Vector<float>) ) |
|||
spec "Vector.scanBack" |
|||
(Vector.scanBack (fun x acc -> acc + x) smallv |> should approximately_vector_equal 14 (new DenseVector( [|1.5;1.2;0.9;0.6;0.3|] ) :> Vector<float>) ) |
|||
spec "Vector.reduce" |
|||
(Vector.reduce (fun acc x -> acc ** x) smallv |> should approximately_equal 14 0.990295218585507) |
|||
spec "Vector.reduceBack" |
|||
(Vector.reduceBack (fun x acc -> x ** acc) smallv |> should approximately_equal 14 0.488911287726319) |
|||
spec "Vector.insert" |
|||
(Vector.insert 2 0.5 smallv |> should approximately_vector_equal 14 (new DenseVector ( [|0.3;0.3;0.5;0.3;0.3;0.3|] ) :> Vector<float>) ) |
|||
] |
|||
|
|||
|
|||
/// Unit tests for the matrix type. |
|||
let MatrixTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallM = new DenseMatrix( Array2D.create 2 2 0.3 ) |
|||
let failingFoldBackM = DenseMatrix.init 2 3 (fun i j -> 1.0) |
|||
|
|||
|
|||
/// A large vector with increasingly large entries |
|||
let largeM = new DenseMatrix( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) ) |
|||
|
|||
specs "Matrix" [ |
|||
spec "Matrix.fold" |
|||
(Matrix.fold (fun a b -> a - b) 0.0 smallM |> should equal -1.2) |
|||
spec "Matrix.foldBack" |
|||
(Matrix.foldBack (fun a b -> a - b) 0.0 smallM |> should equal 0.0) |
|||
spec "Matrix.foldBackSummation" |
|||
(Matrix.foldBack( fun a b -> a + b) 0.0 failingFoldBackM |> should equal 6.0) |
|||
spec "Matrix.foldi" |
|||
(Matrix.foldi (fun i j acc x -> acc + x + float (i+j)) 0.0 smallM |> should equal 5.2) |
|||
spec "Matrix.toArray2" |
|||
(Matrix.toArray2 smallM |> should array2_equal (Array2D.create 2 2 0.3)) |
|||
spec "Matrix.forall" |
|||
(Matrix.forall (fun x -> x = 0.3) smallM |> should equal true) |
|||
spec "Matrix.exists" |
|||
(Matrix.exists (fun x -> x = 0.5) smallM |> should equal false) |
|||
spec "Matrix.foralli" |
|||
(Matrix.foralli (fun i j x -> x = float i * 100.0 + float j) largeM |> should equal true) |
|||
spec "Matrix.existsi" |
|||
(Matrix.existsi (fun i j x -> x = float i * 100.0 + float j) largeM |> should equal true) |
|||
spec "Matrix.map" |
|||
(Matrix.map (fun x -> 2.0 * x) smallM |> should equal (2.0 * smallM)) |
|||
spec "Matrix.mapi" |
|||
(Matrix.mapi (fun i j x -> float i * 100.0 + float j + x) largeM |> should equal (2.0 * largeM)) |
|||
spec "Matrix.mapCols" |
|||
(Matrix.mapCols (fun j col -> col.Add(float j)) smallM |> should approximately_matrix_equal 14 (matrix [[0.3;1.3];[0.3;1.3]])) |
|||
spec "Matrix.mapRows" |
|||
(Matrix.mapRows (fun i row -> row.Add(float i)) smallM |> should approximately_matrix_equal 14 (matrix [[0.3;0.3];[1.3;1.3]])) |
|||
spec "Matrix.inplaceAssign" |
|||
( let N = smallM.Clone() |
|||
Matrix.inplaceAssign (fun i j -> 0.0) N |
|||
N |> should equal (0.0 * smallM)) |
|||
spec "Matrix.inplaceMapi" |
|||
( let N = largeM.Clone() |
|||
Matrix.inplaceMapi (fun i j x -> 2.0 * (float i * 100.0 + float j) + x) N |
|||
N |> should equal (3.0 * largeM)) |
|||
spec "Matrix.nonZeroEntries" |
|||
(Seq.length (Matrix.nonZeroEntries smallM) |> should equal 4) |
|||
spec "Matrix.sum" |
|||
(Matrix.sum smallM |> should equal 1.2) |
|||
spec "Matrix.sumColsBy" |
|||
(Matrix.sumColsBy (fun j col -> col.[0] * col.[1]) (matrix [[1.0; 2.0]; [3.0; 4.0]]) |> should equal 11.0) |
|||
spec "Matrix.sumRowsBy" |
|||
(Matrix.sumRowsBy (fun i row -> row.[0] * row.[1]) (matrix [[1.0; 2.0]; [3.0; 4.0]]) |> should equal 14.0) |
|||
spec "Matrix.foldCol" |
|||
(Matrix.foldCol (+) 0.0 largeM 0 |> should equal 495000.0) |
|||
spec "Matrix.foldRow" |
|||
(Matrix.foldRow (+) 0.0 largeM 0 |> should equal 4950.0) |
|||
spec "Matrix.foldByCol" |
|||
(Matrix.foldByCol (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector<float>)) |
|||
spec "Matrix.foldByRow" |
|||
(Matrix.foldByRow (+) 0.0 smallM |> should equal (DenseVector.ofList [0.6;0.6] :> Vector<float>)) |
|||
] |
|||
|
|||
|
|||
/// Unit tests for the dense matrix type. |
|||
let DenseMatrixTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallM = new DenseMatrix( Array2D.create 2 2 0.3 ) |
|||
|
|||
/// A large vector with increasingly large entries |
|||
let largeM = new DenseMatrix( Array2D.init 100 100 (fun i j -> float i * 100.0 + float j) ) |
|||
|
|||
specs "DenseMatrix" [ |
|||
spec "DenseMatrix.init" |
|||
(DenseMatrix.init 100 100 (fun i j -> float i * 100.0 + float j) |> should equal largeM) |
|||
spec "DenseMatrix.ofList" |
|||
(DenseMatrix.ofList [[0.3;0.3];[0.3;0.3]] |> should equal smallM) |
|||
spec "DenseMatrix.ofSeq" |
|||
(DenseMatrix.ofSeq (Seq.ofList [[0.3;0.3];[0.3;0.3]]) |> should equal smallM) |
|||
spec "DenseMatrix.ofArray2" |
|||
(DenseMatrix.ofArray2 (Array2D.create 2 2 0.3) |> should equal smallM) |
|||
spec "DenseMatrix.initDense" |
|||
(DenseMatrix.initDense 100 100 (seq { for i in 0 .. 99 do |
|||
for j in 0 .. 99 -> (i,j, float i * 100.0 + float j)}) |> should equal largeM) |
|||
spec "DenseMatrix.constDiag" |
|||
(DenseMatrix.constDiag 100 2.0 |> should equal (2.0 * (DenseMatrix.Identity 100))) |
|||
spec "DenseMatrix.diag" |
|||
(DenseMatrix.diag (new DenseVector(100, 2.0)) |> should equal (2.0 * (DenseMatrix.Identity 100))) |
|||
spec "DenseMatrix.init_row" |
|||
(DenseMatrix.initRow 100 100 (fun i -> (DenseVector.init 100 (fun j -> float i * 100.0 + float j))) |> should equal largeM) |
|||
spec "DenseMatrix.init_col" |
|||
(DenseMatrix.initCol 100 100 (fun j -> (DenseVector.init 100 (fun i -> float i * 100.0 + float j))) |> should equal largeM) |
|||
] |
|||
|
|||
|
|||
/// Unit tests for the sparse matrix type. |
|||
let SparseMatrixTests = |
|||
|
|||
/// A small uniform vector. |
|||
let smallM = DenseMatrix.init 4 4 (fun i j -> if i = 1 && j = 2 then 1.0 else 0.0) :> Matrix<float> |
|||
|
|||
specs "SparseMatrix" [ |
|||
spec "SparseMatrix.ofList" |
|||
((SparseMatrix.ofList 4 4 [(1,2,1.0)] :> Matrix<float>) |> should equal smallM) |
|||
spec "SparseMatrix.ofSeq" |
|||
((SparseMatrix.ofSeq 4 4 (Seq.ofList [(1,2,1.0)]) :> Matrix<float>) |> should equal smallM) |
|||
spec "SparseMatrix.constDiag" |
|||
(SparseMatrix.constDiag 100 2.0 |> should equal (2.0 * (SparseMatrix.Identity 100))) |
|||
spec "SparseMatrix.diag" |
|||
(SparseMatrix.diag (new DenseVector(100, 2.0)) |> should equal (2.0 * (SparseMatrix.Identity 100))) |
|||
] |
|||
|
|||
|
|||
/// Report on errors and success and exit. |
|||
printfn "F# Test Results:" |
|||
printfn "%s" (Results.summary()) |
|||
|
|||
let code = if Results.erredCount() > 0 || Results.failedCount() > 0 then -1 else 0;; |
|||
exit code;; |
|||
Binary file not shown.
@ -0,0 +1,118 @@ |
|||
/* Body style, for the entire document */ |
|||
body |
|||
{ |
|||
background: #F3F3F4; |
|||
color: #1E1E1F; |
|||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; |
|||
padding: 0; |
|||
margin: 0; |
|||
} |
|||
|
|||
/* Header1 style, used for the main title */ |
|||
h1 |
|||
{ |
|||
padding: 10px 0px 10px 10px; |
|||
font-size: 21pt; |
|||
background-color: #E2E2E2; |
|||
border-bottom: 1px #C1C1C2 solid; |
|||
color: #201F20; |
|||
margin: 0; |
|||
font-weight: normal; |
|||
} |
|||
|
|||
/* Header2 style, used for "Overview" and other sections */ |
|||
h2 |
|||
{ |
|||
font-size: 18pt; |
|||
font-weight: normal; |
|||
padding: 15px 0 5px 0; |
|||
margin: 0; |
|||
} |
|||
|
|||
/* Header3 style, used for sub-sections, such as project name */ |
|||
h3 |
|||
{ |
|||
font-weight: normal; |
|||
font-size: 15pt; |
|||
margin: 0; |
|||
padding: 15px 0 5px 0; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
/* Color all hyperlinks one color */ |
|||
a |
|||
{ |
|||
color: #1382CE; |
|||
} |
|||
|
|||
/* Table styles */ |
|||
table |
|||
{ |
|||
border-spacing: 0 0; |
|||
border-collapse: collapse; |
|||
font-size: 10pt; |
|||
} |
|||
|
|||
table th |
|||
{ |
|||
background: #E7E7E8; |
|||
text-align: left; |
|||
text-decoration: none; |
|||
font-weight: normal; |
|||
padding: 3px 6px 3px 6px; |
|||
} |
|||
|
|||
table td |
|||
{ |
|||
vertical-align: top; |
|||
padding: 3px 6px 5px 5px; |
|||
margin: 0px; |
|||
border: 1px solid #E7E7E8; |
|||
background: #F7F7F8; |
|||
} |
|||
|
|||
/* Local link is a style for hyperlinks that link to file:/// content, there are lots so color them as 'normal' text until the user mouse overs */ |
|||
.localLink |
|||
{ |
|||
color: #1E1E1F; |
|||
background: #EEEEED; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.localLink:hover |
|||
{ |
|||
color: #1382CE; |
|||
background: #FFFF99; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
/* Center text, used in the over views cells that contain message level counts */ |
|||
.textCentered |
|||
{ |
|||
text-align: center; |
|||
} |
|||
|
|||
/* The message cells in message tables should take up all avaliable space */ |
|||
.messageCell |
|||
{ |
|||
width: 100%; |
|||
} |
|||
|
|||
/* Padding around the content after the h1 */ |
|||
#content |
|||
{ |
|||
padding: 0px 12px 12px 12px; |
|||
} |
|||
|
|||
/* The overview table expands to width, with a max width of 97% */ |
|||
#overview table |
|||
{ |
|||
width: auto; |
|||
max-width: 75%; |
|||
} |
|||
|
|||
/* The messages tables are always 97% width */ |
|||
#messages table |
|||
{ |
|||
width: 97%; |
|||
} |
|||
@ -0,0 +1,558 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl='urn:schemas-microsoft-com:xslt'> |
|||
<xsl:output omit-xml-declaration="yes" /> |
|||
|
|||
<!-- Keys --> |
|||
<xsl:key name="ProjectKey" match="Event" use="@Project" /> |
|||
|
|||
<!-- String split template --> |
|||
<xsl:template name="SplitString"> |
|||
<xsl:param name="source" select="''" /> |
|||
<xsl:param name="separator" select="','" /> |
|||
<xsl:if test="not($source = '' or $separator = '')"> |
|||
<xsl:variable name="head" select="substring-before(concat($source, $separator), $separator)" /> |
|||
<xsl:variable name="tail" select="substring-after($source, $separator)" /> |
|||
<part> |
|||
<xsl:value-of select="$head"/> |
|||
</part> |
|||
<xsl:call-template name="SplitString"> |
|||
<xsl:with-param name="source" select="$tail" /> |
|||
<xsl:with-param name="separator" select="$separator" /> |
|||
</xsl:call-template> |
|||
</xsl:if> |
|||
</xsl:template> |
|||
|
|||
<!-- Intermediate Templates --> |
|||
<xsl:template match="UpgradeReport" mode="ProjectOverviewXML"> |
|||
<Projects> |
|||
<xsl:for-each select="Event[generate-id(.) = generate-id(key('ProjectKey', @Project))]"> |
|||
<Project> |
|||
<xsl:variable name="pNode" select="current()" /> |
|||
<xsl:variable name="errorCount" select="count(../Event[@Project = current()/@Project and @ErrorLevel=2])" /> |
|||
<xsl:variable name="warningCount" select="count(../Event[@Project = current()/@Project and @ErrorLevel=1])" /> |
|||
<xsl:variable name="messageCount" select="count(../Event[@Project = current()/@Project and @ErrorLevel=0])" /> |
|||
<xsl:variable name="pathSplitSeparator"> |
|||
<xsl:text>\</xsl:text> |
|||
</xsl:variable> |
|||
<xsl:variable name="projectName"> |
|||
<xsl:choose> |
|||
<xsl:when test="@Project = ''">Solution</xsl:when> |
|||
<xsl:otherwise> |
|||
<xsl:value-of select="@Project"/> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
</xsl:variable> |
|||
<xsl:attribute name="IsSolution"> |
|||
<xsl:value-of select="@Project = ''"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Project"> |
|||
<xsl:value-of select="$projectName"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="ProjectDisplayName"> |
|||
|
|||
<xsl:variable name="localProjectName" select="@Project" /> |
|||
|
|||
<!-- Sometimes it is possible to have project name set to a path over a real project name, |
|||
we split the string on '\' and if we end up with >1 part in the resulting tokens set |
|||
we format the ProjectDisplayName as ..\prior\last --> |
|||
<xsl:variable name="pathTokens"> |
|||
<xsl:call-template name="SplitString"> |
|||
<xsl:with-param name="source" select="$localProjectName" /> |
|||
<xsl:with-param name="separator" select="$pathSplitSeparator" /> |
|||
</xsl:call-template> |
|||
</xsl:variable> |
|||
|
|||
<xsl:choose> |
|||
<xsl:when test="count(msxsl:node-set($pathTokens)/part) > 1"> |
|||
<xsl:value-of select="concat('..', $pathSplitSeparator, msxsl:node-set($pathTokens)/part[last() - 1], $pathSplitSeparator, msxsl:node-set($pathTokens)/part[last()])"/> |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
<xsl:value-of select="$localProjectName"/> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
|
|||
</xsl:attribute> |
|||
<xsl:attribute name="ProjectSafeName"> |
|||
<xsl:value-of select="translate($projectName, '\', '-')"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Solution"> |
|||
<xsl:value-of select="/UpgradeReport/Properties/Property[@Name='Solution']/@Value"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Source"> |
|||
<xsl:value-of select="@Source"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Status"> |
|||
<xsl:choose> |
|||
<xsl:when test="$errorCount > 0">Error</xsl:when> |
|||
<xsl:when test="$warningCount > 0">Warning</xsl:when> |
|||
<xsl:otherwise>Success</xsl:otherwise> |
|||
</xsl:choose> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="ErrorCount"> |
|||
<xsl:value-of select="$errorCount" /> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="WarningCount"> |
|||
<xsl:value-of select="$warningCount" /> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="MessageCount"> |
|||
<xsl:value-of select="$messageCount" /> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="TotalCount"> |
|||
<xsl:value-of select="$errorCount + $warningCount + $messageCount"/> |
|||
</xsl:attribute> |
|||
<xsl:for-each select="../Event[@Project = $pNode/@Project and @ErrorLevel=3]"> |
|||
<ConversionStatus> |
|||
<xsl:value-of select="@Description"/> |
|||
</ConversionStatus> |
|||
</xsl:for-each> |
|||
<Messages> |
|||
<xsl:for-each select="../Event[@Project = $pNode/@Project and @ErrorLevel<3]"> |
|||
<Message> |
|||
<xsl:attribute name="Level"> |
|||
<xsl:value-of select="@ErrorLevel" /> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Status"> |
|||
<xsl:choose> |
|||
<xsl:when test="@ErrorLevel = 0">Message</xsl:when> |
|||
<xsl:when test="@ErrorLevel = 1">Warning</xsl:when> |
|||
<xsl:when test="@ErrorLevel = 2">Error</xsl:when> |
|||
<xsl:otherwise>Message</xsl:otherwise> |
|||
</xsl:choose> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Source"> |
|||
<xsl:value-of select="@Source"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="Message"> |
|||
<xsl:value-of select="@Description"/> |
|||
</xsl:attribute> |
|||
</Message> |
|||
</xsl:for-each> |
|||
</Messages> |
|||
</Project> |
|||
</xsl:for-each> |
|||
</Projects> |
|||
</xsl:template> |
|||
|
|||
|
|||
|
|||
<!-- Project Overview template --> |
|||
<xsl:template match="Projects" mode="ProjectOverview"> |
|||
|
|||
<table> |
|||
<tr> |
|||
<th></th> |
|||
<th _locID="ProjectTableHeader">Project</th> |
|||
<th _locID="PathTableHeader">Path</th> |
|||
<th _locID="ErrorsTableHeader">Errors</th> |
|||
<th _locID="WarningsTableHeader">Warnings</th> |
|||
<th _locID="MessagesTableHeader">Messages</th> |
|||
</tr> |
|||
|
|||
<xsl:for-each select="Project"> |
|||
|
|||
<xsl:sort select="@ErrorCount" order="descending" /> |
|||
<xsl:sort select="@WarningCount" order="descending" /> |
|||
<!-- Always make solution last within a group --> |
|||
<xsl:sort select="@IsSolution" order="ascending" /> |
|||
<xsl:sort select="@ProjectSafeName" order="ascending" /> |
|||
|
|||
<tr> |
|||
<td> |
|||
<img width="16" height="16"> |
|||
<xsl:attribute name="src"> |
|||
<xsl:choose> |
|||
<xsl:when test="@Status = 'Error'">_UpgradeReport_Files\UpgradeReport_Error.png</xsl:when> |
|||
<xsl:when test="@Status = 'Warning'">_UpgradeReport_Files\UpgradeReport_Warning.png</xsl:when> |
|||
<xsl:when test="@Status = 'Success'">_UpgradeReport_Files\UpgradeReport_Success.png</xsl:when> |
|||
</xsl:choose> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="alt"> |
|||
<xsl:value-of select="@Status" /> |
|||
</xsl:attribute> |
|||
</img> |
|||
</td> |
|||
<td> |
|||
<strong> |
|||
<a> |
|||
<xsl:attribute name="href"> |
|||
<xsl:value-of select="concat('#', @ProjectSafeName)"/> |
|||
</xsl:attribute> |
|||
<xsl:choose> |
|||
<xsl:when test="@ProjectDisplayName = ''"> |
|||
<span _locID="OverviewSolutionSpan">Solution</span> |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
<xsl:value-of select="@ProjectDisplayName" /> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
</a> |
|||
</strong> |
|||
</td> |
|||
<td> |
|||
<xsl:value-of select="@Source" /> |
|||
</td> |
|||
<td class="textCentered"> |
|||
<a> |
|||
<xsl:if test="@ErrorCount > 0"> |
|||
<xsl:attribute name="href"> |
|||
<xsl:value-of select="concat('#', @ProjectSafeName, 'Error')"/> |
|||
</xsl:attribute> |
|||
</xsl:if> |
|||
<xsl:value-of select="@ErrorCount" /> |
|||
</a> |
|||
</td> |
|||
<td class="textCentered"> |
|||
<a> |
|||
<xsl:if test="@WarningCount > 0"> |
|||
<xsl:attribute name="href"> |
|||
<xsl:value-of select="concat('#', @ProjectSafeName, 'Warning')"/> |
|||
</xsl:attribute> |
|||
</xsl:if> |
|||
<xsl:value-of select="@WarningCount" /> |
|||
</a> |
|||
</td> |
|||
<td class="textCentered"> |
|||
<a href="#"> |
|||
<xsl:if test="@MessageCount > 0"> |
|||
<xsl:attribute name="onclick"> |
|||
<xsl:variable name="apos"> |
|||
<xsl:text>'</xsl:text> |
|||
</xsl:variable> |
|||
<xsl:variable name="JS" select="concat('ScrollToFirstVisibleMessage(', $apos, @ProjectSafeName, $apos, ')')" /> |
|||
<xsl:value-of select="concat($JS, '; return false;')"/> |
|||
</xsl:attribute> |
|||
</xsl:if> |
|||
<xsl:value-of select="@MessageCount" /> |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
</xsl:for-each> |
|||
</table> |
|||
</xsl:template> |
|||
|
|||
<!-- Show messages row --> |
|||
<xsl:template match="Project" mode="ProjectShowMessages"> |
|||
<tr> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat('MessageRowHeaderShow', @ProjectSafeName)"/> |
|||
</xsl:attribute> |
|||
<td> |
|||
<img width="16" height="16" src="_UpgradeReport_Files\UpgradeReport_Information.png" /> |
|||
</td> |
|||
<td class="messageCell"> |
|||
<xsl:variable name="apos"> |
|||
<xsl:text>'</xsl:text> |
|||
</xsl:variable> |
|||
<xsl:variable name="toggleRowsJS" select="concat('ToggleMessageVisibility(', $apos, @ProjectSafeName, $apos, ')')" /> |
|||
|
|||
<a _locID="ShowAdditionalMessages" href="#"> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat(@ProjectSafeName, 'Message')"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="onclick"> |
|||
<xsl:value-of select="concat($toggleRowsJS, '; return false;')"/> |
|||
</xsl:attribute> |
|||
Show <xsl:value-of select="@MessageCount" /> additional messages |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
</xsl:template> |
|||
|
|||
<!-- Hide messages row --> |
|||
<xsl:template match="Project" mode="ProjectHideMessages"> |
|||
<tr style="display: none"> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat('MessageRowHeaderHide', @ProjectSafeName)"/> |
|||
</xsl:attribute> |
|||
<td> |
|||
<img width="16" height="16" src="_UpgradeReport_Files\UpgradeReport_Information.png" /> |
|||
</td> |
|||
<td class="messageCell"> |
|||
<xsl:variable name="apos"> |
|||
<xsl:text>'</xsl:text> |
|||
</xsl:variable> |
|||
<xsl:variable name="toggleRowsJS" select="concat('ToggleMessageVisibility(', $apos, @ProjectSafeName, $apos, ')')" /> |
|||
|
|||
<a _locID="HideAdditionalMessages" href="#"> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat(@ProjectSafeName, 'Message')"/> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="onclick"> |
|||
<xsl:value-of select="concat($toggleRowsJS, '; return false;')"/> |
|||
</xsl:attribute> |
|||
Hide <xsl:value-of select="@MessageCount" /> additional messages |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
</xsl:template> |
|||
|
|||
<!-- Message row templates --> |
|||
<xsl:template match="Message"> |
|||
<tr> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat(@Status, 'RowClass', ../../@ProjectSafeName)"/> |
|||
</xsl:attribute> |
|||
|
|||
<xsl:if test="@Level = 0"> |
|||
<xsl:attribute name="style">display: none</xsl:attribute> |
|||
</xsl:if> |
|||
<td> |
|||
<a> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="concat(../../@ProjectSafeName, @Status)"/> |
|||
</xsl:attribute> |
|||
</a> |
|||
<img width="16" height="16"> |
|||
<xsl:attribute name="src"> |
|||
<xsl:choose> |
|||
<xsl:when test="@Status = 'Error'">_UpgradeReport_Files\UpgradeReport_Error.png</xsl:when> |
|||
<xsl:when test="@Status = 'Warning'">_UpgradeReport_Files\UpgradeReport_Warning.png</xsl:when> |
|||
<xsl:when test="@Status = 'Message'">_UpgradeReport_Files\UpgradeReport_Information.png</xsl:when> |
|||
</xsl:choose> |
|||
</xsl:attribute> |
|||
<xsl:attribute name="alt"> |
|||
<xsl:value-of select="@Status" /> |
|||
</xsl:attribute> |
|||
</img> |
|||
</td> |
|||
<td class="messageCell"> |
|||
<strong> |
|||
<xsl:value-of select="@Source"/>: |
|||
</strong> |
|||
<span> |
|||
<xsl:value-of select="@Message"/> |
|||
</span> |
|||
</td> |
|||
</tr> |
|||
</xsl:template> |
|||
|
|||
<!-- Project Details Template --> |
|||
<xsl:template match="Projects" mode="ProjectDetails"> |
|||
|
|||
<xsl:for-each select="Project"> |
|||
<xsl:sort select="@ErrorCount" order="descending" /> |
|||
<xsl:sort select="@WarningCount" order="descending" /> |
|||
<!-- Always make solution last within a group --> |
|||
<xsl:sort select="@IsSolution" order="ascending" /> |
|||
<xsl:sort select="@ProjectSafeName" order="ascending" /> |
|||
|
|||
<a> |
|||
<xsl:attribute name="name"> |
|||
<xsl:value-of select="@ProjectSafeName"/> |
|||
</xsl:attribute> |
|||
</a> |
|||
<xsl:choose> |
|||
<xsl:when test="@ProjectDisplayName = ''"> |
|||
<h3 _locID="ProjectDisplayNameHeader">Solution</h3> |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
<h3> |
|||
<xsl:value-of select="@ProjectDisplayName"/> |
|||
</h3> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
|
|||
<table> |
|||
<tr> |
|||
<xsl:attribute name="id"> |
|||
<xsl:value-of select="concat(@ProjectSafeName, 'HeaderRow')"/> |
|||
</xsl:attribute> |
|||
<th></th> |
|||
<th class="messageCell" _locID="MessageTableHeader">Message</th> |
|||
</tr> |
|||
|
|||
<!-- Errors and warnings --> |
|||
<xsl:for-each select="Messages/Message[@Level > 0]"> |
|||
<xsl:sort select="@Level" order="descending" /> |
|||
<xsl:apply-templates select="." /> |
|||
</xsl:for-each> |
|||
|
|||
<xsl:if test="@MessageCount > 0"> |
|||
<xsl:apply-templates select="." mode="ProjectShowMessages" /> |
|||
</xsl:if> |
|||
|
|||
<!-- Messages --> |
|||
<xsl:for-each select="Messages/Message[@Level = 0]"> |
|||
<xsl:apply-templates select="." /> |
|||
</xsl:for-each> |
|||
|
|||
<xsl:choose> |
|||
<!-- Additional row as a 'place holder' for 'Show/Hide' additional messages --> |
|||
<xsl:when test="@MessageCount > 0"> |
|||
<xsl:apply-templates select="." mode="ProjectHideMessages" /> |
|||
</xsl:when> |
|||
<!-- No messages at all, show blank row --> |
|||
<xsl:when test="@TotalCount = 0"> |
|||
<tr> |
|||
<td> |
|||
<img width="16" height="16" src="_UpgradeReport_Files\UpgradeReport_Information.png" /> |
|||
</td> |
|||
<xsl:choose> |
|||
<xsl:when test="@ProjectDisplayName = ''"> |
|||
<td class="messageCell" _locID="NoMessagesRow2"> |
|||
Solution logged no messages. |
|||
</td> |
|||
</xsl:when> |
|||
<xsl:otherwise> |
|||
<td class="messageCell" _locID="NoMessagesRow"> |
|||
<xsl:value-of select="@ProjectDisplayName" /> logged no messages. |
|||
</td> |
|||
</xsl:otherwise> |
|||
</xsl:choose> |
|||
</tr> |
|||
</xsl:when> |
|||
</xsl:choose> |
|||
</table> |
|||
</xsl:for-each> |
|||
</xsl:template> |
|||
|
|||
<!-- Document, matches "UpgradeReport" --> |
|||
<xsl:template match="UpgradeReport"> |
|||
<!-- Output doc type the 'Mark of the web' which disabled prompting to run JavaScript from local HTML Files in IE --> |
|||
<!-- NOTE: The whitespace around the 'Mark of the web' is important it must be exact --> |
|||
<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE html> |
|||
<!-- saved from url=(0014)about:internet --> |
|||
]]> |
|||
</xsl:text> |
|||
<html> |
|||
<head> |
|||
<meta content="en-us" http-equiv="Content-Language" /> |
|||
<meta content="text/html; charset=utf-16" http-equiv="Content-Type" /> |
|||
<link type="text/css" rel="stylesheet" href="_UpgradeReport_Files\UpgradeReport.css" /> |
|||
<title _locID="ConversionReport0"> |
|||
Migration Report |
|||
</title> |
|||
|
|||
<script type="text/javascript" language="javascript"> |
|||
<xsl:text disable-output-escaping="yes"> |
|||
<![CDATA[ |
|||
|
|||
// Startup |
|||
// Hook up the the loaded event for the document/window, to linkify the document content |
|||
var startupFunction = function() { linkifyElement("messages"); }; |
|||
|
|||
if(window.attachEvent) |
|||
{ |
|||
window.attachEvent('onload', startupFunction); |
|||
} |
|||
else if (window.addEventListener) |
|||
{ |
|||
window.addEventListener('load', startupFunction, false); |
|||
} |
|||
else |
|||
{ |
|||
document.addEventListener('load', startupFunction, false); |
|||
} |
|||
|
|||
// Toggles the visibility of table rows with the specified name |
|||
function toggleTableRowsByName(name) |
|||
{ |
|||
var allRows = document.getElementsByTagName('tr'); |
|||
for (i=0; i < allRows.length; i++) |
|||
{ |
|||
var currentName = allRows[i].getAttribute('name'); |
|||
if(!!currentName && currentName.indexOf(name) == 0) |
|||
{ |
|||
var isVisible = allRows[i].style.display == ''; |
|||
isVisible ? allRows[i].style.display = 'none' : allRows[i].style.display = ''; |
|||
} |
|||
} |
|||
} |
|||
|
|||
function scrollToFirstVisibleRow(name) |
|||
{ |
|||
var allRows = document.getElementsByTagName('tr'); |
|||
for (i=0; i < allRows.length; i++) |
|||
{ |
|||
var currentName = allRows[i].getAttribute('name'); |
|||
var isVisible = allRows[i].style.display == ''; |
|||
if(!!currentName && currentName.indexOf(name) == 0 && isVisible) |
|||
{ |
|||
allRows[i].scrollIntoView(true); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
// Linkifies the specified text content, replaces candidate links with html links |
|||
function linkify(text) |
|||
{ |
|||
if(!text || 0 === text.length) |
|||
{ |
|||
return text; |
|||
} |
|||
|
|||
// Find http, https and ftp links and replace them with hyper links |
|||
var urlLink = /(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.]+(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._\?\,\/\\\+&%\$#\=~;\{\}])*/gi; |
|||
|
|||
return text.replace(urlLink, '<a href="$&">$&</a>') ; |
|||
} |
|||
|
|||
// Linkifies the specified element by ID |
|||
function linkifyElement(id) |
|||
{ |
|||
var element = document.getElementById(id); |
|||
if(!!element) |
|||
{ |
|||
element.innerHTML = linkify(element.innerHTML); |
|||
} |
|||
} |
|||
|
|||
function ToggleMessageVisibility(projectName) |
|||
{ |
|||
if(!projectName || 0 === projectName.length) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
toggleTableRowsByName("MessageRowClass" + projectName); |
|||
toggleTableRowsByName('MessageRowHeaderShow' + projectName); |
|||
toggleTableRowsByName('MessageRowHeaderHide' + projectName); |
|||
} |
|||
|
|||
function ScrollToFirstVisibleMessage(projectName) |
|||
{ |
|||
if(!projectName || 0 === projectName.length) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// First try the 'Show messages' row |
|||
if(!scrollToFirstVisibleRow('MessageRowHeaderShow' + projectName)) |
|||
{ |
|||
// Failed to find a visible row for 'Show messages', try an actual message row |
|||
scrollToFirstVisibleRow('MessageRowClass' + projectName); |
|||
} |
|||
} |
|||
]]> |
|||
</xsl:text> |
|||
</script> |
|||
</head> |
|||
<body> |
|||
<h1 _locID="ConversionReport"> |
|||
Migration Report - <xsl:value-of select="Properties/Property[@Name='Solution']/@Value"/> |
|||
</h1> |
|||
|
|||
<div id="content"> |
|||
<h2 _locID="OverviewTitle">Overview</h2> |
|||
<xsl:variable name="projectOverview"> |
|||
<xsl:apply-templates select="self::node()" mode="ProjectOverviewXML" /> |
|||
</xsl:variable> |
|||
|
|||
<div id="overview"> |
|||
<xsl:apply-templates select="msxsl:node-set($projectOverview)/*" mode="ProjectOverview" /> |
|||
</div> |
|||
|
|||
<h2 _locID="SolutionAndProjectsTitle">Solution and projects</h2> |
|||
|
|||
<div id="messages"> |
|||
<xsl:apply-templates select="msxsl:node-set($projectOverview)/*" mode="ProjectDetails" /> |
|||
</div> |
|||
</div> |
|||
</body> |
|||
</html> |
|||
</xsl:template> |
|||
|
|||
</xsl:stylesheet> |
|||
|
After Width: | Height: | Size: 397 B |
|
After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 381 B |
|
After Width: | Height: | Size: 292 B |
@ -0,0 +1,355 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Complex |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using MathNet.Numerics.LinearAlgebra.Storage; |
|||
using Generic; |
|||
using Properties; |
|||
using Threading; |
|||
using System.Numerics; |
|||
using Storage; |
|||
|
|||
/// <summary>
|
|||
/// A Matrix class with sparse storage. The underlying storage scheme is pointers to lefter and upper elements Format.
|
|||
/// Algorithm was posted in "The Art of Computer Programming" - Knuth - 1968
|
|||
/// </summary>
|
|||
public class KnuthSparseMatrix : Matrix |
|||
{ |
|||
/// <summary>
|
|||
/// Storage element
|
|||
/// </summary>
|
|||
private KnuthSparseMatrixStorage<Complex> storage; |
|||
|
|||
/// <summary>
|
|||
/// Creates a <c>KnuthSparseMatrix</c> for the given number of rows and columns.
|
|||
/// </summary>
|
|||
/// <param name="numberOfRows">The number of rows.</param>
|
|||
/// <param name="numberOfColumns">The number of columns.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
|||
/// <returns>
|
|||
/// A <c>SparseMatrix</c> with the given dimensions.
|
|||
/// </returns>
|
|||
public override Matrix<Complex> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
|||
{ |
|||
return new KnuthSparseMatrix(numberOfRows, numberOfColumns); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="SparseVector"/> with a the given dimension.
|
|||
/// </summary>
|
|||
/// <param name="size">The size of the vector.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="SparseVector"/> with the given dimension.
|
|||
/// </returns>
|
|||
public override Vector<Complex> CreateVector(int size, bool fullyMutable = false) |
|||
{ |
|||
return new SparseVector(size); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of non zero elements in the matrix.
|
|||
/// </summary>
|
|||
/// <value>The number of non zero elements.</value>
|
|||
public int NonZerosCount() |
|||
{ |
|||
int result = 0; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
KnuthNode<Complex> iter = storage.Rows[i]; |
|||
while (iter.Left != storage.Rows[i]) |
|||
{ |
|||
++result; |
|||
iter = iter.Left; |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Insert new value to current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
/// <param name="val">value to insert</param>
|
|||
public void At(int row, int col, Complex val) |
|||
{ |
|||
storage.At(row, col, val); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value at current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
public Complex At(int row, int col) |
|||
{ |
|||
return storage.At(row, col); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if elements are equals
|
|||
/// </summary>
|
|||
/// <param name="obj">opject to compare</param>
|
|||
/// <returns>if they are equals</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return base.Equals(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets hash code of element
|
|||
/// </summary>
|
|||
/// <returns>hash code</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return base.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrixStorage<Complex> _storage) |
|||
: base(_storage) |
|||
{ |
|||
storage = _storage; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrix mtx) |
|||
: base(mtx.storage) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="rows">
|
|||
/// The number of rows.
|
|||
/// </param>
|
|||
/// <param name="columns">
|
|||
/// The number of columns.
|
|||
/// </param>
|
|||
public KnuthSparseMatrix(int rows, int columns) |
|||
: this(new KnuthSparseMatrixStorage<Complex>(rows, columns, 0)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class. This matrix is square with a given size.
|
|||
/// </summary>
|
|||
/// <param name="order">the size of the square matrix.</param>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// If <paramref name="order"/> is less than one.
|
|||
/// </exception>
|
|||
public KnuthSparseMatrix(int order) |
|||
: this(order, order) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SparseMatrix"/> class from a 2D array.
|
|||
/// </summary>
|
|||
/// <param name="array">The 2D array to create this matrix from.</param>
|
|||
public KnuthSparseMatrix(Complex[,] array) |
|||
: this(array.GetLength(0), array.GetLength(1)) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i, j]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix in list<list> presentation to set as sparse</param>
|
|||
public KnuthSparseMatrix(List<List<Complex>> array) |
|||
: this(array.Count, array[0].Count) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i][j]); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
public void Negate() |
|||
{ |
|||
KnuthNode<Complex> rw; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
rw = storage.Rows[i]; |
|||
while (rw.Left != storage.Rows[i]) |
|||
{ |
|||
rw.Val *= -1; |
|||
rw = rw.Left; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiply two sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of multiplying this matrix</returns>
|
|||
public static KnuthSparseMatrix operator *(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Cols.Count != mtx2.storage.Rows.Count) |
|||
throw new Exception("Wrong size of matrix to multiple"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx2.storage.Cols.Count); |
|||
Complex tmp; |
|||
KnuthNode<Complex> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
for (int j = 0; j < mtx2.storage.Cols.Count; ++j) |
|||
{ |
|||
tmp = 0; //initalize mult of i-th row and j-th column
|
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Cols[j].Up; |
|||
while (Iter1 != mtx1.storage.Rows[i] && Iter2 != mtx2.storage.Cols[j]) |
|||
{ |
|||
if (Iter1.Col == Iter2.Row) |
|||
{ |
|||
tmp += Iter1.Val * Iter2.Val; |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else if (Iter1.Col < Iter2.Row) |
|||
{ |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
if (tmp != Complex.Zero) // paste not 0 element
|
|||
{ |
|||
Res.At(i, j, tmp); |
|||
} |
|||
|
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds two matrixes
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of summing this matrixes</returns>
|
|||
public static KnuthSparseMatrix operator +(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Rows.Count != mtx2.storage.Rows.Count || mtx1.storage.Cols.Count != mtx2.storage.Cols.Count) |
|||
throw new Exception("Wrong size of matrix to summ"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx1.storage.Cols.Count); |
|||
KnuthNode<Complex> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Rows[i].Left; |
|||
while (Iter1 != mtx1.storage.Rows[i] || Iter2 != mtx2.storage.Rows[i]) |
|||
{ |
|||
if (Iter1 == mtx1.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter2 == mtx2.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
else if (Iter1.Col == Iter2.Col) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val + Iter2.Val); |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter1.Col < Iter2.Col) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
/// <param name="rightSide"></param>
|
|||
/// <returns></returns>
|
|||
public static KnuthSparseMatrix operator -(KnuthSparseMatrix rightSide) |
|||
{ |
|||
if (rightSide == null) |
|||
{ |
|||
throw new ArgumentNullException("rightSide"); |
|||
} |
|||
KnuthSparseMatrix res = new KnuthSparseMatrix(rightSide); |
|||
res.Negate(); |
|||
return res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if two matrixes is equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are equal, else false</returns>
|
|||
public static bool operator ==(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return mtx1.Equals(mtx2); |
|||
} |
|||
/// <summary>
|
|||
/// Check if two matrixes aren`t equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are not equals, else - false</returns>
|
|||
public static bool operator !=(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return !mtx1.Equals(mtx2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Get current matrix in full standart form
|
|||
/// </summary>
|
|||
/// <returns>matrix in full form</returns>
|
|||
public Complex[][] getFullMatrix() |
|||
{ |
|||
return storage.getFullMatrix(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,349 @@ |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Double |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using MathNet.Numerics.LinearAlgebra.Storage; |
|||
using Generic; |
|||
using Properties; |
|||
using Threading; |
|||
|
|||
/// <summary>
|
|||
/// A Matrix class with sparse storage. The underlying storage scheme is pointers to lefter and upper elements Format.
|
|||
/// Algorithm was posted in "The Art of Computer Programming" - Knuth - 1968
|
|||
/// </summary>
|
|||
public class KnuthSparseMatrix : Matrix |
|||
{ |
|||
/// <summary>
|
|||
/// Storage element
|
|||
/// </summary>
|
|||
private KnuthSparseMatrixStorage<double> storage; |
|||
|
|||
/// <summary>
|
|||
/// Creates a <c>KnuthSparseMatrix</c> for the given number of rows and columns.
|
|||
/// </summary>
|
|||
/// <param name="numberOfRows">The number of rows.</param>
|
|||
/// <param name="numberOfColumns">The number of columns.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
|||
/// <returns>
|
|||
/// A <c>SparseMatrix</c> with the given dimensions.
|
|||
/// </returns>
|
|||
public override Matrix<double> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
|||
{ |
|||
return new KnuthSparseMatrix(numberOfRows, numberOfColumns); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="SparseVector"/> with a the given dimension.
|
|||
/// </summary>
|
|||
/// <param name="size">The size of the vector.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="SparseVector"/> with the given dimension.
|
|||
/// </returns>
|
|||
public override Vector<double> CreateVector(int size, bool fullyMutable = false) |
|||
{ |
|||
return new SparseVector(size); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of non zero elements in the matrix.
|
|||
/// </summary>
|
|||
/// <value>The number of non zero elements.</value>
|
|||
public int NonZerosCount() |
|||
{ |
|||
int result = 0; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
KnuthNode<double> iter = storage.Rows[i]; |
|||
while (iter.Left != storage.Rows[i]) |
|||
{ |
|||
++result; |
|||
iter = iter.Left; |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Insert new value to current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
/// <param name="val">value to insert</param>
|
|||
public void At(int row, int col, double val) |
|||
{ |
|||
storage.At(row, col, val); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value at current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
public double At(int row, int col) |
|||
{ |
|||
return storage.At(row, col); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if elements are equals
|
|||
/// </summary>
|
|||
/// <param name="obj">opject to compare</param>
|
|||
/// <returns>if they are equals</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return base.Equals(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets hash code of element
|
|||
/// </summary>
|
|||
/// <returns>hash code</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return base.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrixStorage<double> _storage) |
|||
: base(_storage) |
|||
{ |
|||
storage = _storage; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrix mtx) |
|||
: base(mtx.storage) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="rows">
|
|||
/// The number of rows.
|
|||
/// </param>
|
|||
/// <param name="columns">
|
|||
/// The number of columns.
|
|||
/// </param>
|
|||
public KnuthSparseMatrix(int rows, int columns) |
|||
: this(new KnuthSparseMatrixStorage<double>(rows, columns, 0d)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class. This matrix is square with a given size.
|
|||
/// </summary>
|
|||
/// <param name="order">the size of the square matrix.</param>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// If <paramref name="order"/> is less than one.
|
|||
/// </exception>
|
|||
public KnuthSparseMatrix(int order) |
|||
: this(order, order) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SparseMatrix"/> class from a 2D array.
|
|||
/// </summary>
|
|||
/// <param name="array">The 2D array to create this matrix from.</param>
|
|||
public KnuthSparseMatrix(double[,] array) |
|||
: this(array.GetLength(0), array.GetLength(1)) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i, j]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix in list<list> presentation to set as sparse</param>
|
|||
public KnuthSparseMatrix(List<List<double>> array) |
|||
: this(array.Count, array[0].Count) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i][j]); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
public void Negate() |
|||
{ |
|||
KnuthNode<double> rw; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
rw = storage.Rows[i]; |
|||
while (rw.Left != storage.Rows[i]) |
|||
{ |
|||
rw.Val *= -1; |
|||
rw = rw.Left; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiply two sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of multiplying this matrix</returns>
|
|||
public static KnuthSparseMatrix operator *(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Cols.Count != mtx2.storage.Rows.Count) |
|||
throw new Exception("Wrong size of matrix to multiple"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx2.storage.Cols.Count); |
|||
double tmp; |
|||
KnuthNode<double> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
for (int j = 0; j < mtx2.storage.Cols.Count; ++j) |
|||
{ |
|||
tmp = 0; //initalize mult of i-th row and j-th column
|
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Cols[j].Up; |
|||
while (Iter1 != mtx1.storage.Rows[i] && Iter2 != mtx2.storage.Cols[j]) |
|||
{ |
|||
if (Iter1.Col == Iter2.Row) |
|||
{ |
|||
tmp += Iter1.Val * Iter2.Val; |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else if (Iter1.Col < Iter2.Row) |
|||
{ |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
if (tmp != 0) // paste not 0 element
|
|||
{ |
|||
Res.At(i, j, tmp); |
|||
} |
|||
|
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds two matrixes
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of summing this matrixes</returns>
|
|||
public static KnuthSparseMatrix operator +(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Rows.Count != mtx2.storage.Rows.Count || mtx1.storage.Cols.Count != mtx2.storage.Cols.Count) |
|||
throw new Exception("Wrong size of matrix to summ"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx1.storage.Cols.Count); |
|||
KnuthNode<double> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Rows[i].Left; |
|||
while (Iter1 != mtx1.storage.Rows[i] || Iter2 != mtx2.storage.Rows[i]) |
|||
{ |
|||
if (Iter1 == mtx1.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter2 == mtx2.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
else if (Iter1.Col == Iter2.Col) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val + Iter2.Val); |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter1.Col < Iter2.Col) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
/// <param name="rightSide"></param>
|
|||
/// <returns></returns>
|
|||
public static KnuthSparseMatrix operator -(KnuthSparseMatrix rightSide) |
|||
{ |
|||
if (rightSide == null) |
|||
{ |
|||
throw new ArgumentNullException("rightSide"); |
|||
} |
|||
KnuthSparseMatrix res = new KnuthSparseMatrix(rightSide); |
|||
res.Negate(); |
|||
return res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if two matrixes is equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are equal, else false</returns>
|
|||
public static bool operator ==(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return mtx1.Equals(mtx2); |
|||
} |
|||
/// <summary>
|
|||
/// Check if two matrixes aren`t equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are not equals, else - false</returns>
|
|||
public static bool operator !=(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return !mtx1.Equals(mtx2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Get current matrix in full standart form
|
|||
/// </summary>
|
|||
/// <returns>matrix in full form</returns>
|
|||
public double[][] getFullMatrix() |
|||
{ |
|||
return storage.getFullMatrix(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,353 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Single |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using MathNet.Numerics.LinearAlgebra.Storage; |
|||
using Generic; |
|||
using Properties; |
|||
using Threading; |
|||
|
|||
/// <summary>
|
|||
/// A Matrix class with sparse storage. The underlying storage scheme is pointers to lefter and upper elements Format.
|
|||
/// Algorithm was posted in "The Art of Computer Programming" - Knuth - 1968
|
|||
/// </summary>
|
|||
public class KnuthSparseMatrix : Matrix |
|||
{ |
|||
/// <summary>
|
|||
/// Storage element
|
|||
/// </summary>
|
|||
private KnuthSparseMatrixStorage<float> storage; |
|||
|
|||
/// <summary>
|
|||
/// Creates a <c>KnuthSparseMatrix</c> for the given number of rows and columns.
|
|||
/// </summary>
|
|||
/// <param name="numberOfRows">The number of rows.</param>
|
|||
/// <param name="numberOfColumns">The number of columns.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable (e.g. not a diagonal matrix).</param>
|
|||
/// <returns>
|
|||
/// A <c>SparseMatrix</c> with the given dimensions.
|
|||
/// </returns>
|
|||
public override Matrix<float> CreateMatrix(int numberOfRows, int numberOfColumns, bool fullyMutable = false) |
|||
{ |
|||
return new KnuthSparseMatrix(numberOfRows, numberOfColumns); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="SparseVector"/> with a the given dimension.
|
|||
/// </summary>
|
|||
/// <param name="size">The size of the vector.</param>
|
|||
/// <param name="fullyMutable">True if all fields must be mutable.</param>
|
|||
/// <returns>
|
|||
/// A <see cref="SparseVector"/> with the given dimension.
|
|||
/// </returns>
|
|||
public override Vector<float> CreateVector(int size, bool fullyMutable = false) |
|||
{ |
|||
return new SparseVector(size); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of non zero elements in the matrix.
|
|||
/// </summary>
|
|||
/// <value>The number of non zero elements.</value>
|
|||
public int NonZerosCount() |
|||
{ |
|||
int result = 0; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
KnuthNode<float> iter = storage.Rows[i]; |
|||
while (iter.Left != storage.Rows[i]) |
|||
{ |
|||
++result; |
|||
iter = iter.Left; |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Insert new value to current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
/// <param name="val">value to insert</param>
|
|||
public void At(int row, int col, float val) |
|||
{ |
|||
storage.At(row, col, val); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a value at current possition
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="col">number of column</param>
|
|||
public float At(int row, int col) |
|||
{ |
|||
return storage.At(row, col); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if elements are equals
|
|||
/// </summary>
|
|||
/// <param name="obj">opject to compare</param>
|
|||
/// <returns>if they are equals</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return base.Equals(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets hash code of element
|
|||
/// </summary>
|
|||
/// <returns>hash code</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return base.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrixStorage<float> _storage) |
|||
: base(_storage) |
|||
{ |
|||
storage = _storage; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="_storage">
|
|||
/// Saved at KnuthSparseMatrixStorage matrix.
|
|||
/// </param>
|
|||
internal KnuthSparseMatrix(KnuthSparseMatrix mtx) |
|||
: base(mtx.storage) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class.
|
|||
/// </summary>
|
|||
/// <param name="rows">
|
|||
/// The number of rows.
|
|||
/// </param>
|
|||
/// <param name="columns">
|
|||
/// The number of columns.
|
|||
/// </param>
|
|||
public KnuthSparseMatrix(int rows, int columns) |
|||
: this(new KnuthSparseMatrixStorage<float>(rows, columns, 0)) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KnuthSparseMatrix"/> class. This matrix is square with a given size.
|
|||
/// </summary>
|
|||
/// <param name="order">the size of the square matrix.</param>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// If <paramref name="order"/> is less than one.
|
|||
/// </exception>
|
|||
public KnuthSparseMatrix(int order) |
|||
: this(order, order) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SparseMatrix"/> class from a 2D array.
|
|||
/// </summary>
|
|||
/// <param name="array">The 2D array to create this matrix from.</param>
|
|||
public KnuthSparseMatrix(float[,] array) |
|||
: this(array.GetLength(0), array.GetLength(1)) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i, j]); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix in list<list> presentation to set as sparse</param>
|
|||
public KnuthSparseMatrix(List<List<float>> array) |
|||
: this(array.Count, array[0].Count) |
|||
{ |
|||
for (var i = 0; i < storage.RowCount; i++) |
|||
{ |
|||
for (var j = 0; j < storage.ColumnCount; j++) |
|||
{ |
|||
storage.At(i, j, array[i][j]); |
|||
} |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
public void Negate() |
|||
{ |
|||
KnuthNode<float> rw; |
|||
for (int i = 0; i < storage.Rows.Count; ++i) |
|||
{ |
|||
rw = storage.Rows[i]; |
|||
while (rw.Left != storage.Rows[i]) |
|||
{ |
|||
rw.Val *= -1; |
|||
rw = rw.Left; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiply two sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of multiplying this matrix</returns>
|
|||
public static KnuthSparseMatrix operator *(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Cols.Count != mtx2.storage.Rows.Count) |
|||
throw new Exception("Wrong size of matrix to multiple"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx2.storage.Cols.Count); |
|||
float tmp; |
|||
KnuthNode<float> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
for (int j = 0; j < mtx2.storage.Cols.Count; ++j) |
|||
{ |
|||
tmp = 0; //initalize mult of i-th row and j-th column
|
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Cols[j].Up; |
|||
while (Iter1 != mtx1.storage.Rows[i] && Iter2 != mtx2.storage.Cols[j]) |
|||
{ |
|||
if (Iter1.Col == Iter2.Row) |
|||
{ |
|||
tmp += Iter1.Val * Iter2.Val; |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else if (Iter1.Col < Iter2.Row) |
|||
{ |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
if (tmp != 0) // paste not 0 element
|
|||
{ |
|||
Res.At(i, j, tmp); |
|||
} |
|||
|
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds two matrixes
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>result of summing this matrixes</returns>
|
|||
public static KnuthSparseMatrix operator +(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
if (mtx1.storage.Rows.Count != mtx2.storage.Rows.Count || mtx1.storage.Cols.Count != mtx2.storage.Cols.Count) |
|||
throw new Exception("Wrong size of matrix to summ"); |
|||
KnuthSparseMatrix Res = new KnuthSparseMatrix(mtx1.storage.Rows.Count, mtx1.storage.Cols.Count); |
|||
KnuthNode<float> Iter1, Iter2; |
|||
for (int i = 0; i < mtx1.storage.Rows.Count; ++i) |
|||
{ |
|||
Iter1 = mtx1.storage.Rows[i].Left; |
|||
Iter2 = mtx2.storage.Rows[i].Left; |
|||
while (Iter1 != mtx1.storage.Rows[i] || Iter2 != mtx2.storage.Rows[i]) |
|||
{ |
|||
if (Iter1 == mtx1.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter2 == mtx2.storage.Rows[i]) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
else if (Iter1.Col == Iter2.Col) |
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val + Iter2.Val); |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else if (Iter1.Col < Iter2.Col) |
|||
{ |
|||
Res.At(Iter2.Row, Iter2.Col, Iter2.Val); |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
else //(Iter2.Col < Iter1.Col)
|
|||
{ |
|||
Res.At(Iter1.Row, Iter1.Col, Iter1.Val); |
|||
Iter1 = Iter1.Left; |
|||
} |
|||
} |
|||
} |
|||
return Res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Change signs of all values to opposite
|
|||
/// </summary>
|
|||
/// <param name="rightSide"></param>
|
|||
/// <returns></returns>
|
|||
public static KnuthSparseMatrix operator -(KnuthSparseMatrix rightSide) |
|||
{ |
|||
if (rightSide == null) |
|||
{ |
|||
throw new ArgumentNullException("rightSide"); |
|||
} |
|||
KnuthSparseMatrix res = new KnuthSparseMatrix(rightSide); |
|||
res.Negate(); |
|||
return res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if two matrixes is equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are equal, else false</returns>
|
|||
public static bool operator ==(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return mtx1.Equals(mtx2); |
|||
} |
|||
/// <summary>
|
|||
/// Check if two matrixes aren`t equals
|
|||
/// </summary>
|
|||
/// <param name="mtx1">first matrix</param>
|
|||
/// <param name="mtx2">second matrix</param>
|
|||
/// <returns>true if matrixes are not equals, else - false</returns>
|
|||
public static bool operator !=(KnuthSparseMatrix mtx1, KnuthSparseMatrix mtx2) |
|||
{ |
|||
return !mtx1.Equals(mtx2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Get current matrix in full standart form
|
|||
/// </summary>
|
|||
/// <returns>matrix in full form</returns>
|
|||
public float[][] getFullMatrix() |
|||
{ |
|||
return storage.getFullMatrix(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,176 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Storage |
|||
{ |
|||
/// <summary>
|
|||
/// Node to store elements in Knuth sparse matrix
|
|||
/// </summary>
|
|||
public partial class KnuthNode<T> |
|||
where T : struct, IEquatable<T>, IFormattable |
|||
{ |
|||
/// <summary>
|
|||
/// Define zero element for current type
|
|||
/// </summary>
|
|||
readonly T zero; |
|||
|
|||
/// <summary>
|
|||
/// Row position of element
|
|||
/// </summary>
|
|||
public int Row |
|||
{ |
|||
set; |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Column possition of element
|
|||
/// </summary>
|
|||
public int Col |
|||
{ |
|||
set; |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Stored value
|
|||
/// </summary>
|
|||
public T Val |
|||
{ |
|||
set; |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Pointer to lefter element in row
|
|||
/// </summary>
|
|||
public KnuthNode<T> Left |
|||
{ |
|||
set; |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Pointer to upper element in column
|
|||
/// </summary>
|
|||
public KnuthNode<T> Up |
|||
{ |
|||
set; |
|||
get; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initialize new default instanse of KnuthNode class
|
|||
/// </summary>
|
|||
public KnuthNode(T _zero) |
|||
{ |
|||
zero = _zero; |
|||
Row = -1; |
|||
Col = -1; |
|||
Val = _zero; |
|||
Left = this; |
|||
Up = this; |
|||
} |
|||
/// <summary>
|
|||
/// Initialize new instanse of KnuthNode class
|
|||
/// </summary>
|
|||
/// <param name="x">row number </param>
|
|||
/// <param name="y">column number</param>
|
|||
/// <param name="val">value</param>
|
|||
public KnuthNode(int x, int y, T val, T _zero) |
|||
{ |
|||
zero = _zero; |
|||
Row = x; |
|||
Col = y; |
|||
Val = val; |
|||
Left = this; |
|||
Up = this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initialize new instanse of KnuthNode class
|
|||
/// </summary>
|
|||
/// <param name="x">row number </param>
|
|||
/// <param name="y">column number</param>
|
|||
/// <param name="val">value</param>
|
|||
/// <param name="left">pointer to lefter element in row</param>
|
|||
/// <param name="up">pointer to upper element in column</param>
|
|||
public KnuthNode(int x, int y, T val, KnuthNode<T> left, KnuthNode<T> up, T _zero) |
|||
{ |
|||
zero = _zero; |
|||
Row = x; |
|||
Col = y; |
|||
Val = val; |
|||
Left = left; |
|||
Up = up; |
|||
Left = this; |
|||
Up = this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if elements are equal
|
|||
/// </summary>
|
|||
/// <param name="nd2">second element</param>
|
|||
/// <returns>if elements are equal</returns>
|
|||
public bool Equals(KnuthNode<T> nd2) |
|||
{ |
|||
if (nd2 == null) |
|||
return false; |
|||
return Val.Equals(nd2.Val) && Row == nd2.Row && Col == nd2.Col; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Oparetor of equality
|
|||
/// </summary>
|
|||
/// <param name="nd1">first element</param>
|
|||
/// <param name="nd2">second element</param>
|
|||
/// <returns>if elements are equals</returns>
|
|||
public static bool operator ==(KnuthNode<T> nd1, KnuthNode<T> nd2) |
|||
{ |
|||
return nd1.Equals(nd2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Oparetor of equality
|
|||
/// </summary>
|
|||
/// <param name="nd1">first element</param>
|
|||
/// <param name="nd2">second element</param>
|
|||
/// <returns>if elements aren`t equals</returns>
|
|||
public static bool operator !=(KnuthNode<T> nd1, KnuthNode<T> nd2) |
|||
{ |
|||
return !nd1.Equals(nd2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if elements are equal
|
|||
/// </summary>
|
|||
/// <param name="nd2">second element</param>
|
|||
/// <returns>if elements are equal</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return base.Equals(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets hash code of node
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
var hashNum = Math.Min(Row * Col, 25); |
|||
int hash = 17; |
|||
unchecked |
|||
{ |
|||
for (var i = 0; i < hashNum; i++) |
|||
{ |
|||
var col = i % Row; |
|||
var row = (i - col) / Col; |
|||
hash = hash * 31 + Val.GetHashCode(); |
|||
} |
|||
} |
|||
return hash; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,453 @@ |
|||
|
|||
namespace MathNet.Numerics.LinearAlgebra.Storage |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// class to storage matrix using algorithm of Knuth
|
|||
/// </summary>
|
|||
public class KnuthSparseMatrixStorage<T> : MatrixStorage<T> |
|||
where T : struct, IEquatable<T>, IFormattable |
|||
{ |
|||
/// <summary>
|
|||
/// Define zero element for cuurnt type
|
|||
/// </summary>
|
|||
readonly T zero; |
|||
|
|||
/// <summary>
|
|||
/// list to begin rows elements
|
|||
/// </summary>
|
|||
public List<KnuthNode<T>> Rows; |
|||
|
|||
/// <summary>
|
|||
/// list to begin cols elements
|
|||
/// </summary>
|
|||
public List<KnuthNode<T>> Cols; |
|||
|
|||
/// <summary>
|
|||
/// Compare to elements if they equals
|
|||
/// </summary>
|
|||
/// <param name="mtx2">element to compare</param>
|
|||
/// <returns>if there quals</returns>
|
|||
public bool Equals(KnuthSparseMatrixStorage<T> mtx2) |
|||
{ |
|||
if (this.Rows.Count != mtx2.Rows.Count || this.Cols.Count != mtx2.Cols.Count) |
|||
return false; |
|||
KnuthNode<T> Iter1, Iter2; |
|||
//check rows
|
|||
for (int i = 0; i < this.Rows.Count; ++i) |
|||
{ |
|||
Iter1 = this.Rows[i]; |
|||
Iter2 = mtx2.Rows[i]; |
|||
//empty and not empty row
|
|||
if (Iter1.Left == Iter1 && Iter2.Left != Iter2) |
|||
return false; |
|||
if (Iter2.Left == Iter2 && Iter1.Left != Iter1) |
|||
return false; |
|||
while (Iter1.Left != this.Rows[i]) |
|||
{ |
|||
//row of second mtx allready ends
|
|||
if (Iter2.Left == mtx2.Rows[i]) |
|||
return false; |
|||
//not equal elements
|
|||
if (Iter1 != Iter2) |
|||
return false; |
|||
Iter1 = Iter1.Left; |
|||
Iter2 = Iter2.Left; |
|||
} |
|||
//row of second mtx not allready ends
|
|||
if (Iter2.Left != mtx2.Rows[i]) |
|||
return false; |
|||
} |
|||
//check cols
|
|||
for (int i = 0; i < this.Cols.Count; ++i) |
|||
{ |
|||
Iter1 = this.Cols[i]; |
|||
Iter2 = mtx2.Cols[i]; |
|||
//empty and not empty coll
|
|||
if (Iter1.Up == Iter1 && Iter2.Up != Iter2) |
|||
return false; |
|||
if (Iter2.Up == Iter2 && Iter1.Up != Iter1) |
|||
return false; |
|||
while (Iter1.Up != this.Cols[i]) |
|||
{ |
|||
//coll of second mtx allready ends
|
|||
if (Iter2.Up == mtx2.Cols[i]) |
|||
return false; |
|||
//not equal elements
|
|||
if (Iter1 != Iter2) |
|||
return false; |
|||
Iter1 = Iter1.Up; |
|||
Iter2 = Iter2.Up; |
|||
} |
|||
//row of second mtx not allready ends
|
|||
if (Iter2.Up != mtx2.Cols[i]) |
|||
return false; |
|||
} |
|||
//all elements are equals
|
|||
return true; |
|||
} |
|||
|
|||
public override bool Equals(MatrixStorage<T> other) |
|||
{ |
|||
return base.Equals(other); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets element at current position
|
|||
/// </summary>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="column">number of column</param>
|
|||
/// <returns>value on this position</returns>
|
|||
public override T At(int row, int column) |
|||
{ |
|||
return Get(row, column); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets element to current position
|
|||
/// </summary>
|
|||
/// <param name="row"></param>
|
|||
/// <param name="row">number of row</param>
|
|||
/// <param name="column">number of column</param>
|
|||
public override void At(int row, int column, T val) |
|||
{ |
|||
Insert(row, column, val); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Insert new value to current possition
|
|||
/// </summary>
|
|||
/// <param name="x">number of row</param>
|
|||
/// <param name="y">number of column</param>
|
|||
/// <param name="val">value to insert</param>
|
|||
private void Insert(int x, int y, T val) |
|||
{ |
|||
if (val.Equals(zero)) //var == 0
|
|||
{ |
|||
Delete(x, y); |
|||
return; |
|||
} |
|||
KnuthNode<T> rw = Rows[x]; |
|||
KnuthNode<T> cl = Cols[y]; |
|||
KnuthNode<T> toInsert = new KnuthNode<T>(x, y, val, zero); |
|||
//search needed row
|
|||
while (rw.Left != Rows[x] && rw.Left.Col >= y) |
|||
{ |
|||
rw = rw.Left; |
|||
} |
|||
//insert to row
|
|||
if (rw.Col == y) // element allready exist
|
|||
{ |
|||
rw.Val = val; |
|||
} |
|||
else |
|||
{ |
|||
toInsert.Left = rw.Left; |
|||
rw.Left = toInsert; |
|||
} |
|||
//search needed column
|
|||
while (cl.Up != Cols[y] && cl.Up.Row >= x) |
|||
{ |
|||
cl = cl.Up; |
|||
} |
|||
//insert to column
|
|||
if (cl.Row == x) // element allready exist
|
|||
{ |
|||
cl.Val = val; |
|||
} |
|||
else |
|||
{ |
|||
toInsert.Up = cl.Up; |
|||
cl.Up = toInsert; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Delete current element
|
|||
/// </summary>
|
|||
/// <param name="x">number of row</param>
|
|||
/// <param name="y">number of column</param>
|
|||
private void Delete(int x, int y) |
|||
{ |
|||
KnuthNode<T> rw = Rows[x].Left, prewRw = Rows[x]; |
|||
KnuthNode<T> cl = Cols[y].Up, prewCl = Cols[y]; |
|||
bool haver = false, havec = false; |
|||
for (int i = 0; i < Rows.Count; ++i) |
|||
{ |
|||
if (rw.Col == y) |
|||
{ |
|||
haver = true; |
|||
break; |
|||
} |
|||
prewRw = rw; |
|||
rw = rw.Left; |
|||
} |
|||
for (int i = 0; i < Cols.Count; ++i) |
|||
{ |
|||
if (cl.Row == x) |
|||
{ |
|||
havec = true; |
|||
break; |
|||
} |
|||
prewCl = cl; |
|||
cl = cl.Up; |
|||
} |
|||
if (havec && haver) |
|||
{ |
|||
prewCl.Up = cl.Up; |
|||
prewRw.Left = rw.Left; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Set bounds of new sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="row">count of rows</param>
|
|||
/// <param name="col">count of cols</param>
|
|||
private void SetBounds(int row, int col) |
|||
{ |
|||
Rows = new List<KnuthNode<T>>(row); |
|||
for (int i = 0; i < row; ++i) |
|||
{ |
|||
Rows.Add(new KnuthNode<T>(zero)); |
|||
} |
|||
Cols = new List<KnuthNode<T>>(col); |
|||
for (int i = 0; i < col; ++i) |
|||
{ |
|||
Cols.Add(new KnuthNode<T>(zero)); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="row">number of rows</param>
|
|||
/// <param name="col">number of columns</param>
|
|||
internal KnuthSparseMatrixStorage(int rows, int columns, T _zero) |
|||
: base(rows, columns) |
|||
{ |
|||
zero = _zero; |
|||
SetBounds(rows, columns); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix in standart presentation to set as sparse</param>
|
|||
internal KnuthSparseMatrixStorage(int rows, int columns, T[][] mtx, T _zero) |
|||
: base(rows, columns) |
|||
{ |
|||
zero = _zero; |
|||
SetBounds(mtx.Length, mtx[0].Length); |
|||
for (int i = 0; i < mtx.Length; ++i) |
|||
{ |
|||
for (int j = 0; j < mtx[i].Length; ++j) |
|||
{ |
|||
if (!mtx[i][j].Equals(zero)) |
|||
{ |
|||
Insert(i, j, mtx[i][j]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Create new instanse of sparse matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix in list<list> presentation to set as sparse</param>
|
|||
internal KnuthSparseMatrixStorage(int rows, int columns, List<List<T>> mtx, T _zero) |
|||
: base(rows, columns) |
|||
{ |
|||
zero = _zero; |
|||
SetBounds(mtx.Count, mtx[0].Count); |
|||
for (int i = 0; i < mtx.Count; ++i) |
|||
{ |
|||
for (int j = 0; j < mtx[i].Count; ++j) |
|||
{ |
|||
if (!mtx[i][j].Equals(zero)) |
|||
{ |
|||
Insert(i, j, mtx[i][j]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Copy existing instanse of matrix to new matrix
|
|||
/// </summary>
|
|||
/// <param name="mtx">matrix to copy</param>
|
|||
public KnuthSparseMatrixStorage<T> Copy() |
|||
{ |
|||
KnuthSparseMatrixStorage<T> res = new KnuthSparseMatrixStorage<T>(this.Rows.Count, this.Cols.Count, zero); |
|||
KnuthNode<T> rw; |
|||
for (int i = 0; i < Rows.Count; ++i) |
|||
{ |
|||
rw = Rows[i].Left; |
|||
while (rw != Rows[i]) |
|||
{ |
|||
res.Insert(rw.Row, rw.Col, rw.Val); |
|||
rw = rw.Left; |
|||
} |
|||
} |
|||
return res; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets element at curent position
|
|||
/// </summary>
|
|||
/// <param name="row"></param>
|
|||
/// <param name="column"></param>
|
|||
/// <returns></returns>
|
|||
public T Get(int row, int column) |
|||
{ |
|||
KnuthNode<T> rw = Rows[row].Left, prewRw = Rows[row]; |
|||
KnuthNode<T> cl = Cols[column].Up, prewCl = Cols[column]; |
|||
bool haver = false, havec = false; |
|||
for (int i = 0; i < Rows.Count; ++i) |
|||
{ |
|||
if (rw.Col == column) |
|||
{ |
|||
haver = true; |
|||
break; |
|||
} |
|||
prewRw = rw; |
|||
rw = rw.Left; |
|||
} |
|||
for (int i = 0; i < Cols.Count; ++i) |
|||
{ |
|||
if (cl.Row == row) |
|||
{ |
|||
havec = true; |
|||
break; |
|||
} |
|||
prewCl = cl; |
|||
cl = cl.Up; |
|||
} |
|||
if (havec && haver) |
|||
{ |
|||
return cl.Val; |
|||
} |
|||
else |
|||
{ |
|||
return zero; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the value at the given row and column.
|
|||
/// </summary>
|
|||
/// <param name="row">
|
|||
/// The row of the element.
|
|||
/// </param>
|
|||
/// <param name="column">
|
|||
/// The column of the element.
|
|||
/// </param>
|
|||
/// <value>The value to get or set.</value>
|
|||
//public T this[int row, int column]
|
|||
//{
|
|||
// get
|
|||
// {
|
|||
// if(row< 0 || row >= Rows.Count)
|
|||
// throw new ArgumentOutOfRangeException("row");
|
|||
// if (column < 0 || column >= Cols.Count)
|
|||
// throw new ArgumentOutOfRangeException("column");
|
|||
// return Get(row, column);
|
|||
// }
|
|||
|
|||
// set
|
|||
// {
|
|||
// if (row < 0 || row >= Rows.Count)
|
|||
// throw new ArgumentOutOfRangeException("row");
|
|||
// if (column < 0 || column >= Cols.Count)
|
|||
// throw new ArgumentOutOfRangeException("column");
|
|||
// Insert(row, column, value);
|
|||
// }
|
|||
//}
|
|||
|
|||
public override void CopyTo(MatrixStorage<T> target, bool skipClearing = false) |
|||
{ |
|||
base.CopyTo(target, skipClearing); |
|||
} |
|||
///// <summary>
|
|||
///// Check if two matrixes is equals
|
|||
///// </summary>
|
|||
///// <param name="mtx1">first matrix</param>
|
|||
///// <param name="mtx2">second matrix</param>
|
|||
///// <returns>true if matrixes are equal, else false</returns>
|
|||
//public static bool operator ==(KnuthSparseMatrixStorage<T> mtx1, KnuthSparseMatrixStorage<T> mtx2)
|
|||
//{
|
|||
// return mtx1.Equals(mtx2);
|
|||
//}
|
|||
///// <summary>
|
|||
///// Check if two matrixes aren`t equals
|
|||
///// </summary>
|
|||
///// <param name="mtx1">first matrix</param>
|
|||
///// <param name="mtx2">second matrix</param>
|
|||
///// <returns>true if matrixes are not equals, else - false</returns>
|
|||
//public static bool operator !=(KnuthSparseMatrixStorage<T> mtx1, KnuthSparseMatrixStorage<T> mtx2)
|
|||
//{
|
|||
// return !mtx1.Equals(mtx2);
|
|||
//}
|
|||
|
|||
/// <summary>
|
|||
/// Get current matrix in full standart form
|
|||
/// </summary>
|
|||
/// <returns>matrix in full form</returns>
|
|||
public T[][] getFullMatrix() |
|||
{ |
|||
T[][] res = new T[Rows.Count][]; |
|||
for (int i = 0; i < Rows.Count; ++i) |
|||
{ |
|||
res[i] = new T[Cols.Count]; |
|||
} |
|||
//initialize
|
|||
KnuthNode<T> iterator; |
|||
for (int i = 0; i < Rows.Count; ++i) |
|||
{ |
|||
iterator = Rows[i].Left; |
|||
while (iterator != Rows[i]) |
|||
{ |
|||
res[iterator.Row][iterator.Col] = iterator.Val; |
|||
iterator = iterator.Left; |
|||
} |
|||
} |
|||
return res; |
|||
} |
|||
|
|||
///// <summary>
|
|||
///// Compare to elements if they equals
|
|||
///// </summary>
|
|||
///// <param name="mtx2">element to compare</param>
|
|||
///// <returns>if there quals</returns>
|
|||
//public override bool Equals(object obj)
|
|||
//{
|
|||
// return base.Equals(obj);
|
|||
//}
|
|||
|
|||
/// <summary>
|
|||
/// Serves as a hash function for a particular type.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A hash code for the current <see cref="T:System.Object"/>.
|
|||
/// </returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
int RowCount = Rows.Count; |
|||
int ColumnCount = Cols.Count; |
|||
var hashNum = Math.Min(RowCount * ColumnCount, 25); |
|||
int hash = 17; |
|||
unchecked |
|||
{ |
|||
for (var i = 0; i < hashNum; i++) |
|||
{ |
|||
var col = i % ColumnCount; |
|||
var row = (i - col) / RowCount; |
|||
hash = hash * 31 + Get(row, col).GetHashCode(); |
|||
} |
|||
} |
|||
return hash; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue