Browse Source

Build: .Net 3.5 support for F# extensions #243

pull/248/head
Christoph Ruegg 12 years ago
parent
commit
07cd0194f3
  1. 20
      MathNet.Numerics.All.sln
  2. 18
      MathNet.Numerics.Net35Only.sln
  3. 5
      build.fsx
  4. 60
      src/FSharp/Compatibility.fs
  5. 166
      src/FSharp/Complex.fs
  6. 94
      src/FSharp/FSharp-Net35.fsproj
  7. 1
      src/FSharp/FSharp-Portable328.fsproj
  8. 1
      src/FSharp/FSharp-Portable47.fsproj
  9. 1
      src/FSharp/FSharp.fsproj
  10. 3
      src/FSharp/Fit.fs
  11. 111
      src/FSharp/LinearAlgebra.Matrix.fs
  12. 57
      src/FSharp/LinearAlgebra.Vector.fs
  13. 7
      src/FSharpUnitTests/App.config
  14. 2
      src/FSharpUnitTests/DenseMatrixTests.fs
  15. 2
      src/FSharpUnitTests/DenseVectorTests.fs
  16. 103
      src/FSharpUnitTests/FSharpUnitTests-Net35.fsproj
  17. 4
      src/FSharpUnitTests/FindRootsTests.fs
  18. 2
      src/FSharpUnitTests/SparseMatrixTests.fs
  19. 2
      src/FSharpUnitTests/Utilities.fs
  20. 6
      src/FSharpUnitTests/VectorTests.fs

20
MathNet.Numerics.All.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}"
ProjectSection(SolutionItems) = preProject
@ -55,6 +55,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{B54A0B40
build\packages.config = build\packages.config
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp-Net35", "src\FSharp\FSharp-Net35.fsproj", "{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests-Net35", "src\FSharpUnitTests\FSharpUnitTests-Net35.fsproj", "{8C96F2E9-681B-4201-8BDD-0AA901203725}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -143,6 +147,18 @@ Global
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release|Any CPU.Build.0 = Release|Any CPU
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release|Any CPU.Build.0 = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release|Any CPU.Build.0 = Release|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -158,6 +174,8 @@ Global
{EC24DA9F-8772-491D-BA56-3ADA75072B3D} = {9D409E95-D567-4C2F-A0DF-87A6DF5B3A2E}
{E54E712D-EB6B-4FBF-B29A-6BB95E719BAC} = {14DAACDA-AD68-4AAE-B65F-9F6C60866327}
{9014A0CE-725D-4718-918C-923C0CA19FEE} = {14DAACDA-AD68-4AAE-B65F-9F6C60866327}
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4} = {14DAACDA-AD68-4AAE-B65F-9F6C60866327}
{8C96F2E9-681B-4201-8BDD-0AA901203725} = {14DAACDA-AD68-4AAE-B65F-9F6C60866327}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = src\Numerics\Numerics.csproj

18
MathNet.Numerics.Net35Only.sln

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Readme", "Readme", "{C2F37492-38AE-4186-8A7F-17B0B080942C}"
ProjectSection(SolutionItems) = preProject
@ -17,6 +17,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Numerics-Net35", "src\Numer
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests-Net35", "src\UnitTests\UnitTests-Net35.csproj", "{9014A0CE-725D-4718-918C-923C0CA19FEE}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp-Net35", "src\FSharp\FSharp-Net35.fsproj", "{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpUnitTests-Net35", "src\FSharpUnitTests\FSharpUnitTests-Net35.fsproj", "{8C96F2E9-681B-4201-8BDD-0AA901203725}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -36,6 +40,18 @@ Global
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release|Any CPU.Build.0 = Release|Any CPU
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release-Signed|Any CPU.ActiveCfg = Release|Any CPU
{9014A0CE-725D-4718-918C-923C0CA19FEE}.Release-Signed|Any CPU.Build.0 = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release|Any CPU.Build.0 = Release|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{D5DBCEC0-9D9D-4A62-9EE0-F78E1895D4F4}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release|Any CPU.Build.0 = Release|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release-Signed|Any CPU.ActiveCfg = Release-Signed|Any CPU
{8C96F2E9-681B-4201-8BDD-0AA901203725}.Release-Signed|Any CPU.Build.0 = Release-Signed|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

5
build.fsx

@ -66,7 +66,7 @@ trace (sprintf " Math.NET Numerics v%s" packageVersion)
let summary = "Math.NET Numerics, providing methods and algorithms for numerical computations in science, engineering and every day use."
let description = "Math.NET Numerics is the numerical foundation of the Math.NET project, aiming to provide methods and algorithms for numerical computations in science, engineering and every day use. "
let support = "Supports .Net 4.0, .Net 3.5 and Mono on Windows, Linux and Mac; Silverlight 5, WindowsPhone/SL 8, WindowsPhone 8.1 and Windows 8 with PCL Portable Profiles 47 and 328; Android/iOS with Xamarin."
let supportFsharp = "Supports F# 3.0 on .Net 4.0 and Mono on Windows, Linux and Mac; Silverlight 5, WindowsPhone/SL 8, WindowsPhone 8.1 and Windows 8 with PCL Portable Profiles 47 and 328; Android/iOS with Xamarin."
let supportFsharp = "Supports F# 3.0 on .Net 4.0, .Net 3.5 and Mono on Windows, Linux and Mac; Silverlight 5, WindowsPhone/SL 8, WindowsPhone 8.1 and Windows 8 with PCL Portable Profiles 47 and 328; Android/iOS with Xamarin."
let supportSigned = "Supports .Net 4.0."
let tags = "math numeric statistics probability integration interpolation regression solve fit linear algebra matrix fft"
@ -98,7 +98,8 @@ let fsharpPack =
Description = description + supportFsharp
Tags = "fsharp F# " + tags
Dependencies = [{ FrameworkVersion=""; Dependencies=[ "MathNet.Numerics", RequireExactly packageVersion ] }]
Files = [ @"..\..\out\lib\Net40\MathNet.Numerics.FSharp.*", Some libnet40, None;
Files = [ @"..\..\out\lib\Net35\MathNet.Numerics.FSharp.*", Some libnet35, None;
@"..\..\out\lib\Net40\MathNet.Numerics.FSharp.*", Some libnet40, None;
@"..\..\out\lib\Profile47\MathNet.Numerics.FSharp.*", Some libpcl47, None;
@"..\..\out\lib\Profile328\MathNet.Numerics.FSharp.*", Some libpcl328, None;
@"..\..\out\lib\Profile328\MathNet.Numerics.FSharp.*", Some libpcl328, None;

60
src/FSharp/Compatibility.fs

@ -0,0 +1,60 @@
// <copyright file="Compatibility.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-2014 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
[<AutoOpen>]
module internal Compatibility =
#if NET35
let inline internal properTuple2 (tuple: MathNet.Numerics.Tuple<'a,'b>) = tuple.Item1, tuple.Item2
let inline internal properTuple3 (tuple: MathNet.Numerics.Tuple<'a,'b,'c>) = tuple.Item1, tuple.Item2, tuple.Item3
let inline internal internalTuple2 ((a,b): ('a * 'b)) = MathNet.Numerics.Tuple<'a,'b>(a, b)
let inline internal internalTuple3 ((a,b,c): ('a * 'b * 'c)) = MathNet.Numerics.Tuple<'a,'b,'c>(a, b, c)
let inline internal properTuple2Seq x = x |> Seq.map properTuple2
let inline internal properTuple3Seq x = x |> Seq.map properTuple3
let inline internal internalTuple2Seq x = x |> Seq.map internalTuple2
let inline internal internalTuple3Seq x = x |> Seq.map internalTuple3
#else
let inline internal properTuple2 x = x
let inline internal properTuple3 x = x
let inline internal internalTuple2 x = x
let inline internal internalTuple3 x = x
let inline internal properTuple2Seq x = x
let inline internal properTuple3Seq x = x
let inline internal internalTuple2Seq x = x
let inline internal internalTuple3Seq x = x
#endif

166
src/FSharp/Complex.fs

@ -26,168 +26,168 @@ module Complex =
/// Create a complex number using magnitude/phase polar coordinates
let mkPolar(a,b) = Complex.FromPolarCoordinates(a,b)
/// A complex of magnitude 1 and the given phase and , i.e. cis x = mkPolar 1.0 x
let cis b = mkPolar(1.0,b)
//
let private ofComplex32 (x : complex32) =
Complex(float x.Real, float x.Imaginary)
/// The complex number 0+0i
let zero = Complex.Zero
/// The complex number 1+0i
let one = Complex.One
/// The complex number 0+1i
let onei = Complex.ImaginaryOne
/// pi
let pi = mkRect (Math.PI,0.0)
/// The real part of a complex number
let realPart (c:complex) = c.Real
/// The imaginary part of a complex number
let imagPart (c:complex) = c.Imaginary
/// The polar-coordinate magnitude of a complex number
let magnitude (c:complex) = c.Magnitude
/// The polar-coordinate phase of a complex number
let phase (c:complex) = c.Phase
/// Unary negation of a complex number
let neg (a:complex) = -a
/// The conjugate of a complex number, i.e. x-yi
let conjugate (c:complex) = c.Conjugate()
/// Add two complex numbers
let add (a:complex) (b:complex) = a + b
/// Subtract one complex number from another
let sub (a:complex) (b:complex) = a - b
/// Multiply two complex numbers
let mul (a:complex) (b:complex) = a * b
/// Complex division of two complex numbers
let div (x:complex) (y:complex) = x / y
/// Multiply a scalar by a complex number
let smul (a:float) (b:complex) = new Complex(a * b.Real, a * b.Imaginary)
/// Multiply a complex number by a scalar
let muls (a:complex) (b:float) = new Complex(a.Real * b, a.Imaginary * b)
/// exp(x) = e^x
let exp (x:complex) = Complex.Exp(x)
/// ln(x) is natural log (base e)
let ln x = Complex.Log(x)
/// log10(x) is common log (base 10)
let log10 x = Complex.Log10(x)
/// log(base,x) is log with custom base
let log b x = Complex.Log(x,b)
/// pow(power,x) is the complex power
let pow (power : complex) x = Complex.Pow(x,power)
/// pow(power,x) is the scalar power
let powf (power : float) x = Complex.Pow(x,power)
/// sqr(x) is the square (power 2)
let sqr (x : complex) = x.Square()
/// sqrt(x) and 0 <= phase(x) < pi
let sqrt (x : complex) = x.SquareRoot() // numerically more stable than Complex.Sqrt
/// Sine
let sin x = Complex.Sin(x)
/// Cosine
let cos x = Complex.Cos(x)
/// Tagent
let tan x = Complex.Tan(x)
/// Cotangent
let cot (x : complex) = Trig.Cot(x)
/// Secant
let sec (x : complex) = Trig.Sec(x)
/// Cosecant
let csc (x : complex) = Trig.Csc(x)
/// Arc Sine
let asin (x : complex) =
// numerically more stable than Complex.Asin
Trig.Asin(x)
/// Arc Cosine
let acos (x : complex) =
// numerically more stable than Complex.Acos
Trig.Acos(x)
/// Arc Tagent
let atan x = Complex.Atan(x)
/// Arc Cotangent
let acot (x : complex) = Trig.Acot(x)
/// Arc Secant
let asec (x : complex) = Trig.Asec(x)
/// Arc Cosecant
let acsc (x : complex) = Trig.Acsc(x)
/// Hyperbolic Sine
let sinh x = Complex.Sinh(x)
/// Hyperbolic Cosine
let cosh x = Complex.Cosh(x)
/// Hyperbolic Tagent
let tanh x = Complex.Tanh(x)
/// Hyperbolic Cotangent
let coth (x : complex) = Trig.Coth(x)
/// Hyperbolic Secant
let sech (x : complex) = Trig.Sech(x)
/// Hyperbolic Cosecant
let csch (x : complex) = Trig.Csch(x)
/// Inverse Hyperbolic Sine
let asinh (x : complex) = Trig.Asinh(x)
/// Inverse Hyperbolic Cosine
let acosh (x : complex) = Trig.Acosh(x)
/// Inverse Hyperbolic Tagent
let atanh (x : complex) = Trig.Atanh(x)
/// Inverse Hyperbolic Cotangent
let acoth (x : complex) = Trig.Acoth(x)
/// Inverse Hyperbolic Secant
let asech (x : complex) = Trig.Asech(x)
/// Inverse Hyperbolic Cosecant
let acsch (x : complex) = Trig.Acsch(x)
@ -197,7 +197,7 @@ module Complex =
module Complex32 =
/// Create a complex number using real and imaginary parts
let mkRect(a,b) = new Complex32(a,b)
/// Create a complex number using magnitude/phase polar coordinates
let mkPolar(a,b) = Complex32.FromPolarCoordinates(a,b)
@ -211,46 +211,46 @@ module Complex32 =
/// The complex number 0+0i
let zero = Complex32.Zero
/// The complex number 1+0i
let one = Complex32.One
/// The complex number 0+1i
let onei = Complex32.ImaginaryOne
/// pi
let pi = mkRect (float32 Math.PI,0.0f)
/// The real part of a complex number
let realPart (c:complex32) = c.Real
/// The imaginary part of a complex number
let imagPart (c:complex32) = c.Imaginary
/// The polar-coordinate magnitude of a complex number
let magnitude (c:complex32) = c.Magnitude
/// The polar-coordinate phase of a complex number
let phase (c:complex32) = c.Phase
/// Unary negation of a complex number
let neg (a:complex32) = -a
/// The conjugate of a complex number, i.e. x-yi
let conjugate (c:complex32) = c.Conjugate()
/// Add two complex numbers
let add (a:complex32) (b:complex32) = a + b
/// Subtract one complex number from another
let sub (a:complex32) (b:complex32) = a - b
/// Multiply two complex numbers
let mul (a:complex32) (b:complex32) = a * b
/// Complex division of two complex numbers
let div (x:complex32) (y:complex32) = x / y
@ -258,7 +258,7 @@ module Complex32 =
/// Multiply a scalar by a complex number
let smul (a:float32) (b:complex32) =
Complex32(a * b.Real, a * b.Imaginary)
/// Multiply a complex number by a scalar
let muls (a:complex32) (b:float32) =
Complex32(a.Real * b, a.Imaginary * b)
@ -266,50 +266,50 @@ module Complex32 =
/// exp(x) = e^x
let exp (x:complex32) = Complex32.Exp(x)
/// ln(x) is natural log (base e)
let ln x = Complex32.Log(x)
/// log10(x) is common log (base 10)
let log10 x = Complex32.Log10(x)
/// log(base,x) is log with custom base
let log b x = Complex32.Log(x,b)
/// pow(power,x) is the complex power
let pow (power:complex32) x = Complex32.Pow(x,power)
/// pow(power,x) is the scalar power
let powf (power:float32) x = Complex32.Pow(x,power)
/// sqr(x) is the square (power 2)
let sqr (x:complex32) = x.Square()
/// sqrt(x) and 0 <= phase(x) < pi
let sqrt (x:complex32) =
// numerically more stable than Complex.Sqrt
x.SquareRoot()
(* Complex32 implementations are not yet available for some of the functions below.
TODO : Fix the functions below to use the Complex32 implementations once available. *)
/// Sine
let sin x = Complex32.Sin(x)
/// Cosine
let cos x = Complex32.Cos(x)
/// Tagent
let tan x = Complex32.Tan(x)
/// Cotangent
let cot (x:complex32) = ofComplex <| Trig.Cot(x.ToComplex())
/// Secant
let sec (x:complex32) = ofComplex <| Trig.Sec(x.ToComplex())
/// Cosecant
let csc (x:complex32) = ofComplex <| Trig.Csc(x.ToComplex())
@ -318,56 +318,56 @@ module Complex32 =
let asin (x:complex32) =
// numerically more stable than Complex.Asin
ofComplex <| Trig.Asin(x.ToComplex())
/// Arc Cosine
let acos (x:complex32) =
// numerically more stable than Complex.Acos
ofComplex <| Trig.Acos(x.ToComplex())
/// Arc Tagent
let atan x = Complex32.Atan(x)
/// Arc Cotangent
let acot (x:complex32) = ofComplex <| Trig.Acot(x.ToComplex())
/// Arc Secant
let asec (x:complex32) = ofComplex <| Trig.Asec(x.ToComplex())
/// Arc Cosecant
let acsc (x:complex32) = ofComplex <| Trig.Acsc(x.ToComplex())
/// Hyperbolic Sine
let sinh x = Complex32.Sinh(x)
/// Hyperbolic Cosine
let cosh x = Complex32.Cosh(x)
/// Hyperbolic Tagent
let tanh x = Complex32.Tanh(x)
/// Hyperbolic Cotangent
let coth (x:complex32) = ofComplex <| Trig.Coth(x.ToComplex())
/// Hyperbolic Secant
let sech (x:complex32) = ofComplex <| Trig.Sech(x.ToComplex())
/// Hyperbolic Cosecant
let csch (x:complex32) = ofComplex <| Trig.Csch(x.ToComplex())
/// Inverse Hyperbolic Sine
let asinh (x:complex32) = ofComplex <| Trig.Asinh(x.ToComplex())
/// Inverse Hyperbolic Cosine
let acosh (x:complex32) = ofComplex <| Trig.Acosh(x.ToComplex())
/// Inverse Hyperbolic Tagent
let atanh (x:complex32) = ofComplex <| Trig.Atanh(x.ToComplex())
/// Inverse Hyperbolic Cotangent
let acoth (x:complex32) = ofComplex <| Trig.Acoth(x.ToComplex())
/// Inverse Hyperbolic Secant
let asech (x:complex32) = ofComplex <| Trig.Asech(x.ToComplex())

94
src/FSharp/FSharp-Net35.fsproj

@ -0,0 +1,94 @@
<?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>
<ProjectGuid>{d5dbcec0-9d9d-4a62-9ee0-f78e1895d4f4}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MathNet.Numerics</RootNamespace>
<AssemblyName>MathNet.Numerics.FSharp</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<Name>FSharp</Name>
<TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
<!-- Conditional Strong Name -->
<AssemblyOriginatorKeyFile>..\MathNet.Numerics.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>..\..\out\lib\Net35\</OutputPath>
<IntermediateOutputPath>..\..\obj\lib\Net35\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\lib\Net35\</BaseIntermediateOutputPath>
<DocumentationFile>..\..\out\lib\Net35\MathNet.Numerics.FSharp.xml</DocumentationFile>
<DefineConstants>TRACE;NET35;NOSYSNUMERICS</DefineConstants>
<WarningLevel>3</WarningLevel>
<!-- Conditional Strong Name: NO -->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>..\..\out\lib-debug\Net35\</OutputPath>
<IntermediateOutputPath>..\..\obj\lib-debug\Net35\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\lib-debug\Net35\</BaseIntermediateOutputPath>
<DefineConstants>TRACE;DEBUG;NET35;NOSYSNUMERICS</DefineConstants>
<WarningLevel>3</WarningLevel>
<!-- Conditional Strong Name: NO -->
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Signed|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<DefineConstants>TRACE;NET35;NOSYSNUMERICS;STRONGNAME</DefineConstants>
<WarningLevel>3</WarningLevel>
<OutputPath>..\..\out\lib-signed\Net35\</OutputPath>
<IntermediateOutputPath>..\..\obj\lib-signed\Net35\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\lib-signed\Net35\</BaseIntermediateOutputPath>
<DocumentationFile>..\..\out\lib-signed\Net35\MathNet.Numerics.FSharp.xml</DocumentationFile>
<!-- Conditional Strong Name: YES -->
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0' Or $(OS) != 'Windows_NT'">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Compatibility.fs" />
<Compile Include="Statistics.fs" />
<Compile Include="Random.fs" />
<Compile Include="Distributions.fs" />
<Compile Include="Generate.fs" />
<Compile Include="LinearAlgebra.Vector.fs" />
<Compile Include="LinearAlgebra.Matrix.fs" />
<Compile Include="Complex.fs" />
<Compile Include="BigIntegerExtensions.fs" />
<Compile Include="BigRational.fsi" />
<Compile Include="BigRational.fs" />
<Compile Include="Fit.fs" />
<Compile Include="FindRoots.fs" />
<Compile Include="RandomVariable.fs" />
<None Include="MathNet.Numerics.fsx" />
</ItemGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=2.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>False</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Numerics\Numerics-Net35.csproj">
<Name>Numerics-Net35</Name>
<Project>{e54e712d-eb6b-4fbf-b29a-6bb95e719bac}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
</Project>

1
src/FSharp/FSharp-Portable328.fsproj

@ -46,6 +46,7 @@
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Compatibility.fs" />
<Compile Include="Statistics.fs" />
<Compile Include="Random.fs" />
<Compile Include="Distributions.fs" />

1
src/FSharp/FSharp-Portable47.fsproj

@ -46,6 +46,7 @@
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Compatibility.fs" />
<Compile Include="Statistics.fs" />
<Compile Include="Random.fs" />
<Compile Include="Distributions.fs" />

1
src/FSharp/FSharp.fsproj

@ -59,6 +59,7 @@
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="Compatibility.fs" />
<Compile Include="Statistics.fs" />
<Compile Include="Random.fs" />
<Compile Include="Distributions.fs" />

3
src/FSharp/Fit.fs

@ -31,6 +31,7 @@
namespace MathNet.Numerics
open System
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
open MathNet.Numerics.LinearAlgebra.Factorization
@ -41,7 +42,7 @@ module Fit =
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning its best fitting parameters as (a, b) tuple.
let line x y = Fit.Line(x,y)
let line x y = Fit.Line(x,y) |> properTuple2
/// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
/// returning a function y' for the best fitting line.

111
src/FSharp/LinearAlgebra.Matrix.fs

@ -31,6 +31,7 @@
namespace MathNet.Numerics.LinearAlgebra
open System
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
@ -46,163 +47,163 @@ module Matrix =
let inline toSeq (m: #Matrix<_>) = m.Enumerate(Zeros.Include)
/// Transform a matrix into an indexed sequence.
let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include)
let inline toSeqi (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> properTuple3Seq
/// Transform a matrix into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip)
/// Transform a matrix into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip)
let inline toSeqiSkipZeros (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> properTuple3Seq
/// Transform a matrix into a column sequence.
let inline toColSeq (m: #Matrix<_>) = m.EnumerateColumns()
/// Transform a matrix into an indexed column sequence.
let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed()
let inline toColSeqi (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> properTuple2Seq
/// Transform a matrix into a row sequence.
let inline toRowSeq (m: #Matrix<_>) = m.EnumerateRows()
/// Transform a matrix into an indexed row sequence.
let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed()
let inline toRowSeqi (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> properTuple2Seq
/// Applies a function to all elements of the matrix.
let inline iter f (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.iter f
let inline iter f (m: #Matrix<_>) = m |> toSeq |> Seq.iter f
/// Applies a function to all indexed elements of the matrix.
let inline iteri f (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.iter (fun (i, j, x) -> f i j x)
let inline iteri f (m: #Matrix<_>) = m |> toSeqi |> Seq.iter (fun (i, j, x) -> f i j x)
/// Applies a function to all non-zero elements of the matrix. Skipping zeros is efficient on sparse data.
let inline iterSkipZerosnz f (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.iter f
let inline iterSkipZerosnz f (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.iter f
/// Applies a function to all non-zero indexed elements of the matrix. Skipping zeros is efficient on sparse data.
let inline iteriSkipZeros f (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.iter (fun (i, j, x) -> f i j x)
let inline iteriSkipZeros f (m: #Matrix<_>) = m |> toSeqiSkipZeros |> Seq.iter (fun (i, j, x) -> f i j x)
/// Applies a function to all columns of the matrix.
let inline iterCols f (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.iter f
let inline iterCols f (m: #Matrix<_>) = m |> toColSeq |> Seq.iter f
/// Applies a function to all indexed columns of the matrix.
let inline iteriCols f (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.iteri f
let inline iteriCols f (m: #Matrix<_>) = m |> toColSeq |> Seq.iteri f
/// Applies a function to all rows of the matrix.
let inline iterRows f (m: #Matrix<_>) = m.EnumerateRows() |> Seq.iter f
let inline iterRows f (m: #Matrix<_>) = m |> toRowSeq |> Seq.iter f
/// Applies a function to all indexed rows of the matrix.
let inline iteriRows f (m: #Matrix<_>) = m.EnumerateRows() |> Seq.iteri f
let inline iteriRows f (m: #Matrix<_>) = m |> toRowSeq |> Seq.iteri f
/// Fold all entries of a matrix.
let inline fold f state (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.fold f state
let inline fold f state (m: #Matrix<_>) = m |> toSeq |> Seq.fold f state
/// Fold all entries of a matrix with an indexed folding function.
let inline foldi f state (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.fold (fun s (i,j,x) -> f i j s x) state
let inline foldi f state (m: #Matrix<_>) = m |> toSeqi |> Seq.fold (fun s (i,j,x) -> f i j s x) state
/// Fold all non-zero entries of a matrix. Skipping zeros is efficient on sparse data.
let inline foldSkipZeros f state (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.fold f state
let inline foldSkipZeros f state (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.fold f state
/// Fold all non-zero entries of a matrix with an indexed folding function. Skipping zeros is efficient on sparse data.
let inline foldiSkipZeros f state (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.fold (fun s (i,j,x) -> f i j s x) state
let inline foldiSkipZeros f state (m: #Matrix<_>) = m |> toSeqiSkipZeros |> Seq.fold (fun s (i,j,x) -> f i j s x) state
/// Fold all columns of a matrix.
let inline foldCols f state (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.fold f state
let inline foldCols f state (m: #Matrix<_>) = m |> toColSeq |> Seq.fold f state
/// Fold all columns of a matrix with an indexed folding function.
let inline foldiCols f state (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.fold (fun s (j,x) -> f j s x) state
let inline foldiCols f state (m: #Matrix<_>) = m |> toColSeqi |> Seq.fold (fun s (j,x) -> f j s x) state
/// Fold all rows of a matrix.
let inline foldRows f state (m: #Matrix<_>) = m.EnumerateRows() |> Seq.fold f state
let inline foldRows f state (m: #Matrix<_>) = m |> toRowSeq |> Seq.fold f state
/// Fold all rows of a matrix with an indexed folding function.
let inline foldiRows f state (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.fold (fun s (i,x) -> f i s x) state
let inline foldiRows f state (m: #Matrix<_>) = m |> toRowSeqi |> Seq.fold (fun s (i,x) -> f i s x) state
/// Scan all entries of a matrix.
let inline scan f state (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.scan f state
let inline scan f state (m: #Matrix<_>) = m |> toSeq |> Seq.scan f state
/// Scan all entries of a matrix with an indexed folding function.
let inline scani f state (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.scan (fun s (i,j,x) -> f i j s x) state
let inline scani f state (m: #Matrix<_>) = m |> toSeqi |> Seq.scan (fun s (i,j,x) -> f i j s x) state
/// Scan all non-zero entries of a matrix. Skipping zeros is efficient on sparse data.
let inline scanSkipZeros f state (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.scan f state
let inline scanSkipZeros f state (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.scan f state
/// Scan all non-zero entries of a matrix with an indexed folding function. Skipping zeros is efficient on sparse data.
let inline scaniSkipZeros f state (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.scan (fun s (i,j,x) -> f i j s x) state
let inline scaniSkipZeros f state (m: #Matrix<_>) = m |> toSeqiSkipZeros |> Seq.scan (fun s (i,j,x) -> f i j s x) state
/// Scan all columns of a matrix.
let inline scanCols f state (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.scan f state
let inline scanCols f state (m: #Matrix<_>) = m |> toColSeq |> Seq.scan f state
/// Scan all columns of a matrix with an indexed folding function.
let inline scaniCols f state (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.scan (fun s (j,x) -> f j s x) state
let inline scaniCols f state (m: #Matrix<_>) = m |> toColSeqi |> Seq.scan (fun s (j,x) -> f j s x) state
/// Scan all rows of a matrix.
let inline scanRows f state (m: #Matrix<_>) = m.EnumerateRows() |> Seq.scan f state
let inline scanRows f state (m: #Matrix<_>) = m |> toRowSeq |> Seq.scan f state
/// Scan all rows of a matrix with an indexed folding function.
let inline scaniRows f state (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.scan (fun s (i,x) -> f i s x) state
let inline scaniRows f state (m: #Matrix<_>) = m |> toRowSeqi |> Seq.scan (fun s (i,x) -> f i s x) state
/// Reduce all entries of a matrix.
let inline reduce f (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.reduce f
let inline reduce f (m: #Matrix<_>) = m |> toSeq |> Seq.reduce f
/// Reduce all non-zero entries of a matrix. Skipping zeros is efficient on sparse data.
let inline reduceSkipZeros f (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.reduce f
let inline reduceSkipZeros f (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.reduce f
/// Reduce all columns of a matrix.
let inline reduceCols f (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.reduce f
let inline reduceCols f (m: #Matrix<_>) = m |> toColSeq |> Seq.reduce f
/// Reduce all rows of a matrix.
let inline reduceRows f (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.reduce f
let inline reduceRows f (m: #Matrix<_>) = m |> toColSeq |> Seq.reduce f
/// Checks whether there is an entry in the matrix that satisfies a predicate.
let inline exists p (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.exists p
let inline exists p (m: #Matrix<_>) = m |> toSeq |> Seq.exists p
/// Checks whether there is an entry in the matrix that satisfies a position dependent predicate.
let inline existsi p (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.exists (fun (i,j,x) -> p i j x)
let inline existsi p (m: #Matrix<_>) = m |> toSeqi |> Seq.exists (fun (i,j,x) -> p i j x)
/// Checks whether there is a non-zero entry in the matrix that satisfies a predicate. Skipping zeros is efficient on sparse data.
let inline existsSkipZeros p (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.exists p
let inline existsSkipZeros p (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.exists p
/// Checks whether there is a non-zero entry in the matrix that satisfies a position dependent predicate. Skipping zeros is efficient on sparse data.
let inline existsiSkipZeros p (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.exists (fun (i,j,x) -> p i j x)
let inline existsiSkipZeros p (m: #Matrix<_>) = m |> toSeqiSkipZeros |> Seq.exists (fun (i,j,x) -> p i j x)
/// Checks whether there is a column in the matrix that satisfies a predicate.
let inline existsCol p (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.exists p
let inline existsCol p (m: #Matrix<_>) = m |> toColSeq |> Seq.exists p
/// Checks whether there is a column in the matrix that satisfies a position dependent predicate.
let inline existsiCol p (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.exists (fun (j,x) -> p j x)
let inline existsiCol p (m: #Matrix<_>) = m |> toColSeqi |> Seq.exists (fun (j,x) -> p j x)
/// Checks whether there is a row in the matrix that satisfies a predicate.
let inline existsRow p (m: #Matrix<_>) = m.EnumerateRows() |> Seq.exists p
let inline existsRow p (m: #Matrix<_>) = m |> toRowSeq |> Seq.exists p
/// Checks whether there is a row in the matrix that satisfies a position dependent predicate.
let inline existsiRow p (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.exists (fun (i,x) -> p i x)
let inline existsiRow p (m: #Matrix<_>) = m |> toRowSeqi |> Seq.exists (fun (i,x) -> p i x)
/// Checks whether all entries in the matrix that satisfies a given predicate.
let inline forall p (m: #Matrix<_>) = m.Enumerate(Zeros.Include) |> Seq.forall p
let inline forall p (m: #Matrix<_>) = m |> toSeq |> Seq.forall p
/// Checks whether all entries in the matrix that satisfies a given position dependent predicate.
let inline foralli p (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.Include) |> Seq.forall (fun (i,j,x) -> p i j x)
let inline foralli p (m: #Matrix<_>) = m |> toSeqi |> Seq.forall (fun (i,j,x) -> p i j x)
/// Checks whether all non-zero entries in the matrix that satisfies a given predicate. Skipping zeros is efficient on sparse data.
let inline forallSkipZeros p (m: #Matrix<_>) = m.Enumerate(Zeros.AllowSkip) |> Seq.forall p
let inline forallSkipZeros p (m: #Matrix<_>) = m |> toSeqSkipZeros |> Seq.forall p
/// Checks whether all non-zero entries in the matrix that satisfies a given position dependent predicate. Skipping zeros is efficient on sparse data.
let inline foralliSkipZeros p (m: #Matrix<_>) = m.EnumerateIndexed(Zeros.AllowSkip) |> Seq.forall (fun (i,j,x) -> p i j x)
let inline foralliSkipZeros p (m: #Matrix<_>) = m |> toSeqiSkipZeros |> Seq.forall (fun (i,j,x) -> p i j x)
/// Checks whether all columns in the matrix that satisfy a predicate.
let inline forallCols p (m: #Matrix<_>) = m.EnumerateColumns() |> Seq.forall p
let inline forallCols p (m: #Matrix<_>) = m |> toColSeq |> Seq.forall p
/// Checks whether all columns in the matrix that satisfy a position dependent predicate.
let inline foralliCols p (m: #Matrix<_>) = m.EnumerateColumnsIndexed() |> Seq.forall (fun (j,x) -> p j x)
let inline foralliCols p (m: #Matrix<_>) = m |> toColSeqi |> Seq.forall (fun (j,x) -> p j x)
/// Checks whether all rows in the matrix that satisfy a predicate.
let inline forallRows p (m: #Matrix<_>) = m.EnumerateRows() |> Seq.forall p
let inline forallRows p (m: #Matrix<_>) = m |> toRowSeq |> Seq.forall p
/// Checks whether all rows in the matrix that satisfy a position dependent predicate.
let inline foralliRows p (m: #Matrix<_>) = m.EnumerateRowsIndexed() |> Seq.forall (fun (i,x) -> p i x)
let inline foralliRows p (m: #Matrix<_>) = m |> toRowSeqi |> Seq.forall (fun (i,x) -> p i x)
@ -327,11 +328,11 @@ module Matrix =
/// Returns the sum of the results generated by applying a position dependent function to each column of the matrix.
let inline sumColsBy f (A: #Matrix<_>) =
A.EnumerateColumnsIndexed() |> Seq.map (fun (j,col) -> f j col) |> Seq.reduce (+)
A |> toColSeqi |> 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 (A: #Matrix<_>) =
A.EnumerateRowsIndexed() |> Seq.map (fun (i,row) -> f i row) |> Seq.reduce (+)
A |> toRowSeqi |> Seq.map (fun (i,row) -> f i row) |> Seq.reduce (+)
let inline rowCount (A: #Matrix<_>) = A.RowCount
@ -457,10 +458,10 @@ module DenseMatrix =
let inline ofColumnSeq2 (rows: int) (cols: int) (seqOfCols: #seq<seq<'T>>) = Matrix<'T>.Build.DenseOfColumns(rows, cols, seqOfCols)
/// Create a matrix with a given dimension from an indexed list of row, column, value tuples.
let inline ofListi (rows: int) (cols: int) (indexed: list<int * int * 'T>) = Matrix<'T>.Build.DenseOfIndexed(rows, cols, Seq.ofList indexed)
let inline ofListi (rows: int) (cols: int) (indexed: list<int * int * 'T>) = Matrix<'T>.Build.DenseOfIndexed(rows, cols, Seq.ofList indexed |> internalTuple3Seq)
/// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples.
let inline ofSeqi (rows: int) (cols: int) (indexed: #seq<int * int * 'T>) = Matrix<'T>.Build.DenseOfIndexed(rows, cols, indexed)
let inline ofSeqi (rows: int) (cols: int) (indexed: #seq<int * int * 'T>) = Matrix<'T>.Build.DenseOfIndexed(rows, cols, indexed |> internalTuple3Seq)
/// Create a square matrix with the vector elements on the diagonal.
let inline ofDiag (v: Vector<'T>) = Matrix<'T>.Build.DenseOfDiagonalVector(v)
@ -552,10 +553,10 @@ module SparseMatrix =
let inline ofColumnSeq2 (rows: int) (cols: int) (seqOfCols: #seq<seq<'T>>) = Matrix<'T>.Build.SparseOfColumns(rows, cols, seqOfCols)
/// Create a matrix with a given dimension from an indexed list of row, column, value tuples.
let inline ofListi (rows: int) (cols: int) (indexed: list<int * int * 'T>) = Matrix<'T>.Build.SparseOfIndexed(rows, cols, Seq.ofList indexed)
let inline ofListi (rows: int) (cols: int) (indexed: list<int * int * 'T>) = Matrix<'T>.Build.SparseOfIndexed(rows, cols, Seq.ofList indexed |> internalTuple3Seq)
/// Create a matrix with a given dimension from an indexed sequences of row, column, value tuples.
let inline ofSeqi (rows: int) (cols: int) (indexed: #seq<int * int * 'T>) = Matrix<'T>.Build.SparseOfIndexed(rows, cols, indexed)
let inline ofSeqi (rows: int) (cols: int) (indexed: #seq<int * int * 'T>) = Matrix<'T>.Build.SparseOfIndexed(rows, cols, indexed |> internalTuple3Seq)
/// Create a square matrix with the vector elements on the diagonal.
let inline ofDiag (v: Vector<'T>) = Matrix<'T>.Build.SparseOfDiagonalVector(v)
@ -576,7 +577,7 @@ module DiagonalMatrix =
/// Create a matrix that directly binds to a storage object.
let inline ofStorage (storage:Storage.DiagonalMatrixStorage<_>) = Matrix<'T>.Build.Diagonal(storage)
/// Create a square matrix that directly binds to a raw storage array that represents the diagonal, without copying.
let inline raw (diagonal: 'T[]) = Matrix<'T>.Build.Diagonal(diagonal)

57
src/FSharp/LinearAlgebra.Vector.fs

@ -31,6 +31,7 @@
namespace MathNet.Numerics.LinearAlgebra
open System
open MathNet.Numerics
open MathNet.Numerics.LinearAlgebra
@ -49,85 +50,85 @@ module Vector =
let inline toSeq (v: #Vector<_>) = v.Enumerate(Zeros.Include)
/// Transform a vector into an indexed sequence.
let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include)
let inline toSeqi (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> properTuple2Seq
/// Transform a vector into a sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqSkipZeros (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip)
/// Transform a vector into an indexed sequence where zero-values are skipped. Skipping zeros is efficient on sparse data.
let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip)
let inline toSeqiSkipZeros (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> properTuple2Seq
/// Applies a function to all elements of the vector.
let inline iter f (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.iter f
let inline iter f (v: #Vector<_>) = v |> toSeq |> Seq.iter f
/// Applies a function to all indexed elements of the vector.
let inline iteri f (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.iteri f
let inline iteri f (v: #Vector<_>) = v |> toSeq |> Seq.iteri f
/// Applies a function to all non-zero elements of the vector. Skipping zeros is efficient on sparse data.
let inline iterSkipZeros f (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.iter f
let inline iterSkipZeros f (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.iter f
/// Applies a function to all non-zero indexed elements of the vector. Skipping zeros is efficient on sparse data.
let inline iteriSkipZeros f (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.iter (fun (i,x) -> f i x)
let inline iteriSkipZeros f (v: #Vector<_>) = v |> toSeqiSkipZeros |> Seq.iter (fun (i,x) -> f i x)
/// Fold all entries of a vector.
let inline fold f state (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.fold f state
let inline fold f state (v: #Vector<_>) = v |> toSeq |> Seq.fold f state
/// Fold all entries of a vector using a position dependent folding function.
let inline foldi f state (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.fold (fun s (i,x) -> f i s x) state
let inline foldi f state (v: #Vector<_>) = v |> toSeqi |> Seq.fold (fun s (i,x) -> f i s x) state
/// Fold all non-zero entries of a vector. Skipping zeros is efficient on sparse data.
let inline foldSkipZeros f state (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.fold f state
let inline foldSkipZeros f state (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.fold f state
/// Fold all non-zero entries of a vector using a position dependent folding function. Skipping zeros is efficient on sparse data.
let inline foldiSkipZeros f state (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.fold (fun s (i,x) -> f i s x) state
let inline foldiSkipZeros f state (v: #Vector<_>) = v |> toSeqiSkipZeros |> Seq.fold (fun s (i,x) -> f i s x) state
/// Scan all entries of a vector.
let inline scan f state (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.scan f state
let inline scan f state (v: #Vector<_>) = v |> toSeq |> Seq.scan f state
/// Scan all entries of a vector using a position dependent folding function.
let inline scani f state (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.scan (fun s (i,x) -> f i s x) state
let inline scani f state (v: #Vector<_>) = v |> toSeqi |> Seq.scan (fun s (i,x) -> f i s x) state
/// Scan all non-zero entries of a vector. Skipping zeros is efficient on sparse data.
let inline scanSkipZeros f state (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.scan f state
let inline scanSkipZeros f state (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.scan f state
/// Scan all non-zero entries of a vector using a position dependent folding function. Skipping zeros is efficient on sparse data.
let inline scaniSkipZeros f state (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.scan (fun s (i,x) -> f i s x) state
let inline scaniSkipZeros f state (v: #Vector<_>) = v |> toSeqiSkipZeros |> Seq.scan (fun s (i,x) -> f i s x) state
/// Reduce all entries of a vector.
let inline reduce f (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.reduce f
let inline reduce f (v: #Vector<_>) = v |> toSeq |> Seq.reduce f
/// Reduce all non-zero entries of a vector. Skipping zeros is efficient on sparse data.
let inline reduceSkipZeros f (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.reduce f
let inline reduceSkipZeros f (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.reduce f
/// Checks whether there is an entry in the vector that satisfies a predicate.
let inline exists p (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.exists p
let inline exists p (v: #Vector<_>) = v |> toSeq |> Seq.exists p
/// Checks whether there is an entry in the vector that satisfies a position dependent predicate.
let inline existsi p (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.exists (fun (i,x) -> p i x)
let inline existsi p (v: #Vector<_>) = v |> toSeqi |> Seq.exists (fun (i,x) -> p i x)
/// Checks whether there is a non-zero entry in the vector that satisfies a predicate. Skipping zeros is efficient on sparse data.
let inline existsSkipZeros p (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.exists p
let inline existsSkipZeros p (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.exists p
/// Checks whether there is a non-zero entry in the vector that satisfies a position dependent predicate. Skipping zeros is efficient on sparse data.
let inline existsiSkipZeros p (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.exists (fun (i,x) -> p i x)
let inline existsiSkipZeros p (v: #Vector<_>) = v |> toSeqiSkipZeros |> Seq.exists (fun (i,x) -> p i x)
/// Checks whether all entries in the vector that satisfies a given predicate.
let inline forall p (v: #Vector<_>) = v.Enumerate(Zeros.Include) |> Seq.forall p
let inline forall p (v: #Vector<_>) = v |> toSeq |> Seq.forall p
/// Checks whether all entries in the vector that satisfies a given position dependent predicate.
let inline foralli p (v: #Vector<_>) = v.EnumerateIndexed(Zeros.Include) |> Seq.forall (fun (i,x) -> p i x)
let inline foralli p (v: #Vector<_>) = v |> toSeqi |> Seq.forall (fun (i,x) -> p i x)
/// Checks whether all non-zero entries in the vector that satisfies a given predicate. Skipping zeros is efficient on sparse data.
let inline forallSkipZeros p (v: #Vector<_>) = v.Enumerate(Zeros.AllowSkip) |> Seq.forall p
let inline forallSkipZeros p (v: #Vector<_>) = v |> toSeqSkipZeros |> Seq.forall p
/// Checks whether all non-zero entries in the vector that satisfies a given position dependent predicate. Skipping zeros is efficient on sparse data.
let inline foralliSkipZeros p (v: #Vector<_>) = v.EnumerateIndexed(Zeros.AllowSkip) |> Seq.forall (fun (i,x) -> p i x)
let inline foralliSkipZeros p (v: #Vector<_>) = v |> toSeqiSkipZeros |> Seq.forall (fun (i,x) -> p i x)
@ -272,10 +273,10 @@ module DenseVector =
let inline ofSeq (fs: #seq<'T>) = Vector<'T>.Build.DenseOfEnumerable(fs)
/// Create a vector with a given dimension from an indexed list of index, value pairs.
let inline ofListi (n: int) (fl: list<int * 'T>) = Vector<'T>.Build.DenseOfIndexed(n, Seq.ofList fl)
let inline ofListi (n: int) (fl: list<int * 'T>) = Vector<'T>.Build.DenseOfIndexed(n, Seq.ofList fl |> internalTuple2Seq)
/// Create a vector with a given dimension from an indexed sequences of index, value pairs.
let inline ofSeqi (n: int) (fs: #seq<int * 'T>) = Vector<'T>.Build.DenseOfIndexed(n, fs)
let inline ofSeqi (n: int) (fs: #seq<int * 'T>) = Vector<'T>.Build.DenseOfIndexed(n, fs |> internalTuple2Seq)
/// Create a vector with integer entries in the given range.
let inline range (start: int) (step: int) (stop: int) = raw [| for i in start..step..stop -> float i |]
@ -311,10 +312,10 @@ module SparseVector =
let inline ofSeq (fs: #seq<'T>) = Vector<'T>.Build.SparseOfEnumerable(fs)
/// Create a sparse vector with a given dimension from an indexed list of index, value pairs.
let inline ofListi (n: int) (fl: list<int * 'T>) = Vector<'T>.Build.SparseOfIndexed(n, Seq.ofList fl)
let inline ofListi (n: int) (fl: list<int * 'T>) = Vector<'T>.Build.SparseOfIndexed(n, Seq.ofList fl |> internalTuple2Seq)
/// Create a sparse vector with a given dimension from an indexed sequence of index, value pairs.
let inline ofSeqi (n: int) (fs: #seq<int * 'T>) = Vector<'T>.Build.SparseOfIndexed(n, fs)
let inline ofSeqi (n: int) (fs: #seq<int * 'T>) = Vector<'T>.Build.SparseOfIndexed(n, fs |> internalTuple2Seq)
/// Module that contains implementation of useful F#-specific extension members for generic vectors

7
src/FSharpUnitTests/App.config

@ -4,8 +4,8 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="4.3.0.0" />
<bindingRedirect oldVersion="2.3.5.0" newVersion="4.3.0.0" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="2.3.0.0" />
<bindingRedirect oldVersion="2.3.5.0" newVersion="2.3.0.0" />
<bindingRedirect oldVersion="4.0.0.0" newVersion="4.3.0.0" />
</dependentAssembly>
<dependentAssembly>
@ -14,7 +14,4 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

2
src/FSharpUnitTests/DenseMatrixTests.fs

@ -83,7 +83,7 @@ module DenseMatrixTests =
let ``DenseMatrix.ofListi`` () =
[ for i in 0 .. 99 do for j in 0 .. 119 -> (i,j, float i * 100.0 + float j) ]
|> DenseMatrix.ofListi 100 120 |> should equal largeM
[<Test>]
let ``DenseMatrix.diag`` () =
DenseMatrix.diag 100 2.0 |> should equal (2.0 * (DenseMatrix.identity 100))

2
src/FSharpUnitTests/DenseVectorTests.fs

@ -18,7 +18,7 @@ module DenseVectorTests =
[<Test>]
let ``DenseVector.zero`` () =
(DenseVector.zero 100) + largev |> should equal largev
[<Test>]
let ``DenseVector.random`` () =
let m = DenseVector.random 100 (Normal.WithMeanStdDev(100.0,0.1))

103
src/FSharpUnitTests/FSharpUnitTests-Net35.fsproj

@ -0,0 +1,103 @@
<?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>
<ProjectGuid>{8c96f2e9-681b-4201-8bdd-0aa901203725}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>FSharpUnitTests</RootNamespace>
<AssemblyName>MathNet.Numerics.FSharp.UnitTests</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<Name>FSharpUnitTests</Name>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
<TargetFSharpCoreVersion>4.3.0.0</TargetFSharpCoreVersion>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>..\..\out\test\Net40\</OutputPath>
<IntermediateOutputPath>..\..\obj\test\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\test\Net40\</BaseIntermediateOutputPath>
<DefineConstants>TRACE;NET35;NOSYSNUMERICS</DefineConstants>
<WarningLevel>3</WarningLevel>
</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>
<IntermediateOutputPath>..\..\obj\test-debug\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\test-debug\Net40\</BaseIntermediateOutputPath>
<DefineConstants>DEBUG;TRACE;NET35;NOSYSNUMERICS</DefineConstants>
<WarningLevel>3</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release-Signed|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<DefineConstants>TRACE;NET35;NOSYSNUMERICS</DefineConstants>
<WarningLevel>3</WarningLevel>
<OutputPath>..\..\out\test-signed\Net40\</OutputPath>
<IntermediateOutputPath>..\..\obj\test-signed\Net40\</IntermediateOutputPath>
<BaseIntermediateOutputPath>..\..\obj\test-signed\Net40\</BaseIntermediateOutputPath>
</PropertyGroup>
<PropertyGroup>
<!-- Workaround - remove once no longer needed! -->
<DefineConstants>$(DefineConstants);NOFSSLICESET1D</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.Core, Version=2.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>False</Private>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="FsUnit.NUnit">
<HintPath>..\..\packages\FsUnit.1.2.1.0\Lib\Net20\FsUnit.NUnit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.fs" />
<Compile Include="VectorTests.fs" />
<Compile Include="SparseVectorTests.fs" />
<Compile Include="DenseVectorTests.fs" />
<Compile Include="MatrixTests.fs" />
<Compile Include="SparseMatrixTests.fs" />
<Compile Include="DenseMatrixTests.fs" />
<Compile Include="Utilities.fs" />
<Compile Include="BigRationalTests.fs" />
<Compile Include="RandomVariableTests.fs" />
<Compile Include="PokerTests.fs" />
<Compile Include="FitTests.fs" />
<Compile Include="FindRootsTests.fs" />
<None Include="packages.config" />
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FSharp\FSharp-Net35.fsproj">
<Name>FSharp-Net35</Name>
<Project>{d5dbcec0-9d9d-4a62-9ee0-f78e1895d4f4}</Project>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\Numerics\Numerics-Net35.csproj">
<Name>Numerics-Net35</Name>
<Project>{e54e712d-eb6b-4fbf-b29a-6bb95e719bac}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0' Or $(OS) != 'Windows_NT'">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
<Import Project="$(FSharpTargetsPath)" Condition="Exists('$(FSharpTargetsPath)')" />
</Project>

4
src/FSharpUnitTests/FindRootsTests.fs

@ -9,7 +9,7 @@ module FindRootsTests =
let f x = (x - 3.0)*(x - 4.0)
let df x = 2.0*x - 7.0
let g (xa:float[]) =
let g (xa:float[]) =
let x = xa.[0];
let T = xa.[1];
let k = 0.12 * Math.Exp(12581.0 * (T - 298.0) / (298.0 * T));
@ -36,7 +36,7 @@ module FindRootsTests =
let ``Newton-Raphson by Guess should find both roots of (x - 3) * (x - 4)``() =
(f, df) ||> FindRoots.newtonRaphsonGuess 100 1e-14 2.8 |> should equal (Some 3.0)
(f, df) ||> FindRoots.newtonRaphsonGuess 100 1e-14 3.7 |> should equal (Some 4.0)
[<Test>]
let ``Robust Newton-Raphson should find both roots of (x - 3) * (x - 4)``() =
(f, df) ||> FindRoots.newtonRaphsonRobust 100 20 1e-14 -5.0 3.5 |> should equal (Some 3.0)

2
src/FSharpUnitTests/SparseMatrixTests.fs

@ -53,7 +53,7 @@ module SparseMatrixTests =
[<Test>]
let ``SparseMatrix.ofListi`` () =
SparseMatrix.ofListi 4 6 [(1,2,1.0)] |> should equal smallM
[<Test>]
let ``SparseMatrix.diag`` () =
SparseMatrix.diag 100 2.0 |> should equal (2.0 * (SparseMatrix.identity 100))

2
src/FSharpUnitTests/Utilities.fs

@ -124,5 +124,3 @@ module Utilities =
let checkThrowsKeyNotFoundException f = checkThrowsExn<KeyNotFoundException> f
let checkThrowsDivideByZeroException f = checkThrowsExn<DivideByZeroException> f
let checkThrowsInvalidOperationExn f = checkThrowsExn<InvalidOperationException> f

6
src/FSharpUnitTests/VectorTests.fs

@ -171,14 +171,14 @@ module VectorTests =
[<Test>]
let ``Pointwise Multiplication using .* Operator`` () =
let z = largev .* largev
z |> should equal (DenseVector.init 100 (fun i -> (float i / 100.0) ** 2.0))
z |> should (approximately_equal 14) (DenseVector.init 100 (fun i -> (float i / 100.0) ** 2.0))
[<Test>]
let ``Pointwise Division using ./ Operator`` () =
let z = largev ./ DenseVector.create 100 2.0
z |> should equal (largev * 0.5)
z |> should (approximately_equal 14) (largev * 0.5)
[<Test>]
let ``Pointwise Modulus using .% Operator`` () =
let z = largev .% DenseVector.create 100 2.0
z |> should equal (largev % 2.0)
z |> should (approximately_equal 14) (largev % 2.0)

Loading…
Cancel
Save