diff --git a/src/FSharp/DenseVector.fs b/src/FSharp/DenseVector.fs
new file mode 100644
index 00000000..5126d7f0
--- /dev/null
+++ b/src/FSharp/DenseVector.fs
@@ -0,0 +1,48 @@
+//
+// 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.
+//
+
+namespace MathNet.Numerics
+
+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 of_list (fl: float list) =
+ let n = List.length fl
+ let v = Double.DenseVector(n)
+ fl |> List.iteri (fun i f -> v.[i] <- f)
+ v
\ No newline at end of file
diff --git a/src/FSharp/FSharp.fsproj b/src/FSharp/FSharp.fsproj
new file mode 100644
index 00000000..69c3e408
--- /dev/null
+++ b/src/FSharp/FSharp.fsproj
@@ -0,0 +1,59 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {37e8e802-a354-4114-bfc1-6e1357da605b}
+ Library
+ FSharp
+ MathNet.Numerics.FSharp
+ v3.5
+ FSharp
+
+
+ true
+ full
+ false
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ 3
+
+
+ pdbonly
+ true
+ true
+ bin\Release\
+ TRACE
+ 3
+
+
+
+
+
+
+ 3.5
+
+
+
+
+ Numerics
+ {b7cae5f4-a23f-4438-b5be-41226618b695}
+ True
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/FSharp/Main.fs b/src/FSharp/Main.fs
new file mode 100644
index 00000000..2a6bfe62
--- /dev/null
+++ b/src/FSharp/Main.fs
@@ -0,0 +1,37 @@
+//
+// 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.
+//
+
+namespace MathNet.Numerics
+
+open MathNet.Numerics.LinearAlgebra.Double
+
+/// A module which implements some F# utility functions.
+module FSharp =
+
+ /// Construct a dense vector from a list of floating point numbers.
+ let inline vector (lst: list) = DenseVector.of_list lst :> Vector
\ No newline at end of file
diff --git a/src/FSharpExamples/DenseVector.fs b/src/FSharpExamples/DenseVector.fs
new file mode 100644
index 00000000..bd2a1280
--- /dev/null
+++ b/src/FSharpExamples/DenseVector.fs
@@ -0,0 +1,11 @@
+open MathNet.Numerics.FSharp
+open MathNet.Numerics.LinearAlgebra
+
+/// Create a new 100 dimensional dense vector.
+let v = DenseVector.init 100 (fun i -> float i / 100.0)
+
+/// Another way to create a 100 dimensional dense vector is as follows.
+let w = vector (List.init 100 (fun i -> float i ** 2.0))
+
+/// Perform some binary arithmetic on vectors.
+let x = v + w
\ No newline at end of file
diff --git a/src/FSharpExamples/FSharpExamples.fsproj b/src/FSharpExamples/FSharpExamples.fsproj
new file mode 100644
index 00000000..e264d823
--- /dev/null
+++ b/src/FSharpExamples/FSharpExamples.fsproj
@@ -0,0 +1,63 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {bc81ea37-8ee6-4bf9-b8a9-b30497aef8b1}
+ Library
+ FSharpExamples
+ FSharpExamples
+ v3.5
+ FSharpExamples
+
+
+ true
+ full
+ false
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ 3
+
+
+ pdbonly
+ true
+ true
+ bin\Release\
+ TRACE
+ 3
+
+
+
+
+
+
+ 3.5
+
+
+
+
+ FSharp
+ {37e8e802-a354-4114-bfc1-6e1357da605b}
+ True
+
+
+ Numerics
+ {b7cae5f4-a23f-4438-b5be-41226618b695}
+ True
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/FSharpUnitTests/FSharpUnitTests.fsproj b/src/FSharpUnitTests/FSharpUnitTests.fsproj
new file mode 100644
index 00000000..d73c1d8f
--- /dev/null
+++ b/src/FSharpUnitTests/FSharpUnitTests.fsproj
@@ -0,0 +1,64 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {f2f8032b-a31d-4e33-a05e-f2cdcbfaa75d}
+ Library
+ FSharpUnitTests
+ FSharpUnitTests
+ v3.5
+ FSharpUnitTests
+
+
+ true
+ full
+ false
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ 3
+
+
+ pdbonly
+ true
+ true
+ bin\Release\
+ TRACE
+ 3
+
+
+
+
+
+
+ 3.5
+
+
+
+
+
+
+
+
+ FSharp
+ {37e8e802-a354-4114-bfc1-6e1357da605b}
+ True
+
+
+ Numerics
+ {b7cae5f4-a23f-4438-b5be-41226618b695}
+ True
+
+
+
+
+
\ No newline at end of file
diff --git a/src/FSharpUnitTests/FsUnit.fs b/src/FSharpUnitTests/FsUnit.fs
new file mode 100644
index 00000000..e6da2926
--- /dev/null
+++ b/src/FSharpUnitTests/FsUnit.fs
@@ -0,0 +1,222 @@
+(*
+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
+
+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
+
+[]
+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 = 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 approximately_equal (expected: float) (actual: float) =
+ make (fun () ->
+ if Precision.AlmostEqualInDecimalPlaces(actual, expected, 5)
+ then Pass
+ else Fail (sprintf "Expected: %A\nActual: %A" expected actual))
+ (sprintf "NOT Expected: %A\nActual: %A" expected actual)
+
+ let approximately_vector_equal (expected: #Vector) (actual: #Vector) =
+ make (fun () ->
+ let mutable f = true
+ for i=0 to expected.Count-1 do
+ f <- f && Precision.AlmostEqualInDecimalPlaces(expected.[i], actual.[i], 5)
+ 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 (expected: #Matrix) (actual: #Matrix) =
+ 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], 5)
+ 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.Printf
+
+ let internal currentResults = new ResizeArray()
+
+ 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()
+ bprintf buff "%d passed.\n%d failed.\n%d erred." (passedCount()) (failedCount()) (erredCount())
+ failed()
+ |> Seq.iter (function (lbl,Fail msg) -> bprintf buff "\n----\nFailed: %s\n%s" lbl msg | _ -> ())
+ erred()
+ |> Seq.iter (function (lbl,Error msg) -> bprintf buff "\n----\nErred: %s\n%s" lbl msg | _ -> ())
+ buff.ToString()
+
+
+[]
+module SpecHelpers =
+ let spec lbl s = (lbl, check s)
+
+ let should f x = f x
+
+ let specs lbl (results: seq) =
+ results |> Seq.iter (fun x -> Results.add x)
diff --git a/src/FSharpUnitTests/Program.fs b/src/FSharpUnitTests/Program.fs
new file mode 100644
index 00000000..2445077d
--- /dev/null
+++ b/src/FSharpUnitTests/Program.fs
@@ -0,0 +1,19 @@
+open FsUnit
+open MathNet.Numerics.FSharp
+open MathNet.Numerics.LinearAlgebra
+
+/// Unit tests for the dense vector type.
+let DenseVectorTests =
+
+ /// A small uniform vector.
+ let smallv = new Double.DenseVector( [|0.3;0.3;0.3;0.3;0.3|] )
+
+ /// A large vector with increasingly large entries
+ let largev = new Double.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.of_list"
+ (DenseVector.of_list [ for i in 0 .. 99 -> float i / 100.0 ] |> should equal largev)
+ ]
\ No newline at end of file
diff --git a/src/MathNet.Numerics.sln b/src/MathNet.Numerics.sln
index b0cc8130..f22f09ff 100644
--- a/src/MathNet.Numerics.sln
+++ b/src/MathNet.Numerics.sln
@@ -7,6 +7,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics", "Numerics\Numeri
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{8C9A5D3F-A20C-4D24-A09C-98E187A8D720}"
EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp", "FSharp\FSharp.fsproj", "{37E8E802-A354-4114-BFC1-6E1357DA605B}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpExamples", "FSharpExamples\FSharpExamples.fsproj", "{BC81EA37-8EE6-4BF9-B8A9-B30497AEF8B1}"
+EndProject
+Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests", "FSharpUnitTests\FSharpUnitTests.fsproj", "{F2F8032B-A31D-4E33-A05E-F2CDCBFAA75D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -25,6 +31,18 @@ Global
{8C9A5D3F-A20C-4D24-A09C-98E187A8D720}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C9A5D3F-A20C-4D24-A09C-98E187A8D720}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C9A5D3F-A20C-4D24-A09C-98E187A8D720}.Release|Any CPU.Build.0 = Release|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
+ {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
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE